← back to CelebritySignatures
iOS app: native Expo/EAS scaffold over celebsignatures.com APIs
73d91377c2e9a7db12011b8cf84d59a62b02e367 · 2026-08-05 15:43:37 -0700 · Steve
Clones the proven Charge&Explore mobile template (Expo SDK 56 / RN 0.85.3).
Native screens (no thin-WebView) for App Store Guideline 4.2: Gallery (grid over
/api/signatures + portraits), Signature detail (+ evolution timeline), Whose-
signature Game (leaderboard), Murals browse (+ quote form; physical-print
checkout opens web = IAP-exempt), Account (auth + saved + delete-account).
Reused ui/glass (recolored museum gold) + ui/no-track (strips ads/analytics in
the binary → App Privacy 'no tracking'). bundle com.abrams.celebsignatures,
team 3VAV3KMNZK. tsc --noEmit clean. eas.json ios.image:latest (ITMS-90725
guard). ASC app record + .p8 + eas submit remain gated.
Files touched
A apps/mobile/.gitignoreA apps/mobile/App.tsxA apps/mobile/api.tsA apps/mobile/app.jsonA apps/mobile/eas.jsonA apps/mobile/index.tsA apps/mobile/package-lock.jsonA apps/mobile/package.jsonA apps/mobile/screens/AccountScreen.tsxA apps/mobile/screens/GalleryScreen.tsxA apps/mobile/screens/GameScreen.tsxA apps/mobile/screens/MuralsScreen.tsxA apps/mobile/screens/SignatureDetail.tsxA apps/mobile/tsconfig.jsonA apps/mobile/ui/glass.tsxA apps/mobile/ui/no-track.ts
Diff
commit 73d91377c2e9a7db12011b8cf84d59a62b02e367
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Aug 5 15:43:37 2026 -0700
iOS app: native Expo/EAS scaffold over celebsignatures.com APIs
Clones the proven Charge&Explore mobile template (Expo SDK 56 / RN 0.85.3).
Native screens (no thin-WebView) for App Store Guideline 4.2: Gallery (grid over
/api/signatures + portraits), Signature detail (+ evolution timeline), Whose-
signature Game (leaderboard), Murals browse (+ quote form; physical-print
checkout opens web = IAP-exempt), Account (auth + saved + delete-account).
Reused ui/glass (recolored museum gold) + ui/no-track (strips ads/analytics in
the binary → App Privacy 'no tracking'). bundle com.abrams.celebsignatures,
team 3VAV3KMNZK. tsc --noEmit clean. eas.json ios.image:latest (ITMS-90725
guard). ASC app record + .p8 + eas submit remain gated.
---
apps/mobile/.gitignore | 12 +
apps/mobile/App.tsx | 131 +
apps/mobile/api.ts | 83 +
apps/mobile/app.json | 28 +
apps/mobile/eas.json | 42 +
apps/mobile/index.ts | 4 +
apps/mobile/package-lock.json | 6103 +++++++++++++++++++++++++++++++
apps/mobile/package.json | 28 +
apps/mobile/screens/AccountScreen.tsx | 564 +++
apps/mobile/screens/GalleryScreen.tsx | 374 ++
apps/mobile/screens/GameScreen.tsx | 740 ++++
apps/mobile/screens/MuralsScreen.tsx | 532 +++
apps/mobile/screens/SignatureDetail.tsx | 294 ++
apps/mobile/tsconfig.json | 7 +
apps/mobile/ui/glass.tsx | 166 +
apps/mobile/ui/no-track.ts | 50 +
16 files changed, 9158 insertions(+)
diff --git a/apps/mobile/.gitignore b/apps/mobile/.gitignore
new file mode 100644
index 0000000..c1e43d7
--- /dev/null
+++ b/apps/mobile/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.expo/
+dist/
+web-build/
+*.log
+.DS_Store
+ios/
+android/
+credentials/
+*.p8
+*.p12
+*.mobileprovision
diff --git a/apps/mobile/App.tsx b/apps/mobile/App.tsx
new file mode 100644
index 0000000..10bb27b
--- /dev/null
+++ b/apps/mobile/App.tsx
@@ -0,0 +1,131 @@
+import React, { useCallback, useState } from 'react';
+import {
+ ActivityIndicator, Modal, Pressable, SafeAreaView, StyleSheet, Text, View,
+} from 'react-native';
+import { StatusBar } from 'expo-status-bar';
+import * as Haptics from 'expo-haptics';
+import { WebView } from 'react-native-webview';
+import { api, WEB_BASE, Evolution, Signature } from './api';
+import { NO_TRACK } from './ui/no-track';
+import { GLASS, GlassBar, GlassScene } from './ui/glass';
+import GalleryScreen from './screens/GalleryScreen';
+import SignatureDetail from './screens/SignatureDetail';
+import GameScreen from './screens/GameScreen';
+import MuralsScreen from './screens/MuralsScreen';
+import AccountScreen from './screens/AccountScreen';
+
+// Native shell: the gallery, game, murals-browse, and account are all real
+// native screens over the existing celebsignatures.com JSON APIs (the App
+// Review 4.2 mitigation — not a WebView wrapper). The only WebView is the
+// mural print CHECKOUT, which is a physical good (IAP-exempt) and rides the
+// site's redirect-based Stripe flow; NO_TRACK strips its ads/analytics so the
+// binary does no tracking (App Privacy = "not used to track you").
+
+type Tab = 'gallery' | 'game' | 'murals' | 'account';
+const TABS: { key: Tab; label: string; glyph: string }[] = [
+ { key: 'gallery', label: 'Gallery', glyph: '✒︎' },
+ { key: 'game', label: 'Game', glyph: '◆' },
+ { key: 'murals', label: 'Murals', glyph: '▦' },
+ { key: 'account', label: 'Account', glyph: '☺' },
+];
+
+export default function App() {
+ const [tab, setTab] = useState<Tab>('gallery');
+ const [selected, setSelected] = useState<Signature | null>(null);
+ const [evolution, setEvolution] = useState<Evolution | null>(null);
+ const [webUrl, setWebUrl] = useState<string | null>(null);
+
+ const openSignature = useCallback((sig: Signature) => {
+ Haptics.selectionAsync().catch(() => {});
+ setSelected(sig);
+ // Lazy-load the evolution map once, on first detail open.
+ setEvolution((cur) => {
+ if (!cur) api.evolution().then(setEvolution).catch(() => {});
+ return cur;
+ });
+ }, []);
+
+ const orderMural = useCallback((sig: Signature) => {
+ setSelected(null);
+ setWebUrl(`${WEB_BASE}/murals?name=${encodeURIComponent(sig.full_name)}`);
+ }, []);
+
+ const selectTab = useCallback((t: Tab) => {
+ Haptics.selectionAsync().catch(() => {});
+ setTab(t);
+ }, []);
+
+ return (
+ <GlassScene>
+ <SafeAreaView style={styles.safe}>
+ <StatusBar style="light" />
+
+ <View style={styles.body}>
+ {tab === 'gallery' && <GalleryScreen onOpen={openSignature} />}
+ {tab === 'game' && <GameScreen />}
+ {tab === 'murals' && <MuralsScreen onOpenWeb={setWebUrl} />}
+ {tab === 'account' && <AccountScreen />}
+ </View>
+
+ {/* Native bottom tab bar */}
+ <View style={styles.tabbar}>
+ {TABS.map((t) => {
+ const active = t.key === tab;
+ return (
+ <Pressable key={t.key} style={styles.tab} onPress={() => selectTab(t.key)} hitSlop={8}>
+ <Text style={[styles.tabGlyph, active && styles.tabActive]}>{t.glyph}</Text>
+ <Text style={[styles.tabLabel, active && styles.tabActive]}>{t.label}</Text>
+ </Pressable>
+ );
+ })}
+ </View>
+
+ {/* Signature detail */}
+ <Modal visible={!!selected} animationType="slide" onRequestClose={() => setSelected(null)}>
+ <GlassScene>
+ <SafeAreaView style={styles.modalSafe}>
+ <GlassBar title={selected?.full_name ?? 'Signature'} onDone={() => setSelected(null)} />
+ {selected && (
+ <SignatureDetail sig={selected} evolution={evolution} onOrderMural={orderMural} />
+ )}
+ </SafeAreaView>
+ </GlassScene>
+ </Modal>
+
+ {/* Web checkout (physical mural print — IAP-exempt) */}
+ <Modal visible={!!webUrl} animationType="slide" onRequestClose={() => setWebUrl(null)}>
+ <SafeAreaView style={styles.webSafe}>
+ <GlassBar light title="Order a mural" onDone={() => setWebUrl(null)} />
+ {webUrl && (
+ <WebView
+ source={{ uri: webUrl }}
+ startInLoadingState
+ sharedCookiesEnabled
+ injectedJavaScriptBeforeContentLoaded={NO_TRACK}
+ renderLoading={() => (
+ <ActivityIndicator style={styles.webLoading} size="large" color={GLASS.accent} />
+ )}
+ />
+ )}
+ </SafeAreaView>
+ </Modal>
+ </SafeAreaView>
+ </GlassScene>
+ );
+}
+
+const styles = StyleSheet.create({
+ safe: { flex: 1 },
+ body: { flex: 1 },
+ tabbar: {
+ flexDirection: 'row', paddingVertical: 8, paddingHorizontal: 8,
+ borderTopWidth: StyleSheet.hairlineWidth, borderTopColor: GLASS.edgeFaint,
+ },
+ tab: { flex: 1, alignItems: 'center', paddingVertical: 4, gap: 2 },
+ tabGlyph: { fontSize: 18, color: GLASS.textDim },
+ tabLabel: { fontSize: 11, color: GLASS.textDim, fontWeight: '600', letterSpacing: 0.2 },
+ tabActive: { color: GLASS.accent },
+ modalSafe: { flex: 1 },
+ webSafe: { flex: 1, backgroundColor: '#fff' },
+ webLoading: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 },
+});
diff --git a/apps/mobile/api.ts b/apps/mobile/api.ts
new file mode 100644
index 0000000..fe5ca2a
--- /dev/null
+++ b/apps/mobile/api.ts
@@ -0,0 +1,83 @@
+// Thin typed client over the existing celebsignatures.com Express JSON APIs.
+// Native app keeps the backend on Kamatera (no rewrite) — see plan. RN has its
+// own cookie jar, so the cs_sess auth cookie set by /api/auth/* is retained
+// across fetches automatically (no CORS constraints apply to a native client).
+import Constants from 'expo-constants';
+
+export const WEB_BASE: string =
+ (Constants.expoConfig?.extra as any)?.webBase ?? 'https://celebsignatures.com';
+
+export type Signature = {
+ category: string;
+ rank?: number;
+ full_name: string;
+ wikidata?: string;
+ reason_for_ranking?: string;
+ signature_image_url?: string;
+ image_license?: string;
+ image_author?: string;
+ deceased?: string;
+ death_date?: string;
+ museums?: string[];
+};
+
+export type EvolutionEntry = { file: string; year: number | null; source: string; url: string; license: string };
+export type Evolution = Record<string, { name: string; sigs: EvolutionEntry[] }>;
+export type Portraits = Record<string, string>;
+
+export type Mural = {
+ code: string; slug: string; title: string; blurb?: string; sigs?: number;
+ roster?: string[]; met_accent?: string;
+};
+export type MuralsCatalog = {
+ pricePerSqFt: number;
+ size: { widthFt: number; heightFt: number; dpi: number; pxW: number; pxH: number; sqft: number };
+ murals: Mural[];
+};
+
+export type User = { email: string; name?: string } | null;
+export type LeaderRow = { id: string; name: string; score: number; at: string };
+
+/** Wikidata QID from a `.../Q12345` url — the key portraits + evolution use. */
+export function qidOf(sig: Signature): string | null {
+ const m = (sig.wikidata || '').match(/Q\d+/);
+ return m ? m[0] : null;
+}
+
+async function getJSON<T>(path: string): Promise<T> {
+ const r = await fetch(`${WEB_BASE}${path}`);
+ if (!r.ok) throw new Error(`${path} → ${r.status}`);
+ return r.json() as Promise<T>;
+}
+async function postJSON<T>(path: string, body: unknown): Promise<T> {
+ const r = await fetch(`${WEB_BASE}${path}`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(body),
+ });
+ return r.json() as Promise<T>;
+}
+
+export const api = {
+ signatures: () => getJSON<Signature[]>('/api/signatures'),
+ portraits: () => getJSON<Portraits>('/api/portraits'),
+ evolution: () => getJSON<Evolution>('/api/signature-evolution'),
+ murals: () => getJSON<MuralsCatalog>('/api/murals-catalog'),
+
+ leaderboardTop: (game: string, diff: string) =>
+ getJSON<{ ok: boolean; top: LeaderRow[] }>(`/api/leaderboard?game=${game}&diff=${diff}`),
+ leaderboardSubmit: (game: string, diff: string, score: number, name: string) =>
+ postJSON<{ ok: boolean; rank?: number; top?: LeaderRow[] }>('/api/leaderboard', { game, diff, score, name }),
+
+ me: () => getJSON<{ ok: boolean; user: User }>('/api/auth/me'),
+ login: (email: string, password: string) =>
+ postJSON<{ ok: boolean; user?: User; error?: string }>('/api/auth/login', { email, password }),
+ signup: (email: string, password: string, name?: string) =>
+ postJSON<{ ok: boolean; user?: User; error?: string }>('/api/auth/signup', { email, password, name }),
+ logout: () => postJSON<{ ok: boolean }>('/api/auth/logout', {}),
+ // account deletion — Apple 5.1.1(v). Backend endpoint added in the same effort.
+ deleteAccount: () => postJSON<{ ok: boolean; error?: string }>('/api/auth/delete', {}),
+
+ muralOrder: (body: { name: string; email: string; mural?: string; note?: string }) =>
+ postJSON<{ ok: boolean; id?: string }>('/api/mural-order', body),
+};
diff --git a/apps/mobile/app.json b/apps/mobile/app.json
new file mode 100644
index 0000000..659a246
--- /dev/null
+++ b/apps/mobile/app.json
@@ -0,0 +1,28 @@
+{
+ "expo": {
+ "name": "Celebrity Signatures",
+ "slug": "celebrity-signatures",
+ "version": "1.0.0",
+ "orientation": "portrait",
+ "scheme": "celebsignatures",
+ "userInterfaceStyle": "dark",
+ "backgroundColor": "#141210",
+ "ios": {
+ "supportsTablet": true,
+ "bundleIdentifier": "com.abrams.celebsignatures",
+ "infoPlist": {
+ "ITSAppUsesNonExemptEncryption": false
+ }
+ },
+ "android": {
+ "package": "com.abrams.celebsignatures"
+ },
+ "plugins": [
+ "expo-asset"
+ ],
+ "extra": {
+ "webBase": "https://celebsignatures.com"
+ },
+ "owner": "agentabrams"
+ }
+}
diff --git a/apps/mobile/eas.json b/apps/mobile/eas.json
new file mode 100644
index 0000000..5c21b73
--- /dev/null
+++ b/apps/mobile/eas.json
@@ -0,0 +1,42 @@
+{
+ "cli": {
+ "version": ">= 5.0.0",
+ "appVersionSource": "remote"
+ },
+ "build": {
+ "development": {
+ "developmentClient": true,
+ "distribution": "internal",
+ "ios": {
+ "simulator": true
+ }
+ },
+ "preview": {
+ "distribution": "internal",
+ "ios": {
+ "simulator": false
+ }
+ },
+ "production": {
+ "autoIncrement": true,
+ "ios": {
+ "image": "latest"
+ },
+ "android": {
+ "buildType": "app-bundle"
+ }
+ }
+ },
+ "submit": {
+ "production": {
+ "ios": {
+ "appleId": "steveabramsdesigns@gmail.com",
+ "appleTeamId": "3VAV3KMNZK",
+ "ascAppId": "TODO_CREATE_ASC_APP_RECORD",
+ "ascApiKeyPath": "./credentials/AuthKey_TODO.p8",
+ "ascApiKeyId": "TODO_ASC_KEY_ID",
+ "ascApiKeyIssuerId": "TODO_ASC_ISSUER_ID"
+ }
+ }
+ }
+}
diff --git a/apps/mobile/index.ts b/apps/mobile/index.ts
new file mode 100644
index 0000000..5fd059f
--- /dev/null
+++ b/apps/mobile/index.ts
@@ -0,0 +1,4 @@
+import { registerRootComponent } from 'expo';
+import App from './App';
+
+registerRootComponent(App);
diff --git a/apps/mobile/package-lock.json b/apps/mobile/package-lock.json
new file mode 100644
index 0000000..3fc4015
--- /dev/null
+++ b/apps/mobile/package-lock.json
@@ -0,0 +1,6103 @@
+{
+ "name": "celebrity-signatures-mobile",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "celebrity-signatures-mobile",
+ "version": "1.0.0",
+ "dependencies": {
+ "expo": "^56.0.18",
+ "expo-asset": "~56.0.21",
+ "expo-blur": "~56.0.4",
+ "expo-constants": "~56.0.22",
+ "expo-haptics": "~56.0.3",
+ "expo-linear-gradient": "~56.0.4",
+ "expo-splash-screen": "~56.0.14",
+ "expo-status-bar": "~56.0.4",
+ "react": "19.2.3",
+ "react-native": "0.85.3",
+ "react-native-webview": "13.16.1"
+ },
+ "devDependencies": {
+ "@types/react": "~19.2.0",
+ "typescript": "~6.0.3"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
+ "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
+ "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
+ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz",
+ "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz",
+ "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
+ "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz",
+ "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-create-regexp-features-plugin": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz",
+ "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.29.7",
+ "regexpu-core": "^6.3.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-define-polyfill-provider": {
+ "version": "0.6.8",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz",
+ "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==",
+ "license": "MIT",
+ "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"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
+ "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-member-expression-to-functions": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz",
+ "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
+ "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
+ "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-optimise-call-expression": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz",
+ "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz",
+ "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-remap-async-to-generator": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz",
+ "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.29.7",
+ "@babel/helper-wrap-function": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-replace-supers": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz",
+ "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-member-expression-to-functions": "^7.29.7",
+ "@babel/helper-optimise-call-expression": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz",
+ "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+ "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
+ "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-wrap-function": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz",
+ "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.29.7",
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz",
+ "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz",
+ "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.8"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-decorators": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.29.7.tgz",
+ "integrity": "sha512-EtU0Hi3GvrTqD56xKmZvV/uCXK2ZbwVNPNLAquVItcAZpUhkXwWlo3Fmj0c2LxgSf2I8IDULeAepwNP1OefLXg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.29.7",
+ "@babel/helper-plugin-utils": "^7.29.7",
+ "@babel/plugin-syntax-decorators": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-export-default-from": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.29.7.tgz",
+ "integrity": "sha512-p+G5BNXDcy3bOXplhY4HybQ1GxH3i2Tppmdm/3epyRu2VgJJZuUlZ61MqRTg582Q7ZLBdP7fePYvsumSEkMxcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-decorators": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.29.7.tgz",
+ "integrity": "sha512-9MTTLbF39X6sqM92JPEsoI7++26hjZvzkxKZy64aMhWLH2mPkJ/Q3AV4QLmls3R14FpSpkOwQQfUh962JGQxxg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-dynamic-import": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
+ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-export-default-from": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.29.7.tgz",
+ "integrity": "sha512-foag0BB37ROhdeIX9O8G0jX7hw0UekJc04cHMrYLOnrErsnBKqJGHJ8eDRpoCFZBvEPPygmmtw4qyU97qa4oOw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-flow": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.29.7.tgz",
+ "integrity": "sha512-ajMX6QPcyomotqwpzhkYGxcK2i/us0rs1Qo9QvUpa+Fca0FTmqrzKrctoIYLMxcOhGZldGT/BAVkRGTWBiR8gQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz",
+ "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz",
+ "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-async-generator-functions": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz",
+ "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7",
+ "@babel/helper-remap-async-to-generator": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-async-to-generator": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz",
+ "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.29.7",
+ "@babel/helper-plugin-utils": "^7.29.7",
+ "@babel/helper-remap-async-to-generator": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoping": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz",
+ "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-class-properties": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz",
+ "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.29.7",
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-class-static-block": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz",
+ "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.29.7",
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.12.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-classes": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz",
+ "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-destructuring": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz",
+ "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-export-namespace-from": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz",
+ "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-flow-strip-types": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.29.7.tgz",
+ "integrity": "sha512-wRHeUjUjCZnMHmiO5bRgjFLcoEh7JyTdByOW11ahhwNa4V0bmeGEaIvt51yq0zQp2yWIpqfxXXPyUP6GFJZHOQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7",
+ "@babel/plugin-syntax-flow": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-for-of": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz",
+ "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-logical-assignment-operators": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz",
+ "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz",
+ "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.29.7",
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz",
+ "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.29.7",
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz",
+ "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-object-rest-spread": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz",
+ "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-optional-catch-binding": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz",
+ "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-optional-chaining": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz",
+ "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-parameters": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz",
+ "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-private-methods": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz",
+ "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.29.7",
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-private-property-in-object": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz",
+ "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-display-name": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.29.7.tgz",
+ "integrity": "sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.29.7.tgz",
+ "integrity": "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-development": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.29.7.tgz",
+ "integrity": "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-transform-react-jsx": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-pure-annotations": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.29.7.tgz",
+ "integrity": "sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.29.7",
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-runtime": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.29.7.tgz",
+ "integrity": "sha512-xmAscdE/AsqRW7vutbPNoUmu/nF5SrLKPs7aoJgEjo35lLKA/Bc0i2rMv/hr1+Y0o1bQCiVtith3u2vdgRL39Q==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-runtime/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typescript": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.29.7.tgz",
+ "integrity": "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-regex": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz",
+ "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.29.7",
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-typescript": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.29.7.tgz",
+ "integrity": "sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz",
+ "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
+ "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz",
+ "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
+ "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@expo/code-signing-certificates": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@expo/code-signing-certificates/-/code-signing-certificates-0.0.6.tgz",
+ "integrity": "sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w==",
+ "license": "MIT",
+ "dependencies": {
+ "node-forge": "^1.3.3"
+ }
+ },
+ "node_modules/@expo/config": {
+ "version": "56.0.13",
+ "resolved": "https://registry.npmjs.org/@expo/config/-/config-56.0.13.tgz",
+ "integrity": "sha512-Fi1J1mjD3O2qDQsUPTHhsFXoHduZ5gSkWvCeyKxyp3R9fXgXrmhbpo6T+lZJG8x2t6xL1P/SIc6bLdsTJkKaOg==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config-plugins": "~56.0.14",
+ "@expo/config-types": "^56.0.7",
+ "@expo/json-file": "^10.2.0",
+ "@expo/require-utils": "^56.1.6",
+ "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"
+ }
+ },
+ "node_modules/@expo/config-plugins": {
+ "version": "56.0.14",
+ "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-56.0.14.tgz",
+ "integrity": "sha512-pdjBwH67BF1dnim4N/OxgBshhil27eu3C9uuhwzzK2Bnzl6bIcdt9WjEVuMXluFnEpWe0ws5sxE8NvBR5Ms7bQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config-types": "^56.0.7",
+ "@expo/json-file": "~10.2.0",
+ "@expo/plist": "^0.7.0",
+ "@expo/require-utils": "^56.1.6",
+ "@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"
+ }
+ },
+ "node_modules/@expo/config-types": {
+ "version": "56.0.7",
+ "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-56.0.7.tgz",
+ "integrity": "sha512-V7bxawNsNned/yMppAHdisIOxniZXgPKRWpIUiQOQBs45/A5MBd2gfDM4Ecq5gnbilnQUTaI6Zxn6JcW7L3TAA==",
+ "license": "MIT"
+ },
+ "node_modules/@expo/devcert": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@expo/devcert/-/devcert-1.2.1.tgz",
+ "integrity": "sha512-qC4eaxmKMTmJC2ahwyui6ud8f3W60Ss7pMkpBq40Hu3zyiAaugPXnZ24145U7K36qO9UHdZUVxsCvIpz2RYYCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/sudo-prompt": "^9.3.1",
+ "debug": "^3.1.0"
+ }
+ },
+ "node_modules/@expo/devcert/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/@expo/devtools": {
+ "version": "56.0.2",
+ "resolved": "https://registry.npmjs.org/@expo/devtools/-/devtools-56.0.2.tgz",
+ "integrity": "sha512-ANl4kPdbe0/HQYWkDEN79S6bQhI+i/ZCnPxuC853pPsB4svhINC7Ku9lmGOKPsUUWWnrHg1spkDGQBZ4sD6JxQ==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.2"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@expo/env": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.4.2.tgz",
+ "integrity": "sha512-28pqaEqwnmLduZ00Pq9HkSzE5wbj1MTwp5/n8nm8rD8MCjR9eUnVOwmNksPI3Be2ReAPO/DbPn1puy0mvoocsQ==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "debug": "^4.3.4",
+ "getenv": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=20.12.0"
+ }
+ },
+ "node_modules/@expo/expo-modules-macros-plugin": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@expo/expo-modules-macros-plugin/-/expo-modules-macros-plugin-0.2.2.tgz",
+ "integrity": "sha512-4IMzPDIo/VOXREQjsJtliSfqYVZvfzU2SLFS/9sKMWF848S8CHx+e/E+Vf0TcMvpWCCKX5umyqxb13KJJ+YUzg==",
+ "license": "MIT"
+ },
+ "node_modules/@expo/fingerprint": {
+ "version": "0.19.9",
+ "resolved": "https://registry.npmjs.org/@expo/fingerprint/-/fingerprint-0.19.9.tgz",
+ "integrity": "sha512-gphqoJt5dXPfq6iWFwSLKFcUi6gDnBy9GM4XuKkKbjQEqGyBH6v2iS16Oht6xfCBWkRSy28CNFsm8lKmoJVP2g==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/env": "^2.3.1",
+ "@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"
+ }
+ },
+ "node_modules/@expo/image-utils": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.10.4.tgz",
+ "integrity": "sha512-QGdC9eeNyF7vozMV77wQQwX4z3ZJK8D707WSTcBTE/XI19T41g5NtGVM/BMqb1oBV+zSZlNwpOA6bXbbvtC2UA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/require-utils": "^56.1.6",
+ "@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"
+ }
+ },
+ "node_modules/@expo/inline-modules": {
+ "version": "0.0.15",
+ "resolved": "https://registry.npmjs.org/@expo/inline-modules/-/inline-modules-0.0.15.tgz",
+ "integrity": "sha512-EtGaKjzsNF0Jp3Alcn6aKX/QOPEdf1P6i5qTm91mJBmJ4lcWbQkyPrCVNEZHjp989w7c4exd8myA6c0whHcghg==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config-plugins": "~56.0.14"
+ }
+ },
+ "node_modules/@expo/json-file": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-10.2.0.tgz",
+ "integrity": "sha512-S6XzKe3R9GQeHiUPXc3xJjOv2VJhOEwFYf7xdC2z2cUqt3kZJ9mSO877sNQloVdnW/SUCtPY3bexlM7nwq+CAQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.20.0",
+ "json5": "^2.2.3"
+ }
+ },
+ "node_modules/@expo/local-build-cache-provider": {
+ "version": "56.0.11",
+ "resolved": "https://registry.npmjs.org/@expo/local-build-cache-provider/-/local-build-cache-provider-56.0.11.tgz",
+ "integrity": "sha512-2SfYrb5vBs0Ra3bZfpvtJXJbS1oTSwo9DmG4bpZUW/sKUT0+kXHkPI9uGiUa687SIOEQuFBinylD3C9Z2lma3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config": "~56.0.13",
+ "chalk": "^4.1.2"
+ }
+ },
+ "node_modules/@expo/metro": {
+ "version": "56.0.0",
+ "resolved": "https://registry.npmjs.org/@expo/metro/-/metro-56.0.0.tgz",
+ "integrity": "sha512-5gIgQHtEpjjvsjKfVtIv23a98LLRV0/y07PDShEwYSytAMlE3FSF8RHXqtHc1sUJL6dn7hnuIBpIbrLXXuVi0A==",
+ "license": "MIT",
+ "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"
+ }
+ },
+ "node_modules/@expo/metro-file-map": {
+ "version": "56.0.3",
+ "resolved": "https://registry.npmjs.org/@expo/metro-file-map/-/metro-file-map-56.0.3.tgz",
+ "integrity": "sha512-5OGW3z8LgEYgMJOR7F3pC8llFLkb1fVqwAewbCl6S4Vkha8AFQMwOjT+9Wbka+V4rmpljpGqOnMhF4xZbD961w==",
+ "license": "MIT",
+ "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"
+ }
+ },
+ "node_modules/@expo/osascript": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.7.1.tgz",
+ "integrity": "sha512-Zn03EX6In7ts2lPUW2ESUSkEhEWQN1qqsiXjadtZMJOuZRkMiAg1ZQHuvz9DjByDWNJ2pBwAGyrts9lj9k389g==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/spawn-async": "^1.8.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@expo/package-manager": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-1.13.1.tgz",
+ "integrity": "sha512-y/K+CaYYpZpNGZhSX4HyLT/vyIunFjNfyoxNysPBCefeLKI/VCx6f9LNPzrxayr3rCYO5bl9O8H+HRQK265Nkg==",
+ "license": "MIT",
+ "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"
+ }
+ },
+ "node_modules/@expo/package-manager/node_modules/@expo/json-file": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-11.0.1.tgz",
+ "integrity": "sha512-zxHWj4MKKMAL29ZQSY/Fssx4Thluk40JmuGNaeS078wy/NhlFhnVi+rHHunulE3xJAJ0CM73m8VK2+GkF9eRwQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.20.0",
+ "json5": "^2.2.3"
+ }
+ },
+ "node_modules/@expo/plist": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.7.0.tgz",
+ "integrity": "sha512-vrpryU1GoqSIRNqRB2D3IjXDmzNYfiQpEF6AH/xknlD7eiYmEDt3mb26V7cLcedcPG8PY/1xWHdBXVQJfEAh6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@xmldom/xmldom": "^0.8.8",
+ "base64-js": "^1.5.1",
+ "xmlbuilder": "^15.1.1"
+ }
+ },
+ "node_modules/@expo/prebuild-config": {
+ "version": "56.0.21",
+ "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-56.0.21.tgz",
+ "integrity": "sha512-HjhcxGsi6OoDSQxxw06tRq27gRXfXLYlsiXj3cH0R4GKiNK4yQAINKUFup4R3DtYxYNde87eHaNX28IMBCm9qA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config": "~56.0.13",
+ "@expo/config-plugins": "~56.0.14",
+ "@expo/config-types": "^56.0.7",
+ "@expo/image-utils": "^0.10.4",
+ "@expo/json-file": "^10.2.0",
+ "@react-native/normalize-colors": "0.85.3",
+ "debug": "^4.3.1",
+ "expo-modules-autolinking": "~56.0.21",
+ "resolve-from": "^5.0.0",
+ "semver": "^7.6.0"
+ }
+ },
+ "node_modules/@expo/require-utils": {
+ "version": "56.1.6",
+ "resolved": "https://registry.npmjs.org/@expo/require-utils/-/require-utils-56.1.6.tgz",
+ "integrity": "sha512-e68r6X+c7yPxJP0gac/CaJc/RCHeLB2Bf4MyCuqfNM4YXfl1ONmQbQlRL0RbwBfEHn6A6UZKj+5UX9j0Im646g==",
+ "license": "MIT",
+ "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"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@expo/schema-utils": {
+ "version": "56.0.2",
+ "resolved": "https://registry.npmjs.org/@expo/schema-utils/-/schema-utils-56.0.2.tgz",
+ "integrity": "sha512-WcOH1E6rwxRqNwBzPOVhd5GBbMlS04+5n+ZMdhdwKOg/Kt3suV+F8F6An+z8mUJ8eSuMM3HD9Sj09t7vc/Xjkw==",
+ "license": "MIT"
+ },
+ "node_modules/@expo/sdk-runtime-versions": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@expo/sdk-runtime-versions/-/sdk-runtime-versions-1.0.0.tgz",
+ "integrity": "sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ==",
+ "license": "MIT"
+ },
+ "node_modules/@expo/spawn-async": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@expo/spawn-async/-/spawn-async-1.8.0.tgz",
+ "integrity": "sha512-eb9xxd/LbuEGSdua4NumCu/McVB9EM+F/JxB9pWgnERw4HQ9XyTNH1KapG6oqLWR8TuRK2LQfzJlmNi94CVobw==",
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.6"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@expo/sudo-prompt": {
+ "version": "9.3.2",
+ "resolved": "https://registry.npmjs.org/@expo/sudo-prompt/-/sudo-prompt-9.3.2.tgz",
+ "integrity": "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==",
+ "license": "MIT"
+ },
+ "node_modules/@expo/xcpretty": {
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/@expo/xcpretty/-/xcpretty-4.4.4.tgz",
+ "integrity": "sha512-4aQzz9vgxcNXFfo/iyNgDDYfsU5XGKKxWxZopw0cVotHiW+U8IJbIxMaxsINs6bHhtkG3StKNPcOrn3eBuxKPw==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/code-frame": "^7.20.0",
+ "chalk": "^4.1.0",
+ "js-yaml": "^4.1.0"
+ },
+ "bin": {
+ "excpretty": "build/cli.js"
+ }
+ },
+ "node_modules/@isaacs/ttlcache": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz",
+ "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.11",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz",
+ "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@react-native/assets-registry": {
+ "version": "0.85.3",
+ "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.85.3.tgz",
+ "integrity": "sha512-u9ZiYP23vA2IFtdFQFmetzSmk6SM0xgKIoiOsr1hXNHjHaLhOm+/Ph1ud57wX6+Dbwdzx8coJgnzSKL3W21PCg==",
+ "license": "MIT",
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/@react-native/babel-plugin-codegen": {
+ "version": "0.85.3",
+ "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.85.3.tgz",
+ "integrity": "sha512-Wc94zGfeFG8Njf9SHMPfYZP04kjigkOps6F1TYTvd7ZVXuGxqseCDgxc50LWcOhOCLypI9n3oVVqz81C3p44ZA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.29.0",
+ "@react-native/codegen": "0.85.3"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/@react-native/codegen": {
+ "version": "0.85.3",
+ "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.85.3.tgz",
+ "integrity": "sha512-/JkS1lGLyzBWP1FbgDwaqEf7qShIC6pUC1M0a/YMAd/v4iqR24MRkQWe7jkYvcBQ2LpEhs5NGE9InhxSv21zCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/parser": "^7.29.0",
+ "hermes-parser": "0.33.3",
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1",
+ "tinyglobby": "^0.2.15",
+ "yargs": "^17.6.2"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "*"
+ }
+ },
+ "node_modules/@react-native/codegen/node_modules/hermes-estree": {
+ "version": "0.33.3",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.33.3.tgz",
+ "integrity": "sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg==",
+ "license": "MIT"
+ },
+ "node_modules/@react-native/codegen/node_modules/hermes-parser": {
+ "version": "0.33.3",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.33.3.tgz",
+ "integrity": "sha512-Yg3HgaG4CqgyowtYjX/FsnPAuZdHOqSMtnbpylbptsQ9nwwSKsy6uRWcGO5RK0EqiX12q8HvDWKgeAVajRO5DA==",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.33.3"
+ }
+ },
+ "node_modules/@react-native/community-cli-plugin": {
+ "version": "0.85.3",
+ "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.85.3.tgz",
+ "integrity": "sha512-fs85dmbIqNmtzEixDb0g+q6R3Vt4H9eAt8/inIZdDKfjN76+sUJA2r1nxODQ76bU23MrIbz8sI7KFBPaWk/zQw==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-native/dev-middleware": "0.85.3",
+ "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"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ },
+ "peerDependencies": {
+ "@react-native-community/cli": "*",
+ "@react-native/metro-config": "0.85.3"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-community/cli": {
+ "optional": true
+ },
+ "@react-native/metro-config": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@react-native/debugger-frontend": {
+ "version": "0.85.3",
+ "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.85.3.tgz",
+ "integrity": "sha512-uAu7rM5o/Np1zgp6fi5zM1sP1aB8DcS7DdOLcj/TkSutOAjkMqqd2lWt1/+3S7qXexRHVK5XcP+o3VXo4L/V0A==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/@react-native/debugger-shell": {
+ "version": "0.85.3",
+ "resolved": "https://registry.npmjs.org/@react-native/debugger-shell/-/debugger-shell-0.85.3.tgz",
+ "integrity": "sha512-/jRAaT9boiCttIcEwS02WPwYkUihqsjSaK/TMtHz05vT6uMgac9PaQt5kzBQLIABv5aEIa5gtrMmKVz49MjkjQ==",
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.4.0",
+ "fb-dotslash": "0.5.8"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/@react-native/dev-middleware": {
+ "version": "0.85.3",
+ "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.85.3.tgz",
+ "integrity": "sha512-JYzBiT4A8w+KQt+dOD5v+ti+tDrGoPnsSTuApq3Ls4RB5sfWbDlYMyz3dbc8qBIHz9tv0sQ5+eOu6Xwqzr5AQA==",
+ "license": "MIT",
+ "dependencies": {
+ "@isaacs/ttlcache": "^1.4.1",
+ "@react-native/debugger-frontend": "0.85.3",
+ "@react-native/debugger-shell": "0.85.3",
+ "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"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/@react-native/gradle-plugin": {
+ "version": "0.85.3",
+ "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.85.3.tgz",
+ "integrity": "sha512-39dY2j50Q1pntejzwt3XL7vwXtrj8jcIfHq6E+gyu3jzYxZJVvMkMutQ39vSg6zinIQOX36oQDhidXUbCXzgoA==",
+ "license": "MIT",
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/@react-native/js-polyfills": {
+ "version": "0.85.3",
+ "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.85.3.tgz",
+ "integrity": "sha512-U2+aMshIXf1uFn77tpBb/xhHWB9vkVrMpt7kkucAugF8hJKYTDGB587X7WwelHduK2KBfhl4giSv0rzZGoef9A==",
+ "license": "MIT",
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/@react-native/normalize-colors": {
+ "version": "0.85.3",
+ "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.85.3.tgz",
+ "integrity": "sha512-hj0PScZEhIbcOvQV5yMKX3ha4XEIOy/SVE1Rrpp0beW0dpNLOgSC7KDxGewmDnIHK9YdQUXGY9eMEfShUMIaZw==",
+ "license": "MIT"
+ },
+ "node_modules/@react-native/virtualized-lists": {
+ "version": "0.85.3",
+ "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.85.3.tgz",
+ "integrity": "sha512-dsCjI//OIPEUJMyNHp4l7zNLVjCx7bcaRUceOCkU+IB17hkbtbGWvi7HjGFSzy7FJGmS/MOlcfpb72xXiy1Oig==",
+ "license": "MIT",
+ "dependencies": {
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ },
+ "peerDependencies": {
+ "@types/react": "^19.2.0",
+ "react": "*",
+ "react-native": "0.85.3"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.12",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.12.tgz",
+ "integrity": "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==",
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "26.1.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.2.tgz",
+ "integrity": "sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~8.3.0"
+ }
+ },
+ "node_modules/@types/react": {
+ "version": "19.2.18",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz",
+ "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.35",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz",
+ "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "license": "MIT"
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz",
+ "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==",
+ "license": "ISC"
+ },
+ "node_modules/@xmldom/xmldom": {
+ "version": "0.8.13",
+ "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.13.tgz",
+ "integrity": "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "license": "MIT",
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
+ "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "^3.0.0",
+ "negotiator": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
+ "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==",
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/agent-cli-detector": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/agent-cli-detector/-/agent-cli-detector-0.1.5.tgz",
+ "integrity": "sha512-6xvLw0EGPuxoYGZeqyMV4AK+WoZ31jsqb7a5pln1BTf6oDFsrgvfCJT7E7y9oAqifJZhJ3fZ0J36H7o6JzrB0Q==",
+ "license": "MIT",
+ "bin": {
+ "agent-cli-detector": "dist/cli.js"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/anser": {
+ "version": "1.4.10",
+ "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz",
+ "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==",
+ "license": "MIT"
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-escapes/node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/arg": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
+ "license": "MIT"
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "license": "Python-2.0"
+ },
+ "node_modules/asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+ "license": "MIT"
+ },
+ "node_modules/babel-plugin-polyfill-corejs2": {
+ "version": "0.4.17",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz",
+ "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==",
+ "license": "MIT",
+ "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"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs3": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz",
+ "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==",
+ "license": "MIT",
+ "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"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-regenerator": {
+ "version": "0.6.8",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz",
+ "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.6.8"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-plugin-react-compiler": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-1.0.0.tgz",
+ "integrity": "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.26.0"
+ }
+ },
+ "node_modules/babel-plugin-react-native-web": {
+ "version": "0.21.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.21.2.tgz",
+ "integrity": "sha512-SPD0J6qjJn8231i0HZhlAGH6NORe+QvRSQM2mwQEzJ2Fb3E4ruWTiiicPlHjmeWShDXLcvoorOCXjeR7k/lyWA==",
+ "license": "MIT"
+ },
+ "node_modules/babel-plugin-syntax-hermes-parser": {
+ "version": "0.33.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.33.3.tgz",
+ "integrity": "sha512-/Z9xYdaJ1lC0pT9do6TqCqhOSLfZ5Ot8D5za1p+feEfWYupCOfGbhhEXN9r2ZgJtDNUNRw/Z+T2CvAGKBqtqWA==",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-parser": "0.33.3"
+ }
+ },
+ "node_modules/babel-plugin-syntax-hermes-parser/node_modules/hermes-estree": {
+ "version": "0.33.3",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.33.3.tgz",
+ "integrity": "sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg==",
+ "license": "MIT"
+ },
+ "node_modules/babel-plugin-syntax-hermes-parser/node_modules/hermes-parser": {
+ "version": "0.33.3",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.33.3.tgz",
+ "integrity": "sha512-Yg3HgaG4CqgyowtYjX/FsnPAuZdHOqSMtnbpylbptsQ9nwwSKsy6uRWcGO5RK0EqiX12q8HvDWKgeAVajRO5DA==",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.33.3"
+ }
+ },
+ "node_modules/babel-plugin-transform-flow-enums": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz",
+ "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-syntax-flow": "^7.12.1"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.11.12",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.12.tgz",
+ "integrity": "sha512-r7WnVImvVCeFpf2DOXfy41aPWzeNg3H/A2X4dKmy1QL0MSyyk/e7z8ihJ3N6Nn2PsdhkVlqnEfnUE4a05P2aTA==",
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/big-integer": {
+ "version": "1.6.52",
+ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz",
+ "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==",
+ "license": "Unlicense",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/bplist-creator": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz",
+ "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==",
+ "license": "MIT",
+ "dependencies": {
+ "stream-buffers": "2.2.x"
+ }
+ },
+ "node_modules/bplist-parser": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz",
+ "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==",
+ "license": "MIT",
+ "dependencies": {
+ "big-integer": "1.6.x"
+ },
+ "engines": {
+ "node": ">= 5.10.0"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
+ "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.7",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.7.tgz",
+ "integrity": "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.10.44",
+ "caniuse-lite": "^1.0.30001806",
+ "electron-to-chromium": "^1.5.393",
+ "node-releases": "^2.0.51",
+ "update-browserslist-db": "^1.2.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "license": "MIT"
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001806",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz",
+ "integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chrome-launcher": {
+ "version": "0.15.2",
+ "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz",
+ "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==",
+ "license": "Apache-2.0",
+ "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"
+ },
+ "engines": {
+ "node": ">=12.13.0"
+ }
+ },
+ "node_modules/chromium-edge-launcher": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.3.0.tgz",
+ "integrity": "sha512-p03azHlGjtyRvFEee3cyvtsRYdniSkwjkzmM/KmVnqT5d7QkkwpJBhis/zCLMYdQMVJ5tt140TBNqqrZPaWeFA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/node": "*",
+ "escape-string-regexp": "^4.0.0",
+ "is-wsl": "^2.2.0",
+ "lighthouse-logger": "^1.0.0",
+ "mkdirp": "^1.0.4"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+ "license": "MIT"
+ },
+ "node_modules/cli-cursor": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+ "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==",
+ "license": "MIT",
+ "dependencies": {
+ "restore-cursor": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
+ "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/compressible": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
+ "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": ">= 1.43.0 < 2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/compression": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz",
+ "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/compression/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/compression/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/compression/node_modules/negotiator": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
+ "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/connect": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
+ "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "finalhandler": "1.1.2",
+ "parseurl": "~1.3.3",
+ "utils-merge": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/connect/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/connect/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "license": "MIT"
+ },
+ "node_modules/core-js-compat": {
+ "version": "3.50.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.50.0.tgz",
+ "integrity": "sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.7"
+ },
+ "engines": {
+ "node": ">=6.4.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/defaults": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "clone": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dnssd-advertise": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/dnssd-advertise/-/dnssd-advertise-1.1.6.tgz",
+ "integrity": "sha512-Ndrrf6BMPalkQPd/zubL+4YghH2J9NspapQ09uDXwYbvOPkP0oaqf5CkcwJ0b50kS2O3ul6yVu+jz+RY62Cejg==",
+ "license": "MIT"
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.401",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.401.tgz",
+ "integrity": "sha512-H6ViHN68nGYlChEvlIU67fn8O2/tpbWQPwck98yaJmh+08LSvHiydzDQ6oXNccLU3kNRVIRS9A4mA7CG+i6fLQ==",
+ "license": "ISC"
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/error-stack-parser": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
+ "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
+ "license": "MIT",
+ "dependencies": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT"
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/expo": {
+ "version": "56.0.18",
+ "resolved": "https://registry.npmjs.org/expo/-/expo-56.0.18.tgz",
+ "integrity": "sha512-xEYiFlkeOzEKEEJlE6qFYtSo+HOwcIDcwZodRqLQRlhPOHU8bYzutyednlcKbytrS6NMEFpwsBwt5LiN1ZLEjA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.20.0",
+ "@expo/cli": "^56.1.22",
+ "@expo/config": "~56.0.13",
+ "@expo/config-plugins": "~56.0.14",
+ "@expo/devtools": "~56.0.2",
+ "@expo/dom-webview": "~56.0.6",
+ "@expo/fingerprint": "^0.19.9",
+ "@expo/local-build-cache-provider": "^56.0.11",
+ "@expo/log-box": "^56.0.14",
+ "@expo/metro": "~56.0.0",
+ "@expo/metro-config": "~56.0.18",
+ "@ungap/structured-clone": "^1.3.0",
+ "babel-preset-expo": "~56.0.18",
+ "expo-asset": "~56.0.21",
+ "expo-constants": "~56.0.22",
+ "expo-file-system": "~56.0.8",
+ "expo-font": "~56.0.7",
+ "expo-keep-awake": "~56.0.3",
+ "expo-modules-autolinking": "~56.0.21",
+ "expo-modules-core": "~56.0.22",
+ "pretty-format": "^29.7.0",
+ "react-refresh": "^0.14.2",
+ "whatwg-url-minimum": "^0.1.2"
+ },
+ "bin": {
+ "expo": "bin/cli",
+ "expo-modules-autolinking": "bin/autolinking",
+ "fingerprint": "bin/fingerprint"
+ },
+ "peerDependencies": {
+ "@expo/dom-webview": "*",
+ "@expo/metro-runtime": "*",
+ "react": "*",
+ "react-dom": "*",
+ "react-native": "*",
+ "react-native-web": "*",
+ "react-native-webview": "*"
+ },
+ "peerDependenciesMeta": {
+ "@expo/dom-webview": {
+ "optional": true
+ },
+ "@expo/metro-runtime": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ },
+ "react-native-web": {
+ "optional": true
+ },
+ "react-native-webview": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/expo-asset": {
+ "version": "56.0.21",
+ "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-56.0.21.tgz",
+ "integrity": "sha512-0p5JByDPy6MxB1S2TBoz38r6I8IYx6z5uD/e00nc0sc9f8xRpcZPCJALbOsGW8PjOwXNfTyEE9KsC6xTLjC2ZA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/image-utils": "^0.10.4",
+ "expo-constants": "~56.0.22"
+ },
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo-blur": {
+ "version": "56.0.4",
+ "resolved": "https://registry.npmjs.org/expo-blur/-/expo-blur-56.0.4.tgz",
+ "integrity": "sha512-/rNpe2NDTmMbSktVJb5z7HoX6apYtq8KVKJNjWOQV7NG01+LvctWzFeMNxWSZVWfIKTndqdqABwqcpYmiCRxxg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo-constants": {
+ "version": "56.0.22",
+ "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-56.0.22.tgz",
+ "integrity": "sha512-XNRssTBSGDR3gsaYhhp513WdpPsLi89wgfYT0wLsCtMY8vXAgXR4jNlaYGXFCnvNVbx9gEDSBHOSntqRK1i8Lw==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/env": "~2.3.1"
+ },
+ "peerDependencies": {
+ "expo": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo-constants/node_modules/@expo/env": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.3.1.tgz",
+ "integrity": "sha512-JvBdZa5OkTd+dGEtt3fLW9OF6RlIp9SNu9VyMSiWPV5szMDTSAYbX8Uj3cRvZcU1zzaRbqnTSsHk2AE8WXHfxQ==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "debug": "^4.3.4",
+ "getenv": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=20.12.0"
+ }
+ },
+ "node_modules/expo-haptics": {
+ "version": "56.0.3",
+ "resolved": "https://registry.npmjs.org/expo-haptics/-/expo-haptics-56.0.3.tgz",
+ "integrity": "sha512-ycoahZJnR9tWAVh/0mJYxbETtHRYaWjiWS8cHlP6aDGU6Q6Y8rZ5NKsuBwWw6HR2Pe30mfVFgbF2HrBR6gtYmw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-linear-gradient": {
+ "version": "56.0.4",
+ "resolved": "https://registry.npmjs.org/expo-linear-gradient/-/expo-linear-gradient-56.0.4.tgz",
+ "integrity": "sha512-KUp1dNSRtuMyiExhf6FJf5YUtmw2cRaPytl10HQi7isj5Yac38udmD55T2tglNYTZlvgT5+oflpyFoH15hmOcw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo-modules-autolinking": {
+ "version": "56.0.21",
+ "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-56.0.21.tgz",
+ "integrity": "sha512-DG0ykIaC4cTXmEL49x7b8Pet/ZCcoNgQ00ooeroH/p8TKLMRs/KULiv9kiHWZRL3n0E0llsaHSvfKj9fAsaI/A==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/require-utils": "^56.1.6",
+ "@expo/spawn-async": "^1.8.0",
+ "chalk": "^4.1.0",
+ "commander": "^7.2.0"
+ },
+ "bin": {
+ "expo-modules-autolinking": "bin/expo-modules-autolinking.js"
+ }
+ },
+ "node_modules/expo-modules-core": {
+ "version": "56.0.22",
+ "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-56.0.22.tgz",
+ "integrity": "sha512-VmkVNpbjC+gTny1pvxyxu90LafGpMdhUB5TRSpe+So4ICrZCwcWBADjWc0JVBHKdFCMOaWBMskuIHI/RcNhEtQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/expo-modules-macros-plugin": "0.2.2",
+ "expo-modules-jsi": "~56.0.12",
+ "invariant": "^2.2.4"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*",
+ "react-native-worklets": "^0.7.4 || ^0.8.0"
+ },
+ "peerDependenciesMeta": {
+ "react-native-worklets": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/expo-modules-jsi": {
+ "version": "56.0.12",
+ "resolved": "https://registry.npmjs.org/expo-modules-jsi/-/expo-modules-jsi-56.0.12.tgz",
+ "integrity": "sha512-OnXiNbXzYybZPh5QnJyIIwQjQfN7PP4Di/2Hz0xQHKLgQmCfn/zAQziOjbUXVeL3cAyZ8+uDnTDYmDAc3B2qhQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo-server": {
+ "version": "56.0.5",
+ "resolved": "https://registry.npmjs.org/expo-server/-/expo-server-56.0.5.tgz",
+ "integrity": "sha512-SmM2p2g3Jrktpiazcst+OxhjSzOHXKAY4BPURHYHXvApzzoybMmrNF4IEZ8DKZ145BhSe4ydAmlEFCRTsdtgUQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.16.0"
+ }
+ },
+ "node_modules/expo-splash-screen": {
+ "version": "56.0.14",
+ "resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-56.0.14.tgz",
+ "integrity": "sha512-7cc09zKllBrmDGpbkVDiq09JBdpzyZMboOYNOd7Q+h4YbCbvkAW4WmZtxXLpZUEeBrc2uakxWyrz5nwcuHqMoQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config-plugins": "~56.0.14",
+ "@expo/image-utils": "^0.10.4",
+ "xml2js": "0.6.0"
+ },
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-status-bar": {
+ "version": "56.0.4",
+ "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-56.0.4.tgz",
+ "integrity": "sha512-IGs/fDfkHXofy2ZQrGiXayhFK04HB85FZXorhcEhDZEcqASKgSqpak+HwUtAaR0MeTJwWyHNF7I6VmVbbp8EcA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo/node_modules/@expo/cli": {
+ "version": "56.1.22",
+ "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-56.1.22.tgz",
+ "integrity": "sha512-G9IOhKU62TexMJGeZkDmyAYLsvbYT40RvIG7AR4y2ha8OEmhbbHNLNQ0mI0xK4QVf4MXiC0CPHLhMMh/ak8XQA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/code-signing-certificates": "^0.0.6",
+ "@expo/config": "~56.0.13",
+ "@expo/config-plugins": "~56.0.14",
+ "@expo/devcert": "^1.2.1",
+ "@expo/env": "~2.3.1",
+ "@expo/image-utils": "^0.10.4",
+ "@expo/inline-modules": "^0.0.15",
+ "@expo/json-file": "^10.2.0",
+ "@expo/log-box": "^56.0.14",
+ "@expo/metro": "~56.0.0",
+ "@expo/metro-config": "~56.0.18",
+ "@expo/metro-file-map": "^56.0.3",
+ "@expo/osascript": "^2.6.0",
+ "@expo/package-manager": "^1.12.1",
+ "@expo/plist": "^0.7.0",
+ "@expo/prebuild-config": "^56.0.21",
+ "@expo/require-utils": "^56.1.6",
+ "@expo/router-server": "^56.0.17",
+ "@expo/schema-utils": "^56.0.2",
+ "@expo/spawn-async": "^1.8.0",
+ "@expo/ws-tunnel": "^2.0.0",
+ "@expo/xcpretty": "^4.4.4",
+ "@react-native/dev-middleware": "0.85.3",
+ "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.6",
+ "expo-server": "^56.0.5",
+ "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"
+ },
+ "bin": {
+ "expo-internal": "main.js"
+ },
+ "peerDependencies": {
+ "expo": "*",
+ "expo-router": "*",
+ "react-native": "*"
+ },
+ "peerDependenciesMeta": {
+ "expo-router": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/expo/node_modules/@expo/cli/node_modules/@expo/router-server": {
+ "version": "56.0.17",
+ "resolved": "https://registry.npmjs.org/@expo/router-server/-/router-server-56.0.17.tgz",
+ "integrity": "sha512-ogGX5cxqAXIzMmstjwZ03QAjCU8cFOU5yooDSbqPDVxscbnzsxV8oquHSMUsqiEy3vlyZp5S5HVPnCsrjoCDqw==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "peerDependencies": {
+ "@expo/metro-runtime": "^56.0.18",
+ "expo": "*",
+ "expo-constants": "^56.0.22",
+ "expo-font": "^56.0.7",
+ "expo-router": "*",
+ "expo-server": "^56.0.5",
+ "react": "*",
+ "react-dom": "*",
+ "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1"
+ },
+ "peerDependenciesMeta": {
+ "@expo/metro-runtime": {
+ "optional": true
+ },
+ "expo-router": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ },
+ "react-server-dom-webpack": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/expo/node_modules/@expo/dom-webview": {
+ "version": "56.0.6",
+ "resolved": "https://registry.npmjs.org/@expo/dom-webview/-/dom-webview-56.0.6.tgz",
+ "integrity": "sha512-DQY3Tj5nrPbpIfEQiD9xbyEFTu25yEORa02Eyzl5rXszDzxDT4VkZDHkyErNQOyE1qjublJHNFhE5bDm4tRfqA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo/node_modules/@expo/env": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.3.1.tgz",
+ "integrity": "sha512-JvBdZa5OkTd+dGEtt3fLW9OF6RlIp9SNu9VyMSiWPV5szMDTSAYbX8Uj3cRvZcU1zzaRbqnTSsHk2AE8WXHfxQ==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "debug": "^4.3.4",
+ "getenv": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=20.12.0"
+ }
+ },
+ "node_modules/expo/node_modules/@expo/log-box": {
+ "version": "56.0.14",
+ "resolved": "https://registry.npmjs.org/@expo/log-box/-/log-box-56.0.14.tgz",
+ "integrity": "sha512-3Eadcxz0J2NESG2iKe8DnAggsRCWqY0mBLhgQPNzClPVjS6o4NyD0F8kuOvWNngFwpJBC08HhY2o8P1mgSgeJg==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/dom-webview": "^56.0.6",
+ "anser": "^1.4.9",
+ "stacktrace-parser": "^0.1.10"
+ },
+ "peerDependencies": {
+ "@expo/dom-webview": "^56.0.6",
+ "expo": "*",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo/node_modules/@expo/metro-config": {
+ "version": "56.0.18",
+ "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-56.0.18.tgz",
+ "integrity": "sha512-X7ephejQE7YjL4401ObdfpluL0enEmLK4ZjMLJrhtkFh0ksZI7jQMvUHxLXZzCHD0SlMXa/RdB9abnWsOj1E5A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.20.0",
+ "@babel/core": "^7.20.0",
+ "@babel/generator": "^7.20.5",
+ "@expo/config": "~56.0.13",
+ "@expo/env": "~2.3.1",
+ "@expo/json-file": "~10.2.0",
+ "@expo/metro": "~56.0.0",
+ "@expo/require-utils": "^56.1.6",
+ "@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.33.3",
+ "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": "*"
+ },
+ "peerDependenciesMeta": {
+ "expo": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/expo/node_modules/@expo/ws-tunnel": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@expo/ws-tunnel/-/ws-tunnel-2.0.0.tgz",
+ "integrity": "sha512-j+JfTRdCk820J9dU0sA2SqshQIKFOMo7ED84w9MJFcebfbNQgsLztEY/SABDkGnjatrW4xGqnUhVRxSBVyCkXw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "ws": "^8.0.0"
+ }
+ },
+ "node_modules/expo/node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/expo/node_modules/babel-preset-expo": {
+ "version": "56.0.18",
+ "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-56.0.18.tgz",
+ "integrity": "sha512-QHEa3AasSFjnA08ciQkKKdVKWPRc2ye6UvxwCweYr3rKATBwTUVOuA0mzRD2PFVdB16R9yqgHROpiqL+K4A0Ww==",
+ "license": "MIT",
+ "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.85.3",
+ "babel-plugin-react-compiler": "^1.0.0",
+ "babel-plugin-react-native-web": "~0.21.0",
+ "babel-plugin-syntax-hermes-parser": "^0.33.3",
+ "babel-plugin-transform-flow-enums": "^0.0.2",
+ "debug": "^4.3.4"
+ },
+ "peerDependencies": {
+ "@babel/runtime": "^7.20.0",
+ "expo": "*",
+ "expo-widgets": "^56.0.24",
+ "react-refresh": ">=0.14.0 <1.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@babel/runtime": {
+ "optional": true
+ },
+ "expo": {
+ "optional": true
+ },
+ "expo-widgets": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/expo/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/expo/node_modules/expo-file-system": {
+ "version": "56.0.8",
+ "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-56.0.8.tgz",
+ "integrity": "sha512-NrH41/8snGIBSbYicwVLB4txPdgCATd7ZYhMAGS3YJZ9GbnduhlAoV4/YCbGayjrbpE9bJb/6wegPL/zmvRMnQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo/node_modules/expo-font": {
+ "version": "56.0.7",
+ "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-56.0.7.tgz",
+ "integrity": "sha512-hpU/vRwPzsby9lPGkA4blDqLIIXYzoWnCZHr6PxvcWbY/uPObAiyhh6q+e0WYsB65SthK+PLH95jEnVag7fwEg==",
+ "license": "MIT",
+ "dependencies": {
+ "fontfaceobserver": "^2.1.0"
+ },
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo/node_modules/expo-keep-awake": {
+ "version": "56.0.3",
+ "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-56.0.3.tgz",
+ "integrity": "sha512-CLMJXtEiMKknD3Rpm8CRwE6ZJUzu2yCEmRk1sgfHAJ1zIbuEWY3dpPDubtsnuzWm+2k6Sru+yaFbYsvPWmTiBA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*"
+ }
+ },
+ "node_modules/expo/node_modules/hermes-estree": {
+ "version": "0.33.3",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.33.3.tgz",
+ "integrity": "sha512-6kzYZHCk8Fy1Uc+t3HGYyJn3OL4aeqKLTyina4UFtWl8I0kSL7OmKThaiX+Uh2f8nGw3mo4Ifxg0M5Zk3/Oeqg==",
+ "license": "MIT"
+ },
+ "node_modules/expo/node_modules/hermes-parser": {
+ "version": "0.33.3",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.33.3.tgz",
+ "integrity": "sha512-Yg3HgaG4CqgyowtYjX/FsnPAuZdHOqSMtnbpylbptsQ9nwwSKsy6uRWcGO5RK0EqiX12q8HvDWKgeAVajRO5DA==",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.33.3"
+ }
+ },
+ "node_modules/expo/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/expo/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/expo/node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/expo/node_modules/picomatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/expo/node_modules/ws": {
+ "version": "8.21.2",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.2.tgz",
+ "integrity": "sha512-54dMVAo4WIe6SKy3vBgN+9bJZqqQ8IMRevAkOLQALhi49qkkQDQfWdAZ8KQlXiEabw88ARXXdUrlvtbKQX+aKw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/exponential-backoff": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz",
+ "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/fb-dotslash": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/fb-dotslash/-/fb-dotslash-0.5.8.tgz",
+ "integrity": "sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA==",
+ "license": "(MIT OR Apache-2.0)",
+ "bin": {
+ "dotslash": "bin/dotslash"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/fetch-nodeshim": {
+ "version": "0.4.10",
+ "resolved": "https://registry.npmjs.org/fetch-nodeshim/-/fetch-nodeshim-0.4.10.tgz",
+ "integrity": "sha512-m6I8ALe4L4XpdETy7MJZWs6L1IVMbjs99bwbpIKphxX+0CTns4IKDWJY0LWfr4YsFjfg+z1TjzTMU8lKl8rG0w==",
+ "license": "MIT"
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/finalhandler/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/finalhandler/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/flow-enums-runtime": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz",
+ "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==",
+ "license": "MIT"
+ },
+ "node_modules/fontfaceobserver": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz",
+ "integrity": "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/getenv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/getenv/-/getenv-2.0.0.tgz",
+ "integrity": "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/glob": {
+ "version": "13.0.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz",
+ "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "minimatch": "^10.2.2",
+ "minipass": "^7.1.3",
+ "path-scurry": "^2.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "license": "ISC"
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hermes-compiler": {
+ "version": "250829098.0.10",
+ "resolved": "https://registry.npmjs.org/hermes-compiler/-/hermes-compiler-250829098.0.10.tgz",
+ "integrity": "sha512-TcRlZ0/TlyfJqquRFAWoyElVNnkdYRi/sEp4/Qy8/GYxjg8j2cS9D4MjuaQ+qimkmLN7AmO+44IznRf06mAr0w==",
+ "license": "MIT"
+ },
+ "node_modules/hermes-estree": {
+ "version": "0.35.0",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.35.0.tgz",
+ "integrity": "sha512-xVx5Opwy8Oo1I5yGpVRhCvWL/iV3M+ylksSKVNlxxD90cpDpR/AR1jLYqK8HWihm065a6UI3HeyAmYzwS8NOOg==",
+ "license": "MIT"
+ },
+ "node_modules/hermes-parser": {
+ "version": "0.35.0",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.35.0.tgz",
+ "integrity": "sha512-9JLjeHxBx8T4CAsydZR49PNZUaix+WpQJwu9p2010lu+7Kwl6D/7wYFFJxoz+aXkaaClp9Zfg6W6/zVlSJORaA==",
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.35.0"
+ }
+ },
+ "node_modules/hosted-git-info": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz",
+ "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==",
+ "license": "ISC",
+ "dependencies": {
+ "lru-cache": "^10.0.1"
+ },
+ "engines": {
+ "node": "^16.14.0 || >=18.0.0"
+ }
+ },
+ "node_modules/hosted-git-info/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/http-errors/node_modules/statuses": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/image-size": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz",
+ "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==",
+ "license": "MIT",
+ "dependencies": {
+ "queue": "6.0.2"
+ },
+ "bin": {
+ "image-size": "bin/image-size.js"
+ },
+ "engines": {
+ "node": ">=16.x"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
+ "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "license": "ISC"
+ },
+ "node_modules/jest-get-type": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-util/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-validate": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/jimp-compact": {
+ "version": "0.16.1",
+ "resolved": "https://registry.npmjs.org/jimp-compact/-/jimp-compact-0.16.1.tgz",
+ "integrity": "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==",
+ "license": "MIT"
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz",
+ "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/puzrin"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/nodeca"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsc-safe-url": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz",
+ "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==",
+ "license": "0BSD"
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/lan-network": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/lan-network/-/lan-network-0.2.1.tgz",
+ "integrity": "sha512-ONPnazC96VKDntab9j9JKwIWhZ4ZUceB4A9Epu4Ssg0hYFmtHZSeQ+n15nIwTFmcBUKtExOer8WTJ4GF9MO64A==",
+ "license": "MIT",
+ "bin": {
+ "lan-network": "dist/lan-network-cli.js"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/lighthouse-logger": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz",
+ "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "debug": "^2.6.9",
+ "marky": "^1.2.2"
+ }
+ },
+ "node_modules/lighthouse-logger/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/lighthouse-logger/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/lightningcss": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz",
+ "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==",
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "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"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz",
+ "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz",
+ "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz",
+ "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz",
+ "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz",
+ "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz",
+ "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz",
+ "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz",
+ "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz",
+ "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz",
+ "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz",
+ "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.throttle": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
+ "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==",
+ "license": "MIT"
+ },
+ "node_modules/log-symbols": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
+ "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/log-symbols/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/log-symbols/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/log-symbols/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/log-symbols/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "license": "MIT"
+ },
+ "node_modules/log-symbols/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/log-symbols/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/log-symbols/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "node_modules/marky": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz",
+ "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/memoize-one": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
+ "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
+ "license": "MIT"
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "license": "MIT"
+ },
+ "node_modules/metro": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/metro/-/metro-0.84.4.tgz",
+ "integrity": "sha512-8ETTubqfD6ornDy2zYDvRcKnVDOXdFJsjetYDBsY4oAsb6NJkiwFR+FaMESyGppFmQUyBQA4H4sFGxzcQSGtFA==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/metro-babel-transformer": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.84.4.tgz",
+ "integrity": "sha512-rvCfz8snl9h20VcvpOHxZuHP1SlAkv4HXbzw7nyyVwu6Eqo5PRerbakQ9XmUCOsRy70spJ37O+G1TK8oMzo48g==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/metro-cache": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.84.4.tgz",
+ "integrity": "sha512-gpcFQdSLUwUCk71saKoE64jLFbx2nwTfVCcPSULMNT8QYq0p1eZZE29Jvd0HtT/UlhC3ZOutLxJME5xqD2JUZg==",
+ "license": "MIT",
+ "dependencies": {
+ "exponential-backoff": "^3.1.1",
+ "flow-enums-runtime": "^0.0.6",
+ "https-proxy-agent": "^7.0.5",
+ "metro-core": "0.84.4"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/metro-cache-key": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.84.4.tgz",
+ "integrity": "sha512-wVO79aGrkYImpnaVS4+d5RrRBRPX31QtvKB3wKGBuiNSznduZTQHzsrJZRroFJSwnygrzdsGUtDQPuqqFjFdvw==",
+ "license": "MIT",
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/metro-config": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.84.4.tgz",
+ "integrity": "sha512-PMotGDjXcXLWo2TMRH+VR99phFNgYTwqh4OoieIKK3yTJa1Jmkl+fZJxDO0jfBvNF+WESHciHvpNuBtXaF3B0Q==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/metro-core": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.84.4.tgz",
+ "integrity": "sha512-HONpWC5LGXZn3ffkd4Hu6AIrfE7j4Z0g0wMo/goV24WOB3lhuFZ40KgvaDiSw8iyQHloMYay5N/wPX+z8oN/PQ==",
+ "license": "MIT",
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6",
+ "lodash.throttle": "^4.1.1",
+ "metro-resolver": "0.84.4"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/metro-file-map": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.84.4.tgz",
+ "integrity": "sha512-KSVDi/u60hKPx++NLu3MTIvyjzNoJnFAF8PQFxaj1jiSka/wjw+Ua6sNuJ0TDHQv+7AAoFQxeMgaRAe8Yic5wQ==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/metro-minify-terser": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.84.4.tgz",
+ "integrity": "sha512-5qpbaVOMC7CPitIpuewzVeGw7E+C3ykbv2mqTjQLl85Z3annSVGlSCTcsZjqXZzjupfK4Ztj3dDc4kc44NZwtQ==",
+ "license": "MIT",
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6",
+ "terser": "^5.15.0"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/metro-resolver": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.84.4.tgz",
+ "integrity": "sha512-1qLgbxQ5ZGhhutuPot1Yp348ofDsATL2WkrHF65TobqTT9K3P9qJXw38bomk7ncp5B7OYMfWwtyBZo1lCV792A==",
+ "license": "MIT",
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/metro-runtime": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.84.4.tgz",
+ "integrity": "sha512-Jibypds4g7AhzdRKY+kDoj51s5EXMwgyp5ddtlreDAsWefMdOx+agWqgm0H2XSZ/ueanHHVM89fnf5OJnlxa8Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.25.0",
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/metro-source-map": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.84.4.tgz",
+ "integrity": "sha512-jbWkPxIesVuo1IWkvezmMJld6iu8nD62GsrZiV6jP37AOdbo4OBq1FJ+qkOg8sV05wAHB//jAbziuW0SlJfW4g==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/metro-symbolicate": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.84.4.tgz",
+ "integrity": "sha512-OnfpacxUqGPZQ27t8qK9mFa7uqHIlVWeqRqkCbvMvreEBiamEeOn8krKtcwgP5M4cYDPwuSmCTopHMVthqG4zA==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/metro-transform-plugins": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.84.4.tgz",
+ "integrity": "sha512-kehr6HbAecqD0/a3xLXobELdPaAmRAl8bel0qagPF4vhZtux93nS8S4eq2kgKt6J2GnQpVjSoW1PXdst04mwow==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/metro-transform-worker": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.84.4.tgz",
+ "integrity": "sha512-W1IYMvvXTu4MxYr7d9h7CeG2vpIr3bmLLIavkPY4O1ilzDrvS8z/NEe6y+pC44Ff7raMXQgYSfdqDUwN/i39gg==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
+ "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "^1.54.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "10.2.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz",
+ "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "brace-expansion": "^5.0.8"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
+ "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/multitars": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/multitars/-/multitars-1.0.1.tgz",
+ "integrity": "sha512-Do9rHaSDfQ2Fk5Dpg2RjQ4M48Ol7rSq1gvKn/dXJYnhKEm8RRjjUvyiGDDEhJqb0hJPGjRaTB1kx6beqKO/i6Q==",
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.17",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz",
+ "integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/negotiator": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
+ "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/node-forge": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz",
+ "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==",
+ "license": "(BSD-3-Clause OR GPL-2.0)",
+ "engines": {
+ "node": ">= 6.13.0"
+ }
+ },
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.52",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.52.tgz",
+ "integrity": "sha512-MRlTqhAfoMx/4mhEbPo3Hi02g9LJZaJkka69V6h67Cb1gjrAG0jsTE4CZX1eptNx+VCAwJmfpnDIF4P0Nh1A7A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/npm-package-arg": {
+ "version": "11.0.3",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.3.tgz",
+ "integrity": "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==",
+ "license": "ISC",
+ "dependencies": {
+ "hosted-git-info": "^7.0.0",
+ "proc-log": "^4.0.0",
+ "semver": "^7.3.5",
+ "validate-npm-package-name": "^5.0.0"
+ },
+ "engines": {
+ "node": "^16.14.0 || >=18.0.0"
+ }
+ },
+ "node_modules/nullthrows": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz",
+ "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==",
+ "license": "MIT"
+ },
+ "node_modules/ob1": {
+ "version": "0.84.4",
+ "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.84.4.tgz",
+ "integrity": "sha512-eJXMpz4aQHXF/YBB9ddqZDIS+ooO91hObo9FoW/xBkr54/zCwYYCDqT/O54vNo8kOkWs5Ou/y28NgdrV0edQNA==",
+ "license": "MIT",
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/on-headers": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
+ "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+ "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/open": {
+ "version": "7.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
+ "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^2.0.0",
+ "is-wsl": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ora": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz",
+ "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ora/node_modules/ansi-regex": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+ "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ora/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ora/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ora/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/ora/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "license": "MIT"
+ },
+ "node_modules/ora/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/ora/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ora/node_modules/strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ora/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/parse-png": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/parse-png/-/parse-png-2.1.0.tgz",
+ "integrity": "sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==",
+ "license": "MIT",
+ "dependencies": {
+ "pngjs": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "license": "MIT"
+ },
+ "node_modules/path-scurry": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz",
+ "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^11.0.0",
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "11.5.2",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz",
+ "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/plist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz",
+ "integrity": "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==",
+ "license": "MIT",
+ "dependencies": {
+ "@xmldom/xmldom": "^0.9.10",
+ "base64-js": "^1.5.1",
+ "xmlbuilder": "^15.1.1"
+ },
+ "engines": {
+ "node": ">=10.4.0"
+ }
+ },
+ "node_modules/plist/node_modules/@xmldom/xmldom": {
+ "version": "0.9.10",
+ "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz",
+ "integrity": "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.6"
+ }
+ },
+ "node_modules/pngjs": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz",
+ "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.25",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz",
+ "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.16",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/proc-log": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz",
+ "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==",
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/promise": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz",
+ "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==",
+ "license": "MIT",
+ "dependencies": {
+ "asap": "~2.0.6"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/queue": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
+ "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "~2.0.3"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/react": {
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
+ "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-devtools-core": {
+ "version": "6.1.5",
+ "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.1.5.tgz",
+ "integrity": "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==",
+ "license": "MIT",
+ "dependencies": {
+ "shell-quote": "^1.6.1",
+ "ws": "^7"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "license": "MIT"
+ },
+ "node_modules/react-native": {
+ "version": "0.85.3",
+ "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.85.3.tgz",
+ "integrity": "sha512-HN/fGC+3nZVcDNcw7gfbM/DuqZAvI9Mz+/SxuhODaua4JY0BPzhfTzWXRyTR4mRgMHmShTPpH2PYMTxvZrsdZA==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-native/assets-registry": "0.85.3",
+ "@react-native/codegen": "0.85.3",
+ "@react-native/community-cli-plugin": "0.85.3",
+ "@react-native/gradle-plugin": "0.85.3",
+ "@react-native/js-polyfills": "0.85.3",
+ "@react-native/normalize-colors": "0.85.3",
+ "@react-native/virtualized-lists": "0.85.3",
+ "abort-controller": "^3.0.0",
+ "anser": "^1.4.9",
+ "ansi-regex": "^5.0.0",
+ "babel-plugin-syntax-hermes-parser": "0.33.3",
+ "base64-js": "^1.5.1",
+ "commander": "^12.0.0",
+ "flow-enums-runtime": "^0.0.6",
+ "hermes-compiler": "250829098.0.10",
+ "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"
+ },
+ "bin": {
+ "react-native": "cli.js"
+ },
+ "engines": {
+ "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
+ },
+ "peerDependencies": {
+ "@react-native/jest-preset": "0.85.3",
+ "@types/react": "^19.1.1",
+ "react": "^19.2.3"
+ },
+ "peerDependenciesMeta": {
+ "@react-native/jest-preset": {
+ "optional": true
+ },
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-native-webview": {
+ "version": "13.16.1",
+ "resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.16.1.tgz",
+ "integrity": "sha512-If0eHhoEdOYDcHsX+xBFwHMbWBGK1BvGDQDQdVkwtSIXiq1uiqjkpWVP2uQ1as94J0CzvFE9PUNDuhiX0Z6ubw==",
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^4.0.0",
+ "invariant": "2.2.4"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/react-native/node_modules/commander": {
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+ "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.14.2",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
+ "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/regenerate": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
+ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
+ "license": "MIT"
+ },
+ "node_modules/regenerate-unicode-properties": {
+ "version": "10.2.2",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz",
+ "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==",
+ "license": "MIT",
+ "dependencies": {
+ "regenerate": "^1.4.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.13.11",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
+ "license": "MIT"
+ },
+ "node_modules/regexpu-core": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz",
+ "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regjsgen": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz",
+ "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==",
+ "license": "MIT"
+ },
+ "node_modules/regjsparser": {
+ "version": "0.13.2",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.2.tgz",
+ "integrity": "sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "jsesc": "~3.1.0"
+ },
+ "bin": {
+ "regjsparser": "bin/parser"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.12",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
+ "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-workspace-root": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/resolve-workspace-root/-/resolve-workspace-root-2.0.1.tgz",
+ "integrity": "sha512-nR23LHAvaI6aHtMg6RWoaHpdR4D881Nydkzi2CixINyg9T00KgaJdJI6Vwty+Ps8WLxZHuxsS0BseWjxSA4C+w==",
+ "license": "MIT"
+ },
+ "node_modules/restore-cursor": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+ "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==",
+ "license": "MIT",
+ "dependencies": {
+ "onetime": "^2.0.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/sax": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz",
+ "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=11.0.0"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/send": {
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
+ "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/send/node_modules/debug/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/send/node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/send/node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/send/node_modules/statuses": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/serialize-error": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz",
+ "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/serve-static": {
+ "version": "1.16.3",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
+ "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "~0.19.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/serve-static/node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC"
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shell-quote": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.10.0.tgz",
+ "integrity": "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "license": "ISC"
+ },
+ "node_modules/simple-plist": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz",
+ "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==",
+ "license": "MIT",
+ "dependencies": {
+ "bplist-creator": "0.1.0",
+ "bplist-parser": "0.3.1",
+ "plist": "^3.0.5"
+ }
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "license": "MIT"
+ },
+ "node_modules/slugify": {
+ "version": "1.6.9",
+ "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.9.tgz",
+ "integrity": "sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/source-map-support/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stackframe": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
+ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
+ "license": "MIT"
+ },
+ "node_modules/stacktrace-parser": {
+ "version": "0.1.11",
+ "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz",
+ "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==",
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.7.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/stream-buffers": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz",
+ "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==",
+ "license": "Unlicense",
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/structured-headers": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/structured-headers/-/structured-headers-0.4.1.tgz",
+ "integrity": "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==",
+ "license": "MIT"
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-hyperlinks": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz",
+ "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0",
+ "supports-color": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/terminal-link": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
+ "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-escapes": "^4.2.1",
+ "supports-hyperlinks": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.49.2",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.49.2.tgz",
+ "integrity": "sha512-rGbJiKeQ4WDe3EXlDAIaQcwftVfv2Q8o1awFNfvXolJYKkb1AuZY1RTOmqx4LJXZENbWZA7eIsYGHuEzHsi1nQ==",
+ "license": "BSD-2-Clause",
+ "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"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/terser/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "license": "MIT"
+ },
+ "node_modules/throat": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
+ "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
+ "license": "MIT"
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyglobby/node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tinyglobby/node_modules/picomatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/toqr": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/toqr/-/toqr-0.1.1.tgz",
+ "integrity": "sha512-FWAPzCIHZHnrE/5/w9MPk0kK25hSQSH2IKhYh9PyjS3SG/+IEMvlwIHbhz+oF7xl54I+ueZlVnMjyzdSwLmAwA==",
+ "license": "MIT"
+ },
+ "node_modules/type-fest": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz",
+ "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
+ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
+ "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
+ "license": "MIT"
+ },
+ "node_modules/unicode-canonical-property-names-ecmascript": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz",
+ "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
+ "license": "MIT",
+ "dependencies": {
+ "unicode-canonical-property-names-ecmascript": "^2.0.0",
+ "unicode-property-aliases-ecmascript": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-value-ecmascript": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz",
+ "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-property-aliases-ecmascript": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz",
+ "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz",
+ "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==",
+ "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).",
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/validate-npm-package-name": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz",
+ "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==",
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/vlq": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz",
+ "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==",
+ "license": "MIT"
+ },
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "node_modules/wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+ "license": "MIT",
+ "dependencies": {
+ "defaults": "^1.0.3"
+ }
+ },
+ "node_modules/whatwg-fetch": {
+ "version": "3.6.20",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
+ "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==",
+ "license": "MIT"
+ },
+ "node_modules/whatwg-url-minimum": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/whatwg-url-minimum/-/whatwg-url-minimum-0.1.2.tgz",
+ "integrity": "sha512-XPEm0XFQWNVG292lII1PrRRJl3sItrs7CettZ4ncYxuDVpLyy+NwlGyut2hXI0JswcJUxeCH+CyOJK0ZzAXD6A==",
+ "license": "MIT"
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/ws": {
+ "version": "7.5.13",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.13.tgz",
+ "integrity": "sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xcode": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz",
+ "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "simple-plist": "^1.1.0",
+ "uuid": "^7.0.3"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/xml2js": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.0.tgz",
+ "integrity": "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==",
+ "license": "MIT",
+ "dependencies": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~11.0.0"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/xml2js/node_modules/xmlbuilder": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/xmlbuilder": {
+ "version": "15.1.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
+ "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "license": "ISC"
+ },
+ "node_modules/yaml": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
+ "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/eemeli"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "17.7.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz",
+ "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/zod": {
+ "version": "3.25.76",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ }
+ }
+}
diff --git a/apps/mobile/package.json b/apps/mobile/package.json
new file mode 100644
index 0000000..d697e53
--- /dev/null
+++ b/apps/mobile/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "celebrity-signatures-mobile",
+ "version": "1.0.0",
+ "private": true,
+ "main": "index.ts",
+ "scripts": {
+ "start": "expo start",
+ "ios": "expo run:ios",
+ "android": "expo run:android"
+ },
+ "dependencies": {
+ "expo": "^56.0.18",
+ "expo-asset": "~56.0.21",
+ "expo-blur": "~56.0.4",
+ "expo-constants": "~56.0.22",
+ "expo-haptics": "~56.0.3",
+ "expo-linear-gradient": "~56.0.4",
+ "expo-splash-screen": "~56.0.14",
+ "expo-status-bar": "~56.0.4",
+ "react": "19.2.3",
+ "react-native": "0.85.3",
+ "react-native-webview": "13.16.1"
+ },
+ "devDependencies": {
+ "@types/react": "~19.2.0",
+ "typescript": "~6.0.3"
+ }
+}
diff --git a/apps/mobile/screens/AccountScreen.tsx b/apps/mobile/screens/AccountScreen.tsx
new file mode 100644
index 0000000..be65c11
--- /dev/null
+++ b/apps/mobile/screens/AccountScreen.tsx
@@ -0,0 +1,564 @@
+// AccountScreen — auth + account management.
+// Apple App Store Review requirement 5.1.1(v): apps that support account creation
+// MUST also offer in-app account deletion. The "Delete my account" button at the
+// bottom of the signed-in view satisfies this requirement. The backend endpoint
+// POST /api/auth/delete performs the irreversible deletion server-side.
+//
+// Usage: <AccountScreen /> (no props — self-contained)
+// Rendered inside App's GlassScene; does NOT wrap itself in one.
+
+import React, { useCallback, useEffect, useRef, useState } from 'react';
+import {
+ ActivityIndicator,
+ Alert,
+ KeyboardAvoidingView,
+ Platform,
+ ScrollView,
+ StyleSheet,
+ Text,
+ TextInput,
+ View,
+} from 'react-native';
+import * as Haptics from 'expo-haptics';
+
+import { api, User } from '../api';
+import { GLASS, GlassButton, GlassPanel } from '../ui/glass';
+
+// ---------------------------------------------------------------------------
+// Types
+// ---------------------------------------------------------------------------
+
+type AuthMode = 'signin' | 'signup';
+type CheckState = 'checking' | 'done';
+
+// ---------------------------------------------------------------------------
+// Segmented toggle: "Sign in" | "Create account"
+// ---------------------------------------------------------------------------
+
+function ModeToggle({
+ mode,
+ onChange,
+}: {
+ mode: AuthMode;
+ onChange: (m: AuthMode) => void;
+}) {
+ return (
+ <View style={styles.toggleRow}>
+ {(['signin', 'signup'] as const).map((m) => {
+ const active = mode === m;
+ const label = m === 'signin' ? 'Sign in' : 'Create account';
+ return (
+ <View key={m} style={[styles.toggleSegment, active && styles.toggleSegmentActive]}>
+ <Text
+ onPress={() => {
+ if (!active) {
+ Haptics.selectionAsync();
+ onChange(m);
+ }
+ }}
+ style={[styles.toggleLabel, active && styles.toggleLabelActive]}
+ >
+ {label}
+ </Text>
+ </View>
+ );
+ })}
+ </View>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Dark-styled TextInput wrapper matching the gallery search bar aesthetic
+// ---------------------------------------------------------------------------
+
+function Field({
+ value,
+ onChangeText,
+ placeholder,
+ secureTextEntry = false,
+ autoCapitalize = 'none',
+ returnKeyType = 'next',
+ onSubmitEditing,
+ inputRef,
+}: {
+ value: string;
+ onChangeText: (v: string) => void;
+ placeholder: string;
+ secureTextEntry?: boolean;
+ autoCapitalize?: 'none' | 'words';
+ returnKeyType?: 'next' | 'done';
+ onSubmitEditing?: () => void;
+ inputRef?: React.RefObject<TextInput | null>;
+}) {
+ return (
+ <View style={styles.fieldWrap}>
+ <TextInput
+ ref={inputRef}
+ style={styles.fieldInput}
+ value={value}
+ onChangeText={onChangeText}
+ placeholder={placeholder}
+ placeholderTextColor={GLASS.textDim}
+ secureTextEntry={secureTextEntry}
+ autoCapitalize={autoCapitalize}
+ autoCorrect={false}
+ returnKeyType={returnKeyType}
+ onSubmitEditing={onSubmitEditing}
+ blurOnSubmit={returnKeyType === 'done'}
+ />
+ </View>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Auth view — sign-in / sign-up form
+// ---------------------------------------------------------------------------
+
+function AuthView({ onSuccess }: { onSuccess: (user: User) => void }) {
+ const [mode, setMode] = useState<AuthMode>('signin');
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [name, setName] = useState('');
+ const [busy, setBusy] = useState(false);
+ const [error, setError] = useState<string | null>(null);
+
+ const passwordRef = useRef<TextInput>(null);
+ const nameRef = useRef<TextInput>(null);
+
+ // Reset error when switching mode
+ const handleModeChange = useCallback((m: AuthMode) => {
+ setMode(m);
+ setError(null);
+ }, []);
+
+ const handleSubmit = useCallback(async () => {
+ const trimmedEmail = email.trim();
+ const trimmedName = name.trim();
+
+ if (!trimmedEmail || !password) {
+ setError('Email and password are required.');
+ return;
+ }
+
+ setBusy(true);
+ setError(null);
+
+ try {
+ const result =
+ mode === 'signin'
+ ? await api.login(trimmedEmail, password)
+ : await api.signup(trimmedEmail, password, trimmedName || undefined);
+
+ if (result.ok && result.user) {
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
+ onSuccess(result.user);
+ } else {
+ setError(result.error ?? 'Something went wrong. Please try again.');
+ }
+ } catch {
+ setError('Network error. Please check your connection.');
+ } finally {
+ setBusy(false);
+ }
+ }, [mode, email, password, name, onSuccess]);
+
+ const submitLabel = mode === 'signin' ? 'Sign in' : 'Create account';
+
+ return (
+ <View style={styles.authRoot}>
+ <Text style={styles.title}>Your Account</Text>
+ <Text style={styles.subtitle}>
+ Save placements and unlock your signature collection.
+ </Text>
+
+ <ModeToggle mode={mode} onChange={handleModeChange} />
+
+ <View style={styles.fields}>
+ <Field
+ value={email}
+ onChangeText={setEmail}
+ placeholder="Email"
+ autoCapitalize="none"
+ returnKeyType="next"
+ onSubmitEditing={() => {
+ if (mode === 'signup') {
+ nameRef.current?.focus();
+ } else {
+ passwordRef.current?.focus();
+ }
+ }}
+ />
+
+ {mode === 'signup' && (
+ <Field
+ inputRef={nameRef}
+ value={name}
+ onChangeText={setName}
+ placeholder="Name (optional)"
+ autoCapitalize="words"
+ returnKeyType="next"
+ onSubmitEditing={() => passwordRef.current?.focus()}
+ />
+ )}
+
+ <Field
+ inputRef={passwordRef}
+ value={password}
+ onChangeText={setPassword}
+ placeholder="Password"
+ secureTextEntry
+ returnKeyType="done"
+ onSubmitEditing={handleSubmit}
+ />
+ </View>
+
+ {error !== null && (
+ <Text style={styles.errorText}>{error}</Text>
+ )}
+
+ <View style={styles.submitBtn}>
+ <GlassButton
+ label={submitLabel}
+ onPress={handleSubmit}
+ solid
+ busy={busy}
+ disabled={busy}
+ />
+ </View>
+ </View>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Signed-in view — greeting + sign out + delete account
+// ---------------------------------------------------------------------------
+
+function SignedInView({
+ user,
+ onSignOut,
+}: {
+ user: NonNullable<User>;
+ onSignOut: () => void;
+}) {
+ const [signOutBusy, setSignOutBusy] = useState(false);
+ const [deleteBusy, setDeleteBusy] = useState(false);
+ const [deleteError, setDeleteError] = useState<string | null>(null);
+ const [deleted, setDeleted] = useState(false);
+
+ const handleSignOut = useCallback(async () => {
+ setSignOutBusy(true);
+ try {
+ await api.logout();
+ } finally {
+ // Always return to auth view regardless of server response
+ setSignOutBusy(false);
+ onSignOut();
+ }
+ }, [onSignOut]);
+
+ // Apple 5.1.1(v) — in-app account deletion with explicit confirmation.
+ const handleDeletePress = useCallback(() => {
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
+
+ Alert.alert(
+ 'Delete Account',
+ 'This permanently deletes your account, saved placements, and uploads. This cannot be undone.',
+ [
+ { text: 'Cancel', style: 'cancel' },
+ {
+ text: 'Delete',
+ style: 'destructive',
+ onPress: async () => {
+ setDeleteError(null);
+ setDeleteBusy(true);
+
+ await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Warning);
+
+ try {
+ const result = await api.deleteAccount();
+ if (result.ok) {
+ setDeleted(true);
+ // Brief "Account deleted" display then return to auth
+ setTimeout(() => onSignOut(), 1800);
+ } else {
+ setDeleteError(result.error ?? 'Deletion failed. Please try again.');
+ }
+ } catch {
+ setDeleteError('Network error. Please check your connection.');
+ } finally {
+ setDeleteBusy(false);
+ }
+ },
+ },
+ ],
+ );
+ }, [onSignOut]);
+
+ if (deleted) {
+ return (
+ <View style={styles.center}>
+ <Text style={styles.deletedText}>Account deleted.</Text>
+ </View>
+ );
+ }
+
+ return (
+ <View style={styles.signedInRoot}>
+ {/* Greeting panel */}
+ <GlassPanel style={styles.greetingPanel}>
+ <Text style={styles.greetingLine}>Signed in as</Text>
+ <Text style={styles.greetingEmail} numberOfLines={1}>
+ {user.email}
+ </Text>
+ {user.name ? (
+ <Text style={styles.greetingName}>{user.name}</Text>
+ ) : null}
+ </GlassPanel>
+
+ {/* Sign out */}
+ <View style={styles.actionBtn}>
+ <GlassButton
+ label="Sign out"
+ onPress={handleSignOut}
+ busy={signOutBusy}
+ disabled={signOutBusy || deleteBusy}
+ />
+ </View>
+
+ {/* Spacer pushes delete to bottom */}
+ <View style={styles.spacer} />
+
+ {/* Delete account — Apple 5.1.1(v) required control */}
+ <View style={styles.deleteSection}>
+ {deleteError !== null && (
+ <Text style={styles.errorText}>{deleteError}</Text>
+ )}
+ <GlassButton
+ label={deleteBusy ? 'Deleting…' : 'Delete my account'}
+ onPress={handleDeletePress}
+ busy={deleteBusy}
+ disabled={deleteBusy || signOutBusy}
+ />
+ <Text style={styles.deleteCaption}>
+ Permanently removes your account, placements, and uploads.
+ </Text>
+ </View>
+ </View>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Root screen — resolves auth state then delegates
+// ---------------------------------------------------------------------------
+
+export default function AccountScreen() {
+ const [checkState, setCheckState] = useState<CheckState>('checking');
+ const [user, setUser] = useState<User>(null);
+
+ useEffect(() => {
+ let cancelled = false;
+ api.me().then((res) => {
+ if (!cancelled) {
+ setUser(res.ok ? res.user : null);
+ setCheckState('done');
+ }
+ }).catch(() => {
+ if (!cancelled) {
+ setUser(null);
+ setCheckState('done');
+ }
+ });
+ return () => { cancelled = true; };
+ }, []);
+
+ const handleAuthSuccess = useCallback((u: User) => {
+ setUser(u);
+ }, []);
+
+ const handleSignOut = useCallback(() => {
+ setUser(null);
+ }, []);
+
+ // While checking session
+ if (checkState === 'checking') {
+ return (
+ <View style={styles.center}>
+ <ActivityIndicator size="large" color={GLASS.accent} />
+ </View>
+ );
+ }
+
+ return (
+ <KeyboardAvoidingView
+ style={styles.flex}
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
+ >
+ <ScrollView
+ style={styles.flex}
+ contentContainerStyle={styles.scrollContent}
+ keyboardShouldPersistTaps="handled"
+ showsVerticalScrollIndicator={false}
+ >
+ {user !== null ? (
+ <SignedInView user={user} onSignOut={handleSignOut} />
+ ) : (
+ <AuthView onSuccess={handleAuthSuccess} />
+ )}
+ </ScrollView>
+ </KeyboardAvoidingView>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Styles
+// ---------------------------------------------------------------------------
+
+const styles = StyleSheet.create({
+ flex: {
+ flex: 1,
+ },
+ scrollContent: {
+ flexGrow: 1,
+ paddingHorizontal: 20,
+ paddingTop: 32,
+ paddingBottom: 48,
+ },
+ center: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ padding: 32,
+ },
+
+ // Auth view
+ authRoot: {
+ flex: 1,
+ },
+ title: {
+ fontSize: 28,
+ fontWeight: '700',
+ color: GLASS.accentSoft,
+ letterSpacing: 0.2,
+ marginBottom: 8,
+ },
+ subtitle: {
+ fontSize: 15,
+ color: GLASS.textDim,
+ marginBottom: 28,
+ lineHeight: 21,
+ },
+
+ // Mode toggle
+ toggleRow: {
+ flexDirection: 'row',
+ borderRadius: 12,
+ overflow: 'hidden',
+ borderWidth: StyleSheet.hairlineWidth,
+ borderColor: GLASS.edge,
+ backgroundColor: 'rgba(255,255,255,0.04)',
+ marginBottom: 24,
+ },
+ toggleSegment: {
+ flex: 1,
+ paddingVertical: 12,
+ alignItems: 'center',
+ },
+ toggleSegmentActive: {
+ backgroundColor: 'rgba(201,168,106,0.18)',
+ borderBottomWidth: 2,
+ borderBottomColor: GLASS.accent,
+ },
+ toggleLabel: {
+ fontSize: 15,
+ fontWeight: '600',
+ color: GLASS.textDim,
+ },
+ toggleLabelActive: {
+ color: GLASS.accent,
+ },
+
+ // Fields
+ fields: {
+ gap: 12,
+ marginBottom: 16,
+ },
+ fieldWrap: {
+ borderRadius: 12,
+ overflow: 'hidden',
+ backgroundColor: 'rgba(255,255,255,0.07)',
+ borderWidth: StyleSheet.hairlineWidth,
+ borderColor: GLASS.edgeFaint,
+ },
+ fieldInput: {
+ paddingHorizontal: 16,
+ paddingVertical: 14,
+ fontSize: 16,
+ color: GLASS.accentSoft,
+ },
+
+ errorText: {
+ color: '#e05c5c',
+ fontSize: 14,
+ marginBottom: 14,
+ lineHeight: 19,
+ },
+ submitBtn: {
+ marginTop: 8,
+ },
+
+ // Signed-in view
+ signedInRoot: {
+ flex: 1,
+ minHeight: 420,
+ },
+ greetingPanel: {
+ marginBottom: 20,
+ },
+ greetingLine: {
+ fontSize: 13,
+ color: GLASS.textDim,
+ letterSpacing: 0.3,
+ marginBottom: 4,
+ textTransform: 'uppercase',
+ },
+ greetingEmail: {
+ fontSize: 18,
+ fontWeight: '700',
+ color: GLASS.accentSoft,
+ marginBottom: 2,
+ },
+ greetingName: {
+ fontSize: 15,
+ color: GLASS.textDim,
+ marginTop: 4,
+ },
+ actionBtn: {
+ marginBottom: 12,
+ },
+ spacer: {
+ flex: 1,
+ minHeight: 32,
+ },
+
+ // Delete section
+ deleteSection: {
+ paddingTop: 20,
+ borderTopWidth: StyleSheet.hairlineWidth,
+ borderTopColor: 'rgba(255,255,255,0.08)',
+ },
+ deleteCaption: {
+ fontSize: 12,
+ color: GLASS.textDim,
+ textAlign: 'center',
+ marginTop: 10,
+ lineHeight: 17,
+ },
+
+ // Post-delete confirmation
+ deletedText: {
+ fontSize: 18,
+ fontWeight: '700',
+ color: GLASS.accentSoft,
+ textAlign: 'center',
+ },
+});
diff --git a/apps/mobile/screens/GalleryScreen.tsx b/apps/mobile/screens/GalleryScreen.tsx
new file mode 100644
index 0000000..fe1b9e2
--- /dev/null
+++ b/apps/mobile/screens/GalleryScreen.tsx
@@ -0,0 +1,374 @@
+// GalleryScreen — 2-column signature grid with category filter chips + search.
+// Rendered inside App's GlassScene, so this file does NOT wrap itself in one.
+// Usage: <GalleryScreen onOpen={(sig) => openDetail(sig)} />
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
+import {
+ ActivityIndicator,
+ FlatList,
+ Image,
+ ListRenderItemInfo,
+ Pressable,
+ ScrollView,
+ StyleSheet,
+ Text,
+ TextInput,
+ View,
+} from 'react-native';
+import * as Haptics from 'expo-haptics';
+
+import { api, qidOf, Signature, Portraits } from '../api';
+import { GLASS, GlassPanel, GlassPill, GlassButton } from '../ui/glass';
+
+// ---------------------------------------------------------------------------
+// Types
+// ---------------------------------------------------------------------------
+type LoadState = 'idle' | 'loading' | 'ok' | 'error';
+
+// ---------------------------------------------------------------------------
+// Sub-components
+// ---------------------------------------------------------------------------
+
+function CategoryBar({
+ categories,
+ selected,
+ onSelect,
+}: {
+ categories: string[];
+ selected: string;
+ onSelect: (cat: string) => void;
+}) {
+ const all = ['All', ...categories];
+ return (
+ <ScrollView
+ horizontal
+ showsHorizontalScrollIndicator={false}
+ contentContainerStyle={styles.catRow}
+ >
+ {all.map((cat) => {
+ const active = cat === selected;
+ return (
+ <Pressable
+ key={cat}
+ onPress={() => {
+ Haptics.selectionAsync();
+ onSelect(cat);
+ }}
+ style={styles.catPressable}
+ >
+ <GlassPill tintColor={active ? GLASS.accent : undefined}>
+ <Text
+ style={[styles.catLabel, active && styles.catLabelActive]}
+ numberOfLines={1}
+ >
+ {cat}
+ </Text>
+ </GlassPill>
+ </Pressable>
+ );
+ })}
+ </ScrollView>
+ );
+}
+
+function SigCard({
+ sig,
+ onOpen,
+}: {
+ sig: Signature;
+ onOpen: (sig: Signature) => void;
+}) {
+ return (
+ <Pressable
+ onPress={() => {
+ Haptics.selectionAsync();
+ onOpen(sig);
+ }}
+ style={styles.cardPressable}
+ >
+ <GlassPanel style={styles.card}>
+ {/* parchment image backing so dark-ink signatures are legible */}
+ <View style={styles.imgBacking}>
+ {sig.signature_image_url ? (
+ <Image
+ source={{ uri: sig.signature_image_url }}
+ style={styles.img}
+ resizeMode="contain"
+ />
+ ) : (
+ <View style={styles.imgPlaceholder} />
+ )}
+ </View>
+ <Text style={styles.cardName} numberOfLines={2}>
+ {sig.full_name}
+ </Text>
+ <Text style={styles.cardCat} numberOfLines={1}>
+ {sig.category}
+ </Text>
+ </GlassPanel>
+ </Pressable>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Main screen
+// ---------------------------------------------------------------------------
+
+export default function GalleryScreen({ onOpen }: { onOpen: (sig: Signature) => void }) {
+ const [loadState, setLoadState] = useState<LoadState>('idle');
+ const [signatures, setSignatures] = useState<Signature[]>([]);
+ // portraits is fetched but not directly rendered in the grid;
+ // it's available as a side-effect for parent to pass into detail.
+ const [, setPortraits] = useState<Portraits>({});
+ const [selectedCat, setSelectedCat] = useState<string>('All');
+ const [query, setQuery] = useState<string>('');
+
+ const load = useCallback(async () => {
+ setLoadState('loading');
+ try {
+ const [sigs, portraits] = await Promise.all([api.signatures(), api.portraits()]);
+ setSignatures(sigs);
+ setPortraits(portraits);
+ setLoadState('ok');
+ } catch {
+ setLoadState('error');
+ }
+ }, []);
+
+ useEffect(() => { load(); }, [load]);
+
+ // Distinct ordered category list
+ const categories = useMemo<string[]>(() => {
+ const seen = new Set<string>();
+ const out: string[] = [];
+ for (const s of signatures) {
+ if (!seen.has(s.category)) { seen.add(s.category); out.push(s.category); }
+ }
+ return out.sort();
+ }, [signatures]);
+
+ // Filtered list
+ const filtered = useMemo<Signature[]>(() => {
+ let list = selectedCat === 'All'
+ ? signatures
+ : signatures.filter((s) => s.category === selectedCat);
+
+ const terms = query.trim().toLowerCase().split(/\s+/).filter(Boolean);
+ if (terms.length > 0) {
+ list = list.filter((s) => {
+ const hay = s.full_name.toLowerCase();
+ return terms.every((t) => hay.includes(t));
+ });
+ }
+ return list;
+ }, [signatures, selectedCat, query]);
+
+ // Stable keyExtractor
+ const keyExtractor = useCallback(
+ (item: Signature, index: number) => qidOf(item) ?? `${item.full_name}-${index}`,
+ [],
+ );
+
+ // getItemLayout for fixed-height cards (card = imgBacking 110 + name ~40 + cat ~20 + padding)
+ // GlassPanel panelBody padding=18 top+bottom=36; imgBacking=110; name=40; cat=20 → ~206 + card margins
+ const CARD_HEIGHT = 216;
+ const CARD_MARGIN = 6;
+ const ITEM_HEIGHT = CARD_HEIGHT + CARD_MARGIN * 2;
+ const getItemLayout = useCallback(
+ (_: ArrayLike<Signature> | null | undefined, index: number) => ({
+ length: ITEM_HEIGHT,
+ offset: ITEM_HEIGHT * Math.floor(index / 2),
+ index,
+ }),
+ [ITEM_HEIGHT],
+ );
+
+ const renderItem = useCallback(
+ ({ item }: ListRenderItemInfo<Signature>) => <SigCard sig={item} onOpen={onOpen} />,
+ [onOpen],
+ );
+
+ // ---------------------------------------------------------------------------
+ // Render states
+ // ---------------------------------------------------------------------------
+
+ if (loadState === 'loading' || loadState === 'idle') {
+ return (
+ <View style={styles.center}>
+ <ActivityIndicator size="large" color={GLASS.accent} />
+ <Text style={styles.loadingText}>Loading signatures…</Text>
+ </View>
+ );
+ }
+
+ if (loadState === 'error') {
+ return (
+ <View style={styles.center}>
+ <Text style={styles.errorText}>Could not load signatures.</Text>
+ <View style={styles.retryBtn}>
+ <GlassButton label="Retry" onPress={load} />
+ </View>
+ </View>
+ );
+ }
+
+ return (
+ <View style={styles.root}>
+ {/* Search bar */}
+ <View style={styles.searchWrap}>
+ <TextInput
+ style={styles.searchInput}
+ placeholder="Search a name…"
+ placeholderTextColor={GLASS.textDim}
+ value={query}
+ onChangeText={setQuery}
+ clearButtonMode="while-editing"
+ autoCorrect={false}
+ autoCapitalize="none"
+ returnKeyType="search"
+ />
+ </View>
+
+ {/* Category chips */}
+ <CategoryBar
+ categories={categories}
+ selected={selectedCat}
+ onSelect={setSelectedCat}
+ />
+
+ {/* Signature grid */}
+ <FlatList<Signature>
+ data={filtered}
+ keyExtractor={keyExtractor}
+ renderItem={renderItem}
+ numColumns={2}
+ columnWrapperStyle={styles.row}
+ contentContainerStyle={styles.listContent}
+ initialNumToRender={10}
+ windowSize={7}
+ removeClippedSubviews
+ getItemLayout={getItemLayout}
+ showsVerticalScrollIndicator={false}
+ ListEmptyComponent={
+ <View style={styles.center}>
+ <Text style={styles.emptyText}>No signatures match your filter.</Text>
+ </View>
+ }
+ />
+ </View>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Styles
+// ---------------------------------------------------------------------------
+
+const styles = StyleSheet.create({
+ root: {
+ flex: 1,
+ },
+ center: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ padding: 32,
+ },
+ loadingText: {
+ marginTop: 16,
+ color: GLASS.textDim,
+ fontSize: 15,
+ },
+ errorText: {
+ color: GLASS.accentSoft,
+ fontSize: 16,
+ marginBottom: 20,
+ textAlign: 'center',
+ },
+ retryBtn: {
+ width: 160,
+ },
+ emptyText: {
+ color: GLASS.textDim,
+ fontSize: 15,
+ textAlign: 'center',
+ },
+ searchWrap: {
+ marginHorizontal: 14,
+ marginTop: 12,
+ marginBottom: 8,
+ borderRadius: 12,
+ overflow: 'hidden',
+ backgroundColor: 'rgba(255,255,255,0.07)',
+ borderWidth: StyleSheet.hairlineWidth,
+ borderColor: GLASS.edgeFaint,
+ },
+ searchInput: {
+ paddingHorizontal: 14,
+ paddingVertical: 11,
+ fontSize: 16,
+ color: GLASS.accentSoft,
+ },
+ catRow: {
+ paddingHorizontal: 14,
+ paddingBottom: 10,
+ gap: 8,
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ catPressable: {
+ // pill handles its own sizing
+ },
+ catLabel: {
+ fontSize: 13,
+ fontWeight: '600',
+ color: GLASS.textDim,
+ letterSpacing: 0.2,
+ },
+ catLabelActive: {
+ color: GLASS.ink,
+ },
+ listContent: {
+ paddingHorizontal: 10,
+ paddingBottom: 32,
+ },
+ row: {
+ justifyContent: 'space-between',
+ },
+ cardPressable: {
+ flex: 1,
+ marginHorizontal: 4,
+ marginVertical: 6,
+ },
+ card: {
+ // GlassPanel handles borderRadius + overflow
+ },
+ imgBacking: {
+ backgroundColor: 'rgba(232,217,184,0.06)',
+ borderRadius: 10,
+ height: 110,
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginBottom: 10,
+ overflow: 'hidden',
+ },
+ img: {
+ width: '100%',
+ height: '100%',
+ },
+ imgPlaceholder: {
+ width: '100%',
+ height: '100%',
+ backgroundColor: 'rgba(255,255,255,0.03)',
+ },
+ cardName: {
+ fontSize: 14,
+ fontWeight: '700',
+ color: GLASS.accentSoft,
+ marginBottom: 4,
+ lineHeight: 19,
+ },
+ cardCat: {
+ fontSize: 12,
+ color: GLASS.textDim,
+ letterSpacing: 0.15,
+ },
+});
diff --git a/apps/mobile/screens/GameScreen.tsx b/apps/mobile/screens/GameScreen.tsx
new file mode 100644
index 0000000..6c35d16
--- /dev/null
+++ b/apps/mobile/screens/GameScreen.tsx
@@ -0,0 +1,740 @@
+/**
+ * GameScreen — "Whose signature is this?"
+ *
+ * Usage (in App/navigation):
+ * import GameScreen from './screens/GameScreen';
+ * // Rendered inside GlassScene by the app shell — do NOT wrap here.
+ * <GameScreen />
+ *
+ * Rules:
+ * • 10 questions per game, 4 choices each (1 correct + 3 wrong), shuffled.
+ * • Correct tap → gold flash + haptic success + increment score.
+ * • Wrong tap → haptic error + reveal correct name + end streak (next Q).
+ * • Game-over card shows score, name TextInput, Submit button → rank display.
+ * • Top-5 leaderboard rendered below at all times (fetched on mount + after submit).
+ */
+
+import React, {
+ useCallback,
+ useEffect,
+ useMemo,
+ useReducer,
+ useRef,
+ useState,
+} from 'react';
+import {
+ ActivityIndicator,
+ Animated,
+ Image,
+ Pressable,
+ ScrollView,
+ StyleSheet,
+ Text,
+ TextInput,
+ View,
+} from 'react-native';
+import * as Haptics from 'expo-haptics';
+
+import { api, Signature, LeaderRow } from '../api';
+import { GLASS, GlassPanel, GlassButton, GlassPill } from '../ui/glass';
+
+// ---------------------------------------------------------------------------
+// Constants
+// ---------------------------------------------------------------------------
+
+const TOTAL_QUESTIONS = 10;
+const CHOICES = 4;
+const GAME_ID = 'whose';
+const DIFF_ID = 'icons';
+
+// ---------------------------------------------------------------------------
+// Types
+// ---------------------------------------------------------------------------
+
+type Question = {
+ signature: Signature; // correct answer
+ choices: string[]; // shuffled full_names (length === CHOICES)
+ correctIndex: number; // index in choices that is correct
+};
+
+type FeedbackState = 'idle' | 'correct' | 'wrong';
+
+type GamePhase = 'loading' | 'error' | 'playing' | 'over';
+
+// ---------------------------------------------------------------------------
+// Helpers
+// ---------------------------------------------------------------------------
+
+function shuffle<T>(arr: T[]): T[] {
+ const a = [...arr];
+ for (let i = a.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ [a[i], a[j]] = [a[j], a[i]];
+ }
+ return a;
+}
+
+/** Pick `n` distinct items from `pool`, excluding `exclude`. */
+function pickDistinct<T>(pool: T[], exclude: T, n: number): T[] {
+ const candidates = pool.filter((x) => x !== exclude);
+ return shuffle(candidates).slice(0, n);
+}
+
+/**
+ * Build a full 10-question deck from the available pool.
+ * Each question needs a signature image URL; the pool is already filtered for that.
+ */
+function buildDeck(pool: Signature[]): Question[] {
+ const allNames = pool.map((s) => s.full_name);
+ const picked = shuffle(pool).slice(0, TOTAL_QUESTIONS);
+
+ return picked.map((sig) => {
+ const wrong = pickDistinct(allNames, sig.full_name, CHOICES - 1);
+ const mixed = shuffle([sig.full_name, ...wrong]);
+ return {
+ signature: sig,
+ choices: mixed,
+ correctIndex: mixed.indexOf(sig.full_name),
+ };
+ });
+}
+
+// ---------------------------------------------------------------------------
+// Sub-components
+// ---------------------------------------------------------------------------
+
+function LoadingView() {
+ return (
+ <View style={styles.centeredFill}>
+ <ActivityIndicator size="large" color={GLASS.accent} />
+ <Text style={styles.dimText}>Loading signatures…</Text>
+ </View>
+ );
+}
+
+function ErrorView({ onRetry }: { onRetry: () => void }) {
+ return (
+ <View style={styles.centeredFill}>
+ <Text style={styles.errorText}>Could not load signatures.</Text>
+ <View style={styles.retryBtn}>
+ <GlassButton label="Retry" onPress={onRetry} solid />
+ </View>
+ </View>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Gold flash overlay (Animated) shown briefly on correct answer
+// ---------------------------------------------------------------------------
+
+function CorrectFlash({ visible }: { visible: boolean }) {
+ const opacity = useRef(new Animated.Value(0)).current;
+
+ useEffect(() => {
+ if (visible) {
+ Animated.sequence([
+ Animated.timing(opacity, { toValue: 0.35, duration: 80, useNativeDriver: true }),
+ Animated.timing(opacity, { toValue: 0, duration: 320, useNativeDriver: true }),
+ ]).start();
+ }
+ }, [visible, opacity]);
+
+ return (
+ <Animated.View
+ pointerEvents="none"
+ style={[StyleSheet.absoluteFill, { backgroundColor: GLASS.accent, opacity, borderRadius: 22 }]}
+ />
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Leaderboard panel
+// ---------------------------------------------------------------------------
+
+function LeaderboardPanel({ rows, loading }: { rows: LeaderRow[]; loading: boolean }) {
+ return (
+ <GlassPanel style={styles.leaderPanel}>
+ <Text style={styles.sectionTitle}>Top Scores</Text>
+ {loading ? (
+ <ActivityIndicator color={GLASS.accent} style={{ marginTop: 8 }} />
+ ) : rows.length === 0 ? (
+ <Text style={styles.dimText}>No scores yet — be the first!</Text>
+ ) : (
+ rows.slice(0, 5).map((row, i) => (
+ <View key={row.id} style={styles.leaderRow}>
+ <Text style={styles.leaderRank}>{i + 1}.</Text>
+ <Text style={styles.leaderName} numberOfLines={1}>{row.name}</Text>
+ <GlassPill tintColor={GLASS.accent}>
+ <Text style={styles.leaderScore}>{row.score}</Text>
+ </GlassPill>
+ </View>
+ ))
+ )}
+ </GlassPanel>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Game-over card
+// ---------------------------------------------------------------------------
+
+type GameOverCardProps = {
+ score: number;
+ onPlayAgain: () => void;
+};
+
+function GameOverCard({ score, onPlayAgain }: GameOverCardProps) {
+ const [name, setName] = useState('');
+ const [submitting, setSubmitting] = useState(false);
+ const [rank, setRank] = useState<number | null>(null);
+ const [submitError, setSubmitError] = useState('');
+
+ const handleSubmit = useCallback(async () => {
+ const trimmed = name.trim();
+ if (!trimmed) return;
+ setSubmitting(true);
+ setSubmitError('');
+ try {
+ const res = await api.leaderboardSubmit(GAME_ID, DIFF_ID, score, trimmed);
+ if (res.ok && res.rank != null) {
+ setRank(res.rank);
+ } else {
+ setSubmitError('Submit failed — try again.');
+ }
+ } catch {
+ setSubmitError('Network error.');
+ } finally {
+ setSubmitting(false);
+ }
+ }, [name, score]);
+
+ return (
+ <GlassPanel style={styles.gameOverPanel}>
+ <Text style={styles.gameOverTitle}>Game Over</Text>
+
+ <View style={styles.scoreRow}>
+ <GlassPill tintColor={GLASS.accent}>
+ <Text style={styles.finalScoreText}>
+ {score} / {TOTAL_QUESTIONS}
+ </Text>
+ </GlassPill>
+ </View>
+
+ {rank != null ? (
+ <Text style={styles.rankText}>You ranked #{rank} — nice!</Text>
+ ) : (
+ <>
+ <TextInput
+ style={styles.nameInput}
+ placeholder="Your name"
+ placeholderTextColor={GLASS.textDim}
+ value={name}
+ onChangeText={setName}
+ maxLength={32}
+ returnKeyType="done"
+ autoCorrect={false}
+ />
+ {submitError !== '' && (
+ <Text style={styles.errorText}>{submitError}</Text>
+ )}
+ <View style={styles.submitBtn}>
+ <GlassButton
+ label="Submit score"
+ onPress={handleSubmit}
+ solid
+ busy={submitting}
+ disabled={name.trim().length === 0}
+ />
+ </View>
+ </>
+ )}
+
+ <View style={styles.playAgainBtn}>
+ <GlassButton label="Play again" onPress={onPlayAgain} />
+ </View>
+ </GlassPanel>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Main GameScreen
+// ---------------------------------------------------------------------------
+
+export default function GameScreen() {
+ // --- Data loading ---
+ const [phase, setPhase] = useState<GamePhase>('loading');
+ const [pool, setPool] = useState<Signature[]>([]);
+
+ // --- Leader board ---
+ const [leaderRows, setLeaderRows] = useState<LeaderRow[]>([]);
+ const [leaderLoading, setLeaderLoading] = useState(true);
+
+ // --- Game state ---
+ const [deck, setDeck] = useState<Question[]>([]);
+ const [qIndex, setQIndex] = useState(0); // 0-based current question
+ const [score, setScore] = useState(0);
+ const [feedback, setFeedback] = useState<FeedbackState>('idle');
+ const [selectedIndex, setSelectedIndex] = useState<number | null>(null);
+ const [correctFlash, setCorrectFlash] = useState(false);
+
+ // Used to prevent double-tap race during feedback animation
+ const lockedRef = useRef(false);
+
+ // ---------------------------------------------------------------------------
+ // Fetch signatures on mount
+ // ---------------------------------------------------------------------------
+
+ const fetchSignatures = useCallback(async () => {
+ setPhase('loading');
+ try {
+ const all = await api.signatures();
+ const withImg = all.filter((s) => !!s.signature_image_url);
+ if (withImg.length < CHOICES) {
+ // Not enough data to build a quiz
+ setPhase('error');
+ return;
+ }
+ setPool(withImg);
+ setPhase('playing');
+ startNewGame(withImg);
+ } catch {
+ setPhase('error');
+ }
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
+
+ // ---------------------------------------------------------------------------
+ // Fetch leaderboard
+ // ---------------------------------------------------------------------------
+
+ const fetchLeaderboard = useCallback(async () => {
+ setLeaderLoading(true);
+ try {
+ const res = await api.leaderboardTop(GAME_ID, DIFF_ID);
+ if (res.ok) setLeaderRows(res.top);
+ } catch {
+ // non-fatal — board just stays empty
+ } finally {
+ setLeaderLoading(false);
+ }
+ }, []);
+
+ useEffect(() => {
+ fetchSignatures();
+ fetchLeaderboard();
+ }, [fetchSignatures, fetchLeaderboard]);
+
+ // ---------------------------------------------------------------------------
+ // Game logic
+ // ---------------------------------------------------------------------------
+
+ function startNewGame(sigPool: Signature[] = pool) {
+ const newDeck = buildDeck(sigPool);
+ setDeck(newDeck);
+ setQIndex(0);
+ setScore(0);
+ setFeedback('idle');
+ setSelectedIndex(null);
+ setCorrectFlash(false);
+ lockedRef.current = false;
+ setPhase('playing');
+ }
+
+ const handlePlayAgain = useCallback(() => {
+ fetchLeaderboard(); // refresh board after game-over view
+ startNewGame();
+ }, [pool]); // eslint-disable-line react-hooks/exhaustive-deps
+
+ const handleChoice = useCallback(
+ (choiceIndex: number) => {
+ if (lockedRef.current || feedback !== 'idle') return;
+ lockedRef.current = true;
+ setSelectedIndex(choiceIndex);
+
+ const q = deck[qIndex];
+ const isCorrect = choiceIndex === q.correctIndex;
+
+ if (isCorrect) {
+ void Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
+ setCorrectFlash(true);
+ setFeedback('correct');
+ const nextScore = score + 1;
+
+ setTimeout(() => {
+ setCorrectFlash(false);
+ const nextIndex = qIndex + 1;
+ if (nextIndex >= TOTAL_QUESTIONS) {
+ setScore(nextScore);
+ setPhase('over');
+ } else {
+ setScore(nextScore);
+ setQIndex(nextIndex);
+ setFeedback('idle');
+ setSelectedIndex(null);
+ lockedRef.current = false;
+ }
+ }, 520);
+ } else {
+ void Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
+ setFeedback('wrong');
+
+ // Reveal answer for 1.4 s then advance
+ setTimeout(() => {
+ const nextIndex = qIndex + 1;
+ if (nextIndex >= TOTAL_QUESTIONS) {
+ setPhase('over');
+ } else {
+ setQIndex(nextIndex);
+ setFeedback('idle');
+ setSelectedIndex(null);
+ lockedRef.current = false;
+ }
+ }, 1400);
+ }
+ },
+ [deck, feedback, qIndex, score],
+ );
+
+ // ---------------------------------------------------------------------------
+ // Derived values
+ // ---------------------------------------------------------------------------
+
+ const currentQuestion: Question | undefined = deck[qIndex];
+
+ // Button color logic per choice:
+ // idle → default glass
+ // correct → gold background on the correct choice
+ // wrong → red on selected, gold on correct
+ function choiceStyle(choiceIndex: number): { tint?: string; textColor?: string } {
+ if (feedback === 'idle') return {};
+ const isCorrectChoice = currentQuestion && choiceIndex === currentQuestion.correctIndex;
+ const isSelectedChoice = choiceIndex === selectedIndex;
+ if (isCorrectChoice) return { tint: GLASS.accent, textColor: GLASS.ink };
+ if (isSelectedChoice && feedback === 'wrong') return { tint: '#b03a2e', textColor: '#fff' };
+ return {};
+ }
+
+ // ---------------------------------------------------------------------------
+ // Render helpers
+ // ---------------------------------------------------------------------------
+
+ function renderChoiceButtons() {
+ if (!currentQuestion) return null;
+ return currentQuestion.choices.map((name, idx) => {
+ const { tint, textColor } = choiceStyle(idx);
+ const isTinted = !!tint;
+
+ // We need tinted buttons — GlassButton only has solid=accent-gold.
+ // For correct/wrong states we render a custom GlassPill-based pressable
+ // so the color override works without forking GlassButton.
+ if (isTinted) {
+ return (
+ <View key={idx} style={styles.choiceOverrideWrap}>
+ <View style={[styles.choiceOverridePill, { backgroundColor: tint }]}>
+ <Text
+ style={[styles.choiceOverrideText, { color: textColor ?? '#fff' }]}
+ numberOfLines={2}
+ >
+ {name}
+ </Text>
+ </View>
+ </View>
+ );
+ }
+
+ return (
+ <View key={idx} style={styles.choiceBtn}>
+ <GlassButton
+ label={name}
+ onPress={() => handleChoice(idx)}
+ disabled={feedback !== 'idle'}
+ />
+ </View>
+ );
+ });
+ }
+
+ function renderProgress() {
+ return (
+ <View style={styles.progressRow}>
+ <GlassPill>
+ <Text style={styles.progressText}>
+ Q {qIndex + 1}/{TOTAL_QUESTIONS} · Score {score}
+ </Text>
+ </GlassPill>
+ </View>
+ );
+ }
+
+ // ---------------------------------------------------------------------------
+ // Phase renders
+ // ---------------------------------------------------------------------------
+
+ if (phase === 'loading') return <LoadingView />;
+ if (phase === 'error') return <ErrorView onRetry={fetchSignatures} />;
+
+ return (
+ <ScrollView
+ style={styles.root}
+ contentContainerStyle={styles.scroll}
+ showsVerticalScrollIndicator={false}
+ keyboardShouldPersistTaps="handled"
+ >
+ {/* ---- Game-over card (replaces quiz) ---- */}
+ {phase === 'over' ? (
+ <>
+ <GameOverCard
+ score={score}
+ onPlayAgain={handlePlayAgain}
+ />
+ <LeaderboardPanel rows={leaderRows} loading={leaderLoading} />
+ </>
+ ) : (
+ <>
+ {/* ---- Progress pill ---- */}
+ {renderProgress()}
+
+ {/* ---- Signature image panel ---- */}
+ {currentQuestion && (
+ <View style={styles.sigWrap}>
+ <GlassPanel
+ style={styles.sigPanel}
+ intensity={18}
+ tint="light" // parchment-tinted (light tint over gold gradient)
+ >
+ <CorrectFlash visible={correctFlash} />
+ <Image
+ source={{ uri: currentQuestion.signature.signature_image_url }}
+ style={styles.sigImage}
+ resizeMode="contain"
+ accessibilityLabel="A handwritten signature — whose is it?"
+ />
+ </GlassPanel>
+ </View>
+ )}
+
+ {/* ---- Category hint ---- */}
+ {currentQuestion && (
+ <View style={styles.categoryRow}>
+ <GlassPill tintColor="rgba(201,168,106,0.18)">
+ <Text style={styles.categoryText}>
+ {currentQuestion.signature.category}
+ </Text>
+ </GlassPill>
+ </View>
+ )}
+
+ {/* ---- Wrong-answer reveal label ---- */}
+ {feedback === 'wrong' && currentQuestion && (
+ <Text style={styles.revealText}>
+ That's {currentQuestion.signature.full_name}
+ </Text>
+ )}
+
+ {/* ---- Answer buttons ---- */}
+ <View style={styles.choicesWrap}>
+ {renderChoiceButtons()}
+ </View>
+
+ {/* ---- Leaderboard ---- */}
+ <LeaderboardPanel rows={leaderRows} loading={leaderLoading} />
+ </>
+ )}
+ </ScrollView>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Styles
+// ---------------------------------------------------------------------------
+
+const styles = StyleSheet.create({
+ root: {
+ flex: 1,
+ },
+ scroll: {
+ paddingHorizontal: 18,
+ paddingTop: 20,
+ paddingBottom: 48,
+ gap: 16,
+ },
+
+ // Loading / error
+ centeredFill: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ gap: 16,
+ padding: 32,
+ },
+ dimText: {
+ color: GLASS.textDim,
+ fontSize: 15,
+ textAlign: 'center',
+ },
+ errorText: {
+ color: '#e05c5c',
+ fontSize: 14,
+ textAlign: 'center',
+ },
+ retryBtn: {
+ width: 160,
+ },
+
+ // Progress
+ progressRow: {
+ alignItems: 'center',
+ },
+ progressText: {
+ color: GLASS.accentSoft,
+ fontSize: 14,
+ fontWeight: '600',
+ letterSpacing: 0.4,
+ },
+
+ // Signature image
+ sigWrap: {
+ borderRadius: 22,
+ // Warm parchment shadow to sell the physical-paper feel
+ shadowColor: GLASS.accent,
+ shadowOffset: { width: 0, height: 8 },
+ shadowOpacity: 0.22,
+ shadowRadius: 24,
+ elevation: 10,
+ },
+ sigPanel: {
+ // override panelBody padding is via children — the GlassPanel adds 18px padding internally
+ },
+ sigImage: {
+ width: '100%',
+ height: 200,
+ // Slight warm tint is applied via the GlassPanel light tint
+ },
+
+ // Category
+ categoryRow: {
+ alignItems: 'center',
+ },
+ categoryText: {
+ color: GLASS.textDim,
+ fontSize: 13,
+ fontWeight: '500',
+ letterSpacing: 0.6,
+ textTransform: 'uppercase',
+ },
+
+ // Wrong reveal
+ revealText: {
+ color: GLASS.accent,
+ fontSize: 16,
+ fontWeight: '700',
+ textAlign: 'center',
+ letterSpacing: 0.2,
+ marginVertical: 4,
+ },
+
+ // Choices
+ choicesWrap: {
+ gap: 10,
+ },
+ choiceBtn: {
+ // no extra style — GlassButton fills full width via its own styles
+ },
+ // Tinted override pill (correct / wrong state)
+ choiceOverrideWrap: {
+ borderRadius: 999,
+ overflow: 'hidden',
+ },
+ choiceOverridePill: {
+ borderRadius: 999,
+ paddingVertical: 16,
+ paddingHorizontal: 20,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ choiceOverrideText: {
+ fontSize: 17,
+ fontWeight: '700',
+ letterSpacing: 0.2,
+ textAlign: 'center',
+ },
+
+ // Game-over
+ gameOverPanel: {
+ gap: 14,
+ },
+ gameOverTitle: {
+ color: GLASS.accentSoft,
+ fontSize: 26,
+ fontWeight: '800',
+ textAlign: 'center',
+ letterSpacing: 0.4,
+ },
+ scoreRow: {
+ alignItems: 'center',
+ },
+ finalScoreText: {
+ color: GLASS.ink,
+ fontSize: 22,
+ fontWeight: '800',
+ letterSpacing: 0.5,
+ },
+ rankText: {
+ color: GLASS.accent,
+ fontSize: 18,
+ fontWeight: '700',
+ textAlign: 'center',
+ marginTop: 4,
+ },
+ nameInput: {
+ borderRadius: 14,
+ borderWidth: StyleSheet.hairlineWidth,
+ borderColor: GLASS.edge,
+ backgroundColor: 'rgba(255,255,255,0.06)',
+ color: GLASS.accentSoft,
+ fontSize: 17,
+ paddingHorizontal: 16,
+ paddingVertical: 13,
+ marginTop: 4,
+ },
+ submitBtn: {
+ marginTop: 4,
+ },
+ playAgainBtn: {
+ marginTop: 4,
+ },
+
+ // Leaderboard
+ leaderPanel: {
+ gap: 10,
+ },
+ sectionTitle: {
+ color: GLASS.accent,
+ fontSize: 16,
+ fontWeight: '700',
+ letterSpacing: 0.6,
+ textTransform: 'uppercase',
+ marginBottom: 2,
+ },
+ leaderRow: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 8,
+ },
+ leaderRank: {
+ color: GLASS.textDim,
+ fontSize: 14,
+ fontWeight: '600',
+ width: 22,
+ },
+ leaderName: {
+ flex: 1,
+ color: GLASS.accentSoft,
+ fontSize: 15,
+ fontWeight: '500',
+ },
+ leaderScore: {
+ color: GLASS.ink,
+ fontSize: 14,
+ fontWeight: '700',
+ },
+});
diff --git a/apps/mobile/screens/MuralsScreen.tsx b/apps/mobile/screens/MuralsScreen.tsx
new file mode 100644
index 0000000..1cd418d
--- /dev/null
+++ b/apps/mobile/screens/MuralsScreen.tsx
@@ -0,0 +1,532 @@
+// MuralsScreen.tsx
+//
+// App Store compliance note (Guideline 3.1.3(e)):
+// Mural prints are PHYSICAL GOODS — IAP-exempt under 3.1.3(e). Checkout is
+// Stripe-hosted (redirect-based), so the full purchase flow opens the website
+// via onOpenWeb(). Do NOT implement native card payment here; that would pull
+// the transaction under App Store billing rules unnecessarily.
+//
+// Usage:
+// <MuralsScreen onOpenWeb={(url) => Linking.openURL(url)} />
+
+import React, { useCallback, useEffect, useRef, useState } from 'react';
+import {
+ ActivityIndicator,
+ FlatList,
+ KeyboardAvoidingView,
+ ListRenderItemInfo,
+ Platform,
+ Pressable,
+ ScrollView,
+ StyleSheet,
+ Text,
+ TextInput,
+ TouchableWithoutFeedback,
+ View,
+} from 'react-native';
+import * as Haptics from 'expo-haptics';
+import { api, Mural, MuralsCatalog, WEB_BASE } from '../api';
+import { GLASS, GlassButton, GlassPanel, GlassPill } from '../ui/glass';
+
+// ---------------------------------------------------------------------------
+// Types
+// ---------------------------------------------------------------------------
+
+type QuoteState =
+ | { phase: 'idle' }
+ | { phase: 'open'; name: string; email: string; note: string; busy: boolean; error: string | null }
+ | { phase: 'done' };
+
+// ---------------------------------------------------------------------------
+// Helpers
+// ---------------------------------------------------------------------------
+
+const MAX_ROSTER_VISIBLE = 4;
+
+function rosterLine(roster: string[]): string {
+ if (roster.length <= MAX_ROSTER_VISIBLE) {
+ return `Featuring: ${roster.join(', ')}`;
+ }
+ const shown = roster.slice(0, MAX_ROSTER_VISIBLE).join(', ');
+ const extra = roster.length - MAX_ROSTER_VISIBLE;
+ return `Featuring: ${shown} +${extra} more`;
+}
+
+function looslyValidEmail(v: string): boolean {
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v.trim());
+}
+
+// ---------------------------------------------------------------------------
+// Inline inquiry form (expands inside the card)
+// ---------------------------------------------------------------------------
+
+function InquiryForm({ mural, onClose }: { mural: Mural; onClose: () => void }) {
+ const [name, setName] = useState('');
+ const [email, setEmail] = useState('');
+ const [note, setNote] = useState('');
+ const [busy, setBusy] = useState(false);
+ const [error, setError] = useState<string | null>(null);
+ const [done, setDone] = useState(false);
+
+ const emailRef = useRef<TextInput>(null);
+ const noteRef = useRef<TextInput>(null);
+
+ const handleSubmit = useCallback(async () => {
+ if (!name.trim()) { setError('Name is required.'); return; }
+ if (!looslyValidEmail(email)) { setError('Enter a valid email address.'); return; }
+ setError(null);
+ setBusy(true);
+ try {
+ const res = await api.muralOrder({ name: name.trim(), email: email.trim(), mural: mural.code, note: note.trim() || undefined });
+ if (res.ok) {
+ setDone(true);
+ } else {
+ setError('Something went wrong — please try again.');
+ }
+ } catch {
+ setError('Network error — please try again.');
+ } finally {
+ setBusy(false);
+ }
+ }, [name, email, note, mural.code]);
+
+ if (done) {
+ return (
+ <View style={styles.formDone}>
+ <Text style={styles.formDoneText}>Request sent ✓</Text>
+ <Text style={styles.formDoneSubtext}>We'll be in touch about your {mural.title} print.</Text>
+ <Pressable onPress={onClose} style={styles.formDismissBtn}>
+ <Text style={styles.formDismissText}>Close</Text>
+ </Pressable>
+ </View>
+ );
+ }
+
+ return (
+ <View style={styles.form}>
+ <Text style={styles.formHeading}>Request a quote</Text>
+
+ <Text style={styles.fieldLabel}>Your name</Text>
+ <TextInput
+ style={styles.input}
+ placeholder="Full name"
+ placeholderTextColor={GLASS.textDim}
+ value={name}
+ onChangeText={setName}
+ autoCapitalize="words"
+ returnKeyType="next"
+ onSubmitEditing={() => emailRef.current?.focus()}
+ blurOnSubmit={false}
+ editable={!busy}
+ />
+
+ <Text style={styles.fieldLabel}>Email</Text>
+ <TextInput
+ ref={emailRef}
+ style={styles.input}
+ placeholder="you@example.com"
+ placeholderTextColor={GLASS.textDim}
+ value={email}
+ onChangeText={setEmail}
+ autoCapitalize="none"
+ autoCorrect={false}
+ keyboardType="email-address"
+ returnKeyType="next"
+ onSubmitEditing={() => noteRef.current?.focus()}
+ blurOnSubmit={false}
+ editable={!busy}
+ />
+
+ <Text style={styles.fieldLabel}>Note (optional)</Text>
+ <TextInput
+ ref={noteRef}
+ style={[styles.input, styles.inputMulti]}
+ placeholder="Room dimensions, timeline, special requests…"
+ placeholderTextColor={GLASS.textDim}
+ value={note}
+ onChangeText={setNote}
+ multiline
+ numberOfLines={3}
+ returnKeyType="done"
+ editable={!busy}
+ />
+
+ {error !== null && <Text style={styles.errorText}>{error}</Text>}
+
+ <View style={styles.formActions}>
+ <View style={styles.formActionBtn}>
+ <GlassButton
+ label="Submit"
+ solid
+ busy={busy}
+ onPress={handleSubmit}
+ />
+ </View>
+ <View style={styles.formActionBtn}>
+ <GlassButton
+ label="Cancel"
+ onPress={onClose}
+ disabled={busy}
+ />
+ </View>
+ </View>
+ </View>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Individual mural card
+// ---------------------------------------------------------------------------
+
+function MuralCard({
+ mural,
+ onOrderWeb,
+}: {
+ mural: Mural;
+ onOrderWeb: (url: string) => void;
+}) {
+ const [quoteOpen, setQuoteOpen] = useState(false);
+
+ const handleOrder = useCallback(async () => {
+ await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
+ onOrderWeb(`${WEB_BASE}/murals?mural=${encodeURIComponent(mural.code)}`);
+ }, [mural.code, onOrderWeb]);
+
+ const handleQuoteToggle = useCallback(() => {
+ setQuoteOpen((v) => !v);
+ }, []);
+
+ const handleQuoteClose = useCallback(() => {
+ setQuoteOpen(false);
+ }, []);
+
+ return (
+ <GlassPanel style={styles.card}>
+ {/* Header row */}
+ <View style={styles.cardHeader}>
+ <Text style={styles.cardTitle}>{mural.title}</Text>
+ {mural.sigs !== undefined && (
+ <GlassPill tintColor={GLASS.accent}>
+ <Text style={styles.pillText}>{mural.sigs} signature{mural.sigs !== 1 ? 's' : ''}</Text>
+ </GlassPill>
+ )}
+ </View>
+
+ {/* Blurb */}
+ {mural.blurb !== undefined && (
+ <Text style={styles.cardBlurb}>{mural.blurb}</Text>
+ )}
+
+ {/* Roster */}
+ {mural.roster !== undefined && mural.roster.length > 0 && (
+ <Text style={styles.cardRoster} numberOfLines={2}>
+ {rosterLine(mural.roster)}
+ </Text>
+ )}
+
+ {/* Action buttons */}
+ {!quoteOpen && (
+ <View style={styles.cardActions}>
+ <View style={styles.cardActionBtn}>
+ <GlassButton
+ label="Order print (on web)"
+ solid
+ onPress={handleOrder}
+ />
+ </View>
+ <View style={styles.cardActionBtn}>
+ <GlassButton
+ label="Request a quote"
+ onPress={handleQuoteToggle}
+ />
+ </View>
+ </View>
+ )}
+
+ {/* Inline inquiry form */}
+ {quoteOpen && (
+ <InquiryForm mural={mural} onClose={handleQuoteClose} />
+ )}
+ </GlassPanel>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Main screen
+// ---------------------------------------------------------------------------
+
+export default function MuralsScreen({ onOpenWeb }: { onOpenWeb: (url: string) => void }) {
+ const [catalog, setCatalog] = useState<MuralsCatalog | null>(null);
+ const [loading, setLoading] = useState(true);
+ const [fetchError, setFetchError] = useState<string | null>(null);
+
+ const loadCatalog = useCallback(async () => {
+ setLoading(true);
+ setFetchError(null);
+ try {
+ const data = await api.murals();
+ setCatalog(data);
+ } catch (e) {
+ setFetchError(e instanceof Error ? e.message : 'Failed to load murals.');
+ } finally {
+ setLoading(false);
+ }
+ }, []);
+
+ useEffect(() => { loadCatalog(); }, [loadCatalog]);
+
+ const renderItem = useCallback(
+ ({ item }: ListRenderItemInfo<Mural>) => (
+ <MuralCard mural={item} onOrderWeb={onOpenWeb} />
+ ),
+ [onOpenWeb],
+ );
+
+ const keyExtractor = useCallback((item: Mural) => item.code, []);
+
+ // Caption derived from catalog metadata
+ const caption = catalog !== null
+ ? `From $${catalog.pricePerSqFt}/sq ft · ${catalog.size.widthFt}×${catalog.size.heightFt} ft standard`
+ : null;
+
+ // ---------------------------------------------------------------------------
+ // Loading
+ // ---------------------------------------------------------------------------
+ if (loading) {
+ return (
+ <View style={styles.centeredFill}>
+ <ActivityIndicator color={GLASS.accent} size="large" />
+ <Text style={styles.loadingText}>Loading murals…</Text>
+ </View>
+ );
+ }
+
+ // ---------------------------------------------------------------------------
+ // Error + retry
+ // ---------------------------------------------------------------------------
+ if (fetchError !== null || catalog === null) {
+ return (
+ <View style={styles.centeredFill}>
+ <Text style={styles.errorHeading}>Couldn't load murals</Text>
+ <Text style={styles.errorBody}>{fetchError ?? 'Unknown error'}</Text>
+ <View style={styles.retryBtn}>
+ <GlassButton label="Retry" solid onPress={loadCatalog} />
+ </View>
+ </View>
+ );
+ }
+
+ // ---------------------------------------------------------------------------
+ // Render
+ // ---------------------------------------------------------------------------
+ return (
+ <KeyboardAvoidingView
+ style={styles.root}
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
+ keyboardVerticalOffset={Platform.OS === 'ios' ? 88 : 0}
+ >
+ <FlatList<Mural>
+ data={catalog.murals}
+ keyExtractor={keyExtractor}
+ renderItem={renderItem}
+ contentContainerStyle={styles.listContent}
+ ListHeaderComponent={
+ <View style={styles.listHeader}>
+ <Text style={styles.headerTitle}>Signature Murals</Text>
+ {caption !== null && (
+ <Text style={styles.headerCaption}>{caption}</Text>
+ )}
+ </View>
+ }
+ showsVerticalScrollIndicator={false}
+ keyboardShouldPersistTaps="handled"
+ />
+ </KeyboardAvoidingView>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Styles
+// ---------------------------------------------------------------------------
+
+const styles = StyleSheet.create({
+ root: {
+ flex: 1,
+ },
+
+ // Full-screen states
+ centeredFill: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ paddingHorizontal: 32,
+ gap: 12,
+ },
+ loadingText: {
+ color: GLASS.textDim,
+ fontSize: 15,
+ marginTop: 12,
+ },
+ errorHeading: {
+ color: GLASS.accentSoft,
+ fontSize: 18,
+ fontWeight: '700',
+ textAlign: 'center',
+ },
+ errorBody: {
+ color: GLASS.textDim,
+ fontSize: 14,
+ textAlign: 'center',
+ lineHeight: 20,
+ },
+ retryBtn: {
+ width: 180,
+ marginTop: 8,
+ },
+
+ // List layout
+ listContent: {
+ paddingHorizontal: 16,
+ paddingBottom: 48,
+ gap: 14,
+ },
+ listHeader: {
+ paddingTop: 20,
+ paddingBottom: 8,
+ gap: 4,
+ },
+ headerTitle: {
+ color: GLASS.accentSoft,
+ fontSize: 26,
+ fontWeight: '800',
+ letterSpacing: 0.3,
+ },
+ headerCaption: {
+ color: GLASS.textDim,
+ fontSize: 13,
+ letterSpacing: 0.1,
+ },
+
+ // Card
+ card: {
+ // GlassPanel adds its own border + borderRadius; we just need margin spacing
+ },
+ cardHeader: {
+ flexDirection: 'row',
+ alignItems: 'flex-start',
+ justifyContent: 'space-between',
+ gap: 10,
+ marginBottom: 6,
+ },
+ cardTitle: {
+ flex: 1,
+ color: GLASS.accentSoft,
+ fontSize: 17,
+ fontWeight: '700',
+ lineHeight: 22,
+ },
+ pillText: {
+ color: GLASS.ink,
+ fontSize: 11,
+ fontWeight: '700',
+ letterSpacing: 0.3,
+ },
+ cardBlurb: {
+ color: GLASS.textDim,
+ fontSize: 13,
+ lineHeight: 19,
+ marginBottom: 6,
+ },
+ cardRoster: {
+ color: GLASS.textDim,
+ fontSize: 12,
+ lineHeight: 17,
+ fontStyle: 'italic',
+ marginBottom: 10,
+ },
+
+ // Card actions
+ cardActions: {
+ marginTop: 10,
+ gap: 8,
+ },
+ cardActionBtn: {
+ // GlassButton is full-width inside its parent by default
+ },
+
+ // Inquiry form
+ form: {
+ marginTop: 12,
+ gap: 4,
+ },
+ formHeading: {
+ color: GLASS.accentSoft,
+ fontSize: 15,
+ fontWeight: '700',
+ marginBottom: 8,
+ },
+ fieldLabel: {
+ color: GLASS.textDim,
+ fontSize: 11,
+ fontWeight: '600',
+ letterSpacing: 0.5,
+ textTransform: 'uppercase',
+ marginTop: 8,
+ marginBottom: 4,
+ },
+ input: {
+ backgroundColor: 'rgba(255,255,255,0.06)',
+ borderRadius: 10,
+ borderWidth: StyleSheet.hairlineWidth,
+ borderColor: 'rgba(255,255,255,0.14)',
+ paddingHorizontal: 13,
+ paddingVertical: Platform.OS === 'ios' ? 12 : 9,
+ color: GLASS.accentSoft,
+ fontSize: 15,
+ },
+ inputMulti: {
+ minHeight: 72,
+ textAlignVertical: 'top',
+ paddingTop: 10,
+ },
+ errorText: {
+ color: '#e07070',
+ fontSize: 12,
+ marginTop: 6,
+ lineHeight: 16,
+ },
+ formActions: {
+ marginTop: 14,
+ gap: 8,
+ },
+ formActionBtn: {},
+
+ // Done state
+ formDone: {
+ marginTop: 12,
+ alignItems: 'center',
+ gap: 6,
+ paddingVertical: 8,
+ },
+ formDoneText: {
+ color: GLASS.accent,
+ fontSize: 18,
+ fontWeight: '800',
+ },
+ formDoneSubtext: {
+ color: GLASS.textDim,
+ fontSize: 13,
+ textAlign: 'center',
+ lineHeight: 18,
+ },
+ formDismissBtn: {
+ marginTop: 8,
+ paddingVertical: 6,
+ paddingHorizontal: 20,
+ },
+ formDismissText: {
+ color: GLASS.accentSoft,
+ fontSize: 14,
+ fontWeight: '600',
+ },
+});
diff --git a/apps/mobile/screens/SignatureDetail.tsx b/apps/mobile/screens/SignatureDetail.tsx
new file mode 100644
index 0000000..5ee9b7f
--- /dev/null
+++ b/apps/mobile/screens/SignatureDetail.tsx
@@ -0,0 +1,294 @@
+// SignatureDetail — full detail view for one signature.
+// The App wraps this in a Modal with its own GlassBar top chrome;
+// this component is just the scrollable body content.
+// Usage: <SignatureDetail sig={sig} evolution={ev} onOrderMural={(sig) => …} />
+import React, { useCallback } from 'react';
+import {
+ Image,
+ ScrollView,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
+import * as Haptics from 'expo-haptics';
+
+import { qidOf, Signature, Evolution } from '../api';
+import { GLASS, GlassPanel, GlassButton, GlassPill } from '../ui/glass';
+
+// ---------------------------------------------------------------------------
+// Sub-components
+// ---------------------------------------------------------------------------
+
+function MuseumChips({ museums }: { museums: string[] }) {
+ return (
+ <View style={styles.chipWrap}>
+ {museums.map((m) => (
+ <GlassPill key={m} style={styles.museumPill}>
+ <Text style={styles.museumLabel}>{m}</Text>
+ </GlassPill>
+ ))}
+ </View>
+ );
+}
+
+function EvolutionReel({
+ sigs,
+}: {
+ sigs: NonNullable<Evolution[string]>['sigs'];
+}) {
+ // Only render entries that have a URL; year may be null (skip caption then)
+ const items = sigs.filter((s) => Boolean(s.url));
+ if (items.length === 0) return null;
+ return (
+ <View style={styles.section}>
+ <Text style={styles.sectionTitle}>Signature over time</Text>
+ <ScrollView
+ horizontal
+ showsHorizontalScrollIndicator={false}
+ contentContainerStyle={styles.reelRow}
+ >
+ {items.map((entry, i) => (
+ <View key={entry.url ?? i} style={styles.reelItem}>
+ <View style={styles.reelImgBacking}>
+ <Image
+ source={{ uri: entry.url }}
+ style={styles.reelImg}
+ resizeMode="contain"
+ />
+ </View>
+ {entry.year != null && (
+ <Text style={styles.reelYear}>{String(entry.year)}</Text>
+ )}
+ </View>
+ ))}
+ </ScrollView>
+ </View>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Main component
+// ---------------------------------------------------------------------------
+
+export default function SignatureDetail({
+ sig,
+ evolution,
+ onOrderMural,
+}: {
+ sig: Signature;
+ evolution: Evolution | null;
+ onOrderMural: (sig: Signature) => void;
+}) {
+ const qid = qidOf(sig);
+ const evEntry = qid && evolution ? evolution[qid] ?? null : null;
+
+ const handleOrder = useCallback(() => {
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
+ onOrderMural(sig);
+ }, [sig, onOrderMural]);
+
+ return (
+ <ScrollView
+ style={styles.root}
+ contentContainerStyle={styles.content}
+ showsVerticalScrollIndicator={false}
+ >
+ {/* Hero signature image on parchment backing */}
+ <GlassPanel style={styles.heroPanel}>
+ <View style={styles.heroBacking}>
+ {sig.signature_image_url ? (
+ <Image
+ source={{ uri: sig.signature_image_url }}
+ style={styles.heroImg}
+ resizeMode="contain"
+ />
+ ) : (
+ <View style={styles.heroImgPlaceholder}>
+ <Text style={styles.placeholderText}>No image available</Text>
+ </View>
+ )}
+ </View>
+ </GlassPanel>
+
+ {/* Name + category + death date */}
+ <View style={styles.nameBlock}>
+ <Text style={styles.fullName}>{sig.full_name}</Text>
+ <Text style={styles.subCaption}>
+ {sig.category}
+ {sig.death_date ? ` · d. ${sig.death_date}` : ''}
+ </Text>
+ </View>
+
+ {/* Reason for ranking */}
+ {Boolean(sig.reason_for_ranking) && (
+ <View style={styles.section}>
+ <Text style={styles.reasonText}>{sig.reason_for_ranking}</Text>
+ </View>
+ )}
+
+ {/* Museums */}
+ {sig.museums && sig.museums.length > 0 && (
+ <View style={styles.section}>
+ <Text style={styles.sectionTitle}>In museum collections</Text>
+ <MuseumChips museums={sig.museums} />
+ </View>
+ )}
+
+ {/* Signature evolution reel */}
+ {evEntry && evEntry.sigs && evEntry.sigs.length > 0 && (
+ <EvolutionReel sigs={evEntry.sigs} />
+ )}
+
+ {/* Image credit */}
+ {(sig.image_author || sig.image_license) && (
+ <View style={styles.section}>
+ <Text style={styles.creditText}>
+ {[sig.image_author, sig.image_license].filter(Boolean).join(' · ')}
+ </Text>
+ </View>
+ )}
+
+ {/* CTA */}
+ <View style={styles.ctaWrap}>
+ <GlassButton
+ label="Order a mural featuring this signature"
+ onPress={handleOrder}
+ solid
+ />
+ </View>
+ </ScrollView>
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Styles
+// ---------------------------------------------------------------------------
+
+const styles = StyleSheet.create({
+ root: {
+ flex: 1,
+ },
+ content: {
+ paddingHorizontal: 16,
+ paddingTop: 8,
+ paddingBottom: 48,
+ gap: 20,
+ },
+
+ // Hero
+ heroPanel: {
+ // GlassPanel adds borderRadius + panelBody padding
+ },
+ heroBacking: {
+ backgroundColor: 'rgba(232,217,184,0.07)',
+ borderRadius: 12,
+ height: 200,
+ alignItems: 'center',
+ justifyContent: 'center',
+ overflow: 'hidden',
+ },
+ heroImg: {
+ width: '100%',
+ height: '100%',
+ },
+ heroImgPlaceholder: {
+ flex: 1,
+ width: '100%',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ placeholderText: {
+ color: GLASS.textDim,
+ fontSize: 14,
+ },
+
+ // Name block
+ nameBlock: {
+ gap: 6,
+ },
+ fullName: {
+ fontSize: 28,
+ fontWeight: '800',
+ color: GLASS.accentSoft,
+ letterSpacing: 0.1,
+ lineHeight: 34,
+ },
+ subCaption: {
+ fontSize: 14,
+ color: GLASS.textDim,
+ letterSpacing: 0.2,
+ },
+
+ // Sections
+ section: {
+ gap: 10,
+ },
+ sectionTitle: {
+ fontSize: 13,
+ fontWeight: '700',
+ color: GLASS.accent,
+ letterSpacing: 0.6,
+ textTransform: 'uppercase',
+ },
+ reasonText: {
+ fontSize: 15,
+ lineHeight: 23,
+ color: GLASS.textDim,
+ },
+
+ // Museum chips
+ chipWrap: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ gap: 8,
+ },
+ museumPill: {
+ // GlassPill handles its own clip/border
+ },
+ museumLabel: {
+ fontSize: 13,
+ fontWeight: '600',
+ color: GLASS.accentSoft,
+ },
+
+ // Evolution reel
+ reelRow: {
+ gap: 12,
+ paddingVertical: 4,
+ },
+ reelItem: {
+ alignItems: 'center',
+ gap: 6,
+ },
+ reelImgBacking: {
+ width: 120,
+ height: 80,
+ backgroundColor: 'rgba(232,217,184,0.07)',
+ borderRadius: 10,
+ overflow: 'hidden',
+ borderWidth: StyleSheet.hairlineWidth,
+ borderColor: GLASS.edgeFaint,
+ },
+ reelImg: {
+ width: '100%',
+ height: '100%',
+ },
+ reelYear: {
+ fontSize: 12,
+ color: GLASS.textDim,
+ letterSpacing: 0.2,
+ },
+
+ // Credit
+ creditText: {
+ fontSize: 11,
+ color: GLASS.textDim,
+ opacity: 0.7,
+ letterSpacing: 0.15,
+ },
+
+ // CTA
+ ctaWrap: {
+ marginTop: 4,
+ },
+});
diff --git a/apps/mobile/tsconfig.json b/apps/mobile/tsconfig.json
new file mode 100644
index 0000000..a0863d0
--- /dev/null
+++ b/apps/mobile/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "expo/tsconfig.base",
+ "compilerOptions": {
+ "strict": true,
+ "jsx": "react-jsx"
+ }
+}
diff --git a/apps/mobile/ui/glass.tsx b/apps/mobile/ui/glass.tsx
new file mode 100644
index 0000000..a40d992
--- /dev/null
+++ b/apps/mobile/ui/glass.tsx
@@ -0,0 +1,166 @@
+import React from 'react';
+import {
+ ActivityIndicator, Platform, Pressable, StyleSheet, Text, View, ViewStyle,
+} from 'react-native';
+import { BlurView } from 'expo-blur';
+import { LinearGradient } from 'expo-linear-gradient';
+
+// Liquid Glass primitives (reused from the Charge & Explore app, recolored to a
+// museum charcoal-and-gold palette for the signatures gallery). Every surface is
+// a real BlurView refracting the gradient scene behind it — not a faked rgba fill
+// — with a specular top edge so panels read as curved glass. Android's BlurView
+// needs the experimental method or it silently renders a gray slab.
+
+export const GLASS = {
+ ink: '#141210',
+ inkDeep: '#0d0b0a',
+ emerald: '#2a2118', // warm brown mid-tone for the scene gradient
+ accent: '#c9a86a', // museum gold
+ accentSoft: '#e8d9b8', // parchment
+ textDim: '#a89f90',
+ edge: 'rgba(255,255,255,0.26)',
+ edgeFaint: 'rgba(255,255,255,0.11)',
+ sheen: 'rgba(255,255,255,0.08)',
+} as const;
+
+const blurProps = Platform.select({
+ android: { experimentalBlurMethod: 'dimezisBlurView' as const },
+ default: {},
+});
+
+/** Full-screen layered gradient the glass refracts. Place once at scene root. */
+export function GlassScene({ children, style }: { children: React.ReactNode; style?: ViewStyle }) {
+ return (
+ <LinearGradient
+ colors={[GLASS.ink, GLASS.inkDeep, GLASS.emerald]}
+ locations={[0, 0.55, 1]}
+ start={{ x: 0.1, y: 0 }}
+ end={{ x: 0.9, y: 1 }}
+ style={[styles.scene, style]}
+ >
+ {/* off-center warm-gold glow orb gives the blur a light source to bend */}
+ <LinearGradient
+ colors={['rgba(201,168,106,0.26)', 'rgba(201,168,106,0)']}
+ style={styles.orb}
+ pointerEvents="none"
+ />
+ {children}
+ </LinearGradient>
+ );
+}
+
+/** Frosted panel — the base glass slab (cards, hero, sections). */
+export function GlassPanel({
+ children, style, intensity = 28, tint = 'dark',
+}: {
+ children: React.ReactNode; style?: ViewStyle; intensity?: number;
+ tint?: 'dark' | 'light';
+}) {
+ return (
+ <View style={[styles.panelClip, style]}>
+ <BlurView intensity={intensity} tint={tint} style={StyleSheet.absoluteFill} {...blurProps} />
+ <View style={styles.sheenTop} pointerEvents="none" />
+ <View style={styles.panelBody}>{children}</View>
+ </View>
+ );
+}
+
+/** Capsule glass button. solid=accent-filled call to action; else clear glass. */
+export function GlassButton({
+ label, onPress, solid = false, busy = false, disabled = false,
+}: {
+ label: string; onPress: () => void; solid?: boolean; busy?: boolean; disabled?: boolean;
+}) {
+ return (
+ <Pressable onPress={onPress} disabled={disabled || busy}
+ style={({ pressed }) => [styles.btnClip, pressed && styles.btnPressed]}>
+ <BlurView intensity={solid ? 50 : 26} tint="dark" style={StyleSheet.absoluteFill} {...blurProps} />
+ {solid && (
+ <LinearGradient
+ colors={['rgba(201,168,106,0.95)', 'rgba(176,142,84,0.92)']}
+ style={StyleSheet.absoluteFill}
+ />
+ )}
+ <View style={styles.sheenTop} pointerEvents="none" />
+ {busy
+ ? <ActivityIndicator color={solid ? GLASS.ink : GLASS.accent} />
+ : <Text style={[styles.btnText, solid ? styles.btnTextSolid : styles.btnTextGlass]}>{label}</Text>}
+ </Pressable>
+ );
+}
+
+/** Small glass pill (score chips, status tags). tintColor washes the glass. */
+export function GlassPill({
+ children, tintColor, style,
+}: { children: React.ReactNode; tintColor?: string; style?: ViewStyle }) {
+ return (
+ <View style={[styles.pillClip, style]}>
+ <BlurView intensity={30} tint="dark" style={StyleSheet.absoluteFill} {...blurProps} />
+ {tintColor && <View style={[StyleSheet.absoluteFill, { backgroundColor: tintColor, opacity: 0.55 }]} />}
+ <View style={styles.sheenTop} pointerEvents="none" />
+ <View style={styles.pillBody}>{children}</View>
+ </View>
+ );
+}
+
+/** Modal top chrome — floating glass bar with Done + centered title. */
+export function GlassBar({
+ title, onDone, light = false,
+}: { title: string; onDone: () => void; light?: boolean }) {
+ return (
+ <View style={styles.barClip}>
+ <BlurView intensity={40} tint={light ? 'light' : 'dark'} style={StyleSheet.absoluteFill} {...blurProps} />
+ <View style={styles.sheenTop} pointerEvents="none" />
+ <View style={styles.barRow}>
+ <Pressable onPress={onDone} hitSlop={12}>
+ <Text style={[styles.barDone, light && styles.barDoneLight]}>Done</Text>
+ </Pressable>
+ <Text style={[styles.barTitle, light && styles.barTitleLight]}>{title}</Text>
+ <View style={{ width: 44 }} />
+ </View>
+ </View>
+ );
+}
+
+const styles = StyleSheet.create({
+ scene: { flex: 1 },
+ orb: {
+ position: 'absolute', top: -120, right: -100,
+ width: 340, height: 340, borderRadius: 170,
+ },
+ panelClip: {
+ borderRadius: 22, overflow: 'hidden',
+ borderWidth: StyleSheet.hairlineWidth, borderColor: GLASS.edgeFaint,
+ },
+ panelBody: { padding: 18 },
+ sheenTop: {
+ position: 'absolute', top: 0, left: 0, right: 0, height: 1.5,
+ backgroundColor: GLASS.edge,
+ },
+ btnClip: {
+ borderRadius: 999, overflow: 'hidden',
+ borderWidth: StyleSheet.hairlineWidth, borderColor: GLASS.edge,
+ paddingVertical: 16, alignItems: 'center', justifyContent: 'center',
+ },
+ btnPressed: { transform: [{ scale: 0.98 }], opacity: 0.9 },
+ btnText: { fontSize: 17, fontWeight: '700', letterSpacing: 0.2 },
+ btnTextSolid: { color: GLASS.ink },
+ btnTextGlass: { color: GLASS.accentSoft },
+ pillClip: {
+ borderRadius: 999, overflow: 'hidden',
+ borderWidth: StyleSheet.hairlineWidth, borderColor: GLASS.edgeFaint,
+ },
+ pillBody: { paddingHorizontal: 10, paddingVertical: 5, alignItems: 'center' },
+ barClip: {
+ marginHorizontal: 12, marginTop: 6, borderRadius: 999, overflow: 'hidden',
+ borderWidth: StyleSheet.hairlineWidth, borderColor: GLASS.edgeFaint,
+ },
+ barRow: {
+ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between',
+ paddingHorizontal: 18, paddingVertical: 12,
+ },
+ barDone: { color: GLASS.accent, fontSize: 16, fontWeight: '600', width: 44 },
+ barDoneLight: { color: '#141210' },
+ barTitle: { fontSize: 16, fontWeight: '700', color: '#fff' },
+ barTitleLight: { color: '#141210' },
+});
diff --git a/apps/mobile/ui/no-track.ts b/apps/mobile/ui/no-track.ts
new file mode 100644
index 0000000..e46dbf7
--- /dev/null
+++ b/apps/mobile/ui/no-track.ts
@@ -0,0 +1,50 @@
+// Injected into every in-app WebView BEFORE page content loads, so the App
+// Store binary performs NO ad/analytics tracking (App Privacy = "not used to
+// track you", so no ATT prompt is required). The public website keeps its
+// AdSense/analytics; only the native app is clean. (Reused verbatim from the
+// Charge & Explore app — same Google ad/analytics script set to block.)
+export const NO_TRACK = `
+(function () {
+ try {
+ window.__IN_APP_NO_ADS__ = true;
+ window.adsbygoogle = { loaded: true, push: function () {} };
+ window.gtag = function () {};
+ window.dataLayer = window.dataLayer || [];
+ window.dataLayer.push = function () {};
+ var BLOCK = /googlesyndication|pagead2|adsbygoogle|doubleclick|google-analytics|googletagmanager|gtag\\/js/i;
+ var origCreate = document.createElement.bind(document);
+ document.createElement = function (tag) {
+ var el = origCreate(tag);
+ if (String(tag).toLowerCase() === 'script') {
+ try {
+ var d = Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype, 'src');
+ Object.defineProperty(el, 'src', {
+ configurable: true,
+ get: function () { return d.get.call(this); },
+ set: function (v) { if (BLOCK.test(String(v))) return; d.set.call(this, v); },
+ });
+ var setAttr = el.setAttribute.bind(el);
+ el.setAttribute = function (name, value) {
+ if (String(name).toLowerCase() === 'src' && BLOCK.test(String(value))) return;
+ return setAttr(name, value);
+ };
+ } catch (e) {}
+ }
+ return el;
+ };
+ var kill = function (n) {
+ if (n && n.tagName === 'SCRIPT') {
+ var src = n.src || (n.getAttribute && n.getAttribute('src')) || '';
+ if (BLOCK.test(String(src))) { try { n.type = 'javascript/blocked'; } catch (e) {} try { n.remove(); } catch (e) {} }
+ }
+ };
+ new MutationObserver(function (muts) {
+ for (var i = 0; i < muts.length; i++) {
+ var an = muts[i].addedNodes || [];
+ for (var j = 0; j < an.length; j++) kill(an[j]);
+ }
+ }).observe(document.documentElement || document, { childList: true, subtree: true });
+ } catch (e) {}
+})();
+true;
+`;
← 77c8879 backend: add POST /api/auth/delete (Apple 5.1.1(v) account d
·
back to CelebritySignatures
·
iOS: wire the 3.1.1 WebView guard + fix evolution-load side fc65300 →