export type Coordinate = { lat: number; lon: number; elevationM?: number; }; export type BikepackingProfileId = | 'loaded_gravel' | 'hardtail_bikepacking' | 'road_touring' | 'ebikepacking' | 'beginner_safe'; export type SleepPreference = | 'official_campsites' | 'mixed_budget' | 'indoor_only' | 'wild_where_legal' | 'any_safe_option'; export type PoiCategory = | 'water' | 'food' | 'sleep' | 'repair' | 'bailout' | 'charging' | 'emergency'; export type Confidence = | 'known_good' | 'high' | 'medium' | 'low' | 'unknown' | 'restricted' | 'conflicting'; export type WarningSeverity = 'info' | 'notice' | 'warning' | 'critical'; export type TripRequest = { start: Coordinate; end: Coordinate; viaPoints?: Coordinate[]; startDate?: string; endDate?: string; profile: BikepackingProfileId; sleepPreference: SleepPreference; dailyDistanceKm: { min: number; target: number; max: number }; dailyAscentM?: { target?: number; max?: number }; maxLoadedGradePercent?: number; preferredUnpavedPercent?: { min?: number; max?: number }; waterGapMaxKm?: number; foodGapMaxKm?: number; requireBailoutEveryKm?: number; }; export type RouteSegment = { id: string; geometry: Coordinate[]; distanceM: number; ascentM?: number; descentM?: number; avgGradePercent?: number; maxGradePercent?: number; surface?: string; smoothness?: string; highway?: string; bicycleAccess?: string; legalAccessConfidence: Confidence; trafficStress?: number; officialCycleRoute?: boolean; protectedAreaOverlap?: boolean; communityScore?: number; sourceConfidence: Confidence; }; export type RouteWarning = { code: string; severity: WarningSeverity; title: string; message: string; metersFromStart?: number; segmentId?: string; }; export type RoutePlan = { id: string; tripId: string; geometry: Coordinate[]; distanceM: number; ascentM: number; descentM: number; segments: RouteSegment[]; surfaceBreakdown: Record; suitabilityScore: number; warnings: RouteWarning[]; provider: string; }; export type Poi = { id: string; category: PoiCategory; name: string; location: Coordinate; source: string; confidence: Confidence; distanceFromRouteM?: number; metersFromStart?: number; detourDistanceM?: number; openingHours?: string; lastConfirmedAt?: string; tags?: Record; }; export type StagePlan = { id: string; routeId: string; dayIndex: number; startMeters: number; endMeters: number; distanceM: number; ascentM?: number; descentM?: number; expectedRideTimeMinutes?: { low: number; high: number }; sleepCandidates: Poi[]; waterPois: Poi[]; foodPois: Poi[]; repairPois: Poi[]; bailoutPois: Poi[]; warnings: RouteWarning[]; planB?: { earlierEndMeters?: number; laterEndMeters?: number; reason: string; }; }; export type OfflinePackManifest = { packId: string; tripId: string; routeId: string; createdAt: string; bbox: [number, number, number, number]; routeBufferKm: number; includedLayers: string[]; dataVersions: Record; files: Array<{ type: string; url?: string; path?: string; bytes?: number }>; warnings: RouteWarning[]; };