The Material 3 migration in Flutter produced a predictable pattern. Teams call ColorScheme.fromSeed(seedColor: brandPurple) , look at the result, decide it is not their brand, and start passing explicit colours to every widget again. Six months later the app has two hundred hard-coded hex values, dark mode is a separate list of two hundred more, and changing the brand colour is a week of work. The thing that was skipped is the idea Material 3 is actually built on: you do not style widgets with colours, you assign them roles . A FilledButton does not have a purple background — it has a primary background with onPrimary content. Once that is true across the app, the palette becomes one object you can swap. The roles, and what each one is for ColorScheme has about thirty members. They are not thirty independent choices; they are pairs and families. Role Used for Its “on” pair primary The main action, filled buttons, active states onPrim...