[object Object]

← 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

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 →