import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; class AppSpacing { static const double xs = 4.0; static const double sm = 8.0; static const double md = 16.0; static const double lg = 24.0; static const double xl = 32.0; static const double xxl = 48.0; static const EdgeInsets paddingXs = EdgeInsets.all(xs); static const EdgeInsets paddingSm = EdgeInsets.all(sm); static const EdgeInsets paddingMd = EdgeInsets.all(md); static const EdgeInsets paddingLg = EdgeInsets.all(lg); static const EdgeInsets paddingXl = EdgeInsets.all(xl); static const EdgeInsets horizontalXs = EdgeInsets.symmetric(horizontal: xs); static const EdgeInsets horizontalSm = EdgeInsets.symmetric(horizontal: sm); static const EdgeInsets horizontalMd = EdgeInsets.symmetric(horizontal: md); static const EdgeInsets horizontalLg = EdgeInsets.symmetric(horizontal: lg); static const EdgeInsets horizontalXl = EdgeInsets.symmetric(horizontal: xl); static const EdgeInsets verticalXs = EdgeInsets.symmetric(vertical: xs); static const EdgeInsets verticalSm = EdgeInsets.symmetric(vertical: sm); static const EdgeInsets verticalMd = EdgeInsets.symmetric(vertical: md); static const EdgeInsets verticalLg = EdgeInsets.symmetric(vertical: lg); static const EdgeInsets verticalXl = EdgeInsets.symmetric(vertical: xl); } class AppRadius { static const double sm = 8.0; static const double md = 12.0; static const double lg = 16.0; static const double xl = 24.0; } extension TextStyleContext on BuildContext { TextTheme get textStyles => Theme.of(this).textTheme; } extension TextStyleExtensions on TextStyle { TextStyle get bold => copyWith(fontWeight: FontWeight.bold); TextStyle get semiBold => copyWith(fontWeight: FontWeight.w600); TextStyle get medium => copyWith(fontWeight: FontWeight.w500); TextStyle get normal => copyWith(fontWeight: FontWeight.w400); TextStyle get light => copyWith(fontWeight: FontWeight.w300); TextStyle withColor(Color color) => copyWith(color: color); TextStyle withSize(double size) => copyWith(fontSize: size); } /// Minimal Mauritanian-inspired palette (flag: green + gold), kept intentionally calm. class LightModeColors { static const lightPrimary = Color(0xFF0F6B3A); static const lightOnPrimary = Color(0xFFFFFFFF); static const lightPrimaryContainer = Color(0xFFDDF4E8); static const lightOnPrimaryContainer = Color(0xFF062716); static const lightSecondary = Color(0xFFD6A100); static const lightOnSecondary = Color(0xFF1B1400); static const lightTertiary = Color(0xFF1B2A24); static const lightOnTertiary = Color(0xFFFFFFFF); static const lightError = Color(0xFFBA1A1A); static const lightOnError = Color(0xFFFFFFFF); static const lightErrorContainer = Color(0xFFFFDAD6); static const lightOnErrorContainer = Color(0xFF410002); static const lightSurface = Color(0xFFFFFFFF); static const lightOnSurface = Color(0xFF0E1512); static const lightBackground = Color(0xFFF7F5EF); static const lightSurfaceVariant = Color(0xFFE9E6DD); static const lightOnSurfaceVariant = Color(0xFF3C4A44); static const lightOutline = Color(0xFF7C8B84); static const lightShadow = Color(0xFF000000); static const lightInversePrimary = Color(0xFF8AD8AE); } class DarkModeColors { static const darkPrimary = Color(0xFF4CD58C); static const darkOnPrimary = Color(0xFF062816); static const darkPrimaryContainer = Color(0xFF0A3D22); static const darkOnPrimaryContainer = Color(0xFFCFF3E0); static const darkSecondary = Color(0xFFFFD16A); static const darkOnSecondary = Color(0xFF261A00); static const darkTertiary = Color(0xFFE7E2D6); static const darkOnTertiary = Color(0xFF13130F); static const darkError = Color(0xFFFFB4AB); static const darkOnError = Color(0xFF690005); static const darkErrorContainer = Color(0xFF93000A); static const darkOnErrorContainer = Color(0xFFFFDAD6); static const darkSurface = Color(0xFF0D1411); static const darkOnSurface = Color(0xFFEAF1ED); static const darkSurfaceVariant = Color(0xFF1C2622); static const darkOnSurfaceVariant = Color(0xFFB8C7C0); static const darkOutline = Color(0xFF5D7067); static const darkShadow = Color(0xFF000000); static const darkInversePrimary = Color(0xFF0F6B3A); } class FontSizes { static const double displayLarge = 57.0; static const double displayMedium = 45.0; static const double displaySmall = 36.0; static const double headlineLarge = 32.0; static const double headlineMedium = 28.0; static const double headlineSmall = 24.0; static const double titleLarge = 22.0; static const double titleMedium = 16.0; static const double titleSmall = 14.0; static const double labelLarge = 14.0; static const double labelMedium = 12.0; static const double labelSmall = 11.0; static const double bodyLarge = 16.0; static const double bodyMedium = 14.0; static const double bodySmall = 12.0; } ThemeData get lightTheme => ThemeData( useMaterial3: true, splashFactory: NoSplash.splashFactory, highlightColor: Colors.transparent, splashColor: Colors.transparent, colorScheme: const ColorScheme.light( primary: LightModeColors.lightPrimary, onPrimary: LightModeColors.lightOnPrimary, primaryContainer: LightModeColors.lightPrimaryContainer, onPrimaryContainer: LightModeColors.lightOnPrimaryContainer, secondary: LightModeColors.lightSecondary, onSecondary: LightModeColors.lightOnSecondary, tertiary: LightModeColors.lightTertiary, onTertiary: LightModeColors.lightOnTertiary, error: LightModeColors.lightError, onError: LightModeColors.lightOnError, errorContainer: LightModeColors.lightErrorContainer, onErrorContainer: LightModeColors.lightOnErrorContainer, surface: LightModeColors.lightSurface, onSurface: LightModeColors.lightOnSurface, surfaceContainerHighest: LightModeColors.lightSurfaceVariant, onSurfaceVariant: LightModeColors.lightOnSurfaceVariant, outline: LightModeColors.lightOutline, shadow: LightModeColors.lightShadow, inversePrimary: LightModeColors.lightInversePrimary, ), brightness: Brightness.light, scaffoldBackgroundColor: LightModeColors.lightBackground, appBarTheme: const AppBarTheme( backgroundColor: Colors.transparent, foregroundColor: LightModeColors.lightOnSurface, elevation: 0, scrolledUnderElevation: 0, ), cardTheme: CardThemeData( elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide(color: LightModeColors.lightOutline.withValues(alpha: 0.20), width: 1), ), ), filledButtonTheme: FilledButtonThemeData( style: ButtonStyle( shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(14))), padding: const WidgetStatePropertyAll(EdgeInsets.symmetric(horizontal: 18, vertical: 14)), textStyle: WidgetStatePropertyAll(GoogleFonts.inter(fontWeight: FontWeight.w700)), ), ), outlinedButtonTheme: OutlinedButtonThemeData( style: ButtonStyle( shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(14))), padding: const WidgetStatePropertyAll(EdgeInsets.symmetric(horizontal: 18, vertical: 14)), textStyle: WidgetStatePropertyAll(GoogleFonts.inter(fontWeight: FontWeight.w700)), ), ), textTheme: _buildTextTheme(Brightness.light), ); ThemeData get darkTheme => ThemeData( useMaterial3: true, splashFactory: NoSplash.splashFactory, highlightColor: Colors.transparent, splashColor: Colors.transparent, colorScheme: const ColorScheme.dark( primary: DarkModeColors.darkPrimary, onPrimary: DarkModeColors.darkOnPrimary, primaryContainer: DarkModeColors.darkPrimaryContainer, onPrimaryContainer: DarkModeColors.darkOnPrimaryContainer, secondary: DarkModeColors.darkSecondary, onSecondary: DarkModeColors.darkOnSecondary, tertiary: DarkModeColors.darkTertiary, onTertiary: DarkModeColors.darkOnTertiary, error: DarkModeColors.darkError, onError: DarkModeColors.darkOnError, errorContainer: DarkModeColors.darkErrorContainer, onErrorContainer: DarkModeColors.darkOnErrorContainer, surface: DarkModeColors.darkSurface, onSurface: DarkModeColors.darkOnSurface, surfaceContainerHighest: DarkModeColors.darkSurfaceVariant, onSurfaceVariant: DarkModeColors.darkOnSurfaceVariant, outline: DarkModeColors.darkOutline, shadow: DarkModeColors.darkShadow, inversePrimary: DarkModeColors.darkInversePrimary, ), brightness: Brightness.dark, scaffoldBackgroundColor: DarkModeColors.darkSurface, appBarTheme: const AppBarTheme( backgroundColor: Colors.transparent, foregroundColor: DarkModeColors.darkOnSurface, elevation: 0, scrolledUnderElevation: 0, ), cardTheme: CardThemeData( elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide(color: DarkModeColors.darkOutline.withValues(alpha: 0.20), width: 1), ), ), filledButtonTheme: FilledButtonThemeData( style: ButtonStyle( shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(14))), padding: const WidgetStatePropertyAll(EdgeInsets.symmetric(horizontal: 18, vertical: 14)), textStyle: WidgetStatePropertyAll(GoogleFonts.inter(fontWeight: FontWeight.w700)), ), ), outlinedButtonTheme: OutlinedButtonThemeData( style: ButtonStyle( shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(14))), padding: const WidgetStatePropertyAll(EdgeInsets.symmetric(horizontal: 18, vertical: 14)), textStyle: WidgetStatePropertyAll(GoogleFonts.inter(fontWeight: FontWeight.w700)), ), ), textTheme: _buildTextTheme(Brightness.dark), ); TextTheme _buildTextTheme(Brightness brightness) { // Keep Inter for a modern look; Arabic glyph support relies on system fallback. return TextTheme( displayLarge: GoogleFonts.inter(fontSize: FontSizes.displayLarge, fontWeight: FontWeight.w400, letterSpacing: -0.25), displayMedium: GoogleFonts.inter(fontSize: FontSizes.displayMedium, fontWeight: FontWeight.w400), displaySmall: GoogleFonts.inter(fontSize: FontSizes.displaySmall, fontWeight: FontWeight.w400), headlineLarge: GoogleFonts.inter(fontSize: FontSizes.headlineLarge, fontWeight: FontWeight.w600, letterSpacing: -0.5), headlineMedium: GoogleFonts.inter(fontSize: FontSizes.headlineMedium, fontWeight: FontWeight.w600), headlineSmall: GoogleFonts.inter(fontSize: FontSizes.headlineSmall, fontWeight: FontWeight.w600), titleLarge: GoogleFonts.inter(fontSize: FontSizes.titleLarge, fontWeight: FontWeight.w600), titleMedium: GoogleFonts.inter(fontSize: FontSizes.titleMedium, fontWeight: FontWeight.w500), titleSmall: GoogleFonts.inter(fontSize: FontSizes.titleSmall, fontWeight: FontWeight.w500), labelLarge: GoogleFonts.inter(fontSize: FontSizes.labelLarge, fontWeight: FontWeight.w500, letterSpacing: 0.1), labelMedium: GoogleFonts.inter(fontSize: FontSizes.labelMedium, fontWeight: FontWeight.w500, letterSpacing: 0.5), labelSmall: GoogleFonts.inter(fontSize: FontSizes.labelSmall, fontWeight: FontWeight.w500, letterSpacing: 0.5), bodyLarge: GoogleFonts.inter(fontSize: FontSizes.bodyLarge, fontWeight: FontWeight.w400, letterSpacing: 0.15), bodyMedium: GoogleFonts.inter(fontSize: FontSizes.bodyMedium, fontWeight: FontWeight.w400, letterSpacing: 0.25), bodySmall: GoogleFonts.inter(fontSize: FontSizes.bodySmall, fontWeight: FontWeight.w400, letterSpacing: 0.4), ); }