✦
Animation extension with five named spring constants (earnedStandard, earnedSnappy, earnedGentle, earnedHeroReveal, earnedEntrance)
✦
AppTheme.Timing with five named sleep durations (autosaveDebounce, savedBadge, keyboardDismiss, scanConfirmation, launchOverlay)
✦
AppTheme.Spacing scale (micro 4pt through xxl 32pt)
✦
AppTheme.Size with named component dimensions (icon badges, comparison chip, insight ring, progress bar, rate card)
✦
nine ViewModifier-backed font helpers to AppTheme: earnedHeroFont, earnedResultFont, earnedInputFont, earnedInputFieldFont, earnedStatFont, earnedSymbolFont, earnedWordmarkFont, earnedStepTitleFont, earnedCompactWordmarkFont — each owns its @ScaledMetric internally so call sites need zero boilerplate
✦
AppTheme.Typography token namespace with nine base point sizes for use with @ScaledMetric
◆
25 animation call sites across CalculatorView, CalculatorViewModel, HistoryView, OnboardingView, DecisionButtonRow, LabeledSlider, PriceScannerViewModel, SettingsView, and TimeResultCard
◆
5 Task.sleep call sites in CalculatorView, HistoryView, PriceScannerView, and SettingsView
◆
all call sites in TimeResultCard, ShareCardView, CalculatorView, InsightsView, OnboardingView, PriceScannerView, and RateHeroCard to use the shared helpers; remove all per-view @ScaledMetric declarations for these roles
✱
build error: move rateDisplaySize @ScaledMetric from SettingsView to RateHeroCard where it is actually used
✱
build error: add @ScaledMetric heroSize and wordmarkSize to ShareCardView (they were declared on TimeResultCard but used in a separate struct)