import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import '../theme/app_colors.dart'; class HomePage extends StatefulWidget { const HomePage({super.key}); @override State createState() => _HomePageState(); } class _HomePageState extends State with SingleTickerProviderStateMixin { late AnimationController _mascotController; late Animation _mascotAnimation; @override void initState() { super.initState(); // Mascot floating animation _mascotController = AnimationController( duration: const Duration(seconds: 4), vsync: this, )..repeat(reverse: true); _mascotAnimation = Tween(begin: -10, end: 10).animate( CurvedAnimation(parent: _mascotController, curve: Curves.easeInOut), ); } @override void dispose() { _mascotController.dispose(); super.dispose(); } void _handleConnect() { Navigator.of(context).pushNamed('/bluetooth'); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: Stack( children: [ // Gradient Background _buildGradientBackground(), SafeArea( child: Column( children: [ // Header (Logo) _buildHeader(), // Main Content (Mascot) Expanded(child: _buildBody()), // Footer (Button) _buildFooter(), ], ), ), ], ), ); } Widget _buildGradientBackground() { final size = MediaQuery.of(context).size; return Positioned.fill( child: Stack( children: [ // Layer 1 Positioned( top: -size.width * 0.2, left: -size.width * 0.2, width: size.width * 1.5, height: size.width * 1.5, child: Container( decoration: BoxDecoration( shape: BoxShape.circle, gradient: RadialGradient( colors: [ const Color(0xFFC4B5FD).withOpacity(0.4), // Violet tinge Colors.transparent, ], radius: 0.6, ), ), ), ), // Layer 2 Positioned( bottom: size.height * 0.1, right: -size.width * 0.3, width: size.width * 1.2, height: size.width * 1.2, child: Container( decoration: BoxDecoration( shape: BoxShape.circle, gradient: RadialGradient( colors: [ const Color(0xFF67E8F9).withOpacity(0.3), // Cyan tinge Colors.transparent, ], radius: 0.6, ), ), ), ), // Layer 3 Positioned( bottom: -size.width * 0.5, left: size.width * 0.1, width: size.width * 1.5, height: size.width * 1.5, child: Container( decoration: BoxDecoration( shape: BoxShape.circle, gradient: RadialGradient( colors: [ const Color(0xFFF9A8D4).withOpacity(0.3), // Pink tinge Colors.transparent, ], radius: 0.6, ), ), ), ), ], ), ); } Widget _buildHeader() { return Container( height: 80, alignment: Alignment.center, child: Text( 'Airhub', // Use Press Start 2P pixel font per HTML CSS style: GoogleFonts.pressStart2p( fontSize: 28, color: const Color(0xFF4B5563), // gray-600 per HTML letterSpacing: 2, // Crisp pixel-stepped shadows (0 blur) per HTML shadows: const [ Shadow( color: Color(0x40A78BFA), // rgba(139, 92, 246, 0.25) offset: Offset(1, 1), blurRadius: 0, ), Shadow( color: Color(0x26A78BFA), // rgba(139, 92, 246, 0.15) offset: Offset(2, 2), blurRadius: 0, ), ], ), ), ); } Widget _buildBody() { return Center( child: AnimatedBuilder( animation: _mascotAnimation, builder: (context, child) { return Transform.translate( offset: Offset(0, _mascotAnimation.value), child: child, ); }, child: Container( // Glow effect behind mascot decoration: BoxDecoration( shape: BoxShape.circle, boxShadow: [ BoxShadow( color: const Color(0xFF8B5CF6).withOpacity(0.3), blurRadius: 60, spreadRadius: 20, ), ], ), child: Image.asset( 'assets/www/home_mascot.png', width: 280, fit: BoxFit.contain, errorBuilder: (_, __, ___) => const Icon(Icons.adb, size: 200, color: Colors.grey), ), ), ), ); } Widget _buildFooter() { return Container( padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 56), child: Container( height: 58, // HTML: height: 58px constraints: const BoxConstraints(maxWidth: 300), // HTML: width: min(300px, 82vw) decoration: BoxDecoration( borderRadius: BorderRadius.circular(29), // HTML: border-radius: 29px gradient: AppColors.btnPrimaryGradient, // 5-layer box-shadow per HTML CSS --btn-primary-glow boxShadow: [ // 0 0 15px rgba(34, 211, 238, 0.35) - cyan outer glow BoxShadow( color: const Color(0xFF22D3EE).withOpacity(0.35), offset: Offset.zero, blurRadius: 15, ), // 0 0 30px rgba(99, 102, 241, 0.25) - indigo wider glow BoxShadow( color: const Color(0xFF6366F1).withOpacity(0.25), offset: Offset.zero, blurRadius: 30, ), // 0 6px 20px rgba(99, 102, 241, 0.4) - bottom shadow BoxShadow( color: const Color(0xFF6366F1).withOpacity(0.4), offset: const Offset(0, 6), blurRadius: 20, ), ], ), child: Stack( children: [ // Shine overlay (top half gradient) Positioned.fill( child: ClipRRect( borderRadius: BorderRadius.circular(29), child: DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.white.withOpacity(0.15), Colors.transparent, ], stops: const [0.0, 0.5], ), ), ), ), ), // Button content Material( color: Colors.transparent, child: InkWell( onTap: _handleConnect, borderRadius: BorderRadius.circular(29), child: Center( // HTML button has NO icon, only text "立即连接" child: Text( '立即连接', style: const TextStyle( fontFamily: 'Inter', fontSize: 17, // HTML: font-size: 17px fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: 0.5, ), ), ), ), ), ], ), ), ); } }