@stacksjs/mobile 0.75.154 → 0.75.156

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -116,6 +116,39 @@ if (health.supports('getHeartRateSamples')) {
116
116
  }
117
117
  ```
118
118
 
119
+ ## Heart-rate strap
120
+
121
+ `heartRate` reads a Bluetooth heart-rate strap (Polar, Garmin, Wahoo), or a
122
+ watch broadcasting its heart rate, through the standard Heart Rate Service.
123
+ `scan` finds straps nearby (`onDevice` hears each), `connect(id)` subscribes
124
+ to its readings (`onReading`: bpm and RR intervals, about once a second) and
125
+ remembers it, so `reconnect()` finds it next time without a scan; a strap that
126
+ drops out is asked for again until `disconnect()`. `startRecording()` keeps
127
+ every reading natively, screen locked or app closed, until `stopRecording()`
128
+ hands them back. iOS only, behind `capabilities.heartRate` (which adds the
129
+ `bluetooth-central` background mode); Bluetooth needs no network.
130
+
131
+ ```ts
132
+ import { createRouteRecorder, heartRate, location } from '@stacksjs/mobile'
133
+
134
+ const stop = heartRate.onDevice(device => list.push(device)) // { id, name, rssi }
135
+ await heartRate.scan({ timeout: 15 }) // can show iOS's Bluetooth prompt
136
+ await heartRate.connect(list[0].id) // rejects TIMEOUT while still asking
137
+ heartRate.onReading(reading => show(reading.bpm))
138
+
139
+ // With a route: the strap records with it, and each fix gets its heart rate.
140
+ const recorder = createRouteRecorder({ location, heartRate })
141
+ await recorder.start()
142
+ const fixes = await recorder.stop() // fixes[i].heartRate
143
+ const samples = recorder.heartRate // every reading: { timestamp, bpm, rr? }
144
+ ```
145
+
146
+ Without a route, record it on its own (`heartRate.startRecording()` /
147
+ `stopRecording()`), and `attachHeartRate(fixes, samples)` pairs readings
148
+ with fixes recorded separately. In a browser and on Android `isAvailable()` is
149
+ false, the state says `available: false` and nothing fires. Word iOS's prompt
150
+ with `ios.usageDescriptions.NSBluetoothAlwaysUsageDescription`.
151
+
119
152
  ## Apple Music
120
153
 
121
154
  `music` shows what the Music app is playing (title, artist, album, a small
package/dist/index.d.ts CHANGED
@@ -83,6 +83,18 @@ declare const brightness: BrightnessApi;
83
83
  * fire. Music control is local to the phone, so it works offline.
84
84
  */
85
85
  declare const music: MusicApi;
86
+ /**
87
+ * A Bluetooth heart-rate strap (Polar, Garmin, Wahoo...), or a watch
88
+ * broadcasting its heart rate, through the standard Heart Rate Service. iOS
89
+ * only, in an app built with `capabilities.heartRate`: scan, connect (the
90
+ * strap is remembered; `reconnect()` finds it next time without a scan), a
91
+ * reading about once a second with its RR intervals, and a recording kept
92
+ * natively, so a workout's heart rate survives the screen being locked and the
93
+ * app being closed. Pass it to `createRouteRecorder({ heartRate })` to record
94
+ * it with a route. In a browser and on Android it is unavailable: the state
95
+ * says `available: false` and nothing fires. Bluetooth works offline.
96
+ */
97
+ declare const heartRate: HeartRateApi;
86
98
  /**
87
99
  * Short spoken cues ("Rest, 15 seconds"). In the app the voice ducks the
88
100
  * user's music and plays with the silent switch on; in a browser it falls back
@@ -437,6 +449,13 @@ declare interface TabRootHost {
437
449
  }
438
450
 
439
451
  // From: src/route.ts
452
+ /**
453
+ * The fixes with the heart rate of the reading nearest each one, when there
454
+ * is one within `maxGapMs`: a strap reads about once a second, a phone fixes
455
+ * about once a second, and neither waits for the other. A fix with no reading
456
+ * near it (the strap off, or not worn yet) keeps none.
457
+ */
458
+ declare function attachHeartRate<T extends RouteFix>(fixes: readonly T[], samples: readonly HeartRateSample[], maxGapMs?: unknown): T[];
440
459
  /** Great-circle distance between two fixes, metres. */
441
460
  declare function fixDistance(a: { latitude: number, longitude: number }, b: { latitude: number, longitude: number }): number;
442
461
  /** The fixes worth counting, oldest first: a known position, accurate enough. */
@@ -462,11 +481,14 @@ declare function speedLabel(metresPerSecond: number | null | undefined): string;
462
481
  * in front. Reading pauses with the page hidden; the recording does not.
463
482
  */
464
483
  declare function createRouteRecorder(options: RouteRecorderOptions): RouteRecorder;
484
+ /** A fix and a strap's reading further apart than this, ms, do not belong together. */
485
+ declare const HEART_RATE_MATCH_MS: 5000;
465
486
  /** Fixes further apart than this, seconds, are a break in the route (a pause). */
466
487
  declare const ROUTE_GAP_S: 30;
467
488
  /** A fix as Craft records it. */
468
489
  declare interface RouteFix extends Location {
469
490
  altitudeAccuracy?: number
491
+ heartRate?: number
470
492
  }
471
493
  declare interface RouteStats {
472
494
  distanceM: number
@@ -486,6 +508,7 @@ declare interface RouteRecorderOptions extends RouteStatsOptions {
486
508
  onUpdate?: (stats: RouteStats) => void
487
509
  location: LocationApi
488
510
  locationOptions?: LocationOptions
511
+ heartRate?: HeartRateRecordingApi
489
512
  }
490
513
  declare interface RouteRecorder {
491
514
  start: () => Promise<RouteStats>
@@ -496,6 +519,7 @@ declare interface RouteRecorder {
496
519
  refresh: () => Promise<RouteStats>
497
520
  dispose: () => void
498
521
  readonly stats: RouteStats
522
+ readonly heartRate: HeartRateSample[]
499
523
  }
500
524
 
501
525
  // From: src/session-clock.ts
@@ -1274,6 +1298,7 @@ declare interface MobileApi {
1274
1298
  keepAwake: KeepAwakeApi
1275
1299
  brightness: BrightnessApi
1276
1300
  music: MusicApi
1301
+ heartRate: HeartRateApi
1277
1302
  speech: SpeechApi
1278
1303
  network: NetworkApi
1279
1304
  pushNotifications: PushNotificationsApi
@@ -1487,6 +1512,70 @@ declare interface NowPlaying {
1487
1512
  declare interface MusicSkipOptions {
1488
1513
  restartAfter?: number
1489
1514
  }
1515
+ /** A heart-rate strap, or a watch broadcasting its heart rate. */
1516
+ declare interface HeartRateDevice {
1517
+ id: string
1518
+ name: string
1519
+ rssi: number | null
1520
+ }
1521
+ declare interface HeartRateRecordingState {
1522
+ id: string | null
1523
+ active: boolean
1524
+ paused: boolean
1525
+ startedAt: number | null
1526
+ sampleCount: number | null
1527
+ }
1528
+ declare interface HeartRateState {
1529
+ available: boolean
1530
+ bluetooth: BluetoothState
1531
+ authorization: HeartRateAuthorization
1532
+ scanning: boolean
1533
+ connection: HeartRateConnection
1534
+ device: HeartRateDevice | null
1535
+ lastDevice: HeartRateDevice | null
1536
+ bpm: number | null
1537
+ lastReadingAt: number | null
1538
+ recording: HeartRateRecordingState
1539
+ }
1540
+ declare interface HeartRateReading {
1541
+ bpm: number
1542
+ rrIntervals: number[]
1543
+ contact: boolean | null
1544
+ energyExpended: number | null
1545
+ timestamp: number
1546
+ deviceId: string | null
1547
+ }
1548
+ /** A reading as a recording keeps it. */
1549
+ declare interface HeartRateSample {
1550
+ timestamp: number
1551
+ bpm: number
1552
+ rr?: number[]
1553
+ }
1554
+ /** The recording half of HeartRateApi: what a route recorder drives. */
1555
+ declare interface HeartRateRecordingApi {
1556
+ isAvailable: () => boolean
1557
+ startRecording: () => Promise<HeartRateRecordingState>
1558
+ pauseRecording: () => Promise<HeartRateRecordingState>
1559
+ resumeRecording: () => Promise<HeartRateRecordingState>
1560
+ stopRecording: () => Promise<HeartRateRecordingState & { samples: HeartRateSample[] }>
1561
+ getRecordingState: () => Promise<HeartRateRecordingState>
1562
+ readRecording: (options?: { since?: number }) => Promise<HeartRateSample[]>
1563
+ }
1564
+ declare interface HeartRateApi extends HeartRateRecordingApi {
1565
+ isAvailable: () => boolean
1566
+ supports: (method: HeartRateMethod) => boolean
1567
+ getState: () => Promise<HeartRateState>
1568
+ requestAuthorization: () => Promise<HeartRateAuthorization>
1569
+ scan: (options?: { timeout?: number }) => Promise<HeartRateState>
1570
+ stopScan: () => Promise<HeartRateState>
1571
+ getDevices: () => Promise<HeartRateDevice[]>
1572
+ connect: (id: string) => Promise<HeartRateState>
1573
+ reconnect: () => Promise<HeartRateState>
1574
+ disconnect: (options?: { forget?: boolean }) => Promise<HeartRateState>
1575
+ onReading: (callback: (reading: HeartRateReading) => void) => () => void
1576
+ onDevice: (callback: (device: HeartRateDevice) => void) => () => void
1577
+ onState: (callback: (state: HeartRateState) => void) => () => void
1578
+ }
1490
1579
  declare interface MusicApi {
1491
1580
  isAvailable: () => boolean
1492
1581
  supports: (method: MusicMethod) => boolean
@@ -1674,6 +1763,14 @@ type HapticKind = 'impact' | 'notification' | 'selection';
1674
1763
  type MusicAuthorization = 'authorized' | 'denied' | 'restricted' | 'notDetermined' | 'unavailable';
1675
1764
  type MusicPlaybackState = 'stopped' | 'playing' | 'paused' | 'interrupted' | 'seekingForward' | 'seekingBackward' | 'unknown';
1676
1765
  type MusicMethod = 'getAuthorizationStatus' | 'requestAuthorization' | 'getNowPlaying' | 'play' | 'pause' | 'togglePlayPause' | 'skipToNext' | 'skipToPrevious' | 'observe';
1766
+ /** Whether the person has let the app use Bluetooth. `unavailable` off a phone. */
1767
+ type HeartRateAuthorization = 'authorized' | 'denied' | 'restricted' | 'notDetermined' | 'unavailable';
1768
+ /** The phone's Bluetooth radio; `unknown` until something has asked for it. */
1769
+ type BluetoothState = 'poweredOn' | 'poweredOff' | 'unauthorized' | 'unsupported' | 'resetting' | 'unknown';
1770
+ /** A strap that drops out is asked for again (`reconnecting`) until `disconnect()`. */
1771
+ type HeartRateConnection = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';
1772
+ type HeartRateMethod = 'getState' | 'requestAuthorization' | 'scan' | 'stopScan' | 'getDevices' | 'connect' | 'reconnect' | 'disconnect'
1773
+ | 'startRecording' | 'pauseRecording' | 'resumeRecording' | 'stopRecording' | 'getRecordingState' | 'readRecording';
1677
1774
  type HealthDataType = | 'steps'
1678
1775
  | 'heartRate'
1679
1776
  | 'activeEnergy'
@@ -1695,6 +1792,6 @@ type HealthSleepStage = 'inBed' | 'awake' | 'asleep' | 'core' | 'deep' | 'rem';
1695
1792
  /** The health reads an installed app build may or may not answer. */
1696
1793
  type HealthReadMethod = 'getWorkouts' | 'getDailyStatistics' | 'getHeartRateSamples' | 'getSleepIntervals';
1697
1794
 
1698
- export { normalizeDeepLinkURL, getNativeMobileBridge, isNativeMobile, whenNativeMobile, onMobileReady, withNativeFeedback, biometrics, camera, device, lifecycle, location, notifications, permissions, secureStorage, share, appReview, haptics, deepLinks, snapshots, keepAwake, brightness, music, speech, network, pushNotifications, health, liveActivities, watchConnectivity, splash, mobile, craftHost, craftRoot, hasNativeMobileHost, bridgePending, whenBridgeReady, nativeFunctionNow, nativeFunction, callNative, afterBridge, subscribeWhenReady, onCraftEvent, BRIDGE_WAIT_MS, CraftHost, CallNativeOptions, observeLongPress, segmentAt, observeSegmentScrub, segmentForKey, focusSegment, installPressables, LongPressOptions, SegmentScrubOptions, currentAppearance, normalizeAppearance, onAppearance, onResume, onMemoryWarning, onSilentPush, onBackgroundRefresh, NativeAppearance, pageScrollTop, observePageScroll, pullDistance, observePullToRefresh, largeTitleMetrics, observeLargeTitle, resolveScrollHost, ScrollHost, PullToRefreshOptions, LargeTitleMetrics, LargeTitleOptions, canGoBack, goBack, enterNavTrail, backLabelFor, navTrail, previousScreenPath, goBackToTabRoot, trailEntryFor, deepLinkPath, followDeepLinks, HistoryHost, NavTrailEntry, TabRootHost, fixDistance, usableFixes, routeStats, paceLabel, speedLabel, createRouteRecorder, ROUTE_GAP_S, RouteFix, RouteStats, RouteStatsOptions, RouteRecorderOptions, RouteRecorder, startSessionClock, pauseSessionClock, resumeSessionClock, sessionClockElapsed, SessionClock, indoorVerdict, typedDistanceKm, INDOOR_CHECK_AFTER_S, IndoorFix, IndoorVerdict, toNativeRect, useActionSheet, confirmAction, showContextMenuFor, dialog, contextMenu, browser, symbols, statusBar, chrome, refresh, background, clipboard, db, files, shortcuts, widgets, orientation, auth, storeKit, DialogApi, ConfirmActionOptions, ContextMenuApi, BrowserOpenOptions, BrowserResult, BrowserApi, SymbolOptions, SymbolsApi, StatusBarApi, ChromeApi, RefreshApi, BackgroundApi, ClipboardApi, DatabaseExecuteResult, DatabaseApi, PickedFile, ScannedCode, FilesApi, HomeScreenShortcut, ShortcutsApi, WidgetsApi, OrientationApi, AppleSignInResult, AppleSignInOptions, AuthApi, StoreProduct, StoreTransaction, StoreKitApi, StatusBarStyle, OrientationLock, ActionSheetOptions, AlertOptions, ChoiceOptions, ConfirmOptions, ContextMenuItem, ContextMenuOptions, DialogAction, DialogActionStyle, NativeRect, isShown, observeNativeRefresh, NativeRefreshOptions, sheetStops, settleSheet, rubberBand, observeSheetDrag, lockBackground, liftToBody, presentPageAsCard, SHEET_FLICK_VELOCITY, SheetStop, SheetDragOptions, SheetDetent, SheetSettle, trapFocus, presentChoice, presentAlert, presentConfirm, presentActionSheet, placeMenu, presentContextMenu, applyAppearance, pageBackground, pageIsDark, installNativeChrome, NativeChromeOptions, readSpotlightKinds, spotlightKind, spotlightAction, spotlightSlot, spotlightActions, spotlightActivityTypes, spotlightTitle, placeSpotlightItem, removeSpotlightItem, spotlightRoute, readSpotlightEntries, spotlightBridge, createSpotlightIndex, onSpotlightTap, MAX_SPOTLIGHT_SLOTS_PER_KIND, SpotlightKind, SpotlightKindInput, SpotlightItem, SpotlightEntry, SpotlightKindsResult, SpotlightPlacement, SpotlightBridge, SpotlightIndexOptions, SpotlightIndex, readTabLinks, nativeTabs, routerHandlesTabs, handleTabReselect, coverTabBar, mirrorTabBar, tabBar, TAB_BAR_COVER_EVENT, TabBarApi, TabLink, TabReselectOptions, MirrorTabBarOptions, CraftMobileCapabilities, CraftMobileBridge, CraftReadyEvent, MobileApi, DeviceInfo, DeviceCapabilities, CameraOptions, PhotoResult, Location, LocationOptions, LocationRecordingState, LocationRecordingResult, ShareOptions, NotificationOptions, DeviceApi, HapticsApi, PermissionsApi, CameraApi, BiometricsApi, SecureStorageApi, LocationApi, ShareApi, LifecycleApi, NotificationsApi, KeepAwakeApi, BrightnessApi, SpeechOptions, SpeechApi, NowPlaying, MusicSkipOptions, MusicApi, DeepLinksApi, SnapshotsApi, NetworkStatus, NetworkApi, AppReviewApi, PushNotificationsApi, HealthDataOptions, HealthDataResult, HealthWorkoutLocation, HealthWorkout, HealthWorkoutResult, HealthWorkoutQuery, HealthWorkoutSample, HealthDailyValue, HealthSampleQuery, HealthHeartRateQuery, HealthHeartRateSample, HealthSleepInterval, HealthAuthorizationOptions, HealthApi, LiveActivityState, LiveActivityOptions, LiveActivitiesApi, WatchConnectivityApi, HapticStyle, HapticNotificationType, PermissionType, PermissionStatus, BiometricType, AppState, HapticKind, MusicAuthorization, MusicPlaybackState, MusicMethod, HealthDataType, HealthDailyType, HealthWorkoutType, HealthWorkoutActivity, HealthSleepStage, HealthReadMethod };
1795
+ export { normalizeDeepLinkURL, getNativeMobileBridge, isNativeMobile, whenNativeMobile, onMobileReady, withNativeFeedback, biometrics, camera, device, lifecycle, location, notifications, permissions, secureStorage, share, appReview, haptics, deepLinks, snapshots, keepAwake, brightness, music, heartRate, speech, network, pushNotifications, health, liveActivities, watchConnectivity, splash, mobile, craftHost, craftRoot, hasNativeMobileHost, bridgePending, whenBridgeReady, nativeFunctionNow, nativeFunction, callNative, afterBridge, subscribeWhenReady, onCraftEvent, BRIDGE_WAIT_MS, CraftHost, CallNativeOptions, observeLongPress, segmentAt, observeSegmentScrub, segmentForKey, focusSegment, installPressables, LongPressOptions, SegmentScrubOptions, currentAppearance, normalizeAppearance, onAppearance, onResume, onMemoryWarning, onSilentPush, onBackgroundRefresh, NativeAppearance, pageScrollTop, observePageScroll, pullDistance, observePullToRefresh, largeTitleMetrics, observeLargeTitle, resolveScrollHost, ScrollHost, PullToRefreshOptions, LargeTitleMetrics, LargeTitleOptions, canGoBack, goBack, enterNavTrail, backLabelFor, navTrail, previousScreenPath, goBackToTabRoot, trailEntryFor, deepLinkPath, followDeepLinks, HistoryHost, NavTrailEntry, TabRootHost, attachHeartRate, fixDistance, usableFixes, routeStats, paceLabel, speedLabel, createRouteRecorder, HEART_RATE_MATCH_MS, ROUTE_GAP_S, RouteFix, RouteStats, RouteStatsOptions, RouteRecorderOptions, RouteRecorder, startSessionClock, pauseSessionClock, resumeSessionClock, sessionClockElapsed, SessionClock, indoorVerdict, typedDistanceKm, INDOOR_CHECK_AFTER_S, IndoorFix, IndoorVerdict, toNativeRect, useActionSheet, confirmAction, showContextMenuFor, dialog, contextMenu, browser, symbols, statusBar, chrome, refresh, background, clipboard, db, files, shortcuts, widgets, orientation, auth, storeKit, DialogApi, ConfirmActionOptions, ContextMenuApi, BrowserOpenOptions, BrowserResult, BrowserApi, SymbolOptions, SymbolsApi, StatusBarApi, ChromeApi, RefreshApi, BackgroundApi, ClipboardApi, DatabaseExecuteResult, DatabaseApi, PickedFile, ScannedCode, FilesApi, HomeScreenShortcut, ShortcutsApi, WidgetsApi, OrientationApi, AppleSignInResult, AppleSignInOptions, AuthApi, StoreProduct, StoreTransaction, StoreKitApi, StatusBarStyle, OrientationLock, ActionSheetOptions, AlertOptions, ChoiceOptions, ConfirmOptions, ContextMenuItem, ContextMenuOptions, DialogAction, DialogActionStyle, NativeRect, isShown, observeNativeRefresh, NativeRefreshOptions, sheetStops, settleSheet, rubberBand, observeSheetDrag, lockBackground, liftToBody, presentPageAsCard, SHEET_FLICK_VELOCITY, SheetStop, SheetDragOptions, SheetDetent, SheetSettle, trapFocus, presentChoice, presentAlert, presentConfirm, presentActionSheet, placeMenu, presentContextMenu, applyAppearance, pageBackground, pageIsDark, installNativeChrome, NativeChromeOptions, readSpotlightKinds, spotlightKind, spotlightAction, spotlightSlot, spotlightActions, spotlightActivityTypes, spotlightTitle, placeSpotlightItem, removeSpotlightItem, spotlightRoute, readSpotlightEntries, spotlightBridge, createSpotlightIndex, onSpotlightTap, MAX_SPOTLIGHT_SLOTS_PER_KIND, SpotlightKind, SpotlightKindInput, SpotlightItem, SpotlightEntry, SpotlightKindsResult, SpotlightPlacement, SpotlightBridge, SpotlightIndexOptions, SpotlightIndex, readTabLinks, nativeTabs, routerHandlesTabs, handleTabReselect, coverTabBar, mirrorTabBar, tabBar, TAB_BAR_COVER_EVENT, TabBarApi, TabLink, TabReselectOptions, MirrorTabBarOptions, CraftMobileCapabilities, CraftMobileBridge, CraftReadyEvent, MobileApi, DeviceInfo, DeviceCapabilities, CameraOptions, PhotoResult, Location, LocationOptions, LocationRecordingState, LocationRecordingResult, ShareOptions, NotificationOptions, DeviceApi, HapticsApi, PermissionsApi, CameraApi, BiometricsApi, SecureStorageApi, LocationApi, ShareApi, LifecycleApi, NotificationsApi, KeepAwakeApi, BrightnessApi, SpeechOptions, SpeechApi, NowPlaying, MusicSkipOptions, HeartRateDevice, HeartRateRecordingState, HeartRateState, HeartRateReading, HeartRateSample, HeartRateRecordingApi, HeartRateApi, MusicApi, DeepLinksApi, SnapshotsApi, NetworkStatus, NetworkApi, AppReviewApi, PushNotificationsApi, HealthDataOptions, HealthDataResult, HealthWorkoutLocation, HealthWorkout, HealthWorkoutResult, HealthWorkoutQuery, HealthWorkoutSample, HealthDailyValue, HealthSampleQuery, HealthHeartRateQuery, HealthHeartRateSample, HealthSleepInterval, HealthAuthorizationOptions, HealthApi, LiveActivityState, LiveActivityOptions, LiveActivitiesApi, WatchConnectivityApi, HapticStyle, HapticNotificationType, PermissionType, PermissionStatus, BiometricType, AppState, HapticKind, MusicAuthorization, MusicPlaybackState, MusicMethod, HeartRateAuthorization, BluetoothState, HeartRateConnection, HeartRateMethod, HealthDataType, HealthDailyType, HealthWorkoutType, HealthWorkoutActivity, HealthSleepStage, HealthReadMethod };
1699
1796
  export { NativeTab } from 'craft-native/mobile';
1700
1797
  export { NativeTabBarOptions } from 'craft-native/mobile';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{appReview as yn,biometrics as xe,brightness as ee,camera as te,deepLinks as pt,device as N,haptics as ne,health as W,keepAwake as ft,lifecycle as xn,liveActivities as Se,location as M,music as R,network as mt,notifications as re,permissions as z,pushNotifications as we,secureStorage as oe,share as gt,speech as Ae,snapshots as ie,splash as Sn,watchConnectivity as Y}from"craft-native/mobile";var zn=2500;function S(){if(typeof window>"u")return;return window}function xt(){let e=S()?.craft;return e&&typeof e==="object"?e:void 0}function St(){return typeof navigator>"u"?"":navigator.userAgent||""}function ce(){let e=S();if(!e)return!1;if(e.CraftAndroid)return!0;return Boolean(e.webkit?.messageHandlers?.craft)&&/iPhone|iPad|iPod/.test(St())}function j(){let e=S();if(!e||e.craft)return!1;return ce()||Boolean(e.webkit?.messageHandlers?.craft)}function I(e=15000){let t=S();if(t?.craft)return Promise.resolve(!0);if(!t||!j())return Promise.resolve(!1);return new Promise((n)=>{let r=()=>{clearTimeout(o),t.removeEventListener("craftReady",r),n(Boolean(t.craft))},o=setTimeout(r,e);t.addEventListener("craftReady",r)})}function wt(e,t){if(!e)return null;let n=t.split("."),r=e;for(let i of n.slice(0,-1))if(r=r?.[i],!r||typeof r!=="object"&&typeof r!=="function")return null;let o=r?.[n[n.length-1]];return typeof o==="function"?o.bind(r):null}function T(e){return wt(xt(),e)}async function At(e,t=2500){let n=T(e);if(n||!j())return n;return await I(t),T(e)}async function b(e,t,n,r={}){let o=await At(e,r.timeoutMs);if(!o)return n();try{return await o(...t)}catch(i){if(r.fallbackOnError)return n();throw i}}async function g(e,t=2500){if(j())await I(t);return e()}function G(e,t=2500){let n,r=!1;if(!j())n=e();else I(t).then(()=>{if(!r)n=e()});return()=>{if(r=!0,typeof n==="function")n()}}function P(e,t){let n=S();if(!n)return()=>{};let r=(o)=>t(o.detail??{});return n.addEventListener(e,r),()=>n.removeEventListener(e,r)}var Ee="native-dialog-styles",kt=`
1
+ import{appReview as kn,biometrics as Ae,brightness as re,camera as oe,deepLinks as gt,device as D,haptics as ie,health as V,heartRate as A,keepAwake as ht,lifecycle as En,liveActivities as ke,location as N,music as P,network as bt,notifications as ae,permissions as G,pushNotifications as Ee,secureStorage as se,share as vt,speech as Te,snapshots as le,splash as Tn,watchConnectivity as X}from"craft-native/mobile";var Jn=2500;function S(){if(typeof window>"u")return;return window}function xt(){let e=S()?.craft;return e&&typeof e==="object"?e:void 0}function wt(){return typeof navigator>"u"?"":navigator.userAgent||""}function pe(){let e=S();if(!e)return!1;if(e.CraftAndroid)return!0;return Boolean(e.webkit?.messageHandlers?.craft)&&/iPhone|iPad|iPod/.test(wt())}function J(){let e=S();if(!e||e.craft)return!1;return pe()||Boolean(e.webkit?.messageHandlers?.craft)}function B(e=15000){let t=S();if(t?.craft)return Promise.resolve(!0);if(!t||!J())return Promise.resolve(!1);return new Promise((n)=>{let r=()=>{clearTimeout(o),t.removeEventListener("craftReady",r),n(Boolean(t.craft))},o=setTimeout(r,e);t.addEventListener("craftReady",r)})}function At(e,t){if(!e)return null;let n=t.split("."),r=e;for(let i of n.slice(0,-1))if(r=r?.[i],!r||typeof r!=="object"&&typeof r!=="function")return null;let o=r?.[n[n.length-1]];return typeof o==="function"?o.bind(r):null}function L(e){return At(xt(),e)}async function kt(e,t=2500){let n=L(e);if(n||!J())return n;return await B(t),L(e)}async function v(e,t,n,r={}){let o=await kt(e,r.timeoutMs);if(!o)return n();try{return await o(...t)}catch(i){if(r.fallbackOnError)return n();throw i}}async function c(e,t=2500){if(J())await B(t);return e()}function _(e,t=2500){let n,r=!1;if(!J())n=e();else B(t).then(()=>{if(!r)n=e()});return()=>{if(r=!0,typeof n==="function")n()}}function O(e,t){let n=S();if(!n)return()=>{};let r=(o)=>t(o.detail??{});return n.addEventListener(e,r),()=>n.removeEventListener(e,r)}var Le="native-dialog-styles",Et=`
2
2
  .native-dialog { position: fixed; inset: 0; z-index: 2147483000; font-size: var(--native-font-size, 17px); font-family: var(--native-font-family, -apple-system, system-ui, sans-serif); -webkit-tap-highlight-color: transparent; }
3
3
  .native-dialog-backdrop { position: absolute; inset: 0; background: rgb(0 0 0 / 0.3); opacity: 0; transition: opacity 220ms ease; }
4
4
  .native-dialog--menu .native-dialog-backdrop { background: rgb(0 0 0 / 0.12); -webkit-backdrop-filter: blur(14px) saturate(140%); backdrop-filter: blur(14px) saturate(140%); }
@@ -52,4 +52,4 @@ import{appReview as yn,biometrics as xe,brightness as ee,camera as te,deepLinks
52
52
  .native-dialog-group, .native-menu { -webkit-backdrop-filter: none; backdrop-filter: none; background: var(--native-dialog-solid, rgb(242 242 247)); }
53
53
  .dark .native-dialog-group, .dark .native-menu { background: var(--native-dialog-solid-dark, rgb(44 44 46)); }
54
54
  }
55
- `;function Te(){return S()?.document}function Et(e){if(e.getElementById(Ee))return;let t=e.createElement("style");t.id=Ee,t.textContent=kt,(e.head??e.documentElement).appendChild(t)}var Tt=0;function A(e,t,n,r){let o=e.createElement(t);if(o.className=n,r!==void 0)o.textContent=r;return o}var Le='button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function Lt(e,t){if(t.key!=="Tab")return;let n=Array.from(e.querySelectorAll(Le));if(n.length===0){t.preventDefault();return}let r=n[0],o=n[n.length-1],i=e.ownerDocument.activeElement;if(t.shiftKey&&(i===r||!e.contains(i)))t.preventDefault(),o.focus();else if(!t.shiftKey&&(i===o||!e.contains(i)))t.preventDefault(),r.focus()}function Re(e,t,n,r){Et(e);let o=S(),i=e.activeElement,a=A(e,"div",`native-dialog native-dialog--${t}`);return a.setAttribute("data-native-dialog",t),a.appendChild(A(e,"div","native-dialog-backdrop")),new Promise((s)=>{let l=!1,m=(h)=>{if(l)return;l=!0,a.classList.remove("is-open"),e.removeEventListener("keydown",p,!0),setTimeout(()=>{if(a.remove(),i&&typeof i.focus==="function")i.focus()},260),s(h)},p=(h)=>{if(h.key==="Escape"){h.preventDefault(),m(r());return}Lt(c,h)},c=n({root:a,settle:m});a.appendChild(c),e.body.appendChild(a),e.addEventListener("keydown",p,!0);let f=o;(typeof f?.requestAnimationFrame==="function"?(h)=>f.requestAnimationFrame(()=>f.requestAnimationFrame(h)):(h)=>setTimeout(h,16))(()=>{if(!l)a.classList.add("is-open")}),(c.querySelector("[data-native-autofocus]")??c.querySelector(Le))?.focus()})}function ue(e){let t=Te();if(!t?.body)return Promise.resolve(null);let n=`native-dialog-${++Tt}`,r=e.actions.find((a)=>a.style==="cancel"),o=e.variant==="sheet"?e.actions.filter((a)=>a.style!=="cancel"):e.actions,i=e.variant==="sheet"?r??{id:"__cancel",title:e.cancelLabel||"Cancel",style:"cancel"}:void 0;return Re(t,e.variant,({root:a,settle:s})=>{let l=(u)=>u.style==="cancel"?null:u.id,m=A(t,"div","native-dialog-panel");m.setAttribute("role","alertdialog"),m.setAttribute("aria-modal","true"),m.tabIndex=-1;let p=A(t,"div","native-dialog-group");if(e.title||e.message){let u=A(t,"div","native-dialog-header");if(e.title){let d=A(t,"p","native-dialog-title",e.title);d.id=`${n}-title`,u.appendChild(d),m.setAttribute("aria-labelledby",d.id)}if(e.message){let d=A(t,"p","native-dialog-message",e.message);d.id=`${n}-message`,u.appendChild(d),m.setAttribute("aria-describedby",d.id)}p.appendChild(u)}let c=A(t,"div","native-dialog-actions");if(e.variant==="alert"&&o.length===2)c.classList.add("is-row");for(let u of o){let d=A(t,"button",`native-dialog-action${u.style==="destructive"?" is-destructive":""}${u.style==="cancel"?" is-cancel":""}`,u.title);d.type="button",d.setAttribute("data-action-id",u.id),d.addEventListener("click",()=>s(l(u))),c.appendChild(d)}if(p.appendChild(c),m.appendChild(p),i){let u=A(t,"div","native-dialog-group"),d=A(t,"button","native-dialog-action is-cancel",i.title);d.type="button",d.setAttribute("data-action-id",i.id),d.addEventListener("click",()=>s(null)),u.appendChild(d),m.appendChild(u)}let f=a.querySelector(".native-dialog-backdrop");if(e.variant==="sheet")f?.addEventListener("click",()=>s(null));return m},()=>{if(e.variant==="sheet")return null;if(r)return null;return o.length===1?o[0].id:null})}async function Pe(e){await ue({variant:"alert",title:e.title,message:e.message,actions:[{id:"ok",title:e.okLabel||"OK"}]})}async function Me(e){return await ue({variant:"alert",title:e.title,message:e.message,actions:[{id:"cancel",title:e.cancelLabel||"Cancel",style:"cancel"},{id:"confirm",title:e.confirmLabel||"OK",style:e.destructive?"destructive":"default"}]})==="confirm"}function Ce(e){return ue({variant:"sheet",title:e.title,message:e.message,actions:e.actions,cancelLabel:e.cancelLabel})}function Rt(e,t,n){let i=Math.max(12,Math.min(e.x,n.width-t.width-12)),a=e.y+e.height+8,s=a+t.height<=n.height-12,l=e.y-8-t.height,m=s||l<12?Math.max(12,Math.min(a,n.height-t.height-12)):l,p=e.x+e.width/2>n.width/2?"right":"left";return{top:m,left:i,origin:`${s||l<12?"top":"bottom"} ${p}`}}function Oe(e){let t=Te();if(!t?.body)return Promise.resolve(null);let n=S();return Re(t,"menu",({root:r,settle:o})=>{let i=A(t,"div","native-menu native-dialog-panel");if(i.setAttribute("role","menu"),e.title)i.appendChild(A(t,"p","native-menu-title",e.title)),i.setAttribute("aria-label",e.title);for(let a of e.items){let s=A(t,"button",`native-menu-item${a.destructive?" is-destructive":""}`);if(s.type="button",s.setAttribute("role","menuitem"),s.setAttribute("data-action-id",a.id),a.disabled)s.disabled=!0;if(s.appendChild(A(t,"span","native-menu-label",a.title)),a.icon){let l=A(t,"i",`native-menu-icon ${a.icon}`);l.setAttribute("aria-hidden","true"),s.appendChild(l)}s.addEventListener("click",()=>o(a.id)),i.appendChild(s)}return r.querySelector(".native-dialog-backdrop")?.addEventListener("click",()=>o(null)),queueMicrotask(()=>{let a=i.getBoundingClientRect?.(),s=Rt(e.anchor,{width:a?.width||248,height:a?.height||e.items.length*44},{width:n?.innerWidth||390,height:n?.innerHeight||844});i.style.top=`${s.top}px`,i.style.left=`${s.left}px`,i.style.setProperty("--native-menu-origin",s.origin)}),i},()=>null)}var _e=()=>!0,E=()=>!1,L=()=>null;function Ne(){return S()?.navigator??(typeof navigator>"u"?void 0:navigator)}function me(e){return{x:Math.round(e.x??e.left??0),y:Math.round(e.y??e.top??0),width:Math.round(e.width),height:Math.round(e.height)}}var D={alert:(e)=>b("dialog.alert",[e],()=>Pe(e),{fallbackOnError:!0}).then(()=>{}),confirm:(e)=>b("dialog.confirm",[e],()=>Me(e),{fallbackOnError:!0}).then(Boolean),actionSheet:async(e)=>{let t={...e,anchor:e.anchor?me(e.anchor):void 0},n=await b("dialog.actionSheet",[t],()=>Ce(e),{fallbackOnError:!0});if(typeof n!=="string")return null;return e.actions.find((r)=>r.id===n)?.style==="cancel"?null:n}};function Jn(){return(e)=>D.actionSheet(e)}async function Qn(e){if((e.style??(e.destructive?"sheet":"alert"))==="alert")return D.confirm(e);return await D.actionSheet({title:e.title,message:e.message,anchor:e.anchor,actions:[{id:"confirm",title:e.confirmLabel||"OK",style:e.destructive?"destructive":"default"},{id:"cancel",title:e.cancelLabel||"Cancel",style:"cancel"}]})==="confirm"}var ge={show:async(e)=>{let t={title:e.title,anchor:me(e.anchor),items:e.items.map(({id:r,title:o,symbol:i,destructive:a,disabled:s})=>({id:r,title:o,symbol:i,destructive:a,disabled:s}))},n=await b("contextMenu.show",[t],()=>Oe(e),{fallbackOnError:!0});return typeof n==="string"?n:null}};function Zn(e,t){return ge.show({...t,anchor:me(e.getBoundingClientRect())})}function Pt(e,t){let n=S();if(!n)return{cancelled:!0};if(typeof n.craft?.openURL==="function")return Promise.resolve(n.craft.openURL(e)).catch(()=>{}),{cancelled:!1};if(t.mode==="auth")return n.location?.assign(e),{cancelled:!1};if(!(typeof n.open==="function"?n.open(e,"_blank","noopener"):null))n.location?.assign(e);return{cancelled:!1}}var De={open:async(e,t={})=>{let n=await b("browser.open",[e,t],()=>Pt(e,t),{fallbackOnError:!0});if(!n||typeof n!=="object")return{cancelled:!1};let{url:r,cancelled:o}=n;return typeof r==="string"?{url:r,cancelled:Boolean(o)}:{cancelled:Boolean(o)}}},de=new Map,pe=new Map;function Ie(e,t){return`${e}|${t.pointSize??""}|${t.weight??""}|${t.color??""}|${t.scale??""}`}var Be={isAvailable:()=>T("symbols.image")!==null,image:(e,t={})=>{let n=Ie(e,t),r=de.get(n);if(r)return r;let o=b("symbols.image",[e,t],L).then((i)=>typeof i==="string"&&i.startsWith("data:")?i:null,L).then((i)=>(pe.set(n,i),i));return de.set(n,o),o},cached:(e,t={})=>pe.get(Ie(e,t)),clearCache:()=>{de.clear(),pe.clear()}},V={setStyle:(e)=>b("statusBar.setStyle",[e],E,{fallbackOnError:!0}).then((t)=>t!==!1)},B={setUnderPageColor:(e)=>b("chrome.setUnderPageColor",[e],E,{fallbackOnError:!0}).then((t)=>t!==!1),setKeyboardAccessory:(e)=>b("chrome.setKeyboardAccessory",[e],E,{fallbackOnError:!0}).then((t)=>t!==!1)},C={isAvailable:()=>T("refresh.enable")!==null,enable:(e)=>b("refresh.enable",[e??{}],E,{fallbackOnError:!0}).then((t)=>t!==!1),disable:()=>b("refresh.disable",[],E,{fallbackOnError:!0}).then((e)=>e!==!1),end:()=>b("refresh.end",[],E,{fallbackOnError:!0}).then((e)=>e!==!1),onRefresh:(e)=>P("craftRefresh",()=>e())},F={complete:(e)=>b("background.complete",[e],E,{fallbackOnError:!0}).then((t)=>t!==!1)},Fe={write:(e)=>b("clipboard.write",[e],async()=>{let t=Ne()?.clipboard;if(!t?.writeText)return!1;return t.writeText(e).then(_e,E)},{fallbackOnError:!0}).then((t)=>t!==!1),read:()=>b("clipboard.read",[],async()=>{let e=Ne()?.clipboard;if(!e?.readText)return null;return e.readText().catch(L)},{fallbackOnError:!0}).then((e)=>typeof e==="string"?e:null)},Ke={isAvailable:()=>T("db.query")!==null,query:(e,t=[])=>b("db.query",[e,t],L).then((n)=>Array.isArray(n)?n:null),execute:(e,t=[])=>b("db.execute",[e,t],L).then((n)=>{if(!n||typeof n!=="object")return null;let{rowsAffected:r,lastInsertId:o}=n;return{rowsAffected:Number(r)||0,lastInsertId:Number(o)||0}})};function fe(e,t){let n=S()?.document;if(!n?.body)return null;let r=n.createElement("a");return r.href=e,r.download=t,r.rel="noopener",r.style.display="none",n.body.appendChild(r),r.click(),r.remove(),t}function Mt(e){let t=S()?.document;if(!t?.body)return Promise.resolve(null);return new Promise((n)=>{let r=t.createElement("input");if(r.type="file",r.style.display="none",e.length)r.accept=e.map((i)=>i.includes("/")||i.startsWith(".")?i:`.${i}`).join(",");let o=(i)=>{r.remove(),n(i)};r.addEventListener("cancel",()=>o(null)),r.addEventListener("change",()=>{let i=r.files?.[0];if(!i)return o(null);let a=new FileReader;a.onload=()=>o({name:i.name,mimeType:i.type||void 0,data:typeof a.result==="string"?a.result:void 0}),a.onerror=()=>o({name:i.name,mimeType:i.type||void 0}),a.readAsDataURL(i)}),t.body.appendChild(r),r.click()})}var $e={openPDF:(e,t=0)=>b("openPDF",[e,t],()=>{let n=S();return Boolean(n?.open?.(e,"_blank","noopener"))}).then((n)=>n!==!1),takeScreenshot:()=>b("takeScreenshot",[],L,{fallbackOnError:!0}).then((e)=>typeof e==="string"?e:null),scanQRCode:()=>b("scanQRCode",[],L).then((e)=>{if(!e||typeof e!=="object")return null;let{type:t,data:n}=e;return typeof n==="string"?{type:String(t??""),data:n}:null},L),pickFile:(e=[])=>b("pickFile",[e],()=>Mt(e)).then((t)=>{if(!t||typeof t!=="object")return null;let n=t;if(typeof n.name!=="string")return null;return{name:n.name,path:typeof n.path==="string"?n.path:void 0,data:typeof n.data==="string"?n.data:void 0,mimeType:typeof n.mimeType==="string"?n.mimeType:void 0}},L),saveFile:(e,t,n)=>b("saveFile",[e,t,n],()=>{if(e.startsWith("data:"))return fe(e,t);let r=new Blob([e],{type:n||"text/plain"}),o=URL.createObjectURL(r),i=fe(o,t);return setTimeout(()=>URL.revokeObjectURL(o),1000),i}).then((r)=>typeof r==="string"?r:null),downloadFile:(e,t)=>b("downloadFile",[e,t],()=>fe(e,t)).then((n)=>typeof n==="string"?n:null)},qe={set:(e)=>b("shortcuts.set",[e.map(({symbol:t,...n})=>t?{...n,iconName:t}:n)],E).then((t)=>t!==!1),clear:()=>b("shortcuts.clear",[],E).then((e)=>e!==!1),onShortcut:(e)=>P("craftShortcut",(t)=>{if(typeof t.type==="string")e(t.type)})},Ue={update:(e)=>b("widget.update",[e],E).then((t)=>t!==!1),reload:()=>b("widget.reload",[],E).then((e)=>e!==!1)},Ct={portrait:"portrait-primary",portraitUpsideDown:"portrait-secondary",landscape:"landscape",landscapeLeft:"landscape-primary",landscapeRight:"landscape-secondary"};function He(){return S()?.screen?.orientation}var We={lock:(e)=>b("lockOrientation",[e],()=>{let t=He();return t?.lock?t.lock(Ct[e]).then(_e,E):!1}).then((t)=>t!==!1),unlock:()=>b("unlockOrientation",[],()=>(He()?.unlock?.(),!0)).then((e)=>e!==!1)},ze={signInWithApple:(e={})=>b("signInWithApple",e.nonce?[{nonce:e.nonce}]:[],L).then((t)=>{if(!t||typeof t!=="object"||typeof t.userId!=="string")return null;return t})},Ye={isAvailable:()=>T("iap.purchase")!==null,products:(e)=>b("iap.getProducts",[e],()=>[]).then((t)=>Array.isArray(t)?t:[]),purchase:(e)=>b("iap.purchase",[e],L).then((t)=>t&&typeof t==="object"?t:null,(t)=>{if(/cancel/i.test(String(t?.message??t)))return null;throw t}),restore:()=>b("iap.restore",[],()=>[]).then((e)=>Array.isArray(e)?e:[])};function nr(e,t){let n=t.delay??500,r=t.tolerance??10,o=null,i=null,a=!1,s=()=>{if(o)clearTimeout(o);if(o=null,i&&!a)t.onPressEnd?.();i=null},l=(f)=>{let u=f;if(u.button!==void 0&&u.button!==0)return;a=!1,i={x:u.clientX,y:u.clientY},t.onPressStart?.(),o=setTimeout(()=>{if(o=null,!i)return;a=!0,t.onLongPress({...i}),i=null},n)},m=(f)=>{if(!i)return;let u=f;if(Math.hypot(u.clientX-i.x,u.clientY-i.y)>r)s()},p=(f)=>{if(!a)return;a=!1,f.preventDefault(),f.stopPropagation()},c=(f)=>f.preventDefault();return e.addEventListener("pointerdown",l),e.addEventListener("pointermove",m),e.addEventListener("pointerup",s),e.addEventListener("pointercancel",s),e.addEventListener("pointerleave",s),e.addEventListener("click",p,!0),e.addEventListener("contextmenu",c),()=>{s(),e.removeEventListener("pointerdown",l),e.removeEventListener("pointermove",m),e.removeEventListener("pointerup",s),e.removeEventListener("pointercancel",s),e.removeEventListener("pointerleave",s),e.removeEventListener("click",p,!0),e.removeEventListener("contextmenu",c)}}function Ot(e,t,n){if(n<=1||t.width<=0)return 0;let r=Math.floor((e-t.left)/t.width*n);return Math.max(0,Math.min(n-1,r))}function rr(e,t){let n=null,r=null,o=!1,i=0,a=(u)=>{let d=e.getBoundingClientRect();return Ot(u,{left:d.left+2,width:d.width-4},t.count())},s=(u)=>{let d=u;if(d.button!==void 0&&d.button!==0)return;let h=a(d.clientX);if(h!==t.selected())return;n=h,i=h,o=!1,r=d.pointerId;try{e.setPointerCapture?.(d.pointerId)}catch{}t.onPress?.(!0)},l=(u)=>{if(n===null)return;let d=a(u.clientX);if(d===i)return;o=!0,i=d,t.onScrub(d)},m=(u)=>{if(n===null)return;if(r!==null)try{e.releasePointerCapture?.(r)}catch{}if(t.onPress?.(!1),u&&o)t.onCommit(i);else if(o)t.onScrub(n);n=null,r=null},p=(u)=>{if(!o)return;o=!1,u.preventDefault(),u.stopPropagation()},c=()=>m(!0),f=()=>m(!1);return e.addEventListener("pointerdown",s),e.addEventListener("pointermove",l),e.addEventListener("pointerup",c),e.addEventListener("pointercancel",f),e.addEventListener("click",p,!0),()=>{e.removeEventListener("pointerdown",s),e.removeEventListener("pointermove",l),e.removeEventListener("pointerup",c),e.removeEventListener("pointercancel",f),e.removeEventListener("click",p,!0)}}function or(e,t,n){if(n<=0)return null;switch(e){case"ArrowRight":case"ArrowDown":return(t+1)%n;case"ArrowLeft":case"ArrowUp":return(t-1+n)%n;case"Home":return 0;case"End":return n-1;default:return null}}function ir(e,t){e.querySelectorAll('[role="tab"]')[t]?.focus()}function ar(e){let t=(n)=>{if(!n.target?.closest?.("[data-native-pressable]"))return;let o=T("haptics.prepare");if(o)Promise.resolve().then(()=>o("impact")).catch(()=>{})};return e.addEventListener("touchstart",t,{passive:!0,capture:!0}),()=>e.removeEventListener("touchstart",t,{capture:!0})}function he(e){let t=S();try{return Boolean(t?.matchMedia?.(e).matches)}catch{return!1}}function je(e){return e!==null&&e!==void 0&&e!=="false"&&e!=="0"}function Ge(){let e=S()?.document?.documentElement,t=Number.parseFloat(e?.style?.getPropertyValue("--craft-font-scale")||"");return{fontScale:Number.isFinite(t)&&t>0?t:1,reduceMotion:je(e?.getAttribute("data-craft-reduce-motion"))||he("(prefers-reduced-motion: reduce)"),reduceTransparency:je(e?.getAttribute("data-craft-reduce-transparency"))||he("(prefers-reduced-transparency: reduce)"),colorScheme:e?.classList?.contains("dark")||he("(prefers-color-scheme: dark)")?"dark":"light"}}function Nt(e){let t=Ge(),n=Number(e?.fontScale);return{contentSizeCategory:typeof e?.contentSizeCategory==="string"?e.contentSizeCategory:void 0,fontScale:Number.isFinite(n)&&n>0?n:t.fontScale,reduceMotion:typeof e?.reduceMotion==="boolean"?e.reduceMotion:t.reduceMotion,reduceTransparency:typeof e?.reduceTransparency==="boolean"?e.reduceTransparency:t.reduceTransparency,colorScheme:e?.colorScheme==="dark"||e?.colorScheme==="light"?e.colorScheme:t.colorScheme}}function Ve(e,t={}){if(t.immediate!==!1)e(Ge());return P("craftAppearance",(n)=>e(Nt(n)))}function ur(e){return P("craftResume",(t)=>e({backgroundedMs:Number(t.backgroundedMs)||0}))}function dr(e){return P("craftMemoryWarning",()=>e())}function Xe(e){return(t)=>{Promise.resolve().then(()=>e(t)).then(()=>F.complete(!0),()=>F.complete(!1))}}function pr(e){let t=Xe(e);return P("craftSilentPush",(n)=>t(n.payload??{}))}function fr(e){let t=Xe(()=>e());return P("craftBackgroundRefresh",()=>t(void 0))}import{haptics as It}from"craft-native/mobile";function be(){if(typeof window>"u")return;return window}function K(e=be()){if(!e)return 0;if(typeof e.scrollY==="number")return e.scrollY;if(typeof e.scrollTop==="number")return e.scrollTop;return e.document?.scrollingElement?.scrollTop??0}function Ht(e,t=be()){if(!t)return()=>{};let n=!1,r=typeof requestAnimationFrame==="function"?requestAnimationFrame:(i)=>setTimeout(i,16),o=()=>{if(n)return;n=!0,r(()=>{n=!1,e(K(t))})};return e(K(t)),t.addEventListener("scroll",o,{passive:!0}),()=>t.removeEventListener("scroll",o)}function _t(e,t){let n=Math.max(0,-e),r=e<=0?Math.max(0,t)*0.5:0;return Math.round(Math.max(n,r))}function hr(e){let t=e.host??be();if(!t)return()=>{};let n=e.threshold??72,r=null,o=!1,i=!1,a=typeof requestAnimationFrame==="function"?requestAnimationFrame:(h)=>setTimeout(h,16),s=null,l=(h)=>{s=null,e.onPull?.(h,o,{bounce:Math.min(h,Math.max(0,-K(t)))})},m=(h)=>{let x=s!==null;if(s=h,x)return;a(()=>{if(s!==null)l(s)})},p=(h)=>{let x=h.touches?.[0];return x?x.clientY:null},c=(h)=>{if(i||K(t)>0)return;r=p(h),o=!1},f=(h)=>{if(r===null)return;let x=p(h);if(x===null)return;let H=_t(K(t),x-r);if(!o&&H>=n)o=!0,Promise.resolve(It.impact("medium")).catch(()=>{});else if(o&&H<n*0.8)o=!1;m(H)},u=async()=>{if(r===null)return;if(r=null,!o){l(0);return}o=!1,i=!0,l(n);try{await e.onRefresh()}finally{i=!1,l(0)}},d=()=>{if(r===null)return;r=null,o=!1,l(0)};return t.addEventListener("touchstart",c,{passive:!0}),t.addEventListener("touchmove",f,{passive:!0}),t.addEventListener("touchend",u),t.addEventListener("touchcancel",d),()=>{s=null,t.removeEventListener("touchstart",c),t.removeEventListener("touchmove",f),t.removeEventListener("touchend",u),t.removeEventListener("touchcancel",d)}}function Dt(e,t=52){let n=Math.max(1,t),r=Math.min(1,Math.max(0,e/n)),o=e<0?1+Math.min(0.1,-e/600):1;return{progress:Math.round(r*1000)/1000,stretch:Math.round(o*1000)/1000}}function br(e,t={}){let n="",r=()=>t.title?.offsetHeight||t.height||52;return Ht((o)=>{let i=Dt(o,r()),a=`${i.progress}|${i.stretch}`;if(a===n)return;n=a,e.style.setProperty("--native-nav-progress",String(i.progress)),e.style.setProperty("--native-nav-stretch",String(i.stretch)),t.onChange?.(i)},t.host)}function vr(e){if(!e||typeof window>"u")return;let t=window.document?.querySelector(e);return t?t:void 0}function Ze(){if(typeof window>"u")return;return window}var Je="__stxPushed",Bt="__stxScroll";function Ft(e=Ze()){let t=e?.history?.state;if(t===null||t===void 0)return!1;if(typeof t!=="object")return!0;let n=t;if(Je in n)return n[Je]===!0;return!(Bt in n)}function xr(e=Ze()){if(!Ft(e))return!1;return e.history.back(),!0}function Sr(e,t,n=50){let r=e[e.length-1];if(e.length>=2&&e[e.length-2].path===t)e.pop();else if(!r||r.path!==t)e.push({path:t,title:""});if(e.length>n)e.splice(0,e.length-n);return{current:e[e.length-1],previous:e[e.length-2]??null}}function wr(e,t,n=12){let r=e?.title.trim()??"";return r&&r.length<=n?r:t}function Ar(){if(typeof window>"u")return[];let e=window;return e.__stacksNavTrail??=[]}function Kt(e){try{let t=new URL(e,"http://local");return`${t.pathname}${t.search}`}catch{return e}}function kr(){if(typeof window>"u")return;let e=window.stxRouter;if(typeof e?.screens!=="function")return;let t=e.screens(),n=t.find((o)=>o.active);if(!n)return;let r=t.filter((o)=>o.tab===n.tab&&o.depth<n.depth);if(!r.length)return null;return Kt(r.reduce((o,i)=>i.depth>o.depth?i:o).url)}function Er(e=typeof window>"u"?void 0:window){let t=e?.stxRouter;if(typeof t?.screens!=="function"||typeof e?.history?.go!=="function")return!1;let n=t.screens(),r=n.find((a)=>a.active);if(!r)return!1;let o=n.filter((a)=>a.tab===r.tab&&a.depth<r.depth);if(!o.length)return!1;let i=o.reduce((a,s)=>s.depth<a.depth?s:a);return e.history.go(i.depth-r.depth),!0}function Tr(e,t){for(let n=e.length-1;n>=0;n--)if(e[n].path===t)return e[n];return null}function $t(e,t=qt()){let n;try{n=new URL(e)}catch{return null}let r=`${n.search}${n.hash}`;if(n.protocol==="http:"||n.protocol==="https:"){if(!t||n.origin!==t)return null;return`${n.pathname||"/"}${r}`}return`${`/${[n.host,n.pathname.replace(/^\/+/,"")].filter(Boolean).join("/")}`}${r}`}function qt(){if(typeof window>"u")return;return window.location?.origin}var Qe="stacks-mobile-deep-link";function Lr(e,t){let n=(r)=>{let o=$t(r);if(o)e(o)};return t.getInitialURL().then((r)=>{if(!r)return;try{if(sessionStorage.getItem(Qe)===r)return;sessionStorage.setItem(Qe,r)}catch{}n(r)}).catch(()=>{}),t.onLink((r,o)=>{if(o?.initial)return;n(r)})}var Pr=30;function Ut(e,t){let n=Math.PI/180,r=(t.latitude-e.latitude)*n,o=(t.longitude-e.longitude)*n,i=Math.sin(r/2)**2+Math.cos(e.latitude*n)*Math.cos(t.latitude*n)*Math.sin(o/2)**2;return 12742017.6*Math.asin(Math.min(1,Math.sqrt(i)))}function Wt(e,t=25){let n=new Set;return e.filter((r)=>Number.isFinite(r.latitude)&&Number.isFinite(r.longitude)&&Number.isFinite(r.timestamp)&&Math.abs(r.latitude)<=90&&Math.abs(r.longitude)<=180&&Number.isFinite(r.accuracy)&&r.accuracy>=0&&r.accuracy<=t).sort((r,o)=>r.timestamp-o.timestamp).filter((r)=>{if(n.has(r.timestamp))return!1;return n.add(r.timestamp),!0})}function et(e,t={}){let n=Wt(e,t.maxAccuracyM??25),r=t.paceWindowS??30,o=[],i=0,a=0,s=null;for(let c of n){let f=o[o.length-1],u=s?(c.timestamp-s.timestamp)/1000:0;if(s=c,!f){o.push({fix:c,cumM:0});continue}if(u>30){o.push({fix:c,cumM:i});continue}let d=(c.timestamp-f.fix.timestamp)/1000,h=Ut(f.fix,c),x=Math.min(10,Math.max(3,f.fix.accuracy,c.accuracy));if(h<x)continue;if(i+=h,d>0&&h/d>=0.5)a+=d;o.push({fix:c,cumM:i})}let l=o[o.length-1],m=null,p=null;if(l&&n.at(-1).timestamp-l.fix.timestamp<=r*1000){let c=l.fix.timestamp-r*1000,f=o.find((h)=>h.fix.timestamp>=c)??l,u=l.cumM-f.cumM,d=(l.fix.timestamp-f.fix.timestamp)/1000;if(u>=20&&d>0)p=u/d,m=d/(u/1000)}return{distanceM:i,movingS:a,paceSPerKm:m,averagePaceSPerKm:i>=50&&a>0?a/(i/1000):null,speedMps:p,accuracyM:n.length?n[n.length-1].accuracy:e.length?e[e.length-1].accuracy??null:null,fixes:n.length}}function Mr(e){if(e==null||e<=0||!Number.isFinite(e)||e>3600)return"–";let t=Math.round(e);return`${Math.floor(t/60)}:${String(t%60).padStart(2,"0")}`}function Cr(e){return e!=null&&e>0&&Number.isFinite(e)?(e*3.6).toFixed(1):"–"}var tt={distanceM:0,movingS:0,paceSPerKm:null,averagePaceSPerKm:null,speedMps:null,accuracyM:null,fixes:0};function Or(e){let t=e.location,n=e.intervalMs??3000,r=tt,o=null,i=()=>typeof document<"u"&&document.visibilityState==="hidden",a=0,s=null,l=Promise.resolve(),m=null,p=!1;function c(h){let x=l.then(h);return l=x.then(()=>{},()=>{}),x}function f(){if(s)return s;let h=a;return s=(async()=>{let x=await t.readRecording();if(h===a&&!p)r=et(x,e),e.onUpdate?.(r);return r})().finally(()=>{s=null}),s}function u(){if(d(),p)return;o=setInterval(()=>{if(!i())f().catch(()=>{})},n)}function d(){if(o)clearInterval(o);o=null}return{get stats(){return r},start(){return m=null,c(async()=>{if(await t.startRecording({enableHighAccuracy:!0,...e.locationOptions}),a++,r={...tt},!p)e.onUpdate?.(r);return u(),r})},attach(){return c(async()=>{let h=await t.getRecordingState();if(!h?.active)return null;if(await f().catch(()=>{}),!h.paused)u();return h})},pause(){return c(async()=>{await t.pauseRecording(),d(),await f().catch(()=>{})})},resume(){return c(async()=>{await t.resumeRecording(),u()})},stop(){if(m)return m;return m=c(async()=>{d(),a++;let x=(await t.stopRecording())?.locations??[];if(r=et(x,e),!p)e.onUpdate?.(r);return x}).catch((h)=>{throw m=null,h}),m},dispose(){p=!0,a++,d()},refresh:f}}function Ir(e){return{startedAt:Number.isFinite(e)?e:null,pausedAt:null,pausedMs:0}}function Hr(e,t){return e.startedAt===null||e.pausedAt!==null||!Number.isFinite(t)?e:{...e,pausedAt:Math.max(e.startedAt,t)}}function _r(e,t){return e.pausedAt===null||!Number.isFinite(t)?e:{...e,pausedAt:null,pausedMs:e.pausedMs+Math.max(0,t-e.pausedAt)}}function Dr(e,t){if(e.startedAt===null)return 0;let n=((e.pausedAt??t)-e.startedAt-e.pausedMs)/1000;return Number.isFinite(n)?Math.max(0,n):0}var Fr=150;function zt(e,t){let n=Math.PI/180,r=(t.latitude-e.latitude)*n,o=(t.longitude-e.longitude)*n,i=Math.sin(r/2)**2+Math.cos(e.latitude*n)*Math.cos(t.latitude*n)*Math.sin(o/2)**2;return 12742017.6*Math.asin(Math.min(1,Math.sqrt(i)))}function X(e,t){let n=[...e].sort((r,o)=>r-o);return n[Math.min(n.length-1,Math.floor(t*n.length))]}function Kr(e,t){let n=(e||[]).filter((a)=>Number.isFinite(a?.latitude)&&Number.isFinite(a?.longitude)&&Math.abs(a.latitude)<=90&&Math.abs(a.longitude)<=180),r=n.filter((a)=>a.accuracy!=null).map((a)=>Number(a.accuracy)).filter((a)=>Number.isFinite(a)&&a>=0),o=r.length?X(r,0.5):Number.POSITIVE_INFINITY,i=0;if(n.length){let a={latitude:X(n.map((s)=>s.latitude),0.5),longitude:X(n.map((s)=>s.longitude),0.5)};i=X(n.map((s)=>zt(a,s)),0.8)}if(n.length>=10&&i>150&&o<=15)return"outside";if(t<150)return"unsure";if(n.length<3||o>30||i<25)return"indoors";if(i<50&&o>10)return"indoors";return"unsure"}function $r(e,t={}){let r=String(e||"").trim().toLowerCase().replace(",",".").match(/^(\d+(?:\.\d*)?|\.\d+)\s*(km|k|m|mi)?$/);if(!r)return null;let o=Number(r[1]),i=r[2]||t.defaultUnit||(o>100?"m":"km"),a=i==="m"?o/1000:i==="mi"?o*1.609344:o;return Number.isFinite(a)&&a>=0&&a<=2000?Math.round(a*1000)/1000:null}var Z=new Set,nt=!1,J=null;function Yt(e){return e.isConnected&&e.getClientRects().length>0}function rt(){return[...Z].find((e)=>Yt(e.element))}function Q(){let e=rt(),t=Boolean(e);if(t===nt)return;if(nt=t,t)C.enable(e?.tintColor?{tintColor:e.tintColor}:{});else C.disable()}function jt(){let e=rt();if(!e){C.end();return}Promise.resolve().then(()=>e.run()).catch(()=>{}).finally(()=>C.end())}function Wr(e,t){let n={element:e,tintColor:t.tintColor,run:t.onRefresh};Z.add(n);let r=e.ownerDocument?.defaultView;if(!J){let o=C.onRefresh(jt),i=()=>Q();r?.addEventListener("stx:load",i),J=()=>{o(),r?.removeEventListener("stx:load",i)}}return Q(),r?.requestAnimationFrame?.(()=>Q()),()=>{if(Z.delete(n),Z.size===0)J?.(),J=null;Q()}}var Yr=0.5;function Gt(e,t,n){let r=[];if(n.includes("large")||n.length===0)r.push({name:"large",y:0});if(n.includes("medium"))r.push({name:"medium",y:Math.max(0,Math.round(e-t*0.5))});return r.push({name:"dismiss",y:Math.max(1,e)}),r.sort((o,i)=>o.y-i.y)}function Vt(e){let{y:t,velocity:n,stops:r}=e,o=r.filter((s)=>s.name!=="dismiss"),i=r.find((s)=>s.name==="dismiss");if(o.length===0)return"dismiss";if(n>0.5)return(r.filter((l)=>l.y>t+1)[0]??i).name;if(n<-0.5){let s=o.filter((l)=>l.y<t-1);return(s[s.length-1]??o[0]).name}let a=o[o.length-1];if(t>a.y+(i.y-a.y)*0.5)return"dismiss";return o.reduce((s,l)=>Math.abs(l.y-t)<Math.abs(s.y-t)?l:s).name}function Xt(e,t=400){if(e<=0)return 0;return e*t*0.55/(t+e*0.55)}function jr(e){let{panel:t}=e,n=null,r=[],o=0,i=()=>e.viewport?.()??t.ownerDocument?.defaultView?.innerHeight??800,a=()=>Gt(t.offsetHeight||t.getBoundingClientRect().height,i(),e.detents()),s=(p)=>{let c=p;if(c.button!==void 0&&c.button!==0)return;if(c.target?.closest?.("button, a, input, select, textarea, [role=button]"))return;let f=a().find((u)=>u.name===e.detent())?.y??0;n={y:c.clientY,base:f,pointerId:c.pointerId},o=f,r=[{y:f,t:c.timeStamp}],t.classList.add("is-dragging");try{p.currentTarget?.setPointerCapture?.(c.pointerId)}catch{}},l=(p)=>{if(!n)return;let c=p,f=n.base+c.clientY-n.y;o=f<0?-Xt(-f):f,r.push({y:o,t:c.timeStamp});while(r.length>2&&c.timeStamp-r[0].t>100)r.shift();t.style.transform=`translateY(${o}px)`;let u=t.offsetHeight||1;t.parentElement?.style.setProperty("--native-sheet-presence",String(Math.max(0,Math.min(1,1-o/u))))},m=(p)=>{if(!n)return;let c=p;n=null;let f=r[0],u=Math.max(1,c.timeStamp-f.t),d=(o-f.y)/u;t.classList.remove("is-dragging"),t.style.transform="",t.parentElement?.style.removeProperty("--native-sheet-presence"),e.onSettle(Vt({y:o,velocity:d,stops:a()}))};for(let p of e.handles)p.addEventListener("pointerdown",s),p.addEventListener("pointermove",l),p.addEventListener("pointerup",m),p.addEventListener("pointercancel",m);return()=>{for(let p of e.handles)p.removeEventListener("pointerdown",s),p.removeEventListener("pointermove",l),p.removeEventListener("pointerup",m),p.removeEventListener("pointercancel",m)}}var ot=0,ve="";function Gr(e){let t=e.ownerDocument,n=[],r=e;while(r.parentElement&&r!==t.body){for(let a of Array.from(r.parentElement.children)){if(a===r||a.hasAttribute("inert")||a.hasAttribute("data-native-dialog"))continue;if(["SCRIPT","STYLE","TEMPLATE","LINK"].includes(a.tagName))continue;if(a.hasAttribute("data-native-sheet")&&a.getAttribute("aria-hidden")==="true")continue;a.setAttribute("inert",""),n.push(a)}r=r.parentElement}let o=t.documentElement;if(ot++===0)ve=o.style.overflow||"",o.style.overflow="hidden";let i=!1;return()=>{if(i)return;i=!0;for(let a of n)a.removeAttribute("inert");if(--ot===0)if(ve)o.style.overflow=ve;else o.style.removeProperty("overflow")}}function Vr(e){let t=e.ownerDocument;if(e.parentElement===t.body)return()=>{};let n=t.createComment("native-sheet");return e.parentNode?.insertBefore(n,e),t.body.appendChild(e),()=>{if(n.parentNode)n.parentNode.insertBefore(e,n);else e.remove();n.remove()}}function Xr(e,t){let n=e.documentElement;if(!t){n.removeAttribute("data-native-sheet-card");return}let r=e.defaultView,o=(r?.scrollY??0)+(r?.innerHeight??800)/2;n.style.setProperty("--native-sheet-card-origin",`${Math.round(o)}px`),n.setAttribute("data-native-sheet-card","")}function Jt(e,t){e.style.setProperty("--native-font-scale",String(t.fontScale)),e.toggleAttribute("data-native-reduce-motion",t.reduceMotion),e.toggleAttribute("data-native-reduce-transparency",t.reduceTransparency)}function Qt(e){let t=e.replace(/\s+/g,"").toLowerCase();return!t||t==="transparent"||/^rgba\(\d+,\d+,\d+,0(\.0+)?\)$/.test(t)||/\/0(\.0+)?\)$/.test(t)}function Zt(e){let t=e.defaultView;if(!t?.getComputedStyle)return null;for(let n of[e.body,e.documentElement]){if(!n)continue;let r=t.getComputedStyle(n).backgroundColor;if(r&&!Qt(r))return r}return null}function en(e){if(e.documentElement.classList.contains("dark"))return!0;if(e.documentElement.classList.contains("light"))return!1;return Boolean(e.defaultView?.matchMedia?.("(prefers-color-scheme: dark)").matches)}function eo(e,t={}){let n=t.root??e.documentElement;B.setKeyboardAccessory(t.keyboardAccessory===!0);let r="",o="",i=()=>{let p=Zt(e);if(p&&p!==r)r=p,B.setUnderPageColor(p);let c=en(e)?"light":"dark";if(c!==o)o=c,V.setStyle(c)},a=Ve((p)=>{Jt(n,p),i()}),s=e.defaultView,l=typeof s?.MutationObserver==="function"?new s.MutationObserver(i):null;l?.observe(e.documentElement,{attributes:!0,attributeFilter:["class","style","data-theme"]});let m=s?.matchMedia?.("(prefers-color-scheme: dark)");return m?.addEventListener?.("change",i),s?.addEventListener("stx:load",i),i(),()=>{a(),l?.disconnect(),m?.removeEventListener?.("change",i),s?.removeEventListener("stx:load",i)}}var no=64;var tn=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,nn=/^(?:0|[1-9]\d*)$/;function at(e){let t=[],n=[],r=e&&typeof e==="object"&&!Array.isArray(e)?e:{};for(let[o,i]of Object.entries(r)){let a=i&&typeof i==="object"?i:null;if(!a){n.push(`spotlight kind "${o}" is not an object`);continue}let{slots:s,route:l}=a,m=typeof a.noun==="string"&&a.noun.trim()?a.noun.trim():"Item";if(!tn.test(o)||o.includes("-slot-")){n.push(`spotlight kind "${o}" is not a usable name: lowercase letters, digits and single dashes, and never "-slot-"`);continue}if(typeof s!=="number"||!Number.isInteger(s)||s<=0||s>64){n.push(`spotlight kind "${o}" needs slots between 1 and 64, not ${String(s)}`);continue}if(typeof l!=="string"||!l.startsWith("/")||!l.includes(":id")){n.push(`spotlight kind "${o}" needs a route starting with "/" and carrying ":id", not ${String(l)}`);continue}t.push({name:o,slots:s,route:l,noun:m})}return{kinds:t,problems:n}}function U(e,t){return e.find((n)=>n.name===t)??null}function q(e,t,n){let r=U(e,t);if(!r||!Number.isInteger(n)||n<0||n>=r.slots)return null;return`${t}-slot-${n}`}function rn(e,t){if(typeof t!=="string")return null;let n=t.lastIndexOf("-slot-");if(n<=0)return null;let r=t.slice(0,n),o=t.slice(n+6);if(!nn.test(o))return null;let i=Number(o);return q(e,r,i)===t?{kind:r,slot:i}:null}function st(e){return e.flatMap((t)=>Array.from({length:t.slots},(n,r)=>`${t.name}-slot-${r}`))}function ro(e,t){let n=e&&typeof e==="object"?e:{};if(n.enabled===!1)return[];let o=[...(Array.isArray(n.activityTypes)?n.activityTypes.filter((i)=>typeof i==="string"&&i.trim().length>0):[]).map((i)=>i.trim()),...st(at(n.kinds).kinds)];return[...new Set(o)].map((i)=>`${t}.${i}`)}function lt(e,t,n){let r=typeof n.name==="string"?n.name.replace(/\s+/g," ").trim():"";if(!r)return`${U(e,t)?.noun??"Item"} #${n.id}`;return r.length>120?`${r.slice(0,119).trimEnd()}…`:r}function on(e,t,n,r,o=Date.now()){let i=U(e,n);if(!i||!Number.isInteger(r.id)||r.id<=0)return null;let a=t.filter((d)=>d.kind===n),s=lt(e,n,r),l=a.find((d)=>d.itemId===r.id)??null,m=l?null:cn(a,i.slots),p=l||m!==null?null:un(a),c=l?.slot??m??p?.slot;if(c===void 0||c===null)return null;let f={kind:n,slot:c,itemId:r.id,title:s,donatedAt:o},u=t.filter((d)=>d.kind!==n||d.slot!==c&&d.itemId!==r.id);return{entries:ct(e,[...u,f]),entry:f,evicted:p,changed:!l||l.title!==s}}function an(e,t,n){let r=e.find((o)=>o.kind===t&&o.itemId===n)??null;return{entries:r?e.filter((o)=>o!==r):[...e],removed:r}}function sn(e,t,n){let r=rn(e,n);if(!r)return null;let o=t.find((a)=>a.kind===r.kind&&a.slot===r.slot),i=U(e,r.kind)?.route;return o&&i?i.replace(":id",String(o.itemId)):null}function ln(e,t){if(!Array.isArray(t))return[];let n=new Map,r=new Set;for(let o of t){if(!o||typeof o!=="object")continue;let i=o,{kind:a,slot:s,itemId:l,title:m,donatedAt:p}=i;if(typeof a!=="string"||typeof s!=="number"||q(e,a,s)===null)continue;if(typeof l!=="number"||!Number.isInteger(l)||l<=0)continue;let c=`${a}-slot-${s}`,f=`${a}#${l}`;if(n.has(c)||r.has(f))continue;n.set(c,{kind:a,slot:s,itemId:l,title:typeof m==="string"&&m.trim()?m:lt(e,a,{id:l}),donatedAt:typeof p==="number"&&Number.isFinite(p)&&p>0?p:0}),r.add(f)}return ct(e,[...n.values()])}function ct(e,t){let n=new Map(e.map((r,o)=>[r.name,o]));return[...t].sort((r,o)=>(n.get(r.kind)??0)-(n.get(o.kind)??0)||r.slot-o.slot)}function cn(e,t){let n=new Set(e.map((r)=>r.slot));for(let r=0;r<t;r++)if(!n.has(r))return r;return null}function un(e){return e.reduce((t,n)=>!t||n.donatedAt<t.donatedAt?n:t,null)}function dn(){let e=globalThis.craft;return e&&typeof e==="object"?e.siri:void 0}var pn="stacks_spotlight_index",fn=3000;function oo(e){let t=e.onProblem??((v)=>console.warn(`[spotlight] ${v}`)),n=Array.isArray(e.kinds)?{kinds:[...e.kinds],problems:[]}:at(e.kinds);for(let v of n.problems)t(v);let r=e.enabled===!1?[]:n.kinds,o=e.storageKey??pn,i=e.legacyStorageKeys??[],a=e.timeoutMs??fn,s=e.now??(()=>Date.now()),l=e.bridge??dn,m=null;function p(){try{return typeof localStorage>"u"?null:localStorage}catch{return null}}function c(){if(m)return m;m=[];let v=p();if(!v)return m;try{let y=[o,...i].map((w)=>v.getItem(w)).find((w)=>w);m=y?ln(r,JSON.parse(y)):[]}catch{m=[]}return m}function f(v){m=v;let y=p();if(!y)return;try{y.setItem(o,JSON.stringify(v));for(let w of i)y.removeItem(w)}catch{}}async function u(v){if(!v)return null;let y;try{return await Promise.race([v,new Promise((w)=>{y=setTimeout(()=>w(null),a)})])}catch{return null}finally{if(y!==void 0)clearTimeout(y)}}let d=Promise.resolve();function h(v){let y=d.then(v,v);return d=y.catch(()=>{return}),y}async function x(v,y){let w=l()?.register;if(!w||r.length===0)return!1;return h(async()=>{let k=on(r,c(),v,y,s()),O=k&&q(r,v,k.entry.slot);if(!k||!O)return!1;if(!k.changed)return f(k.entries),!0;let _=await u(w(k.entry.title,O))!==null;if(_)f(k.entries);return _})}async function H(v,y){let w=l()?.remove;if(!w)return!1;return h(async()=>{let{entries:k,removed:O}=an(c(),v,y);if(!O)return!1;let _=q(r,v,O.slot),yt=_?await u(w(_))!==null:!1;return f(k),yt})}async function bt(v,y){let w=U(r,v)?.slots;if(!w||!l()?.register)return 0;let k=0;for(let O of[...y].slice(0,w).reverse())if(await x(v,O))k++;return k}async function vt(){let v=l()?.remove;if(!v)return f([]),0;return h(async()=>{let y=0;for(let w of c()){let k=q(r,w.kind,w.slot);if(k&&await u(v(k))!==null)y++}return f([]),y})}return{kinds:r,index:x,sync:bt,remove:H,clear:vt,routeFor:(v)=>sn(r,c(),v),entries:()=>c(),activityTypes:(v)=>st(r).map((y)=>`${v}.${y}`),reset:()=>{m=null}}}var it=["craftShortcut","craftSiriShortcut"];function io(e,t){let n=(r)=>{let o=r.detail,i=typeof o==="string"?o:o&&typeof o==="object"?o.action??o.type:null,a=typeof i==="string"?e.routeFor(i):null;if(a)t(a)};if(typeof globalThis.addEventListener!=="function")return()=>{};for(let r of it)globalThis.addEventListener(r,n);return()=>{for(let r of it)globalThis.removeEventListener(r,n)}}import{tabBar as mn}from"craft-native/mobile";var gn=mn;function hn(e){return Array.from(e.querySelectorAll("a[data-native-tab]")).map((t)=>({id:t.getAttribute("href")||"",title:t.getAttribute("data-native-tab")||t.getAttribute("aria-label")||"",symbol:t.getAttribute("data-native-tab-symbol")||"circle",badge:(t.querySelector(".native-tab-badge")?.textContent||"").trim(),current:t.hasAttribute("data-stx-nav-current")||t.classList.contains("is-active")})).filter((t)=>t.id&&t.title)}function bn(e){return{tabs:e.map(({id:n,title:r,symbol:o,badge:i})=>i?{id:n,title:r,symbol:o,badge:i}:{id:n,title:r,symbol:o}),selected:e.find((n)=>n.current)?.id}}function dt(){if(typeof window>"u")return;let e=window.stxRouter;return e&&typeof e==="object"?e:void 0}function vn(){return typeof dt()?.selectTab==="function"}function lo(e,t={}){let n=(r)=>{if(vn()||r.defaultPrevented)return;let o=r.target?.closest?.("a[data-native-tab]");if(!o||!e.contains(o))return;if(!o.hasAttribute("data-stx-nav-current")&&!o.classList.contains("is-active")&&o.getAttribute("aria-current")!=="page")return;r.preventDefault();let i=e.ownerDocument.defaultView;if(t.scrollToTop)t.scrollToTop();else i?.scrollTo?.({top:0,behavior:i.matchMedia?.("(prefers-reduced-motion: reduce)").matches?"auto":"smooth"});i?.dispatchEvent(new CustomEvent("stx:tabreselect",{detail:{href:o.getAttribute("href")||""}}))};return e.addEventListener("click",n),()=>e.removeEventListener("click",n)}function ut(e){let t=e.trim();return/^#[0-9a-f]{6}$/i.test(t)?t:void 0}var ye="stacks:tab-bar-cover";function co(e,t){if(t)e.setAttribute("data-native-covers-tab-bar","");else e.removeAttribute("data-native-covers-tab-bar");e.ownerDocument?.defaultView?.dispatchEvent(new Event(ye))}function uo(e,t={}){let n=t.api??gn;if(!n.isAvailable())return null;let r=t.hidden??(()=>Boolean(e.ownerDocument?.querySelector("[data-native-hide-tab-bar], [data-native-covers-tab-bar]"))),o=typeof getComputedStyle==="function"?getComputedStyle(e):null,i=ut(o?.getPropertyValue("--native-tab-active")||""),a=ut(o?.getPropertyValue("--native-tab-active-dark")||""),s="",l=()=>{if(r()){if(s!=="hidden")n.hide();s="hidden";return}let{tabs:f,selected:u}=bn(hn(e)),d=JSON.stringify({tabs:f,selected:u});if(d===s)return;let h=s&&s!=="hidden"?JSON.parse(s):null;if(h&&u&&JSON.stringify(h.tabs)===JSON.stringify(f))n.select(u);else n.set(f,{selected:u,tint:i,tintDark:a});s=d},m=typeof MutationObserver==="function"?new MutationObserver(l):null;m?.observe(e,{attributes:!0,attributeFilter:["data-stx-nav-current","class"],childList:!0,subtree:!0,characterData:!0});let p=n.onSelect((f)=>{let u=dt();if(u?.selectTab){u.selectTab(f);return}Array.from(e.querySelectorAll("a[data-native-tab]")).find((h)=>h.getAttribute("href")===f)?.click()}),c=()=>l();if(typeof window<"u")window.addEventListener("stx:load",c),window.addEventListener("stx:screen-shown",c),window.addEventListener(ye,c);return l(),()=>{if(m?.disconnect(),p(),typeof window<"u")window.removeEventListener("stx:load",c),window.removeEventListener("stx:screen-shown",c),window.removeEventListener(ye,c);n.hide()}}var wn={isAvailable:()=>g(()=>xe.isAvailable()),getBiometricType:()=>g(()=>xe.getBiometricType()),authenticate:(e)=>g(()=>xe.authenticate(e))},An={takePicture:(e)=>g(()=>te.takePicture(e)),pickImage:()=>g(()=>te.pickImage()),pickMultiple:(e)=>g(()=>te.pickMultiple(e)),isAvailable:()=>g(()=>te.isAvailable())},kn={getInfo:()=>g(()=>N.getInfo()),getCapabilities:()=>g(()=>N.getCapabilities()),isMobile:()=>N.isMobile(),isIOS:()=>N.isIOS(),isAndroid:()=>N.isAndroid(),getLocale:()=>N.getLocale(),getTimezone:()=>N.getTimezone()},En=xn,Tn={getCurrentPosition:(e)=>g(()=>M.getCurrentPosition(e)),watchPosition:(e,t)=>M.watchPosition(e,t),clearWatch:(e)=>M.clearWatch(e),startRecording:(e)=>g(()=>M.startRecording(e)),pauseRecording:()=>g(()=>M.pauseRecording()),resumeRecording:()=>g(()=>M.resumeRecording()),stopRecording:()=>g(()=>M.stopRecording()),getRecordingState:()=>g(()=>M.getRecordingState()),readRecording:()=>g(()=>M.readRecording())},Ln={show:(e)=>g(()=>re.show(e)),schedule:(e)=>g(()=>re.schedule(e)),cancelAll:()=>g(()=>re.cancelAll()),setBadge:(e)=>g(()=>re.setBadge(e))},Rn={check:(e)=>g(()=>z.check(e)),request:(e)=>g(()=>z.request(e)),checkMultiple:(e)=>g(()=>z.checkMultiple(e)),requestMultiple:(e)=>g(()=>z.requestMultiple(e)),openSettings:()=>g(()=>z.openSettings())},Pn={set:(e,t)=>g(()=>oe.set(e,t)),get:(e)=>g(()=>oe.get(e)),delete:(e)=>g(()=>oe.delete(e)),clear:()=>g(()=>oe.clear())},Mn={share:(e)=>g(()=>gt.share(e)),isAvailable:()=>gt.isAvailable()},Cn={request:()=>g(()=>yn.request())},ae={impact:(e)=>Promise.resolve().then(()=>ne.impact(e)).catch(()=>{}),notification:(e)=>Promise.resolve().then(()=>ne.notification(e)).catch(()=>{}),selection:()=>Promise.resolve().then(()=>ne.selection()).catch(()=>{}),vibrate:(e)=>Promise.resolve().then(()=>ne.vibrate(e)).catch(()=>{}),prepare:(e)=>{let t=T("haptics.prepare");return t?Promise.resolve().then(()=>t(e)).then(()=>{},()=>{}):Promise.resolve()}};function ht(e){if(typeof e==="string")return e.trim()||null;if(!e||typeof e!=="object")return null;let t=e.url;return typeof t==="string"&&t.trim()?t:null}var On={async getInitialURL(){if(!await I())return null;return ht(await pt.getInitialURL?.())},onLink(e){let t=null,n=!1,r=()=>{if(n)return;t=pt.onLink?.((o,i)=>{let a=ht(o);if(a)e(a,{initial:i?.initial===!0})})??null};if(le()?.craft)r();else I().then(r);return()=>{n=!0,t?.()}}},ho={isAvailable:()=>ie.isAvailable(),set:(e,t)=>ie.set(e,t),remove:(e)=>ie.remove(e),clear:()=>ie.clear()},Nn={enable:()=>g(()=>ft.enable()),disable:()=>g(()=>ft.disable())},In={isAvailable:()=>ee.isAvailable(),get:()=>g(()=>ee.get()),set:(e)=>g(()=>ee.set(e)),restore:()=>g(()=>ee.restore())},Hn={isAvailable:()=>R.isAvailable(),supports:(e)=>R.supports(e),getAuthorizationStatus:()=>g(()=>R.getAuthorizationStatus()),requestAuthorization:()=>g(()=>R.requestAuthorization()),getNowPlaying:()=>g(()=>R.getNowPlaying()),play:()=>g(()=>R.play()),pause:()=>g(()=>R.pause()),togglePlayPause:()=>g(()=>R.togglePlayPause()),skipToNext:()=>g(()=>R.skipToNext()),skipToPrevious:(e)=>g(()=>R.skipToPrevious(e)),onChange:(e)=>G(()=>R.onChange(e))},_n={isAvailable:()=>Ae.isAvailable(),speak:(e,t)=>g(()=>Ae.speak(e,t)),stop:()=>g(()=>Ae.stop())},Dn={getStatus:()=>g(()=>mt.getStatus()),onChange:(e)=>G(()=>mt.onChange(e))},Bn={register:()=>g(()=>we.register()),onToken:(e)=>we.onToken(e),onNotification:(e)=>G(()=>we.onNotification(e))},Fn={requestAuthorization:(e,t)=>g(()=>W.requestAuthorization(e,t)),getData:(e,t)=>g(()=>W.getData(e,t)),saveWorkout:(e)=>g(()=>W.saveWorkout(e)),getWorkouts:(e)=>g(()=>W.getWorkouts(e)),getDailyStatistics:(e,t)=>g(()=>W.getDailyStatistics(e,t)),getHeartRateSamples:(e)=>b("health.getHeartRateSamples",[e??{}],()=>[]).then((t)=>Array.isArray(t)?t:[]),getSleepIntervals:(e)=>b("health.getSleepIntervals",[e??{}],()=>[]).then((t)=>Array.isArray(t)?t:[]),supports:(e)=>T(`health.${e}`)!==null},Kn={start:(e)=>g(()=>Se.start(e)),update:(e)=>g(()=>Se.update(e)),end:()=>g(()=>Se.end())},$n={send:(e)=>g(()=>Y.send(e)),updateContext:(e)=>g(()=>Y.updateContext(e)),isReachable:()=>g(()=>Y.isReachable()),onMessage:(e)=>Y.onMessage(e),onReachabilityChange:(e)=>Y.onReachabilityChange(e)},bo=Sn;function le(){return S()}function se(){let e=le()?.craft;if(!e||typeof e!=="object")return null;if(!("platform"in e)||e.platform!=="ios"&&e.platform!=="android")return null;let t="capabilities"in e?e.capabilities:void 0,n=t&&typeof t==="object"&&!Array.isArray(t)?Object.fromEntries(Object.entries(t).filter(([,r])=>typeof r==="boolean")):{};return{platform:e.platform,capabilities:n}}function ke(){return se()!==null}function qn(e=2000){if(ke()||ce())return Promise.resolve(!0);let t=le();if(!t||!(t.craft||t.webkit?.messageHandlers?.craft))return Promise.resolve(!1);return new Promise((n)=>{let r=()=>{clearTimeout(o),t.removeEventListener("craftReady",r),n(ke())},o=setTimeout(r,e);t.addEventListener("craftReady",r,{once:!0})})}function Un(e){let t=le();if(!t)return()=>{};if(se()){let r=!1;return queueMicrotask(()=>{if(!r)e(new Event("craftReady"))}),()=>{r=!0}}let n=(r)=>{if(!se())return;t.removeEventListener("craftReady",n),e(r)};return t.addEventListener("craftReady",n),()=>t.removeEventListener("craftReady",n)}async function Wn(e){await ae.impact("light");try{let t=await e();return await ae.notification("success"),t}catch(t){throw await ae.notification("error"),t}}var vo={get nativeBridge(){return se()},biometrics:wn,camera:An,device:kn,haptics:ae,lifecycle:En,location:Tn,notifications:Ln,permissions:Rn,secureStorage:Pn,share:Mn,appReview:Cn,deepLinks:On,keepAwake:Nn,brightness:In,music:Hn,speech:_n,network:Dn,pushNotifications:Bn,health:Fn,liveActivities:Kn,watchConnectivity:$n,dialog:D,contextMenu:ge,browser:De,symbols:Be,statusBar:V,chrome:B,refresh:C,background:F,clipboard:Fe,db:Ke,files:$e,shortcuts:qe,widgets:Ue,orientation:We,auth:ze,storeKit:Ye,isNativeMobile:ke,whenNative:qn,onReady:Un,withFeedback:Wn};export{zn as BRIDGE_WAIT_MS,Fr as INDOOR_CHECK_AFTER_S,no as MAX_SPOTLIGHT_SLOTS_PER_KIND,Pr as ROUTE_GAP_S,Yr as SHEET_FLICK_VELOCITY,ye as TAB_BAR_COVER_EVENT,g as afterBridge,Cn as appReview,Jt as applyAppearance,ze as auth,wr as backLabelFor,F as background,wn as biometrics,j as bridgePending,In as brightness,De as browser,b as callNative,An as camera,Ft as canGoBack,B as chrome,Fe as clipboard,Qn as confirmAction,ge as contextMenu,co as coverTabBar,S as craftHost,xt as craftRoot,Or as createRouteRecorder,oo as createSpotlightIndex,Ge as currentAppearance,Ke as db,$t as deepLinkPath,On as deepLinks,kn as device,D as dialog,Sr as enterNavTrail,$e as files,Ut as fixDistance,ir as focusSegment,Lr as followDeepLinks,se as getNativeMobileBridge,xr as goBack,Er as goBackToTabRoot,lo as handleTabReselect,ae as haptics,ce as hasNativeMobileHost,Fn as health,Kr as indoorVerdict,eo as installNativeChrome,ar as installPressables,ke as isNativeMobile,Yt as isShown,Nn as keepAwake,Dt as largeTitleMetrics,En as lifecycle,Vr as liftToBody,Kn as liveActivities,Tn as location,Gr as lockBackground,uo as mirrorTabBar,vo as mobile,Hn as music,At as nativeFunction,T as nativeFunctionNow,bn as nativeTabs,Ar as navTrail,Dn as network,Nt as normalizeAppearance,ht as normalizeDeepLinkURL,Ln as notifications,br as observeLargeTitle,nr as observeLongPress,Wr as observeNativeRefresh,Ht as observePageScroll,hr as observePullToRefresh,rr as observeSegmentScrub,jr as observeSheetDrag,Ve as onAppearance,fr as onBackgroundRefresh,P as onCraftEvent,dr as onMemoryWarning,Un as onMobileReady,ur as onResume,pr as onSilentPush,io as onSpotlightTap,We as orientation,Mr as paceLabel,Zt as pageBackground,en as pageIsDark,K as pageScrollTop,Hr as pauseSessionClock,Rn as permissions,Rt as placeMenu,on as placeSpotlightItem,Ce as presentActionSheet,Pe as presentAlert,ue as presentChoice,Me as presentConfirm,Oe as presentContextMenu,Xr as presentPageAsCard,kr as previousScreenPath,_t as pullDistance,Bn as pushNotifications,ln as readSpotlightEntries,at as readSpotlightKinds,hn as readTabLinks,C as refresh,an as removeSpotlightItem,vr as resolveScrollHost,_r as resumeSessionClock,et as routeStats,vn as routerHandlesTabs,Xt as rubberBand,Pn as secureStorage,Ot as segmentAt,or as segmentForKey,Dr as sessionClockElapsed,Vt as settleSheet,Mn as share,Gt as sheetStops,qe as shortcuts,Zn as showContextMenuFor,ho as snapshots,_n as speech,Cr as speedLabel,bo as splash,q as spotlightAction,st as spotlightActions,ro as spotlightActivityTypes,dn as spotlightBridge,U as spotlightKind,sn as spotlightRoute,rn as spotlightSlot,lt as spotlightTitle,Ir as startSessionClock,V as statusBar,Ye as storeKit,G as subscribeWhenReady,Be as symbols,gn as tabBar,me as toNativeRect,Tr as trailEntryFor,Lt as trapFocus,$r as typedDistanceKm,Wt as usableFixes,Jn as useActionSheet,$n as watchConnectivity,I as whenBridgeReady,qn as whenNativeMobile,Ue as widgets,Wn as withNativeFeedback};
55
+ `;function Me(){return S()?.document}function Tt(e){if(e.getElementById(Le))return;let t=e.createElement("style");t.id=Le,t.textContent=Et,(e.head??e.documentElement).appendChild(t)}var Rt=0;function E(e,t,n,r){let o=e.createElement(t);if(o.className=n,r!==void 0)o.textContent=r;return o}var Pe='button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function Lt(e,t){if(t.key!=="Tab")return;let n=Array.from(e.querySelectorAll(Pe));if(n.length===0){t.preventDefault();return}let r=n[0],o=n[n.length-1],i=e.ownerDocument.activeElement;if(t.shiftKey&&(i===r||!e.contains(i)))t.preventDefault(),o.focus();else if(!t.shiftKey&&(i===o||!e.contains(i)))t.preventDefault(),r.focus()}function Ce(e,t,n,r){Tt(e);let o=S(),i=e.activeElement,a=E(e,"div",`native-dialog native-dialog--${t}`);return a.setAttribute("data-native-dialog",t),a.appendChild(E(e,"div","native-dialog-backdrop")),new Promise((s)=>{let l=!1,g=(h)=>{if(l)return;l=!0,a.classList.remove("is-open"),e.removeEventListener("keydown",p,!0),setTimeout(()=>{if(a.remove(),i&&typeof i.focus==="function")i.focus()},260),s(h)},p=(h)=>{if(h.key==="Escape"){h.preventDefault(),g(r());return}Lt(u,h)},u=n({root:a,settle:g});a.appendChild(u),e.body.appendChild(a),e.addEventListener("keydown",p,!0);let f=o;(typeof f?.requestAnimationFrame==="function"?(h)=>f.requestAnimationFrame(()=>f.requestAnimationFrame(h)):(h)=>setTimeout(h,16))(()=>{if(!l)a.classList.add("is-open")}),(u.querySelector("[data-native-autofocus]")??u.querySelector(Pe))?.focus()})}function fe(e){let t=Me();if(!t?.body)return Promise.resolve(null);let n=`native-dialog-${++Rt}`,r=e.actions.find((a)=>a.style==="cancel"),o=e.variant==="sheet"?e.actions.filter((a)=>a.style!=="cancel"):e.actions,i=e.variant==="sheet"?r??{id:"__cancel",title:e.cancelLabel||"Cancel",style:"cancel"}:void 0;return Ce(t,e.variant,({root:a,settle:s})=>{let l=(d)=>d.style==="cancel"?null:d.id,g=E(t,"div","native-dialog-panel");g.setAttribute("role","alertdialog"),g.setAttribute("aria-modal","true"),g.tabIndex=-1;let p=E(t,"div","native-dialog-group");if(e.title||e.message){let d=E(t,"div","native-dialog-header");if(e.title){let m=E(t,"p","native-dialog-title",e.title);m.id=`${n}-title`,d.appendChild(m),g.setAttribute("aria-labelledby",m.id)}if(e.message){let m=E(t,"p","native-dialog-message",e.message);m.id=`${n}-message`,d.appendChild(m),g.setAttribute("aria-describedby",m.id)}p.appendChild(d)}let u=E(t,"div","native-dialog-actions");if(e.variant==="alert"&&o.length===2)u.classList.add("is-row");for(let d of o){let m=E(t,"button",`native-dialog-action${d.style==="destructive"?" is-destructive":""}${d.style==="cancel"?" is-cancel":""}`,d.title);m.type="button",m.setAttribute("data-action-id",d.id),m.addEventListener("click",()=>s(l(d))),u.appendChild(m)}if(p.appendChild(u),g.appendChild(p),i){let d=E(t,"div","native-dialog-group"),m=E(t,"button","native-dialog-action is-cancel",i.title);m.type="button",m.setAttribute("data-action-id",i.id),m.addEventListener("click",()=>s(null)),d.appendChild(m),g.appendChild(d)}let f=a.querySelector(".native-dialog-backdrop");if(e.variant==="sheet")f?.addEventListener("click",()=>s(null));return g},()=>{if(e.variant==="sheet")return null;if(r)return null;return o.length===1?o[0].id:null})}async function Oe(e){await fe({variant:"alert",title:e.title,message:e.message,actions:[{id:"ok",title:e.okLabel||"OK"}]})}async function Ne(e){return await fe({variant:"alert",title:e.title,message:e.message,actions:[{id:"cancel",title:e.cancelLabel||"Cancel",style:"cancel"},{id:"confirm",title:e.confirmLabel||"OK",style:e.destructive?"destructive":"default"}]})==="confirm"}function Ie(e){return fe({variant:"sheet",title:e.title,message:e.message,actions:e.actions,cancelLabel:e.cancelLabel})}function Mt(e,t,n){let i=Math.max(12,Math.min(e.x,n.width-t.width-12)),a=e.y+e.height+8,s=a+t.height<=n.height-12,l=e.y-8-t.height,g=s||l<12?Math.max(12,Math.min(a,n.height-t.height-12)):l,p=e.x+e.width/2>n.width/2?"right":"left";return{top:g,left:i,origin:`${s||l<12?"top":"bottom"} ${p}`}}function He(e){let t=Me();if(!t?.body)return Promise.resolve(null);let n=S();return Ce(t,"menu",({root:r,settle:o})=>{let i=E(t,"div","native-menu native-dialog-panel");if(i.setAttribute("role","menu"),e.title)i.appendChild(E(t,"p","native-menu-title",e.title)),i.setAttribute("aria-label",e.title);for(let a of e.items){let s=E(t,"button",`native-menu-item${a.destructive?" is-destructive":""}`);if(s.type="button",s.setAttribute("role","menuitem"),s.setAttribute("data-action-id",a.id),a.disabled)s.disabled=!0;if(s.appendChild(E(t,"span","native-menu-label",a.title)),a.icon){let l=E(t,"i",`native-menu-icon ${a.icon}`);l.setAttribute("aria-hidden","true"),s.appendChild(l)}s.addEventListener("click",()=>o(a.id)),i.appendChild(s)}return r.querySelector(".native-dialog-backdrop")?.addEventListener("click",()=>o(null)),queueMicrotask(()=>{let a=i.getBoundingClientRect?.(),s=Mt(e.anchor,{width:a?.width||248,height:a?.height||e.items.length*44},{width:n?.innerWidth||390,height:n?.innerHeight||844});i.style.top=`${s.top}px`,i.style.left=`${s.left}px`,i.style.setProperty("--native-menu-origin",s.origin)}),i},()=>null)}var Fe=()=>!0,R=()=>!1,M=()=>null;function _e(){return S()?.navigator??(typeof navigator>"u"?void 0:navigator)}function be(e){return{x:Math.round(e.x??e.left??0),y:Math.round(e.y??e.top??0),width:Math.round(e.width),height:Math.round(e.height)}}var q={alert:(e)=>v("dialog.alert",[e],()=>Oe(e),{fallbackOnError:!0}).then(()=>{}),confirm:(e)=>v("dialog.confirm",[e],()=>Ne(e),{fallbackOnError:!0}).then(Boolean),actionSheet:async(e)=>{let t={...e,anchor:e.anchor?be(e.anchor):void 0},n=await v("dialog.actionSheet",[t],()=>Ie(e),{fallbackOnError:!0});if(typeof n!=="string")return null;return e.actions.find((r)=>r.id===n)?.style==="cancel"?null:n}};function rr(){return(e)=>q.actionSheet(e)}async function or(e){if((e.style??(e.destructive?"sheet":"alert"))==="alert")return q.confirm(e);return await q.actionSheet({title:e.title,message:e.message,anchor:e.anchor,actions:[{id:"confirm",title:e.confirmLabel||"OK",style:e.destructive?"destructive":"default"},{id:"cancel",title:e.cancelLabel||"Cancel",style:"cancel"}]})==="confirm"}var ve={show:async(e)=>{let t={title:e.title,anchor:be(e.anchor),items:e.items.map(({id:r,title:o,symbol:i,destructive:a,disabled:s})=>({id:r,title:o,symbol:i,destructive:a,disabled:s}))},n=await v("contextMenu.show",[t],()=>He(e),{fallbackOnError:!0});return typeof n==="string"?n:null}};function ir(e,t){return ve.show({...t,anchor:be(e.getBoundingClientRect())})}function Pt(e,t){let n=S();if(!n)return{cancelled:!0};if(typeof n.craft?.openURL==="function")return Promise.resolve(n.craft.openURL(e)).catch(()=>{}),{cancelled:!1};if(t.mode==="auth")return n.location?.assign(e),{cancelled:!1};if(!(typeof n.open==="function"?n.open(e,"_blank","noopener"):null))n.location?.assign(e);return{cancelled:!1}}var Ke={open:async(e,t={})=>{let n=await v("browser.open",[e,t],()=>Pt(e,t),{fallbackOnError:!0});if(!n||typeof n!=="object")return{cancelled:!1};let{url:r,cancelled:o}=n;return typeof r==="string"?{url:r,cancelled:Boolean(o)}:{cancelled:Boolean(o)}}},me=new Map,ge=new Map;function De(e,t){return`${e}|${t.pointSize??""}|${t.weight??""}|${t.color??""}|${t.scale??""}`}var $e={isAvailable:()=>L("symbols.image")!==null,image:(e,t={})=>{let n=De(e,t),r=me.get(n);if(r)return r;let o=v("symbols.image",[e,t],M).then((i)=>typeof i==="string"&&i.startsWith("data:")?i:null,M).then((i)=>(ge.set(n,i),i));return me.set(n,o),o},cached:(e,t={})=>ge.get(De(e,t)),clearCache:()=>{me.clear(),ge.clear()}},Q={setStyle:(e)=>v("statusBar.setStyle",[e],R,{fallbackOnError:!0}).then((t)=>t!==!1)},U={setUnderPageColor:(e)=>v("chrome.setUnderPageColor",[e],R,{fallbackOnError:!0}).then((t)=>t!==!1),setKeyboardAccessory:(e)=>v("chrome.setKeyboardAccessory",[e],R,{fallbackOnError:!0}).then((t)=>t!==!1)},I={isAvailable:()=>L("refresh.enable")!==null,enable:(e)=>v("refresh.enable",[e??{}],R,{fallbackOnError:!0}).then((t)=>t!==!1),disable:()=>v("refresh.disable",[],R,{fallbackOnError:!0}).then((e)=>e!==!1),end:()=>v("refresh.end",[],R,{fallbackOnError:!0}).then((e)=>e!==!1),onRefresh:(e)=>O("craftRefresh",()=>e())},W={complete:(e)=>v("background.complete",[e],R,{fallbackOnError:!0}).then((t)=>t!==!1)},qe={write:(e)=>v("clipboard.write",[e],async()=>{let t=_e()?.clipboard;if(!t?.writeText)return!1;return t.writeText(e).then(Fe,R)},{fallbackOnError:!0}).then((t)=>t!==!1),read:()=>v("clipboard.read",[],async()=>{let e=_e()?.clipboard;if(!e?.readText)return null;return e.readText().catch(M)},{fallbackOnError:!0}).then((e)=>typeof e==="string"?e:null)},Ue={isAvailable:()=>L("db.query")!==null,query:(e,t=[])=>v("db.query",[e,t],M).then((n)=>Array.isArray(n)?n:null),execute:(e,t=[])=>v("db.execute",[e,t],M).then((n)=>{if(!n||typeof n!=="object")return null;let{rowsAffected:r,lastInsertId:o}=n;return{rowsAffected:Number(r)||0,lastInsertId:Number(o)||0}})};function he(e,t){let n=S()?.document;if(!n?.body)return null;let r=n.createElement("a");return r.href=e,r.download=t,r.rel="noopener",r.style.display="none",n.body.appendChild(r),r.click(),r.remove(),t}function Ct(e){let t=S()?.document;if(!t?.body)return Promise.resolve(null);return new Promise((n)=>{let r=t.createElement("input");if(r.type="file",r.style.display="none",e.length)r.accept=e.map((i)=>i.includes("/")||i.startsWith(".")?i:`.${i}`).join(",");let o=(i)=>{r.remove(),n(i)};r.addEventListener("cancel",()=>o(null)),r.addEventListener("change",()=>{let i=r.files?.[0];if(!i)return o(null);let a=new FileReader;a.onload=()=>o({name:i.name,mimeType:i.type||void 0,data:typeof a.result==="string"?a.result:void 0}),a.onerror=()=>o({name:i.name,mimeType:i.type||void 0}),a.readAsDataURL(i)}),t.body.appendChild(r),r.click()})}var We={openPDF:(e,t=0)=>v("openPDF",[e,t],()=>{let n=S();return Boolean(n?.open?.(e,"_blank","noopener"))}).then((n)=>n!==!1),takeScreenshot:()=>v("takeScreenshot",[],M,{fallbackOnError:!0}).then((e)=>typeof e==="string"?e:null),scanQRCode:()=>v("scanQRCode",[],M).then((e)=>{if(!e||typeof e!=="object")return null;let{type:t,data:n}=e;return typeof n==="string"?{type:String(t??""),data:n}:null},M),pickFile:(e=[])=>v("pickFile",[e],()=>Ct(e)).then((t)=>{if(!t||typeof t!=="object")return null;let n=t;if(typeof n.name!=="string")return null;return{name:n.name,path:typeof n.path==="string"?n.path:void 0,data:typeof n.data==="string"?n.data:void 0,mimeType:typeof n.mimeType==="string"?n.mimeType:void 0}},M),saveFile:(e,t,n)=>v("saveFile",[e,t,n],()=>{if(e.startsWith("data:"))return he(e,t);let r=new Blob([e],{type:n||"text/plain"}),o=URL.createObjectURL(r),i=he(o,t);return setTimeout(()=>URL.revokeObjectURL(o),1000),i}).then((r)=>typeof r==="string"?r:null),downloadFile:(e,t)=>v("downloadFile",[e,t],()=>he(e,t)).then((n)=>typeof n==="string"?n:null)},ze={set:(e)=>v("shortcuts.set",[e.map(({symbol:t,...n})=>t?{...n,iconName:t}:n)],R).then((t)=>t!==!1),clear:()=>v("shortcuts.clear",[],R).then((e)=>e!==!1),onShortcut:(e)=>O("craftShortcut",(t)=>{if(typeof t.type==="string")e(t.type)})},Ye={update:(e)=>v("widget.update",[e],R).then((t)=>t!==!1),reload:()=>v("widget.reload",[],R).then((e)=>e!==!1)},Ot={portrait:"portrait-primary",portraitUpsideDown:"portrait-secondary",landscape:"landscape",landscapeLeft:"landscape-primary",landscapeRight:"landscape-secondary"};function Be(){return S()?.screen?.orientation}var je={lock:(e)=>v("lockOrientation",[e],()=>{let t=Be();return t?.lock?t.lock(Ot[e]).then(Fe,R):!1}).then((t)=>t!==!1),unlock:()=>v("unlockOrientation",[],()=>(Be()?.unlock?.(),!0)).then((e)=>e!==!1)},Ve={signInWithApple:(e={})=>v("signInWithApple",e.nonce?[{nonce:e.nonce}]:[],M).then((t)=>{if(!t||typeof t!=="object"||typeof t.userId!=="string")return null;return t})},Ge={isAvailable:()=>L("iap.purchase")!==null,products:(e)=>v("iap.getProducts",[e],()=>[]).then((t)=>Array.isArray(t)?t:[]),purchase:(e)=>v("iap.purchase",[e],M).then((t)=>t&&typeof t==="object"?t:null,(t)=>{if(/cancel/i.test(String(t?.message??t)))return null;throw t}),restore:()=>v("iap.restore",[],()=>[]).then((e)=>Array.isArray(e)?e:[])};function lr(e,t){let n=t.delay??500,r=t.tolerance??10,o=null,i=null,a=!1,s=()=>{if(o)clearTimeout(o);if(o=null,i&&!a)t.onPressEnd?.();i=null},l=(f)=>{let d=f;if(d.button!==void 0&&d.button!==0)return;a=!1,i={x:d.clientX,y:d.clientY},t.onPressStart?.(),o=setTimeout(()=>{if(o=null,!i)return;a=!0,t.onLongPress({...i}),i=null},n)},g=(f)=>{if(!i)return;let d=f;if(Math.hypot(d.clientX-i.x,d.clientY-i.y)>r)s()},p=(f)=>{if(!a)return;a=!1,f.preventDefault(),f.stopPropagation()},u=(f)=>f.preventDefault();return e.addEventListener("pointerdown",l),e.addEventListener("pointermove",g),e.addEventListener("pointerup",s),e.addEventListener("pointercancel",s),e.addEventListener("pointerleave",s),e.addEventListener("click",p,!0),e.addEventListener("contextmenu",u),()=>{s(),e.removeEventListener("pointerdown",l),e.removeEventListener("pointermove",g),e.removeEventListener("pointerup",s),e.removeEventListener("pointercancel",s),e.removeEventListener("pointerleave",s),e.removeEventListener("click",p,!0),e.removeEventListener("contextmenu",u)}}function Nt(e,t,n){if(n<=1||t.width<=0)return 0;let r=Math.floor((e-t.left)/t.width*n);return Math.max(0,Math.min(n-1,r))}function cr(e,t){let n=null,r=null,o=!1,i=0,a=(d)=>{let m=e.getBoundingClientRect();return Nt(d,{left:m.left+2,width:m.width-4},t.count())},s=(d)=>{let m=d;if(m.button!==void 0&&m.button!==0)return;let h=a(m.clientX);if(h!==t.selected())return;n=h,i=h,o=!1,r=m.pointerId;try{e.setPointerCapture?.(m.pointerId)}catch{}t.onPress?.(!0)},l=(d)=>{if(n===null)return;let m=a(d.clientX);if(m===i)return;o=!0,i=m,t.onScrub(m)},g=(d)=>{if(n===null)return;if(r!==null)try{e.releasePointerCapture?.(r)}catch{}if(t.onPress?.(!1),d&&o)t.onCommit(i);else if(o)t.onScrub(n);n=null,r=null},p=(d)=>{if(!o)return;o=!1,d.preventDefault(),d.stopPropagation()},u=()=>g(!0),f=()=>g(!1);return e.addEventListener("pointerdown",s),e.addEventListener("pointermove",l),e.addEventListener("pointerup",u),e.addEventListener("pointercancel",f),e.addEventListener("click",p,!0),()=>{e.removeEventListener("pointerdown",s),e.removeEventListener("pointermove",l),e.removeEventListener("pointerup",u),e.removeEventListener("pointercancel",f),e.removeEventListener("click",p,!0)}}function ur(e,t,n){if(n<=0)return null;switch(e){case"ArrowRight":case"ArrowDown":return(t+1)%n;case"ArrowLeft":case"ArrowUp":return(t-1+n)%n;case"Home":return 0;case"End":return n-1;default:return null}}function dr(e,t){e.querySelectorAll('[role="tab"]')[t]?.focus()}function pr(e){let t=(n)=>{if(!n.target?.closest?.("[data-native-pressable]"))return;let o=L("haptics.prepare");if(o)Promise.resolve().then(()=>o("impact")).catch(()=>{})};return e.addEventListener("touchstart",t,{passive:!0,capture:!0}),()=>e.removeEventListener("touchstart",t,{capture:!0})}function ye(e){let t=S();try{return Boolean(t?.matchMedia?.(e).matches)}catch{return!1}}function Xe(e){return e!==null&&e!==void 0&&e!=="false"&&e!=="0"}function Je(){let e=S()?.document?.documentElement,t=Number.parseFloat(e?.style?.getPropertyValue("--craft-font-scale")||"");return{fontScale:Number.isFinite(t)&&t>0?t:1,reduceMotion:Xe(e?.getAttribute("data-craft-reduce-motion"))||ye("(prefers-reduced-motion: reduce)"),reduceTransparency:Xe(e?.getAttribute("data-craft-reduce-transparency"))||ye("(prefers-reduced-transparency: reduce)"),colorScheme:e?.classList?.contains("dark")||ye("(prefers-color-scheme: dark)")?"dark":"light"}}function It(e){let t=Je(),n=Number(e?.fontScale);return{contentSizeCategory:typeof e?.contentSizeCategory==="string"?e.contentSizeCategory:void 0,fontScale:Number.isFinite(n)&&n>0?n:t.fontScale,reduceMotion:typeof e?.reduceMotion==="boolean"?e.reduceMotion:t.reduceMotion,reduceTransparency:typeof e?.reduceTransparency==="boolean"?e.reduceTransparency:t.reduceTransparency,colorScheme:e?.colorScheme==="dark"||e?.colorScheme==="light"?e.colorScheme:t.colorScheme}}function Qe(e,t={}){if(t.immediate!==!1)e(Je());return O("craftAppearance",(n)=>e(It(n)))}function hr(e){return O("craftResume",(t)=>e({backgroundedMs:Number(t.backgroundedMs)||0}))}function br(e){return O("craftMemoryWarning",()=>e())}function Ze(e){return(t)=>{Promise.resolve().then(()=>e(t)).then(()=>W.complete(!0),()=>W.complete(!1))}}function vr(e){let t=Ze(e);return O("craftSilentPush",(n)=>t(n.payload??{}))}function yr(e){let t=Ze(()=>e());return O("craftBackgroundRefresh",()=>t(void 0))}import{haptics as Ht}from"craft-native/mobile";function Se(){if(typeof window>"u")return;return window}function z(e=Se()){if(!e)return 0;if(typeof e.scrollY==="number")return e.scrollY;if(typeof e.scrollTop==="number")return e.scrollTop;return e.document?.scrollingElement?.scrollTop??0}function _t(e,t=Se()){if(!t)return()=>{};let n=!1,r=typeof requestAnimationFrame==="function"?requestAnimationFrame:(i)=>setTimeout(i,16),o=()=>{if(n)return;n=!0,r(()=>{n=!1,e(z(t))})};return e(z(t)),t.addEventListener("scroll",o,{passive:!0}),()=>t.removeEventListener("scroll",o)}function Dt(e,t){let n=Math.max(0,-e),r=e<=0?Math.max(0,t)*0.5:0;return Math.round(Math.max(n,r))}function wr(e){let t=e.host??Se();if(!t)return()=>{};let n=e.threshold??72,r=null,o=!1,i=!1,a=typeof requestAnimationFrame==="function"?requestAnimationFrame:(h)=>setTimeout(h,16),s=null,l=(h)=>{s=null,e.onPull?.(h,o,{bounce:Math.min(h,Math.max(0,-z(t)))})},g=(h)=>{let k=s!==null;if(s=h,k)return;a(()=>{if(s!==null)l(s)})},p=(h)=>{let k=h.touches?.[0];return k?k.clientY:null},u=(h)=>{if(i||z(t)>0)return;r=p(h),o=!1},f=(h)=>{if(r===null)return;let k=p(h);if(k===null)return;let C=Dt(z(t),k-r);if(!o&&C>=n)o=!0,Promise.resolve(Ht.impact("medium")).catch(()=>{});else if(o&&C<n*0.8)o=!1;g(C)},d=async()=>{if(r===null)return;if(r=null,!o){l(0);return}o=!1,i=!0,l(n);try{await e.onRefresh()}finally{i=!1,l(0)}},m=()=>{if(r===null)return;r=null,o=!1,l(0)};return t.addEventListener("touchstart",u,{passive:!0}),t.addEventListener("touchmove",f,{passive:!0}),t.addEventListener("touchend",d),t.addEventListener("touchcancel",m),()=>{s=null,t.removeEventListener("touchstart",u),t.removeEventListener("touchmove",f),t.removeEventListener("touchend",d),t.removeEventListener("touchcancel",m)}}function Bt(e,t=52){let n=Math.max(1,t),r=Math.min(1,Math.max(0,e/n)),o=e<0?1+Math.min(0.1,-e/600):1;return{progress:Math.round(r*1000)/1000,stretch:Math.round(o*1000)/1000}}function Ar(e,t={}){let n="",r=()=>t.title?.offsetHeight||t.height||52;return _t((o)=>{let i=Bt(o,r()),a=`${i.progress}|${i.stretch}`;if(a===n)return;n=a,e.style.setProperty("--native-nav-progress",String(i.progress)),e.style.setProperty("--native-nav-stretch",String(i.stretch)),t.onChange?.(i)},t.host)}function kr(e){if(!e||typeof window>"u")return;let t=window.document?.querySelector(e);return t?t:void 0}function nt(){if(typeof window>"u")return;return window}var et="__stxPushed",Ft="__stxScroll";function Kt(e=nt()){let t=e?.history?.state;if(t===null||t===void 0)return!1;if(typeof t!=="object")return!0;let n=t;if(et in n)return n[et]===!0;return!(Ft in n)}function Tr(e=nt()){if(!Kt(e))return!1;return e.history.back(),!0}function Rr(e,t,n=50){let r=e[e.length-1];if(e.length>=2&&e[e.length-2].path===t)e.pop();else if(!r||r.path!==t)e.push({path:t,title:""});if(e.length>n)e.splice(0,e.length-n);return{current:e[e.length-1],previous:e[e.length-2]??null}}function Lr(e,t,n=12){let r=e?.title.trim()??"";return r&&r.length<=n?r:t}function Mr(){if(typeof window>"u")return[];let e=window;return e.__stacksNavTrail??=[]}function $t(e){try{let t=new URL(e,"http://local");return`${t.pathname}${t.search}`}catch{return e}}function Pr(){if(typeof window>"u")return;let e=window.stxRouter;if(typeof e?.screens!=="function")return;let t=e.screens(),n=t.find((o)=>o.active);if(!n)return;let r=t.filter((o)=>o.tab===n.tab&&o.depth<n.depth);if(!r.length)return null;return $t(r.reduce((o,i)=>i.depth>o.depth?i:o).url)}function Cr(e=typeof window>"u"?void 0:window){let t=e?.stxRouter;if(typeof t?.screens!=="function"||typeof e?.history?.go!=="function")return!1;let n=t.screens(),r=n.find((a)=>a.active);if(!r)return!1;let o=n.filter((a)=>a.tab===r.tab&&a.depth<r.depth);if(!o.length)return!1;let i=o.reduce((a,s)=>s.depth<a.depth?s:a);return e.history.go(i.depth-r.depth),!0}function Or(e,t){for(let n=e.length-1;n>=0;n--)if(e[n].path===t)return e[n];return null}function qt(e,t=Ut()){let n;try{n=new URL(e)}catch{return null}let r=`${n.search}${n.hash}`;if(n.protocol==="http:"||n.protocol==="https:"){if(!t||n.origin!==t)return null;return`${n.pathname||"/"}${r}`}return`${`/${[n.host,n.pathname.replace(/^\/+/,"")].filter(Boolean).join("/")}`}${r}`}function Ut(){if(typeof window>"u")return;return window.location?.origin}var tt="stacks-mobile-deep-link";function Nr(e,t){let n=(r)=>{let o=qt(r);if(o)e(o)};return t.getInitialURL().then((r)=>{if(!r)return;try{if(sessionStorage.getItem(tt)===r)return;sessionStorage.setItem(tt,r)}catch{}n(r)}).catch(()=>{}),t.onLink((r,o)=>{if(o?.initial)return;n(r)})}var Hr=5000;function Wt(e,t,n=5000){let r=t.filter((o)=>Number.isFinite(o.timestamp)&&Number.isFinite(o.bpm)&&o.bpm>0).slice().sort((o,i)=>o.timestamp-i.timestamp);if(!r.length)return e.slice();return e.map((o)=>{let i=0,a=r.length;while(i<a){let p=i+a>>1;if(r[p].timestamp<o.timestamp)i=p+1;else a=p}let s=r[i],l=r[i-1],g=!s?l:!l?s:o.timestamp-l.timestamp<=s.timestamp-o.timestamp?l:s;if(!g||Math.abs(g.timestamp-o.timestamp)>n)return o;return{...o,heartRate:Math.round(g.bpm)}})}var zt=6371008.8,Yt=30,jt=Yt;function Vt(e,t){let n=Math.PI/180,r=(t.latitude-e.latitude)*n,o=(t.longitude-e.longitude)*n,i=Math.sin(r/2)**2+Math.cos(e.latitude*n)*Math.cos(t.latitude*n)*Math.sin(o/2)**2;return 2*zt*Math.asin(Math.min(1,Math.sqrt(i)))}function Gt(e,t=25){let n=new Set;return e.filter((r)=>Number.isFinite(r.latitude)&&Number.isFinite(r.longitude)&&Number.isFinite(r.timestamp)&&Math.abs(r.latitude)<=90&&Math.abs(r.longitude)<=180&&Number.isFinite(r.accuracy)&&r.accuracy>=0&&r.accuracy<=t).sort((r,o)=>r.timestamp-o.timestamp).filter((r)=>{if(n.has(r.timestamp))return!1;return n.add(r.timestamp),!0})}function rt(e,t={}){let n=Gt(e,t.maxAccuracyM??25),r=t.paceWindowS??30,o=[],i=0,a=0,s=null;for(let u of n){let f=o[o.length-1],d=s?(u.timestamp-s.timestamp)/1000:0;if(s=u,!f){o.push({fix:u,cumM:0});continue}if(d>jt){o.push({fix:u,cumM:i});continue}let m=(u.timestamp-f.fix.timestamp)/1000,h=Vt(f.fix,u),k=Math.min(10,Math.max(3,f.fix.accuracy,u.accuracy));if(h<k)continue;if(i+=h,m>0&&h/m>=0.5)a+=m;o.push({fix:u,cumM:i})}let l=o[o.length-1],g=null,p=null;if(l&&n.at(-1).timestamp-l.fix.timestamp<=r*1000){let u=l.fix.timestamp-r*1000,f=o.find((h)=>h.fix.timestamp>=u)??l,d=l.cumM-f.cumM,m=(l.fix.timestamp-f.fix.timestamp)/1000;if(d>=20&&m>0)p=d/m,g=m/(d/1000)}return{distanceM:i,movingS:a,paceSPerKm:g,averagePaceSPerKm:i>=50&&a>0?a/(i/1000):null,speedMps:p,accuracyM:n.length?n[n.length-1].accuracy:e.length?e[e.length-1].accuracy??null:null,fixes:n.length}}function _r(e){if(e==null||e<=0||!Number.isFinite(e)||e>3600)return"–";let t=Math.round(e);return`${Math.floor(t/60)}:${String(t%60).padStart(2,"0")}`}function Dr(e){return e!=null&&e>0&&Number.isFinite(e)?(e*3.6).toFixed(1):"–"}var ot={distanceM:0,movingS:0,paceSPerKm:null,averagePaceSPerKm:null,speedMps:null,accuracyM:null,fixes:0};function Br(e){let t=e.location,n=e.intervalMs??3000,r=ot,o=null,i=e.heartRate,a=!1,s=[],l=()=>typeof document<"u"&&document.visibilityState==="hidden",g=0,p=null,u=Promise.resolve(),f=null,d=!1;function m(x){let b=u.then(x);return u=b.then(()=>{},()=>{}),b}function h(){if(p)return p;let x=g;return p=(async()=>{let b=await t.readRecording();if(x===g&&!d)r=rt(b,e),e.onUpdate?.(r);return r})().finally(()=>{p=null}),p}function k(){if(C(),d)return;o=setInterval(()=>{if(!l())h().catch(()=>{})},n)}function C(){if(o)clearInterval(o);o=null}async function F(x){if(!i||!a)return;await x(i).catch(()=>{})}return{get stats(){return r},get heartRate(){return s},start(){return f=null,m(async()=>{if(await t.startRecording({enableHighAccuracy:!0,...e.locationOptions}),s=[],a=!!i?.isAvailable(),await F((x)=>x.startRecording()),g++,r={...ot},!d)e.onUpdate?.(r);return k(),r})},attach(){return m(async()=>{let x=await t.getRecordingState();if(!x?.active)return null;if(i?.isAvailable())a=!!(await i.getRecordingState().catch(()=>null))?.active;if(await h().catch(()=>{}),!x.paused)k();return x})},pause(){return m(async()=>{await t.pauseRecording(),await F((x)=>x.pauseRecording()),C(),await h().catch(()=>{})})},resume(){return m(async()=>{await t.resumeRecording(),await F((x)=>x.resumeRecording()),k()})},stop(){if(f)return f;return f=m(async()=>{C(),g++;let b=(await t.stopRecording())?.locations??[];if(i&&a){let y=await i.stopRecording().catch(()=>null);a=!1,s=y?.samples??[],b=Wt(b,s)}if(r=rt(b,e),!d)e.onUpdate?.(r);return b}).catch((x)=>{throw f=null,x}),f},dispose(){d=!0,g++,C()},refresh:h}}function Kr(e){return{startedAt:Number.isFinite(e)?e:null,pausedAt:null,pausedMs:0}}function $r(e,t){return e.startedAt===null||e.pausedAt!==null||!Number.isFinite(t)?e:{...e,pausedAt:Math.max(e.startedAt,t)}}function qr(e,t){return e.pausedAt===null||!Number.isFinite(t)?e:{...e,pausedAt:null,pausedMs:e.pausedMs+Math.max(0,t-e.pausedAt)}}function Ur(e,t){if(e.startedAt===null)return 0;let n=((e.pausedAt??t)-e.startedAt-e.pausedMs)/1000;return Number.isFinite(n)?Math.max(0,n):0}var zr=150;function Xt(e,t){let n=Math.PI/180,r=(t.latitude-e.latitude)*n,o=(t.longitude-e.longitude)*n,i=Math.sin(r/2)**2+Math.cos(e.latitude*n)*Math.cos(t.latitude*n)*Math.sin(o/2)**2;return 12742017.6*Math.asin(Math.min(1,Math.sqrt(i)))}function Z(e,t){let n=[...e].sort((r,o)=>r-o);return n[Math.min(n.length-1,Math.floor(t*n.length))]}function Yr(e,t){let n=(e||[]).filter((a)=>Number.isFinite(a?.latitude)&&Number.isFinite(a?.longitude)&&Math.abs(a.latitude)<=90&&Math.abs(a.longitude)<=180),r=n.filter((a)=>a.accuracy!=null).map((a)=>Number(a.accuracy)).filter((a)=>Number.isFinite(a)&&a>=0),o=r.length?Z(r,0.5):Number.POSITIVE_INFINITY,i=0;if(n.length){let a={latitude:Z(n.map((s)=>s.latitude),0.5),longitude:Z(n.map((s)=>s.longitude),0.5)};i=Z(n.map((s)=>Xt(a,s)),0.8)}if(n.length>=10&&i>150&&o<=15)return"outside";if(t<150)return"unsure";if(n.length<3||o>30||i<25)return"indoors";if(i<50&&o>10)return"indoors";return"unsure"}function jr(e,t={}){let r=String(e||"").trim().toLowerCase().replace(",",".").match(/^(\d+(?:\.\d*)?|\.\d+)\s*(km|k|m|mi)?$/);if(!r)return null;let o=Number(r[1]),i=r[2]||t.defaultUnit||(o>100?"m":"km"),a=i==="m"?o/1000:i==="mi"?o*1.609344:o;return Number.isFinite(a)&&a>=0&&a<=2000?Math.round(a*1000)/1000:null}var ne=new Set,it=!1,ee=null;function Jt(e){return e.isConnected&&e.getClientRects().length>0}function at(){return[...ne].find((e)=>Jt(e.element))}function te(){let e=at(),t=Boolean(e);if(t===it)return;if(it=t,t)I.enable(e?.tintColor?{tintColor:e.tintColor}:{});else I.disable()}function Qt(){let e=at();if(!e){I.end();return}Promise.resolve().then(()=>e.run()).catch(()=>{}).finally(()=>I.end())}function Xr(e,t){let n={element:e,tintColor:t.tintColor,run:t.onRefresh};ne.add(n);let r=e.ownerDocument?.defaultView;if(!ee){let o=I.onRefresh(Qt),i=()=>te();r?.addEventListener("stx:load",i),ee=()=>{o(),r?.removeEventListener("stx:load",i)}}return te(),r?.requestAnimationFrame?.(()=>te()),()=>{if(ne.delete(n),ne.size===0)ee?.(),ee=null;te()}}var Qr=0.5;function Zt(e,t,n){let r=[];if(n.includes("large")||n.length===0)r.push({name:"large",y:0});if(n.includes("medium"))r.push({name:"medium",y:Math.max(0,Math.round(e-t*0.5))});return r.push({name:"dismiss",y:Math.max(1,e)}),r.sort((o,i)=>o.y-i.y)}function en(e){let{y:t,velocity:n,stops:r}=e,o=r.filter((s)=>s.name!=="dismiss"),i=r.find((s)=>s.name==="dismiss");if(o.length===0)return"dismiss";if(n>0.5)return(r.filter((l)=>l.y>t+1)[0]??i).name;if(n<-0.5){let s=o.filter((l)=>l.y<t-1);return(s[s.length-1]??o[0]).name}let a=o[o.length-1];if(t>a.y+(i.y-a.y)*0.5)return"dismiss";return o.reduce((s,l)=>Math.abs(l.y-t)<Math.abs(s.y-t)?l:s).name}function tn(e,t=400){if(e<=0)return 0;return e*t*0.55/(t+e*0.55)}function Zr(e){let{panel:t}=e,n=null,r=[],o=0,i=()=>e.viewport?.()??t.ownerDocument?.defaultView?.innerHeight??800,a=()=>Zt(t.offsetHeight||t.getBoundingClientRect().height,i(),e.detents()),s=(p)=>{let u=p;if(u.button!==void 0&&u.button!==0)return;if(u.target?.closest?.("button, a, input, select, textarea, [role=button]"))return;let f=a().find((d)=>d.name===e.detent())?.y??0;n={y:u.clientY,base:f,pointerId:u.pointerId},o=f,r=[{y:f,t:u.timeStamp}],t.classList.add("is-dragging");try{p.currentTarget?.setPointerCapture?.(u.pointerId)}catch{}},l=(p)=>{if(!n)return;let u=p,f=n.base+u.clientY-n.y;o=f<0?-tn(-f):f,r.push({y:o,t:u.timeStamp});while(r.length>2&&u.timeStamp-r[0].t>100)r.shift();t.style.transform=`translateY(${o}px)`;let d=t.offsetHeight||1;t.parentElement?.style.setProperty("--native-sheet-presence",String(Math.max(0,Math.min(1,1-o/d))))},g=(p)=>{if(!n)return;let u=p;n=null;let f=r[0],d=Math.max(1,u.timeStamp-f.t),m=(o-f.y)/d;t.classList.remove("is-dragging"),t.style.transform="",t.parentElement?.style.removeProperty("--native-sheet-presence"),e.onSettle(en({y:o,velocity:m,stops:a()}))};for(let p of e.handles)p.addEventListener("pointerdown",s),p.addEventListener("pointermove",l),p.addEventListener("pointerup",g),p.addEventListener("pointercancel",g);return()=>{for(let p of e.handles)p.removeEventListener("pointerdown",s),p.removeEventListener("pointermove",l),p.removeEventListener("pointerup",g),p.removeEventListener("pointercancel",g)}}var st=0,xe="";function eo(e){let t=e.ownerDocument,n=[],r=e;while(r.parentElement&&r!==t.body){for(let a of Array.from(r.parentElement.children)){if(a===r||a.hasAttribute("inert")||a.hasAttribute("data-native-dialog"))continue;if(["SCRIPT","STYLE","TEMPLATE","LINK"].includes(a.tagName))continue;if(a.hasAttribute("data-native-sheet")&&a.getAttribute("aria-hidden")==="true")continue;a.setAttribute("inert",""),n.push(a)}r=r.parentElement}let o=t.documentElement;if(st++===0)xe=o.style.overflow||"",o.style.overflow="hidden";let i=!1;return()=>{if(i)return;i=!0;for(let a of n)a.removeAttribute("inert");if(--st===0)if(xe)o.style.overflow=xe;else o.style.removeProperty("overflow")}}function to(e){let t=e.ownerDocument;if(e.parentElement===t.body)return()=>{};let n=t.createComment("native-sheet");return e.parentNode?.insertBefore(n,e),t.body.appendChild(e),()=>{if(n.parentNode)n.parentNode.insertBefore(e,n);else e.remove();n.remove()}}function no(e,t){let n=e.documentElement;if(!t){n.removeAttribute("data-native-sheet-card");return}let r=e.defaultView,o=(r?.scrollY??0)+(r?.innerHeight??800)/2;n.style.setProperty("--native-sheet-card-origin",`${Math.round(o)}px`),n.setAttribute("data-native-sheet-card","")}function nn(e,t){e.style.setProperty("--native-font-scale",String(t.fontScale)),e.toggleAttribute("data-native-reduce-motion",t.reduceMotion),e.toggleAttribute("data-native-reduce-transparency",t.reduceTransparency)}function rn(e){let t=e.replace(/\s+/g,"").toLowerCase();return!t||t==="transparent"||/^rgba\(\d+,\d+,\d+,0(\.0+)?\)$/.test(t)||/\/0(\.0+)?\)$/.test(t)}function on(e){let t=e.defaultView;if(!t?.getComputedStyle)return null;for(let n of[e.body,e.documentElement]){if(!n)continue;let r=t.getComputedStyle(n).backgroundColor;if(r&&!rn(r))return r}return null}function an(e){if(e.documentElement.classList.contains("dark"))return!0;if(e.documentElement.classList.contains("light"))return!1;return Boolean(e.defaultView?.matchMedia?.("(prefers-color-scheme: dark)").matches)}function ao(e,t={}){let n=t.root??e.documentElement;U.setKeyboardAccessory(t.keyboardAccessory===!0);let r="",o="",i=()=>{let p=on(e);if(p&&p!==r)r=p,U.setUnderPageColor(p);let u=an(e)?"light":"dark";if(u!==o)o=u,Q.setStyle(u)},a=Qe((p)=>{nn(n,p),i()}),s=e.defaultView,l=typeof s?.MutationObserver==="function"?new s.MutationObserver(i):null;l?.observe(e.documentElement,{attributes:!0,attributeFilter:["class","style","data-theme"]});let g=s?.matchMedia?.("(prefers-color-scheme: dark)");return g?.addEventListener?.("change",i),s?.addEventListener("stx:load",i),i(),()=>{a(),l?.disconnect(),g?.removeEventListener?.("change",i),s?.removeEventListener("stx:load",i)}}var lo=64;var sn=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,ln=/^(?:0|[1-9]\d*)$/;function ct(e){let t=[],n=[],r=e&&typeof e==="object"&&!Array.isArray(e)?e:{};for(let[o,i]of Object.entries(r)){let a=i&&typeof i==="object"?i:null;if(!a){n.push(`spotlight kind "${o}" is not an object`);continue}let{slots:s,route:l}=a,g=typeof a.noun==="string"&&a.noun.trim()?a.noun.trim():"Item";if(!sn.test(o)||o.includes("-slot-")){n.push(`spotlight kind "${o}" is not a usable name: lowercase letters, digits and single dashes, and never "-slot-"`);continue}if(typeof s!=="number"||!Number.isInteger(s)||s<=0||s>64){n.push(`spotlight kind "${o}" needs slots between 1 and 64, not ${String(s)}`);continue}if(typeof l!=="string"||!l.startsWith("/")||!l.includes(":id")){n.push(`spotlight kind "${o}" needs a route starting with "/" and carrying ":id", not ${String(l)}`);continue}t.push({name:o,slots:s,route:l,noun:g})}return{kinds:t,problems:n}}function j(e,t){return e.find((n)=>n.name===t)??null}function Y(e,t,n){let r=j(e,t);if(!r||!Number.isInteger(n)||n<0||n>=r.slots)return null;return`${t}-slot-${n}`}function cn(e,t){if(typeof t!=="string")return null;let n=t.lastIndexOf("-slot-");if(n<=0)return null;let r=t.slice(0,n),o=t.slice(n+6);if(!ln.test(o))return null;let i=Number(o);return Y(e,r,i)===t?{kind:r,slot:i}:null}function ut(e){return e.flatMap((t)=>Array.from({length:t.slots},(n,r)=>`${t.name}-slot-${r}`))}function co(e,t){let n=e&&typeof e==="object"?e:{};if(n.enabled===!1)return[];let o=[...(Array.isArray(n.activityTypes)?n.activityTypes.filter((i)=>typeof i==="string"&&i.trim().length>0):[]).map((i)=>i.trim()),...ut(ct(n.kinds).kinds)];return[...new Set(o)].map((i)=>`${t}.${i}`)}function dt(e,t,n){let r=typeof n.name==="string"?n.name.replace(/\s+/g," ").trim():"";if(!r)return`${j(e,t)?.noun??"Item"} #${n.id}`;return r.length>120?`${r.slice(0,119).trimEnd()}…`:r}function un(e,t,n,r,o=Date.now()){let i=j(e,n);if(!i||!Number.isInteger(r.id)||r.id<=0)return null;let a=t.filter((m)=>m.kind===n),s=dt(e,n,r),l=a.find((m)=>m.itemId===r.id)??null,g=l?null:mn(a,i.slots),p=l||g!==null?null:gn(a),u=l?.slot??g??p?.slot;if(u===void 0||u===null)return null;let f={kind:n,slot:u,itemId:r.id,title:s,donatedAt:o},d=t.filter((m)=>m.kind!==n||m.slot!==u&&m.itemId!==r.id);return{entries:pt(e,[...d,f]),entry:f,evicted:p,changed:!l||l.title!==s}}function dn(e,t,n){let r=e.find((o)=>o.kind===t&&o.itemId===n)??null;return{entries:r?e.filter((o)=>o!==r):[...e],removed:r}}function pn(e,t,n){let r=cn(e,n);if(!r)return null;let o=t.find((a)=>a.kind===r.kind&&a.slot===r.slot),i=j(e,r.kind)?.route;return o&&i?i.replace(":id",String(o.itemId)):null}function fn(e,t){if(!Array.isArray(t))return[];let n=new Map,r=new Set;for(let o of t){if(!o||typeof o!=="object")continue;let i=o,{kind:a,slot:s,itemId:l,title:g,donatedAt:p}=i;if(typeof a!=="string"||typeof s!=="number"||Y(e,a,s)===null)continue;if(typeof l!=="number"||!Number.isInteger(l)||l<=0)continue;let u=`${a}-slot-${s}`,f=`${a}#${l}`;if(n.has(u)||r.has(f))continue;n.set(u,{kind:a,slot:s,itemId:l,title:typeof g==="string"&&g.trim()?g:dt(e,a,{id:l}),donatedAt:typeof p==="number"&&Number.isFinite(p)&&p>0?p:0}),r.add(f)}return pt(e,[...n.values()])}function pt(e,t){let n=new Map(e.map((r,o)=>[r.name,o]));return[...t].sort((r,o)=>(n.get(r.kind)??0)-(n.get(o.kind)??0)||r.slot-o.slot)}function mn(e,t){let n=new Set(e.map((r)=>r.slot));for(let r=0;r<t;r++)if(!n.has(r))return r;return null}function gn(e){return e.reduce((t,n)=>!t||n.donatedAt<t.donatedAt?n:t,null)}function hn(){let e=globalThis.craft;return e&&typeof e==="object"?e.siri:void 0}var bn="stacks_spotlight_index",vn=3000;function uo(e){let t=e.onProblem??((b)=>console.warn(`[spotlight] ${b}`)),n=Array.isArray(e.kinds)?{kinds:[...e.kinds],problems:[]}:ct(e.kinds);for(let b of n.problems)t(b);let r=e.enabled===!1?[]:n.kinds,o=e.storageKey??bn,i=e.legacyStorageKeys??[],a=e.timeoutMs??vn,s=e.now??(()=>Date.now()),l=e.bridge??hn,g=null;function p(){try{return typeof localStorage>"u"?null:localStorage}catch{return null}}function u(){if(g)return g;g=[];let b=p();if(!b)return g;try{let y=[o,...i].map((w)=>b.getItem(w)).find((w)=>w);g=y?fn(r,JSON.parse(y)):[]}catch{g=[]}return g}function f(b){g=b;let y=p();if(!y)return;try{y.setItem(o,JSON.stringify(b));for(let w of i)y.removeItem(w)}catch{}}async function d(b){if(!b)return null;let y;try{return await Promise.race([b,new Promise((w)=>{y=setTimeout(()=>w(null),a)})])}catch{return null}finally{if(y!==void 0)clearTimeout(y)}}let m=Promise.resolve();function h(b){let y=m.then(b,b);return m=y.catch(()=>{return}),y}async function k(b,y){let w=l()?.register;if(!w||r.length===0)return!1;return h(async()=>{let T=un(r,u(),b,y,s()),H=T&&Y(r,b,T.entry.slot);if(!T||!H)return!1;if(!T.changed)return f(T.entries),!0;let K=await d(w(T.entry.title,H))!==null;if(K)f(T.entries);return K})}async function C(b,y){let w=l()?.remove;if(!w)return!1;return h(async()=>{let{entries:T,removed:H}=dn(u(),b,y);if(!H)return!1;let K=Y(r,b,H.slot),St=K?await d(w(K))!==null:!1;return f(T),St})}async function F(b,y){let w=j(r,b)?.slots;if(!w||!l()?.register)return 0;let T=0;for(let H of[...y].slice(0,w).reverse())if(await k(b,H))T++;return T}async function x(){let b=l()?.remove;if(!b)return f([]),0;return h(async()=>{let y=0;for(let w of u()){let T=Y(r,w.kind,w.slot);if(T&&await d(b(T))!==null)y++}return f([]),y})}return{kinds:r,index:k,sync:F,remove:C,clear:x,routeFor:(b)=>pn(r,u(),b),entries:()=>u(),activityTypes:(b)=>ut(r).map((y)=>`${b}.${y}`),reset:()=>{g=null}}}var lt=["craftShortcut","craftSiriShortcut"];function po(e,t){let n=(r)=>{let o=r.detail,i=typeof o==="string"?o:o&&typeof o==="object"?o.action??o.type:null,a=typeof i==="string"?e.routeFor(i):null;if(a)t(a)};if(typeof globalThis.addEventListener!=="function")return()=>{};for(let r of lt)globalThis.addEventListener(r,n);return()=>{for(let r of lt)globalThis.removeEventListener(r,n)}}import{tabBar as yn}from"craft-native/mobile";var Sn=yn;function xn(e){return Array.from(e.querySelectorAll("a[data-native-tab]")).map((t)=>({id:t.getAttribute("href")||"",title:t.getAttribute("data-native-tab")||t.getAttribute("aria-label")||"",symbol:t.getAttribute("data-native-tab-symbol")||"circle",badge:(t.querySelector(".native-tab-badge")?.textContent||"").trim(),current:t.hasAttribute("data-stx-nav-current")||t.classList.contains("is-active")})).filter((t)=>t.id&&t.title)}function wn(e){return{tabs:e.map(({id:n,title:r,symbol:o,badge:i})=>i?{id:n,title:r,symbol:o,badge:i}:{id:n,title:r,symbol:o}),selected:e.find((n)=>n.current)?.id}}function mt(){if(typeof window>"u")return;let e=window.stxRouter;return e&&typeof e==="object"?e:void 0}function An(){return typeof mt()?.selectTab==="function"}function go(e,t={}){let n=(r)=>{if(An()||r.defaultPrevented)return;let o=r.target?.closest?.("a[data-native-tab]");if(!o||!e.contains(o))return;if(!o.hasAttribute("data-stx-nav-current")&&!o.classList.contains("is-active")&&o.getAttribute("aria-current")!=="page")return;r.preventDefault();let i=e.ownerDocument.defaultView;if(t.scrollToTop)t.scrollToTop();else i?.scrollTo?.({top:0,behavior:i.matchMedia?.("(prefers-reduced-motion: reduce)").matches?"auto":"smooth"});i?.dispatchEvent(new CustomEvent("stx:tabreselect",{detail:{href:o.getAttribute("href")||""}}))};return e.addEventListener("click",n),()=>e.removeEventListener("click",n)}function ft(e){let t=e.trim();return/^#[0-9a-f]{6}$/i.test(t)?t:void 0}var we="stacks:tab-bar-cover";function ho(e,t){if(t)e.setAttribute("data-native-covers-tab-bar","");else e.removeAttribute("data-native-covers-tab-bar");e.ownerDocument?.defaultView?.dispatchEvent(new Event(we))}function bo(e,t={}){let n=t.api??Sn;if(!n.isAvailable())return null;let r=t.hidden??(()=>Boolean(e.ownerDocument?.querySelector("[data-native-hide-tab-bar], [data-native-covers-tab-bar]"))),o=typeof getComputedStyle==="function"?getComputedStyle(e):null,i=ft(o?.getPropertyValue("--native-tab-active")||""),a=ft(o?.getPropertyValue("--native-tab-active-dark")||""),s="",l=()=>{if(r()){if(s!=="hidden")n.hide();s="hidden";return}let{tabs:f,selected:d}=wn(xn(e)),m=JSON.stringify({tabs:f,selected:d});if(m===s)return;let h=s&&s!=="hidden"?JSON.parse(s):null;if(h&&d&&JSON.stringify(h.tabs)===JSON.stringify(f))n.select(d);else n.set(f,{selected:d,tint:i,tintDark:a});s=m},g=typeof MutationObserver==="function"?new MutationObserver(l):null;g?.observe(e,{attributes:!0,attributeFilter:["data-stx-nav-current","class"],childList:!0,subtree:!0,characterData:!0});let p=n.onSelect((f)=>{let d=mt();if(d?.selectTab){d.selectTab(f);return}Array.from(e.querySelectorAll("a[data-native-tab]")).find((h)=>h.getAttribute("href")===f)?.click()}),u=()=>l();if(typeof window<"u")window.addEventListener("stx:load",u),window.addEventListener("stx:screen-shown",u),window.addEventListener(we,u);return l(),()=>{if(g?.disconnect(),p(),typeof window<"u")window.removeEventListener("stx:load",u),window.removeEventListener("stx:screen-shown",u),window.removeEventListener(we,u);n.hide()}}var Rn={isAvailable:()=>c(()=>Ae.isAvailable()),getBiometricType:()=>c(()=>Ae.getBiometricType()),authenticate:(e)=>c(()=>Ae.authenticate(e))},Ln={takePicture:(e)=>c(()=>oe.takePicture(e)),pickImage:()=>c(()=>oe.pickImage()),pickMultiple:(e)=>c(()=>oe.pickMultiple(e)),isAvailable:()=>c(()=>oe.isAvailable())},Mn={getInfo:()=>c(()=>D.getInfo()),getCapabilities:()=>c(()=>D.getCapabilities()),isMobile:()=>D.isMobile(),isIOS:()=>D.isIOS(),isAndroid:()=>D.isAndroid(),getLocale:()=>D.getLocale(),getTimezone:()=>D.getTimezone()},Pn=En,Cn={getCurrentPosition:(e)=>c(()=>N.getCurrentPosition(e)),watchPosition:(e,t)=>N.watchPosition(e,t),clearWatch:(e)=>N.clearWatch(e),startRecording:(e)=>c(()=>N.startRecording(e)),pauseRecording:()=>c(()=>N.pauseRecording()),resumeRecording:()=>c(()=>N.resumeRecording()),stopRecording:()=>c(()=>N.stopRecording()),getRecordingState:()=>c(()=>N.getRecordingState()),readRecording:()=>c(()=>N.readRecording())},On={show:(e)=>c(()=>ae.show(e)),schedule:(e)=>c(()=>ae.schedule(e)),cancelAll:()=>c(()=>ae.cancelAll()),setBadge:(e)=>c(()=>ae.setBadge(e))},Nn={check:(e)=>c(()=>G.check(e)),request:(e)=>c(()=>G.request(e)),checkMultiple:(e)=>c(()=>G.checkMultiple(e)),requestMultiple:(e)=>c(()=>G.requestMultiple(e)),openSettings:()=>c(()=>G.openSettings())},In={set:(e,t)=>c(()=>se.set(e,t)),get:(e)=>c(()=>se.get(e)),delete:(e)=>c(()=>se.delete(e)),clear:()=>c(()=>se.clear())},Hn={share:(e)=>c(()=>vt.share(e)),isAvailable:()=>vt.isAvailable()},_n={request:()=>c(()=>kn.request())},ce={impact:(e)=>Promise.resolve().then(()=>ie.impact(e)).catch(()=>{}),notification:(e)=>Promise.resolve().then(()=>ie.notification(e)).catch(()=>{}),selection:()=>Promise.resolve().then(()=>ie.selection()).catch(()=>{}),vibrate:(e)=>Promise.resolve().then(()=>ie.vibrate(e)).catch(()=>{}),prepare:(e)=>{let t=L("haptics.prepare");return t?Promise.resolve().then(()=>t(e)).then(()=>{},()=>{}):Promise.resolve()}};function yt(e){if(typeof e==="string")return e.trim()||null;if(!e||typeof e!=="object")return null;let t=e.url;return typeof t==="string"&&t.trim()?t:null}var Dn={async getInitialURL(){if(!await B())return null;return yt(await gt.getInitialURL?.())},onLink(e){let t=null,n=!1,r=()=>{if(n)return;t=gt.onLink?.((o,i)=>{let a=yt(o);if(a)e(a,{initial:i?.initial===!0})})??null};if(de()?.craft)r();else B().then(r);return()=>{n=!0,t?.()}}},wo={isAvailable:()=>le.isAvailable(),set:(e,t)=>le.set(e,t),remove:(e)=>le.remove(e),clear:()=>le.clear()},Bn={enable:()=>c(()=>ht.enable()),disable:()=>c(()=>ht.disable())},Fn={isAvailable:()=>re.isAvailable(),get:()=>c(()=>re.get()),set:(e)=>c(()=>re.set(e)),restore:()=>c(()=>re.restore())},Kn={isAvailable:()=>P.isAvailable(),supports:(e)=>P.supports(e),getAuthorizationStatus:()=>c(()=>P.getAuthorizationStatus()),requestAuthorization:()=>c(()=>P.requestAuthorization()),getNowPlaying:()=>c(()=>P.getNowPlaying()),play:()=>c(()=>P.play()),pause:()=>c(()=>P.pause()),togglePlayPause:()=>c(()=>P.togglePlayPause()),skipToNext:()=>c(()=>P.skipToNext()),skipToPrevious:(e)=>c(()=>P.skipToPrevious(e)),onChange:(e)=>_(()=>P.onChange(e))},$n={isAvailable:()=>A.isAvailable(),supports:(e)=>A.supports(e),getState:()=>c(()=>A.getState()),requestAuthorization:()=>c(()=>A.requestAuthorization()),scan:(e)=>c(()=>A.scan(e)),stopScan:()=>c(()=>A.stopScan()),getDevices:()=>c(()=>A.getDevices()),connect:(e)=>c(()=>A.connect(e)),reconnect:()=>c(()=>A.reconnect()),disconnect:(e)=>c(()=>A.disconnect(e)),startRecording:()=>c(()=>A.startRecording()),pauseRecording:()=>c(()=>A.pauseRecording()),resumeRecording:()=>c(()=>A.resumeRecording()),stopRecording:()=>c(()=>A.stopRecording()),getRecordingState:()=>c(()=>A.getRecordingState()),readRecording:(e)=>c(()=>A.readRecording(e)),onReading:(e)=>_(()=>A.onReading(e)),onDevice:(e)=>_(()=>A.onDevice(e)),onState:(e)=>_(()=>A.onState(e))},qn={isAvailable:()=>Te.isAvailable(),speak:(e,t)=>c(()=>Te.speak(e,t)),stop:()=>c(()=>Te.stop())},Un={getStatus:()=>c(()=>bt.getStatus()),onChange:(e)=>_(()=>bt.onChange(e))},Wn={register:()=>c(()=>Ee.register()),onToken:(e)=>Ee.onToken(e),onNotification:(e)=>_(()=>Ee.onNotification(e))},zn={requestAuthorization:(e,t)=>c(()=>V.requestAuthorization(e,t)),getData:(e,t)=>c(()=>V.getData(e,t)),saveWorkout:(e)=>c(()=>V.saveWorkout(e)),getWorkouts:(e)=>c(()=>V.getWorkouts(e)),getDailyStatistics:(e,t)=>c(()=>V.getDailyStatistics(e,t)),getHeartRateSamples:(e)=>v("health.getHeartRateSamples",[e??{}],()=>[]).then((t)=>Array.isArray(t)?t:[]),getSleepIntervals:(e)=>v("health.getSleepIntervals",[e??{}],()=>[]).then((t)=>Array.isArray(t)?t:[]),supports:(e)=>L(`health.${e}`)!==null},Yn={start:(e)=>c(()=>ke.start(e)),update:(e)=>c(()=>ke.update(e)),end:()=>c(()=>ke.end())},jn={send:(e)=>c(()=>X.send(e)),updateContext:(e)=>c(()=>X.updateContext(e)),isReachable:()=>c(()=>X.isReachable()),onMessage:(e)=>X.onMessage(e),onReachabilityChange:(e)=>X.onReachabilityChange(e)},Ao=Tn;function de(){return S()}function ue(){let e=de()?.craft;if(!e||typeof e!=="object")return null;if(!("platform"in e)||e.platform!=="ios"&&e.platform!=="android")return null;let t="capabilities"in e?e.capabilities:void 0,n=t&&typeof t==="object"&&!Array.isArray(t)?Object.fromEntries(Object.entries(t).filter(([,r])=>typeof r==="boolean")):{};return{platform:e.platform,capabilities:n}}function Re(){return ue()!==null}function Vn(e=2000){if(Re()||pe())return Promise.resolve(!0);let t=de();if(!t||!(t.craft||t.webkit?.messageHandlers?.craft))return Promise.resolve(!1);return new Promise((n)=>{let r=()=>{clearTimeout(o),t.removeEventListener("craftReady",r),n(Re())},o=setTimeout(r,e);t.addEventListener("craftReady",r,{once:!0})})}function Gn(e){let t=de();if(!t)return()=>{};if(ue()){let r=!1;return queueMicrotask(()=>{if(!r)e(new Event("craftReady"))}),()=>{r=!0}}let n=(r)=>{if(!ue())return;t.removeEventListener("craftReady",n),e(r)};return t.addEventListener("craftReady",n),()=>t.removeEventListener("craftReady",n)}async function Xn(e){await ce.impact("light");try{let t=await e();return await ce.notification("success"),t}catch(t){throw await ce.notification("error"),t}}var ko={get nativeBridge(){return ue()},biometrics:Rn,camera:Ln,device:Mn,haptics:ce,lifecycle:Pn,location:Cn,notifications:On,permissions:Nn,secureStorage:In,share:Hn,appReview:_n,deepLinks:Dn,keepAwake:Bn,brightness:Fn,music:Kn,heartRate:$n,speech:qn,network:Un,pushNotifications:Wn,health:zn,liveActivities:Yn,watchConnectivity:jn,dialog:q,contextMenu:ve,browser:Ke,symbols:$e,statusBar:Q,chrome:U,refresh:I,background:W,clipboard:qe,db:Ue,files:We,shortcuts:ze,widgets:Ye,orientation:je,auth:Ve,storeKit:Ge,isNativeMobile:Re,whenNative:Vn,onReady:Gn,withFeedback:Xn};export{Jn as BRIDGE_WAIT_MS,Hr as HEART_RATE_MATCH_MS,zr as INDOOR_CHECK_AFTER_S,lo as MAX_SPOTLIGHT_SLOTS_PER_KIND,Yt as ROUTE_GAP_S,Qr as SHEET_FLICK_VELOCITY,we as TAB_BAR_COVER_EVENT,c as afterBridge,_n as appReview,nn as applyAppearance,Wt as attachHeartRate,Ve as auth,Lr as backLabelFor,W as background,Rn as biometrics,J as bridgePending,Fn as brightness,Ke as browser,v as callNative,Ln as camera,Kt as canGoBack,U as chrome,qe as clipboard,or as confirmAction,ve as contextMenu,ho as coverTabBar,S as craftHost,xt as craftRoot,Br as createRouteRecorder,uo as createSpotlightIndex,Je as currentAppearance,Ue as db,qt as deepLinkPath,Dn as deepLinks,Mn as device,q as dialog,Rr as enterNavTrail,We as files,Vt as fixDistance,dr as focusSegment,Nr as followDeepLinks,ue as getNativeMobileBridge,Tr as goBack,Cr as goBackToTabRoot,go as handleTabReselect,ce as haptics,pe as hasNativeMobileHost,zn as health,$n as heartRate,Yr as indoorVerdict,ao as installNativeChrome,pr as installPressables,Re as isNativeMobile,Jt as isShown,Bn as keepAwake,Bt as largeTitleMetrics,Pn as lifecycle,to as liftToBody,Yn as liveActivities,Cn as location,eo as lockBackground,bo as mirrorTabBar,ko as mobile,Kn as music,kt as nativeFunction,L as nativeFunctionNow,wn as nativeTabs,Mr as navTrail,Un as network,It as normalizeAppearance,yt as normalizeDeepLinkURL,On as notifications,Ar as observeLargeTitle,lr as observeLongPress,Xr as observeNativeRefresh,_t as observePageScroll,wr as observePullToRefresh,cr as observeSegmentScrub,Zr as observeSheetDrag,Qe as onAppearance,yr as onBackgroundRefresh,O as onCraftEvent,br as onMemoryWarning,Gn as onMobileReady,hr as onResume,vr as onSilentPush,po as onSpotlightTap,je as orientation,_r as paceLabel,on as pageBackground,an as pageIsDark,z as pageScrollTop,$r as pauseSessionClock,Nn as permissions,Mt as placeMenu,un as placeSpotlightItem,Ie as presentActionSheet,Oe as presentAlert,fe as presentChoice,Ne as presentConfirm,He as presentContextMenu,no as presentPageAsCard,Pr as previousScreenPath,Dt as pullDistance,Wn as pushNotifications,fn as readSpotlightEntries,ct as readSpotlightKinds,xn as readTabLinks,I as refresh,dn as removeSpotlightItem,kr as resolveScrollHost,qr as resumeSessionClock,rt as routeStats,An as routerHandlesTabs,tn as rubberBand,In as secureStorage,Nt as segmentAt,ur as segmentForKey,Ur as sessionClockElapsed,en as settleSheet,Hn as share,Zt as sheetStops,ze as shortcuts,ir as showContextMenuFor,wo as snapshots,qn as speech,Dr as speedLabel,Ao as splash,Y as spotlightAction,ut as spotlightActions,co as spotlightActivityTypes,hn as spotlightBridge,j as spotlightKind,pn as spotlightRoute,cn as spotlightSlot,dt as spotlightTitle,Kr as startSessionClock,Q as statusBar,Ge as storeKit,_ as subscribeWhenReady,$e as symbols,Sn as tabBar,be as toNativeRect,Or as trailEntryFor,Lt as trapFocus,jr as typedDistanceKm,Gt as usableFixes,rr as useActionSheet,jn as watchConnectivity,B as whenBridgeReady,Vn as whenNativeMobile,Ye as widgets,Xn as withNativeFeedback};
package/dist/route.d.ts CHANGED
@@ -1,4 +1,11 @@
1
- import type { Location, LocationApi, LocationOptions, LocationRecordingState } from './types';
1
+ import type { HeartRateRecordingApi, HeartRateSample, Location, LocationApi, LocationOptions, LocationRecordingState } from './types';
2
+ /**
3
+ * The fixes with the heart rate of the reading nearest each one, when there
4
+ * is one within `maxGapMs`: a strap reads about once a second, a phone fixes
5
+ * about once a second, and neither waits for the other. A fix with no reading
6
+ * near it (the strap off, or not worn yet) keeps none.
7
+ */
8
+ export declare function attachHeartRate<T extends RouteFix>(fixes: readonly T[], samples: readonly HeartRateSample[], maxGapMs?: unknown): T[];
2
9
  /** Great-circle distance between two fixes, metres. */
3
10
  export declare function fixDistance(a: { latitude: number, longitude: number }, b: { latitude: number, longitude: number }): number;
4
11
  /** The fixes worth counting, oldest first: a known position, accurate enough. */
@@ -24,11 +31,14 @@ export declare function speedLabel(metresPerSecond: number | null | undefined):
24
31
  * in front. Reading pauses with the page hidden; the recording does not.
25
32
  */
26
33
  export declare function createRouteRecorder(options: RouteRecorderOptions): RouteRecorder;
34
+ /** A fix and a strap's reading further apart than this, ms, do not belong together. */
35
+ export declare const HEART_RATE_MATCH_MS: 5000;
27
36
  /** Fixes further apart than this, seconds, are a break in the route (a pause). */
28
37
  export declare const ROUTE_GAP_S: 30;
29
38
  /** A fix as Craft records it. */
30
39
  export declare interface RouteFix extends Location {
31
40
  altitudeAccuracy?: number
41
+ heartRate?: number
32
42
  }
33
43
  export declare interface RouteStats {
34
44
  distanceM: number
@@ -48,6 +58,7 @@ export declare interface RouteRecorderOptions extends RouteStatsOptions {
48
58
  onUpdate?: (stats: RouteStats) => void
49
59
  location: LocationApi
50
60
  locationOptions?: LocationOptions
61
+ heartRate?: HeartRateRecordingApi
51
62
  }
52
63
  export declare interface RouteRecorder {
53
64
  start: () => Promise<RouteStats>
@@ -58,4 +69,5 @@ export declare interface RouteRecorder {
58
69
  refresh: () => Promise<RouteStats>
59
70
  dispose: () => void
60
71
  readonly stats: RouteStats
72
+ readonly heartRate: HeartRateSample[]
61
73
  }
package/dist/types.d.ts CHANGED
@@ -70,6 +70,7 @@ export declare interface MobileApi {
70
70
  keepAwake: KeepAwakeApi
71
71
  brightness: BrightnessApi
72
72
  music: MusicApi
73
+ heartRate: HeartRateApi
73
74
  speech: SpeechApi
74
75
  network: NetworkApi
75
76
  pushNotifications: PushNotificationsApi
@@ -283,6 +284,70 @@ export declare interface NowPlaying {
283
284
  export declare interface MusicSkipOptions {
284
285
  restartAfter?: number
285
286
  }
287
+ /** A heart-rate strap, or a watch broadcasting its heart rate. */
288
+ export declare interface HeartRateDevice {
289
+ id: string
290
+ name: string
291
+ rssi: number | null
292
+ }
293
+ export declare interface HeartRateRecordingState {
294
+ id: string | null
295
+ active: boolean
296
+ paused: boolean
297
+ startedAt: number | null
298
+ sampleCount: number | null
299
+ }
300
+ export declare interface HeartRateState {
301
+ available: boolean
302
+ bluetooth: BluetoothState
303
+ authorization: HeartRateAuthorization
304
+ scanning: boolean
305
+ connection: HeartRateConnection
306
+ device: HeartRateDevice | null
307
+ lastDevice: HeartRateDevice | null
308
+ bpm: number | null
309
+ lastReadingAt: number | null
310
+ recording: HeartRateRecordingState
311
+ }
312
+ export declare interface HeartRateReading {
313
+ bpm: number
314
+ rrIntervals: number[]
315
+ contact: boolean | null
316
+ energyExpended: number | null
317
+ timestamp: number
318
+ deviceId: string | null
319
+ }
320
+ /** A reading as a recording keeps it. */
321
+ export declare interface HeartRateSample {
322
+ timestamp: number
323
+ bpm: number
324
+ rr?: number[]
325
+ }
326
+ /** The recording half of HeartRateApi: what a route recorder drives. */
327
+ export declare interface HeartRateRecordingApi {
328
+ isAvailable: () => boolean
329
+ startRecording: () => Promise<HeartRateRecordingState>
330
+ pauseRecording: () => Promise<HeartRateRecordingState>
331
+ resumeRecording: () => Promise<HeartRateRecordingState>
332
+ stopRecording: () => Promise<HeartRateRecordingState & { samples: HeartRateSample[] }>
333
+ getRecordingState: () => Promise<HeartRateRecordingState>
334
+ readRecording: (options?: { since?: number }) => Promise<HeartRateSample[]>
335
+ }
336
+ export declare interface HeartRateApi extends HeartRateRecordingApi {
337
+ isAvailable: () => boolean
338
+ supports: (method: HeartRateMethod) => boolean
339
+ getState: () => Promise<HeartRateState>
340
+ requestAuthorization: () => Promise<HeartRateAuthorization>
341
+ scan: (options?: { timeout?: number }) => Promise<HeartRateState>
342
+ stopScan: () => Promise<HeartRateState>
343
+ getDevices: () => Promise<HeartRateDevice[]>
344
+ connect: (id: string) => Promise<HeartRateState>
345
+ reconnect: () => Promise<HeartRateState>
346
+ disconnect: (options?: { forget?: boolean }) => Promise<HeartRateState>
347
+ onReading: (callback: (reading: HeartRateReading) => void) => () => void
348
+ onDevice: (callback: (device: HeartRateDevice) => void) => () => void
349
+ onState: (callback: (state: HeartRateState) => void) => () => void
350
+ }
286
351
  export declare interface MusicApi {
287
352
  isAvailable: () => boolean
288
353
  supports: (method: MusicMethod) => boolean
@@ -470,6 +535,14 @@ export type HapticKind = 'impact' | 'notification' | 'selection';
470
535
  export type MusicAuthorization = 'authorized' | 'denied' | 'restricted' | 'notDetermined' | 'unavailable';
471
536
  export type MusicPlaybackState = 'stopped' | 'playing' | 'paused' | 'interrupted' | 'seekingForward' | 'seekingBackward' | 'unknown';
472
537
  export type MusicMethod = 'getAuthorizationStatus' | 'requestAuthorization' | 'getNowPlaying' | 'play' | 'pause' | 'togglePlayPause' | 'skipToNext' | 'skipToPrevious' | 'observe';
538
+ /** Whether the person has let the app use Bluetooth. `unavailable` off a phone. */
539
+ export type HeartRateAuthorization = 'authorized' | 'denied' | 'restricted' | 'notDetermined' | 'unavailable';
540
+ /** The phone's Bluetooth radio; `unknown` until something has asked for it. */
541
+ export type BluetoothState = 'poweredOn' | 'poweredOff' | 'unauthorized' | 'unsupported' | 'resetting' | 'unknown';
542
+ /** A strap that drops out is asked for again (`reconnecting`) until `disconnect()`. */
543
+ export type HeartRateConnection = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';
544
+ export type HeartRateMethod = 'getState' | 'requestAuthorization' | 'scan' | 'stopScan' | 'getDevices' | 'connect' | 'reconnect' | 'disconnect'
545
+ | 'startRecording' | 'pauseRecording' | 'resumeRecording' | 'stopRecording' | 'getRecordingState' | 'readRecording';
473
546
  export type HealthDataType = | 'steps'
474
547
  | 'heartRate'
475
548
  | 'activeEnergy'
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/mobile",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.75.154",
5
+ "version": "0.75.156",
6
6
  "description": "Craft-powered native mobile runtime for Stacks and STX applications",
7
7
  "author": "Chris Breuer",
8
8
  "license": "MIT",
@@ -32,10 +32,10 @@
32
32
  "test": "bun test"
33
33
  },
34
34
  "dependencies": {
35
- "craft-native": ">=0.0.144"
35
+ "craft-native": ">=0.0.152"
36
36
  },
37
37
  "devDependencies": {
38
- "@stacksjs/build": "0.75.154",
38
+ "@stacksjs/build": "0.75.156",
39
39
  "better-dx": "^0.2.24"
40
40
  }
41
41
  }