You’re right that call/cc itself can be trivial. The problem is that everything else becomes way more complicated because call/cc exists.
The critical thing to remember is that if you have call/cc, ANY user-supplied function can return multiple times. In general people expect library functions to “just deal with it” and in practice that means that (1) half your library functions might just be broken but you don’t know it because they fail some weird test case involving call/cc that you didn’t cover (1) you can’t do anything clever to speed up your library functions and (2) your compiler won’t be capable of doing the escape analysis to fix the performance issues in your library functions.
The thing is, you can conceptualize of call/cc as being just “free” if you think of the language as a way to program a continuation-passing machine, but when you do that, you’re basically one step away from some weird garbage-collected assembly language with unlimited goto.
In order to reason about programs more effectively we largely abandoned goto except for the few cases where it’s the right tool. Most of the time we like our control structures to match the stack—you go IN to a function exactly once, and then OUT of the function exactly once.