diff --git a/app/CLAUDE.md b/app/CLAUDE.md
new file mode 100644
index 0000000..537f2ea
--- /dev/null
+++ b/app/CLAUDE.md
@@ -0,0 +1,26 @@
+
+# Recent Activity
+
+
+
+### Feb 19, 2026
+
+| ID | Time | T | Title | Read |
+|----|------|---|-------|------|
+| #5001 | 9:35 AM | 🔵 | Host Wrapper Located at Root Layout Level | ~153 |
+| #4964 | 9:23 AM | 🔴 | Added Host Wrapper to Root Layout | ~228 |
+| #4963 | 9:22 AM | ✅ | Root layout wraps Stack in View with pure black background | ~279 |
+| #4910 | 8:16 AM | 🟣 | Added Workout Detail and Complete Screen Routes | ~348 |
+
+### Feb 20, 2026
+
+| ID | Time | T | Title | Read |
+|----|------|---|-------|------|
+| #5224 | 1:24 PM | ✅ | Stage v1.1 files prepared for git commit - SwiftUI Button refactoring complete | ~434 |
+| #5206 | 1:03 PM | ⚖️ | SwiftUI component usage mandated for TabataFit app | ~349 |
+| #5115 | 8:57 AM | 🔵 | Root Layout Stack Configuration with Screen Animations | ~256 |
+| #5061 | 8:47 AM | 🔵 | Expo Router Tab Navigation Structure Found | ~196 |
+| #5053 | 8:23 AM | ✅ | Completed removal of all Host wrappers from application | ~255 |
+| #5052 | " | ✅ | Removed Host wrapper from root layout entirely | ~224 |
+| #5019 | 8:13 AM | 🔵 | Root layout properly wraps Stack with Host component | ~198 |
+
\ No newline at end of file
diff --git a/app/_layout.tsx b/app/_layout.tsx
index f13a8c1..ab66c29 100644
--- a/app/_layout.tsx
+++ b/app/_layout.tsx
@@ -1,60 +1,88 @@
-import { useEffect } from 'react';
-import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
-import { Stack } from 'expo-router';
-import { StatusBar } from 'expo-status-bar';
-import * as SplashScreen from 'expo-splash-screen';
-import 'react-native-reanimated';
+/**
+ * TabataFit Root Layout
+ * Expo Router v3 + Inter font loading
+ */
-import { useColorScheme } from '@/hooks/use-color-scheme';
-import { useIsOnboardingComplete } from '@/src/features/onboarding/hooks/useOnboarding';
+import { useCallback } from 'react'
+import { Stack } from 'expo-router'
+import { StatusBar } from 'expo-status-bar'
+import { View } from 'react-native'
+import * as SplashScreen from 'expo-splash-screen'
+import {
+ useFonts,
+ Inter_400Regular,
+ Inter_500Medium,
+ Inter_600SemiBold,
+ Inter_700Bold,
+ Inter_900Black,
+} from '@expo-google-fonts/inter'
-// Prevent splash screen from auto-hiding
-SplashScreen.preventAutoHideAsync();
+import { DARK } from '@/src/shared/constants/colors'
-export const unstable_settings = {
- anchor: '(tabs)',
-};
+SplashScreen.preventAutoHideAsync()
export default function RootLayout() {
- const colorScheme = useColorScheme();
- const isOnboardingComplete = useIsOnboardingComplete();
+ const [fontsLoaded] = useFonts({
+ Inter_400Regular,
+ Inter_500Medium,
+ Inter_600SemiBold,
+ Inter_700Bold,
+ Inter_900Black,
+ })
- // Hide splash screen once we have a definite state
- useEffect(() => {
- if (isOnboardingComplete !== undefined) {
- SplashScreen.hideAsync();
+ const onLayoutRootView = useCallback(async () => {
+ if (fontsLoaded) {
+ await SplashScreen.hideAsync()
}
- }, [isOnboardingComplete]);
+ }, [fontsLoaded])
- // Show nothing while Zustand hydrates from AsyncStorage
- if (isOnboardingComplete === undefined) {
- return null;
+ if (!fontsLoaded) {
+ return null
}
return (
-
-
-
+
+
-
-
-
-
-
-
- );
+ >
+
+
+
+
+
+
+
+
+ )
}
diff --git a/app/collection/[id].tsx b/app/collection/[id].tsx
new file mode 100644
index 0000000..9beec10
--- /dev/null
+++ b/app/collection/[id].tsx
@@ -0,0 +1,211 @@
+/**
+ * TabataFit Collection Detail Screen
+ * Shows collection info + ordered workout list
+ */
+
+import { useMemo } from 'react'
+import { View, StyleSheet, ScrollView, Pressable, Text as RNText } from 'react-native'
+import { useRouter, useLocalSearchParams } from 'expo-router'
+import { useSafeAreaInsets } from 'react-native-safe-area-context'
+import { LinearGradient } from 'expo-linear-gradient'
+import Ionicons from '@expo/vector-icons/Ionicons'
+
+import { useHaptics } from '@/src/shared/hooks'
+import { getCollectionById, getCollectionWorkouts, getTrainerById, COLLECTION_COLORS } from '@/src/shared/data'
+import { StyledText } from '@/src/shared/components/StyledText'
+
+import {
+ BRAND,
+ DARK,
+ TEXT,
+} from '@/src/shared/constants/colors'
+import { SPACING, LAYOUT } from '@/src/shared/constants/spacing'
+import { RADIUS } from '@/src/shared/constants/borderRadius'
+
+export default function CollectionDetailScreen() {
+ const insets = useSafeAreaInsets()
+ const router = useRouter()
+ const haptics = useHaptics()
+ const { id } = useLocalSearchParams<{ id: string }>()
+
+ const collection = id ? getCollectionById(id) : null
+ const workouts = useMemo(
+ () => id ? getCollectionWorkouts(id) : [],
+ [id]
+ )
+ const collectionColor = COLLECTION_COLORS[id ?? ''] ?? BRAND.PRIMARY
+
+ const handleBack = () => {
+ haptics.selection()
+ router.back()
+ }
+
+ const handleWorkoutPress = (workoutId: string) => {
+ haptics.buttonTap()
+ router.push(`/workout/${workoutId}`)
+ }
+
+ if (!collection) {
+ return (
+
+ Collection not found
+
+ )
+ }
+
+ const totalMinutes = workouts.reduce((sum, w) => sum + (w?.duration ?? 0), 0)
+ const totalCalories = workouts.reduce((sum, w) => sum + (w?.calories ?? 0), 0)
+
+ return (
+
+
+ {/* Hero Header */}
+
+
+
+
+
+
+
+
+ {collection.icon}
+ {collection.title}
+ {collection.description}
+
+
+
+
+ {workouts.length + ' workouts'}
+
+
+
+ {totalMinutes + ' min total'}
+
+
+
+ {totalCalories + ' cal'}
+
+
+
+
+
+ {/* Workout List */}
+
+ {workouts.map((workout, index) => {
+ if (!workout) return null
+ const trainer = getTrainerById(workout.trainerId)
+ return (
+ handleWorkoutPress(workout.id)}
+ >
+
+ {index + 1}
+
+
+ {workout.title}
+
+ {trainer?.name + ' \u00B7 ' + workout.duration + ' min \u00B7 ' + workout.level}
+
+
+
+ {workout.calories + ' cal'}
+
+
+
+ )
+ })}
+
+
+
+ )
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: DARK.BASE,
+ },
+ scrollView: {
+ flex: 1,
+ },
+ scrollContent: {},
+
+ // Hero
+ hero: {
+ height: 260,
+ overflow: 'hidden',
+ },
+ backButton: {
+ width: 44,
+ height: 44,
+ alignItems: 'center',
+ justifyContent: 'center',
+ margin: SPACING[3],
+ },
+ heroContent: {
+ position: 'absolute',
+ bottom: SPACING[5],
+ left: SPACING[5],
+ right: SPACING[5],
+ },
+ heroIcon: {
+ fontSize: 40,
+ marginBottom: SPACING[2],
+ },
+ heroStats: {
+ flexDirection: 'row',
+ gap: SPACING[4],
+ marginTop: SPACING[3],
+ },
+ heroStat: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: SPACING[1],
+ },
+
+ // Workout List
+ workoutList: {
+ paddingHorizontal: LAYOUT.SCREEN_PADDING,
+ paddingTop: SPACING[4],
+ gap: SPACING[2],
+ },
+ workoutCard: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingVertical: SPACING[3],
+ paddingHorizontal: SPACING[4],
+ backgroundColor: DARK.SURFACE,
+ borderRadius: RADIUS.LG,
+ gap: SPACING[3],
+ },
+ workoutNumber: {
+ width: 32,
+ height: 32,
+ borderRadius: 16,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ workoutNumberText: {
+ fontSize: 15,
+ fontWeight: '700',
+ },
+ workoutInfo: {
+ flex: 1,
+ gap: 2,
+ },
+ workoutMeta: {
+ alignItems: 'flex-end',
+ gap: 4,
+ },
+})
diff --git a/app/workout/category/[id].tsx b/app/workout/category/[id].tsx
new file mode 100644
index 0000000..15d24a0
--- /dev/null
+++ b/app/workout/category/[id].tsx
@@ -0,0 +1,209 @@
+/**
+ * TabataFit Category Detail Screen
+ * Filtered workout list for a specific category with level sub-filter
+ */
+
+import { useState, useMemo } from 'react'
+import { View, StyleSheet, ScrollView, Pressable, Text as RNText } from 'react-native'
+import { useRouter, useLocalSearchParams } from 'expo-router'
+import { useSafeAreaInsets } from 'react-native-safe-area-context'
+import Ionicons from '@expo/vector-icons/Ionicons'
+import {
+ Host,
+ Picker,
+} from '@expo/ui/swift-ui'
+
+import { useHaptics } from '@/src/shared/hooks'
+import { getWorkoutsByCategory, getTrainerById, CATEGORIES } from '@/src/shared/data'
+import { StyledText } from '@/src/shared/components/StyledText'
+import type { WorkoutCategory, WorkoutLevel } from '@/src/shared/types'
+
+import {
+ BRAND,
+ DARK,
+ TEXT,
+} from '@/src/shared/constants/colors'
+import { SPACING, LAYOUT } from '@/src/shared/constants/spacing'
+import { RADIUS } from '@/src/shared/constants/borderRadius'
+
+const LEVELS: { id: WorkoutLevel | 'all'; label: string }[] = [
+ { id: 'all', label: 'All Levels' },
+ { id: 'Beginner', label: 'Beginner' },
+ { id: 'Intermediate', label: 'Intermediate' },
+ { id: 'Advanced', label: 'Advanced' },
+]
+
+export default function CategoryDetailScreen() {
+ const insets = useSafeAreaInsets()
+ const router = useRouter()
+ const haptics = useHaptics()
+ const { id } = useLocalSearchParams<{ id: string }>()
+
+ const [selectedLevelIndex, setSelectedLevelIndex] = useState(0)
+
+ const selectedLevel = LEVELS[selectedLevelIndex].id
+ const category = CATEGORIES.find(c => c.id === id)
+ const categoryLabel = category?.label ?? id ?? 'Category'
+
+ const allWorkouts = useMemo(
+ () => (id && id !== 'all') ? getWorkoutsByCategory(id as WorkoutCategory) : [],
+ [id]
+ )
+
+ const filteredWorkouts = useMemo(() => {
+ if (selectedLevel === 'all') return allWorkouts
+ return allWorkouts.filter(w => w.level === selectedLevel)
+ }, [allWorkouts, selectedLevel])
+
+ const handleBack = () => {
+ haptics.selection()
+ router.back()
+ }
+
+ const handleWorkoutPress = (workoutId: string) => {
+ haptics.buttonTap()
+ router.push(`/workout/${workoutId}`)
+ }
+
+ return (
+
+ {/* Header */}
+
+
+
+
+ {categoryLabel}
+
+
+
+ {/* Level Filter */}
+
+
+ {
+ haptics.selection()
+ setSelectedLevelIndex(e.nativeEvent.index)
+ }}
+ variant="segmented"
+ options={LEVELS.map(l => l.label)}
+ color={BRAND.PRIMARY}
+ />
+
+
+
+
+ {filteredWorkouts.length + ' workouts'}
+
+
+
+ {filteredWorkouts.map((workout) => {
+ const trainer = getTrainerById(workout.trainerId)
+ return (
+ handleWorkoutPress(workout.id)}
+ >
+
+ {trainer?.name[0] ?? 'T'}
+
+
+ {workout.title}
+
+ {trainer?.name + ' \u00B7 ' + workout.duration + ' min \u00B7 ' + workout.level}
+
+
+
+ {workout.calories + ' cal'}
+
+
+
+ )
+ })}
+
+ {filteredWorkouts.length === 0 && (
+
+
+
+ No workouts found
+
+
+ )}
+
+
+ )
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: DARK.BASE,
+ },
+ header: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ paddingHorizontal: LAYOUT.SCREEN_PADDING,
+ paddingVertical: SPACING[3],
+ },
+ backButton: {
+ width: 44,
+ height: 44,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ filterContainer: {
+ paddingHorizontal: LAYOUT.SCREEN_PADDING,
+ marginBottom: SPACING[4],
+ },
+ scrollView: {
+ flex: 1,
+ },
+ scrollContent: {
+ paddingHorizontal: LAYOUT.SCREEN_PADDING,
+ },
+ workoutCard: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingVertical: SPACING[3],
+ paddingHorizontal: SPACING[4],
+ backgroundColor: DARK.SURFACE,
+ borderRadius: RADIUS.LG,
+ marginBottom: SPACING[2],
+ gap: SPACING[3],
+ },
+ workoutAvatar: {
+ width: 44,
+ height: 44,
+ borderRadius: 22,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ workoutInitial: {
+ fontSize: 18,
+ fontWeight: '700',
+ color: TEXT.PRIMARY,
+ },
+ workoutInfo: {
+ flex: 1,
+ gap: 2,
+ },
+ workoutMeta: {
+ alignItems: 'flex-end',
+ gap: 4,
+ },
+ emptyState: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ paddingVertical: SPACING[12],
+ },
+})