import 'package:flutter/material.dart'; /// Design tokens and themes for CityPulse (Civic Pro Minimal) class AppColors { // Primary civic colors static const Color civicBlue = Color(0xFF2563EB); static const Color civicBlueDark = Color(0xFF1E40AF); static const Color civicBlueLight = Color(0xFF3B82F6); // Secondary civic colors static const Color civicOrange = Color(0xFFF97316); static const Color civicOrangeLight = Color(0xFFFB923C); // Accent colors static const Color civicGreen = Color(0xFF22C55E); static const Color civicGreenLight = Color(0xFF4ADE80); // Enhanced neutral palette static const Color neutral0 = Color(0xFFFFFFFF); static const Color neutral10 = Color(0xFFF8FAFC); static const Color neutral20 = Color(0xFFF1F5F9); static const Color neutral30 = Color(0xFFE2E8F0); static const Color neutral40 = Color(0xFFCBD5E1); static const Color neutral50 = Color(0xFF94A3B8); static const Color neutral60 = Color(0xFF64748B); static const Color neutral70 = Color(0xFF475569); static const Color neutral80 = Color(0xFF334155); static const Color neutral90 = Color(0xFF1E293B); static const Color neutral100 = Color(0xFF0F172A); // Status colors with light variants static const Color success = Color(0xFF16A34A); static const Color successLight = Color(0xFF86EFAC); static const Color warning = Color(0xFFF59E0B); static const Color warningLight = Color(0xFFFCD34D); static const Color error = Color(0xFFDC2626); static const Color errorLight = Color(0xFFFCA5A5); static const Color info = Color(0xFF0EA5E9); static const Color infoLight = Color(0xFF7DD3FC); // Gradient colors static const Color surfaceGradient1 = Color(0xFFFAFAFA); static const Color surfaceGradient2 = Color(0xFFF8FAFC); // Legacy colors for backward compatibility static const Color brandPrimary = civicBlue; static const Color brandPrimaryDark = civicBlueDark; static const Color brandPrimaryLight = civicBlueLight; } class AppRadii { static const double xs = 6; static const double sm = 8; static const double md = 12; static const double lg = 16; static const double xl = 24; static const double pill = 100; } class AppSpacing { static const double x1 = 4; static const double x2 = 8; static const double x3 = 12; static const double x4 = 16; static const double x5 = 20; static const double x6 = 24; static const double x8 = 32; static const double x10 = 40; static const double x12 = 48; static const double x16 = 64; } class AppMotion { static const Duration fast = Duration(milliseconds: 120); static const Duration medium = Duration(milliseconds: 200); static const Duration slow = Duration(milliseconds: 300); static const Duration slower = Duration(milliseconds: 450); static const Curve standard = Curves.easeOutCubic; static const Curve accelerate = Curves.easeInCubic; static const Curve decelerate = Curves.easeOutCubic; static const Curve emphasize = Cubic(0.2, 0.0, 0.0, 1.0); } class AppThemes { static const PageTransitionsTheme transitions = PageTransitionsTheme( builders: { TargetPlatform.android: ZoomPageTransitionsBuilder(), TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), TargetPlatform.macOS: CupertinoPageTransitionsBuilder(), TargetPlatform.linux: FadeUpwardsPageTransitionsBuilder(), TargetPlatform.windows: FadeUpwardsPageTransitionsBuilder(), }, ); static ThemeData light() { final colorScheme = ColorScheme.fromSeed( seedColor: AppColors.civicBlue, brightness: Brightness.light, primary: AppColors.civicBlue, secondary: AppColors.civicOrange, ); return ThemeData( useMaterial3: true, colorScheme: colorScheme.copyWith( surfaceContainerLowest: AppColors.neutral10, surfaceContainerLow: AppColors.neutral20, surfaceContainer: AppColors.neutral20, surfaceContainerHigh: AppColors.neutral30, surfaceContainerHighest: AppColors.neutral40, ), scaffoldBackgroundColor: AppColors.surfaceGradient1, canvasColor: AppColors.surfaceGradient1, appBarTheme: AppBarTheme( backgroundColor: Colors.transparent, foregroundColor: colorScheme.onSurface, elevation: 0, centerTitle: false, titleTextStyle: TextStyle( color: colorScheme.onSurface, fontSize: 20, fontWeight: FontWeight.w600, ), shadowColor: Colors.transparent, ), elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( backgroundColor: colorScheme.primary, foregroundColor: colorScheme.onPrimary, padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24), textStyle: const TextStyle(fontWeight: FontWeight.w600, fontSize: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadii.xl), ), elevation: 2, shadowColor: colorScheme.primary.withOpacity(0.25), ), ), outlinedButtonTheme: OutlinedButtonThemeData( style: OutlinedButton.styleFrom( foregroundColor: colorScheme.primary, side: BorderSide(color: colorScheme.primary, width: 1.5), padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadii.xl), ), textStyle: const TextStyle(fontWeight: FontWeight.w600, fontSize: 16), ), ), textButtonTheme: TextButtonThemeData( style: TextButton.styleFrom( foregroundColor: colorScheme.primary, padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadii.md), ), textStyle: const TextStyle(fontWeight: FontWeight.w600, fontSize: 16), ), ), inputDecorationTheme: InputDecorationTheme( filled: true, fillColor: colorScheme.surfaceContainerHighest.withOpacity(0.5), border: OutlineInputBorder( borderRadius: BorderRadius.circular(AppRadii.lg), borderSide: BorderSide(color: AppColors.neutral30), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(AppRadii.lg), borderSide: BorderSide(color: AppColors.neutral30), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(AppRadii.lg), borderSide: BorderSide(color: colorScheme.primary, width: 1.6), ), contentPadding: const EdgeInsets.symmetric( vertical: AppSpacing.x4, horizontal: AppSpacing.x4, ), ), cardTheme: CardThemeData( color: colorScheme.surface, elevation: 1, margin: const EdgeInsets.all(0), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadii.lg), ), ), chipTheme: ChipThemeData( backgroundColor: colorScheme.surfaceContainerHighest, selectedColor: colorScheme.primary.withOpacity(0.14), secondarySelectedColor: colorScheme.primary.withOpacity(0.14), labelStyle: TextStyle(color: colorScheme.onSurface), secondaryLabelStyle: TextStyle(color: colorScheme.onSurface), brightness: Brightness.light, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadii.md), ), padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), ), dialogTheme: DialogThemeData( backgroundColor: colorScheme.surface, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadii.xl), ), ), snackBarTheme: SnackBarThemeData( backgroundColor: AppColors.neutral90, contentTextStyle: const TextStyle(color: Colors.white), behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadii.lg), ), ), bottomNavigationBarTheme: BottomNavigationBarThemeData( backgroundColor: colorScheme.surface, selectedItemColor: colorScheme.primary, unselectedItemColor: AppColors.neutral60, type: BottomNavigationBarType.fixed, selectedLabelStyle: const TextStyle(fontWeight: FontWeight.w600), ), pageTransitionsTheme: transitions, visualDensity: VisualDensity.standard, ); } static ThemeData dark() { final colorScheme = ColorScheme.fromSeed( seedColor: AppColors.brandPrimary, brightness: Brightness.dark, primary: AppColors.brandPrimaryLight, ); return ThemeData( useMaterial3: true, colorScheme: colorScheme, scaffoldBackgroundColor: AppColors.neutral100, canvasColor: AppColors.neutral100, appBarTheme: AppBarTheme( backgroundColor: colorScheme.surface, foregroundColor: colorScheme.onSurface, elevation: 0, centerTitle: false, titleTextStyle: TextStyle( color: colorScheme.onSurface, fontSize: 20, fontWeight: FontWeight.w600, ), ), elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( backgroundColor: colorScheme.primary, foregroundColor: colorScheme.onPrimary, padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 16), textStyle: const TextStyle(fontWeight: FontWeight.w600), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadii.lg), ), ), ), outlinedButtonTheme: OutlinedButtonThemeData( style: OutlinedButton.styleFrom( foregroundColor: colorScheme.primary, side: BorderSide(color: colorScheme.primary, width: 1.2), padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadii.lg), ), ), ), inputDecorationTheme: InputDecorationTheme( filled: true, fillColor: colorScheme.surfaceContainerHighest.withOpacity(0.3), border: OutlineInputBorder( borderRadius: BorderRadius.circular(AppRadii.lg), borderSide: BorderSide(color: AppColors.neutral80), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(AppRadii.lg), borderSide: BorderSide(color: AppColors.neutral80), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(AppRadii.lg), borderSide: BorderSide(color: colorScheme.primary, width: 1.6), ), contentPadding: const EdgeInsets.symmetric( vertical: AppSpacing.x4, horizontal: AppSpacing.x4, ), ), cardTheme: CardThemeData( color: colorScheme.surface, elevation: 1, margin: const EdgeInsets.all(0), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadii.lg), ), ), chipTheme: ChipThemeData( backgroundColor: colorScheme.surfaceContainerHighest.withOpacity(0.5), selectedColor: colorScheme.primary.withOpacity(0.22), secondarySelectedColor: colorScheme.primary.withOpacity(0.22), labelStyle: TextStyle(color: colorScheme.onSurface), secondaryLabelStyle: TextStyle(color: colorScheme.onSurface), brightness: Brightness.dark, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadii.md), ), padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), ), dialogTheme: DialogThemeData( backgroundColor: colorScheme.surface, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadii.xl), ), ), snackBarTheme: SnackBarThemeData( backgroundColor: AppColors.neutral90, contentTextStyle: const TextStyle(color: Colors.white), behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadii.lg), ), ), bottomNavigationBarTheme: BottomNavigationBarThemeData( backgroundColor: colorScheme.surface, selectedItemColor: colorScheme.primary, unselectedItemColor: AppColors.neutral60, type: BottomNavigationBarType.fixed, selectedLabelStyle: const TextStyle(fontWeight: FontWeight.w600), ), pageTransitionsTheme: transitions, visualDensity: VisualDensity.standard, ); } static ThemeData highContrast() { // High-contrast light theme with stronger borders and higher on-color contrast final base = light(); final cs = base.colorScheme; final highCs = cs.copyWith( primary: AppColors.brandPrimaryDark, onPrimary: Colors.white, surface: AppColors.neutral0, onSurface: AppColors.neutral100, surfaceTint: Colors.transparent, ); return base.copyWith( colorScheme: highCs, inputDecorationTheme: base.inputDecorationTheme.copyWith( border: OutlineInputBorder( borderRadius: BorderRadius.circular(AppRadii.lg), borderSide: BorderSide(color: AppColors.neutral80, width: 2), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(AppRadii.lg), borderSide: BorderSide(color: AppColors.neutral80, width: 2), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(AppRadii.lg), borderSide: BorderSide(color: highCs.primary, width: 2.2), ), ), elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( backgroundColor: highCs.primary, foregroundColor: highCs.onPrimary, padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 18), textStyle: const TextStyle(fontWeight: FontWeight.w700), ), ), outlinedButtonTheme: OutlinedButtonThemeData( style: OutlinedButton.styleFrom( side: BorderSide(color: highCs.primary, width: 2), ), ), snackBarTheme: base.snackBarTheme.copyWith( backgroundColor: Colors.black, contentTextStyle: const TextStyle( color: Colors.white, fontWeight: FontWeight.w700, ), ), ); } }