import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'app_colors.dart'; import 'app_spacing.dart'; import 'app_typography.dart'; import 'theme_extensions.dart'; /// Authoritative Material 3 theme definitions for MotorSignal. class AppTheme { /// Dark Theme (Cockpit OLED). static ThemeData get darkTheme { const colorScheme = ColorScheme.dark( primary: AppColors.darkPrimary, onPrimary: AppColors.onBrand, primaryContainer: AppColors.brandContainerDark, onPrimaryContainer: AppColors.onBrandContainerDark, secondary: AppColors.darkSecondary, onSecondary: Color(0xFFFFFFFF), secondaryContainer: Color(0xFF311414), onSecondaryContainer: Color(0xFFFFDAD6), surface: AppColors.darkSurface, onSurface: AppColors.darkOnSurface, onSurfaceVariant: AppColors.darkOnSurfaceVariant, outline: AppColors.darkOutline, outlineVariant: AppColors.darkOutlineVariant, error: AppColors.semanticDanger, onError: Color(0xFFFFFFFF), ); return ThemeData( useMaterial3: true, brightness: Brightness.dark, colorScheme: colorScheme, scaffoldBackgroundColor: AppColors.darkBackground, fontFamily: AppTypography.fontBody, extensions: const [ MotorSignalThemeColors.dark, ], appBarTheme: const AppBarTheme( backgroundColor: Colors.transparent, elevation: 0, centerTitle: true, scrolledUnderElevation: 0, titleTextStyle: TextStyle( fontFamily: AppTypography.fontHeadline, fontSize: 15, fontWeight: FontWeight.w700, color: AppColors.darkOnSurface, ), iconTheme: IconThemeData(color: AppColors.darkOnSurface), actionsIconTheme: IconThemeData(color: AppColors.darkOnSurface), systemOverlayStyle: SystemUiOverlayStyle.light, ), cardTheme: CardThemeData( color: AppColors.darkSurfaceContainer, elevation: 0, margin: EdgeInsets.zero, shape: RoundedRectangleBorder( borderRadius: AppRadius.lgBorderRadius, side: const BorderSide(color: AppColors.darkOutlineVariant, width: 0.8), ), ), dialogTheme: DialogThemeData( backgroundColor: AppColors.darkSurfaceContainerHigh, elevation: 6, shape: RoundedRectangleBorder( borderRadius: AppRadius.lgBorderRadius, side: const BorderSide(color: AppColors.darkOutlineVariant, width: 0.8), ), titleTextStyle: AppTypography.headlineMd.copyWith(color: AppColors.darkOnSurface), contentTextStyle: AppTypography.bodyMd.copyWith(color: AppColors.darkOnSurfaceVariant), ), bottomSheetTheme: BottomSheetThemeData( backgroundColor: AppColors.darkSurfaceContainerHigh, modalBackgroundColor: AppColors.darkSurfaceContainerHigh, elevation: 12, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(AppRadius.xl)), ), ), segmentedButtonTheme: SegmentedButtonThemeData( style: ButtonStyle( visualDensity: VisualDensity.compact, tapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: WidgetStateProperty.all( RoundedRectangleBorder(borderRadius: AppRadius.mdBorderRadius), ), side: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return const BorderSide(color: AppColors.darkPrimary, width: 1.2); } return const BorderSide(color: AppColors.darkOutlineVariant, width: 0.8); }), backgroundColor: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return AppColors.darkPrimary.withValues(alpha: 0.12); } return AppColors.darkSurfaceContainer; }), foregroundColor: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return AppColors.darkPrimary; } return AppColors.darkOnSurfaceVariant; }), textStyle: WidgetStateProperty.all(AppTypography.button), ), ), filledButtonTheme: FilledButtonThemeData( style: FilledButton.styleFrom( backgroundColor: AppColors.darkPrimary, foregroundColor: const Color(0xFF0D0F13), minimumSize: const Size(AppSpacing.minTouchTarget, AppSpacing.minTouchTarget), shape: RoundedRectangleBorder(borderRadius: AppRadius.mdBorderRadius), textStyle: AppTypography.button, ), ), elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( backgroundColor: AppColors.darkSurfaceContainerHigh, foregroundColor: AppColors.darkOnSurface, minimumSize: const Size(AppSpacing.minTouchTarget, AppSpacing.minTouchTarget), shape: RoundedRectangleBorder(borderRadius: AppRadius.mdBorderRadius), textStyle: AppTypography.button, elevation: 1, ), ), outlinedButtonTheme: OutlinedButtonThemeData( style: OutlinedButton.styleFrom( foregroundColor: AppColors.darkPrimary, minimumSize: const Size(AppSpacing.minTouchTarget, AppSpacing.minTouchTarget), side: const BorderSide(color: AppColors.darkOutline, width: 1), shape: RoundedRectangleBorder(borderRadius: AppRadius.mdBorderRadius), textStyle: AppTypography.button, ), ), textButtonTheme: TextButtonThemeData( style: TextButton.styleFrom( foregroundColor: AppColors.darkPrimary, minimumSize: const Size(AppSpacing.minTouchTarget, AppSpacing.minTouchTarget), textStyle: AppTypography.button, ), ), inputDecorationTheme: InputDecorationTheme( filled: true, fillColor: AppColors.darkSurfaceContainer, contentPadding: const EdgeInsets.symmetric( horizontal: AppSpacing.lg, vertical: AppSpacing.md, ), border: OutlineInputBorder( borderRadius: AppRadius.mdBorderRadius, borderSide: const BorderSide(color: AppColors.darkOutline, width: 1), ), enabledBorder: OutlineInputBorder( borderRadius: AppRadius.mdBorderRadius, borderSide: const BorderSide(color: AppColors.darkOutline, width: 1), ), focusedBorder: OutlineInputBorder( borderRadius: AppRadius.mdBorderRadius, borderSide: const BorderSide(color: AppColors.cyberCyan, width: 1.5), ), errorBorder: OutlineInputBorder( borderRadius: AppRadius.mdBorderRadius, borderSide: const BorderSide(color: AppColors.hazardRed, width: 1.5), ), labelStyle: AppTypography.bodyMd.copyWith(color: AppColors.darkOnSurfaceVariant), hintStyle: AppTypography.bodyMd.copyWith(color: AppColors.darkOnSurfaceVariant.withValues(alpha: 0.6)), ), chipTheme: ChipThemeData( backgroundColor: AppColors.darkSurfaceContainer, shape: RoundedRectangleBorder( borderRadius: AppRadius.mdBorderRadius, side: const BorderSide(color: AppColors.darkOutline, width: 1), ), labelStyle: AppTypography.badgeLabel.copyWith(color: AppColors.darkOnSurface), padding: const EdgeInsets.symmetric(horizontal: AppSpacing.sm, vertical: AppSpacing.xs), ), dividerTheme: const DividerThemeData( color: AppColors.darkOutline, thickness: 1, space: 1, ), navigationBarTheme: NavigationBarThemeData( backgroundColor: AppColors.darkSurface, indicatorColor: AppColors.darkPrimary.withValues(alpha: 0.14), elevation: 0, labelTextStyle: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return AppTypography.telemetryLabel.copyWith(color: AppColors.darkPrimary); } return AppTypography.telemetryLabel.copyWith(color: AppColors.darkOnSurfaceVariant); }), ), navigationRailTheme: NavigationRailThemeData( backgroundColor: AppColors.darkSurface, indicatorColor: AppColors.darkPrimary.withValues(alpha: 0.14), elevation: 0, selectedLabelTextStyle: AppTypography.telemetryLabel.copyWith(color: AppColors.darkPrimary), unselectedLabelTextStyle: AppTypography.telemetryLabel.copyWith(color: AppColors.darkOnSurfaceVariant), ), snackBarTheme: SnackBarThemeData( backgroundColor: AppColors.darkSurfaceContainerHighest, contentTextStyle: AppTypography.bodyMd.copyWith(color: AppColors.darkOnSurface), shape: RoundedRectangleBorder( borderRadius: AppRadius.mdBorderRadius, side: const BorderSide(color: AppColors.darkOutlineVariant, width: 0.8), ), behavior: SnackBarBehavior.floating, ), ); } /// Light Theme (Daylight HUD). static ThemeData get lightTheme { const colorScheme = ColorScheme.light( primary: AppColors.lightPrimary, onPrimary: AppColors.onBrand, primaryContainer: AppColors.brandContainerLight, onPrimaryContainer: AppColors.onBrandContainerLight, secondary: AppColors.lightSecondary, onSecondary: Color(0xFFFFFFFF), secondaryContainer: Color(0xFFFDE8E8), onSecondaryContainer: Color(0xFF410002), surface: AppColors.lightSurface, onSurface: AppColors.lightOnSurface, onSurfaceVariant: AppColors.lightOnSurfaceVariant, outline: AppColors.lightOutline, outlineVariant: AppColors.lightOutlineVariant, error: AppColors.semanticDanger, onError: Color(0xFFFFFFFF), ); return ThemeData( useMaterial3: true, brightness: Brightness.light, colorScheme: colorScheme, scaffoldBackgroundColor: AppColors.lightBackground, fontFamily: AppTypography.fontBody, extensions: const [ MotorSignalThemeColors.light, ], appBarTheme: const AppBarTheme( backgroundColor: Colors.transparent, elevation: 0, centerTitle: true, scrolledUnderElevation: 0, titleTextStyle: TextStyle( fontFamily: AppTypography.fontHeadline, fontSize: 15, fontWeight: FontWeight.w700, color: AppColors.lightOnSurface, ), iconTheme: IconThemeData(color: AppColors.lightOnSurface), actionsIconTheme: IconThemeData(color: AppColors.lightOnSurface), systemOverlayStyle: SystemUiOverlayStyle.dark, ), cardTheme: CardThemeData( color: AppColors.lightSurfaceContainer, elevation: 0, margin: EdgeInsets.zero, shape: RoundedRectangleBorder( borderRadius: AppRadius.lgBorderRadius, side: const BorderSide(color: AppColors.lightOutlineVariant, width: 0.8), ), ), dialogTheme: DialogThemeData( backgroundColor: AppColors.lightSurfaceContainer, elevation: 6, shape: RoundedRectangleBorder( borderRadius: AppRadius.lgBorderRadius, side: const BorderSide(color: AppColors.lightOutlineVariant, width: 0.8), ), titleTextStyle: AppTypography.headlineMd.copyWith(color: AppColors.lightOnSurface), contentTextStyle: AppTypography.bodyMd.copyWith(color: AppColors.lightOnSurfaceVariant), ), bottomSheetTheme: BottomSheetThemeData( backgroundColor: AppColors.lightSurfaceContainer, modalBackgroundColor: AppColors.lightSurfaceContainer, elevation: 12, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(AppRadius.xl)), ), ), segmentedButtonTheme: SegmentedButtonThemeData( style: ButtonStyle( visualDensity: VisualDensity.compact, tapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: WidgetStateProperty.all( RoundedRectangleBorder(borderRadius: AppRadius.mdBorderRadius), ), side: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return const BorderSide(color: AppColors.lightPrimary, width: 1.2); } return const BorderSide(color: AppColors.lightOutlineVariant, width: 0.8); }), backgroundColor: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return AppColors.lightPrimary.withValues(alpha: 0.10); } return AppColors.lightSurfaceContainer; }), foregroundColor: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return AppColors.lightPrimary; } return AppColors.lightOnSurfaceVariant; }), textStyle: WidgetStateProperty.all(AppTypography.button), ), ), filledButtonTheme: FilledButtonThemeData( style: FilledButton.styleFrom( backgroundColor: AppColors.lightPrimary, foregroundColor: const Color(0xFFFFFFFF), minimumSize: const Size(AppSpacing.minTouchTarget, AppSpacing.minTouchTarget), shape: RoundedRectangleBorder(borderRadius: AppRadius.mdBorderRadius), textStyle: AppTypography.button, ), ), elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( backgroundColor: AppColors.lightSurfaceContainer, foregroundColor: AppColors.lightOnSurface, minimumSize: const Size(AppSpacing.minTouchTarget, AppSpacing.minTouchTarget), shape: RoundedRectangleBorder(borderRadius: AppRadius.mdBorderRadius), textStyle: AppTypography.button, elevation: 1, ), ), outlinedButtonTheme: OutlinedButtonThemeData( style: OutlinedButton.styleFrom( foregroundColor: AppColors.lightPrimary, minimumSize: const Size(AppSpacing.minTouchTarget, AppSpacing.minTouchTarget), side: const BorderSide(color: AppColors.lightOutline, width: 1), shape: RoundedRectangleBorder(borderRadius: AppRadius.mdBorderRadius), textStyle: AppTypography.button, ), ), textButtonTheme: TextButtonThemeData( style: TextButton.styleFrom( foregroundColor: AppColors.lightPrimary, minimumSize: const Size(AppSpacing.minTouchTarget, AppSpacing.minTouchTarget), textStyle: AppTypography.button, ), ), inputDecorationTheme: InputDecorationTheme( filled: true, fillColor: AppColors.lightSurfaceContainer, contentPadding: const EdgeInsets.symmetric( horizontal: AppSpacing.lg, vertical: AppSpacing.md, ), border: OutlineInputBorder( borderRadius: AppRadius.mdBorderRadius, borderSide: const BorderSide(color: AppColors.lightOutline, width: 1), ), enabledBorder: OutlineInputBorder( borderRadius: AppRadius.mdBorderRadius, borderSide: const BorderSide(color: AppColors.lightOutline, width: 1), ), focusedBorder: OutlineInputBorder( borderRadius: AppRadius.mdBorderRadius, borderSide: const BorderSide(color: AppColors.lightPrimary, width: 1.5), ), errorBorder: OutlineInputBorder( borderRadius: AppRadius.mdBorderRadius, borderSide: const BorderSide(color: AppColors.hazardRed, width: 1.5), ), labelStyle: AppTypography.bodyMd.copyWith(color: AppColors.lightOnSurfaceVariant), hintStyle: AppTypography.bodyMd.copyWith(color: AppColors.lightOnSurfaceVariant.withValues(alpha: 0.6)), ), chipTheme: ChipThemeData( backgroundColor: AppColors.lightSurfaceContainerHigh, shape: RoundedRectangleBorder( borderRadius: AppRadius.mdBorderRadius, side: const BorderSide(color: AppColors.lightOutline, width: 1), ), labelStyle: AppTypography.badgeLabel.copyWith(color: AppColors.lightOnSurface), padding: const EdgeInsets.symmetric(horizontal: AppSpacing.sm, vertical: AppSpacing.xs), ), dividerTheme: const DividerThemeData( color: AppColors.lightOutlineVariant, thickness: 1, space: 1, ), navigationBarTheme: NavigationBarThemeData( backgroundColor: AppColors.lightSurface, indicatorColor: AppColors.lightPrimary.withValues(alpha: 0.12), elevation: 0, labelTextStyle: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return AppTypography.telemetryLabel.copyWith(color: AppColors.lightPrimary); } return AppTypography.telemetryLabel.copyWith(color: AppColors.lightOnSurfaceVariant); }), ), navigationRailTheme: NavigationRailThemeData( backgroundColor: AppColors.lightSurface, indicatorColor: AppColors.lightPrimary.withValues(alpha: 0.12), elevation: 0, selectedLabelTextStyle: AppTypography.telemetryLabel.copyWith(color: AppColors.lightPrimary), unselectedLabelTextStyle: AppTypography.telemetryLabel.copyWith(color: AppColors.lightOnSurfaceVariant), ), snackBarTheme: SnackBarThemeData( backgroundColor: AppColors.lightSurfaceContainerHighest, contentTextStyle: AppTypography.bodyMd.copyWith(color: AppColors.lightOnSurface), shape: RoundedRectangleBorder( borderRadius: AppRadius.mdBorderRadius, side: const BorderSide(color: AppColors.lightOutline, width: 1), ), behavior: SnackBarBehavior.floating, ), ); } }