If you have 500 buttons using the exact same set of classes, you should of had a button class in the first place. Almost all my projects have their own button and form input classes for this exact reason!
Where utility-based CSS frameworks really start to shine is the other 75% of your codebase, where you're inventing clever class names, only to end up using them once.
This is also why Tailwind calls itself a utility-FIRST framework. Build things with utilities, and extract components to classes when the need arises. Avoiding early abstractions provides a lot of value (in any programming language for that matter). Not having to invent a name for every single piece of UI also saves a ton of headaches down the road.
But let's say there are 700 components, what's the alternative if we were using BEM? You'd have to change all the 700 CSS classes, breaking things everywhere thanks to cascades, inheritance, multiple selectors, and specificity. With Functional CSS, all you have to do is go to the markup, and change "bg-white" to "bg-offgrey", and nothing breaks.
I think the big shift started to happen when people started to say, let’s treat CSS like code and what would we expect of good code, and then all of these CSS Sacred Cows were then seen in a new light. The biggest of them all for me was ‘naming things are hard’, traditional CSS implies naming your classes is easy, and for a once off example it is always easy, but that approach is a lifetime commmitmnet to generating names on names just to add styles and this adds a naming things complexity burden that until recently has just been a generally unacknowleged invisible cost.