import 'package:flutter/material.dart'; class C { static const bg = Color(0xFFF4F2EC); static const outer = Color(0xFFE7E4DB); static const ink = Color(0xFF1F2A2E); static const muted = Color(0xFF5E6C71); // 4.9:1 on bg, 5.4:1 on white static const navy = Color(0xFF1B2A49); static const navyDeep = Color(0xFF101B33); static const chip = Color(0xFFE1E6F0); static const green = Color(0xFF2F7656); // 5.5:1 on white, 4.7:1 on greenTint static const greenTint = Color(0xFFE3F1EA); static const gold = Color(0xFFD4A64A); static const goldTint = Color(0xFFF7EBD0); static const goldText = Color(0xFF735614); // 5.4:1 on goldTint static const border = Color(0xFFE6E0D4); static const border2 = Color(0xFFC9CED8); static const placeholder = Color(0xFF7A8689); // hints and chevrons, 3.8:1 static const softOnNavy = Color(0xFFB8C2DA); static const red = Color(0xFFB04A37); // 5.4:1 on white static const redDeep = Color(0xFF953D2C); static const redTint = Color(0xFFFBE9E5); static const white = Colors.white; static const hover = Color(0xFFF8F7F3); static const focus = Color(0xFF3D5A99); // Overlays, shadows and disabled fills static const onNavy5 = Color(0x0DFFFFFF); static const onNavy8 = Color(0x14FFFFFF); static const onNavy20 = Color(0x33FFFFFF); static const goldSoft = Color(0x26D4A64A); static const goldGlow = Color(0x55D4A64A); static const shadowNavy = Color(0x331B2A49); static const shadowNav = Color(0x14101B33); static const disabled = Color(0xFFF0EEE8); static const fieldDisabled = Color(0xFFEFEDE6); static const skeleton = Color(0xFFECE8DF); } /// Width breakpoints, measured on the window, not the device. class Bp { static const medium = 600.0; // rail navigation, wider gutters static const expanded = 1024.0; // full sidebar static const pageMax = 1120.0; // widest content column static const readMax = 760.0; // detail and form screens } /// Horizontal padding that keeps content in a centred column of [max] width. double pageGutter(double width, [double max = Bp.pageMax]) { if (width < Bp.medium) return S.s20; final side = (width - max) / 2; return side > S.s32 ? side : S.s32; } /// Spacing scale (logical pixels). class S { static const s2 = 2.0; static const s4 = 4.0; static const s6 = 6.0; static const s8 = 8.0; static const s10 = 10.0; static const s12 = 12.0; static const s14 = 14.0; static const s16 = 16.0; static const s18 = 18.0; static const s20 = 20.0; static const s22 = 22.0; static const s24 = 24.0; static const s28 = 28.0; static const s32 = 32.0; static const s36 = 36.0; } /// Corner radii. class R { static const sm = 8.0; // checkbox, handles static const md = 12.0; // chips, tiles static const input = 14.0; // fields, small cards static const button = 16.0; static const card = 18.0; static const dialog = 24.0; static const hero = 28.0; // hero cards, sheets static const pill = 99.0; } TextStyle ts( double size, { FontWeight w = FontWeight.w500, Color c = C.ink, double? h, double? ls, }) => TextStyle( fontFamily: 'Inter', fontSize: size, fontWeight: w, color: c, height: h, letterSpacing: ls, // Tabular figures keep ticket counts, endings and rupee amounts aligned. fontFeatures: const [FontFeature.tabularFigures()], ); const w4 = FontWeight.w400; const w5 = FontWeight.w500; const w6 = FontWeight.w600; const w7 = FontWeight.w700; ThemeData buildTheme() { final scheme = ColorScheme.fromSeed( seedColor: C.navy, brightness: Brightness.light, ).copyWith( primary: C.navy, onPrimary: Colors.white, surface: C.bg, error: C.red, ); return ThemeData( useMaterial3: true, fontFamily: 'Inter', colorScheme: scheme, scaffoldBackgroundColor: C.bg, splashFactory: NoSplash.splashFactory, highlightColor: Colors.transparent, hoverColor: C.hover, focusColor: C.chip, tooltipTheme: TooltipThemeData( waitDuration: const Duration(milliseconds: 500), textStyle: ts(12, w: w5, c: Colors.white), decoration: BoxDecoration( color: C.navyDeep, borderRadius: BorderRadius.circular(R.sm), ), ), textSelectionTheme: const TextSelectionThemeData(cursorColor: C.navy), snackBarTheme: SnackBarThemeData( behavior: SnackBarBehavior.floating, backgroundColor: C.navyDeep, contentTextStyle: ts(13, w: w6, c: Colors.white), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(R.input), ), ), dialogTheme: DialogThemeData( backgroundColor: Colors.white, surfaceTintColor: Colors.transparent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(R.dialog), ), ), bottomSheetTheme: const BottomSheetThemeData( backgroundColor: Colors.white, surfaceTintColor: Colors.transparent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(R.hero)), ), ), ); }