/// Welcome screen with stacked sample cards and guide drawer. library; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../providers/values_sort_provider.dart'; import '../widgets/practice_chrome.dart'; class WelcomeScreen extends StatelessWidget { const WelcomeScreen({super.key}); @override Widget build(BuildContext context) { final text = Theme.of(context).textTheme; final colors = Theme.of(context).colorScheme; return PracticeScaffold( header: const Padding( padding: EdgeInsets.fromLTRB(12, 0, 12, 0), child: BrandMark(), ), footer: Column( children: [ GhostPillButton( label: 'How this practice works', icon: Icons.info_outline, onPressed: () => _showGuide(context), ), PrimaryPillButton( label: 'Begin Reflection', icon: Icons.arrow_forward, onPressed: () => context.read().beginPractice(), ), ], ), child: ListView( children: [ const SizedBox(height: 8), const _CardFan(), const SizedBox(height: 20), Text( 'Discover what matters most to you', textAlign: TextAlign.center, style: text.displaySmall, ), const SizedBox(height: 10), Text( 'Through a gentle, guided card-sort practice, clarify your intrinsic ' 'values and illuminate the principles that guide your everyday decisions.', textAlign: TextAlign.center, style: text.bodyLarge?.copyWith(color: colors.onSurfaceVariant), ), const SizedBox(height: 18), Wrap( alignment: WrapAlignment.center, crossAxisAlignment: WrapCrossAlignment.center, spacing: 8, runSpacing: 6, children: [ _Meta(icon: Icons.schedule, label: '10–15 min'), Text('•', style: text.labelMedium), _Meta(icon: Icons.timelapse, label: 'Self-paced'), Text('•', style: text.labelMedium), _Meta(icon: Icons.lock_outline, label: 'Private & reflective'), ], ), ], ), ); } Future _showGuide(BuildContext context) async { final controller = context.read(); await showModalBottomSheet( context: context, isScrollControlled: true, builder: (ctx) { final text = Theme.of(ctx).textTheme; final colors = Theme.of(ctx).colorScheme; return Padding( padding: EdgeInsets.only( left: 24, right: 24, top: 8, bottom: MediaQuery.paddingOf(ctx).bottom + 24, ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(Icons.diversity_3, color: colors.tertiary), const SizedBox(width: 8), Expanded( child: Text( 'The Practice of Sorting', style: text.titleLarge, ), ), IconButton( onPressed: () => Navigator.pop(ctx), icon: const Icon(Icons.close), ), ], ), const SizedBox(height: 8), Text( 'Grounded in contemplative psychology, this sorting practice ' 'helps clarify the core tenets that give your life meaning and direction.', style: text.bodyLarge?.copyWith(color: colors.onSurfaceVariant), ), const SizedBox(height: 16), const _GuideStep( index: 1, title: 'One card at a time', body: 'Review cards with diverse values one at a time, checking in with your intuition without overthinking.', ), const _GuideStep( index: 2, title: 'Sort into reflective piles', body: 'Place each card into Most, Very, Important, Somewhat, or Not Important — trusting your first honest response.', ), const _GuideStep( index: 3, title: 'Distill your top values', body: 'Narrow down to your core top values, then reflect so they can guide daily decisions with clarity.', ), const SizedBox(height: 12), Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: colors.surfaceContainerLow, borderRadius: BorderRadius.circular(16), border: Border.all(color: colors.outlineVariant), ), child: Row( children: [ Icon(Icons.spa, color: colors.tertiary, size: 18), const SizedBox(width: 10), Expanded( child: Text( 'There are no right or wrong answers—only your authentic presence.', style: text.bodyMedium?.copyWith( fontStyle: FontStyle.italic, ), ), ), ], ), ), const SizedBox(height: 16), PrimaryPillButton( label: "Got it, let's begin", onPressed: () { Navigator.pop(ctx); controller.beginPractice(); }, ), ], ), ); }, ); } } class _Meta extends StatelessWidget { const _Meta({required this.icon, required this.label}); final IconData icon; final String label; @override Widget build(BuildContext context) { final colors = Theme.of(context).colorScheme; final text = Theme.of(context).textTheme; return Row( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, size: 15, color: colors.tertiary), const SizedBox(width: 4), Text(label, style: text.labelMedium), ], ); } } class _GuideStep extends StatelessWidget { const _GuideStep({ required this.index, required this.title, required this.body, }); final int index; final String title; final String body; @override Widget build(BuildContext context) { final text = Theme.of(context).textTheme; final colors = Theme.of(context).colorScheme; return Padding( padding: const EdgeInsets.only(bottom: 14), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ CircleAvatar( radius: 12, backgroundColor: colors.surfaceContainerHigh, child: Text( '$index', style: text.labelMedium?.copyWith( color: colors.primary, fontWeight: FontWeight.w700, ), ), ), const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: text.titleMedium), const SizedBox(height: 2), Text(body, style: text.bodyMedium), ], ), ), ], ), ); } } class _CardFan extends StatelessWidget { const _CardFan(); @override Widget build(BuildContext context) { final text = Theme.of(context).textTheme; final colors = Theme.of(context).colorScheme; Widget mini({ required String domain, required String title, required String body, required double angle, required double dx, required double dy, bool hero = false, }) { return Transform.translate( offset: Offset(dx, dy), child: Transform.rotate( angle: angle, child: Container( width: hero ? 210 : 180, height: hero ? 155 : 135, padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: hero ? colors.surface : colors.surfaceContainer, borderRadius: BorderRadius.circular(20), border: Border.all(color: colors.outlineVariant), boxShadow: [ BoxShadow( color: colors.shadow.withValues(alpha: 0.08), blurRadius: hero ? 16 : 8, offset: const Offset(0, 4), ), ], ), child: ClipRect( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( domain.toUpperCase(), maxLines: 1, overflow: TextOverflow.ellipsis, style: text.labelSmall?.copyWith( color: hero ? colors.secondary : colors.onSurfaceVariant, letterSpacing: 1.2, ), ), ), if (hero) Icon(Icons.spa, size: 16, color: colors.primary), ], ), const SizedBox(height: 4), Text( title, maxLines: 1, overflow: TextOverflow.ellipsis, style: (hero ? text.headlineMedium : text.titleLarge) ?.copyWith(fontSize: hero ? 22 : 18, height: 1.1), ), const SizedBox(height: 4), Expanded( child: Text( body, maxLines: 3, overflow: TextOverflow.ellipsis, style: text.bodySmall, ), ), ], ), ), ), ), ); } return SizedBox( height: 210, child: Stack( alignment: Alignment.center, children: [ mini( domain: 'Experience', title: 'Adventure', body: 'To have new and exciting experiences.', angle: -0.21, dx: -48, dy: 10, ), mini( domain: 'Relation', title: 'Compassion', body: 'To feel and act on concern for others.', angle: 0.21, dx: 48, dy: 8, ), mini( domain: 'Core Ground', title: 'Genuineness', body: 'To act in a manner that is true to who I am.', angle: 0.02, dx: 0, dy: 4, hero: true, ), ], ), ); } }