profile_screen: SingleChildScrollView + Column eagerly built every event
card (all images, shadows, tiles) at once even when off-screen. Replaced
with CustomScrollView + SliverList so only visible tiles are built per
frame. Also switches to BouncingScrollPhysics for natural momentum.
contribute_screen: Each _formCard wrapped in RepaintBoundary so form
cards are isolated render layers — one card's repaint doesn't invalidate
its siblings. Added BouncingScrollPhysics to the form SingleChildScrollView.
calendar_screen: Blue gradient banner was Positioned(top:0) making it
sticky even as the user scrolled. Removed the fixed Positioned layer and
moved the gradient inside the CustomScrollView as the first sliver in a
Stack alongside the calendar card (which keeps its y=110 visual overlap).
Now the entire page — gradient, calendar, events — scrolls as one unit.
Fix 1: Replace overshooting Cubic(1.95) tab glider curve with
Curves.easeInOutCubic; reduce duration 450ms → 280ms
Fix 2: Replace marquee jumpTo() with animateTo(linear) for fluid scroll
Fix 3: Replace Image.network with CachedNetworkImage in search results
Fix 4: Replace Image.network with CachedNetworkImage in desktop cards
Fix 5: Wrap IndexedStack children in RepaintBoundary to isolate
repaints across tabs (Home/Calendar/Contribute/Profile)
Fix 6: Replace setState on PageView.onPageChanged with ValueNotifier
so only the carousel dots widget rebuilds on swipe
Fix 7: Wrap animated tab glider in RepaintBoundary
Fix 8: Replace shrinkWrap:true ListView with ConstrainedBox(maxHeight)
to eliminate O(n) layout pass in search results
Fix 9: Increase image cache to 200MB / 500 images in main()
- Add Leaderboard tab with top 3 podium, time/district filters, and ranking table
- Add Achievements tab with badge grid (locked/unlocked with progress bars)
- Implement AnimatedSwitcher for smooth tab content transitions
- Add demo data for leaderboard users and achievement badges
- Responsive layout for mobile and desktop views
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Replicate the web app's glass-radio-group animation on the Flutter
contribute screen. Key changes:
- Sliding white glider pill behind active tab using AnimatedPositioned
- Bouncy spring physics: Cubic(0.37, 1.95, 0.66, 0.56) matching the
web CSS cubic-bezier that overshoots and settles
- Glassmorphic container: semi-transparent white bg with white border
- AnimatedDefaultTextStyle for smooth color transitions (blue active,
white 0.7 opacity inactive)
- AnimatedSize for icon appear/disappear on active tab
- LayoutBuilder for responsive tab width calculation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>