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),
);
}