The idea often ignored is: Choose the abstraction, which is simplest, yet powerful enough to express what you need to express and still allows for simple modification / extensibility of the code.
In many cases, that is a function. Functions you can keep mostly on the same level of nested-ness. Occasionally you will have a higher-order thingy. A class, which gets instanciated but then the instance is not used? Well, that's a code smell. Probably not a real class you're dealing with, but someone had the urge to hammer it into a class thingy. Then the next person will come along and inherit from that and the one after that will write an adapter around it and so it goes on, until a degree of complexity is reached, that is mind-boggling.
A lot of classes also disappear when you simply create a struct and write the functions that deal with the struct's members, decoupling state and behavior. Of course this is not how it is done in mainstream OOP. Some language have adopted this kind of approach. For example Rust with structs and traits being implemented for a struct separately.
Hypothetically speaking, when using the concept of a class, one would expect an instance creation somewhere and that instance to be actually used. If it is not used after creation, then that means, that the constructor can probably be written as a function, saving one level of nesting and also using a simpler concept to express the same thing. When looking at a class, I might need to also consider what its base/super class is and might need to look at what members and methods that one has. I might have to look at what interfaces it implements. When I see a class, I expect some kind of state to be stored in it. If there is no state or only a single attribute, then that might be another sign, that I am not actually dealing with a thing, that needs to be a class.
A class is quite a complex thing, wherein one needs to look out for a lot of things.
Often making everything a class comes with another disadvantage when writing unit tests. You always have to instantiate (assuming not everything is static) and, if you hold state in member variables, you need to account for that in tests, covering various values of that member variable. Writing things as a class makes it easy to have side-effects updating your object internal state. This can make testing even more difficult.
There is complexity, which is inherent to a problem, and there is complexity created by people trying to solve problems with more complex than necessary means. Use a class when necessary and useful. Not for everything that does not hide on the count of 3.
For the use I take from your question, I would recommend simply using namespaces for implementing namespaces. If the language does not provide such, then see if there are modules, which serve as namespaces. Only as a last resort use a class to build a namespace. In that case I would already ask myself, why my language does not support something as basic as a namespace.
How is using Math any difficult? And I don’t see not having namespaces as a bad thing. In a class-used-as-namespace, there are basically no restrictions. What benefit would using the `namespace` keyword instead of `class` give? Especially that you have static imports.
In many cases, that is a function. Functions you can keep mostly on the same level of nested-ness. Occasionally you will have a higher-order thingy. A class, which gets instanciated but then the instance is not used? Well, that's a code smell. Probably not a real class you're dealing with, but someone had the urge to hammer it into a class thingy. Then the next person will come along and inherit from that and the one after that will write an adapter around it and so it goes on, until a degree of complexity is reached, that is mind-boggling.
A lot of classes also disappear when you simply create a struct and write the functions that deal with the struct's members, decoupling state and behavior. Of course this is not how it is done in mainstream OOP. Some language have adopted this kind of approach. For example Rust with structs and traits being implemented for a struct separately.