import 'package:flutter/material.dart'; // ── Color tokens ── const bgPrimary = Color(0xFF1a1a2e); const bgCard = Color(0xFF16213e); const bgInput = Color(0xFF111111); const bgPayPeriod = Color(0xFF1b2745); const accentGreen = Color(0xFF4ecca3); const accentAmber = Color(0xFFe8b86d); const accentRed = Color(0xFFe74c3c); const accentBlue = Color(0xFF5b9bd5); const textPrimary = Color(0xFFe0e0e0); const textMuted = Color(0xFF888888); const textDim = Color(0xFF6a6a6a); const borderColor = Color(0xFF333333); const dividerColor = Color(0xFF2a2a4a); // ── Typography ── const monoFont = 'Consolas'; const bodySize = 13.0; const labelSize = 12.0; const smallLabelSize = 11.0; // ── Spacing ── const rowHeight = 34.0; const cardPadding = 12.0; const cardGap = 12.0; // ── Priority enum ── enum BillPriority { green, yellow, red } // ── Payout position enum ── enum PayoutPosition { priority, notable } // ── Payment rule enums ── enum MathSource { totalIncome, // 0: sum of paycheck amounts ledgerRemaining, // 1: balance after non-rule deductions netBalance, // 2: ledger remaining - eating out - misc netMinusBuffer; // 3: net balance - buffer String get label => switch (this) { totalIncome => 'Total Income', ledgerRemaining => 'Ledger Remaining', netBalance => 'Net Balance', netMinusBuffer => 'Net − Buffer', }; } enum RuleType { minimum, // 0: fixed minimum amount math, // 1: multiplier * source + addition remainingBalance; // 2: pay outstanding balance String get label => switch (this) { minimum => 'Minimum', math => 'Math', remainingBalance => 'Remaining Bal', }; } // ── Reusable text styles ── const monoStyle = TextStyle(fontSize: bodySize, fontFamily: monoFont, color: textPrimary); const labelStyle = TextStyle(fontSize: smallLabelSize, color: textDim, letterSpacing: 0.5); const mutedStyle = TextStyle(fontSize: labelSize, color: textMuted); ThemeData buildAppTheme() { return ThemeData.dark().copyWith( scaffoldBackgroundColor: bgPrimary, colorScheme: const ColorScheme.dark( primary: accentGreen, surface: bgCard, error: accentRed, ), ); } // ── Formatting helpers ── String formatCents(int cents) { final negative = cents < 0; final abs = cents.abs(); final dollars = abs ~/ 100; final remainder = abs % 100; final formatted = '\$${_addCommas(dollars)}.${remainder.toString().padLeft(2, '0')}'; return negative ? '-$formatted' : formatted; } String formatCharge(int cents) { if (cents == 0) return '\$0.00'; final prefix = cents > 0 ? '+' : ''; return '$prefix${formatCents(cents)}'; } String _addCommas(int n) { final s = n.toString(); final buf = StringBuffer(); for (var i = 0; i < s.length; i++) { if (i > 0 && (s.length - i) % 3 == 0) buf.write(','); buf.write(s[i]); } return buf.toString(); }