I don't know your background, so I don't know at what level to pitch an explanation. Here's an attempt that assumes some knowledge of modern PLs.
Effects require 1) well-defined control flow (think of IO; you need to know in what order output occurs) and 2) manipulation of control flow (think of error handling or concurrency).
We can model effects as a back-and-forth between effect handlers, which carry out effects, and the user program. The user program passes control to the effect handler to carry out some effect, and the effect handler passes control back to the user program (potentially a different part of the user program; think error handling) when the effect has been performed. Continuations give complete control over control flow, so in their full generality effects require continuations (or some equivalent like monads). Coroutines are a slightly stilted form of continuations, that you can model much, but not all, control flow with.
Aren't coroutines generally one-shot, whereas continuations could potentially be resumed to multiple times? This seems to be a relevant difference between these concepts.
That's my understanding, and why you need full continuations to handle all effects. In my mental model a coroutine gives you an execution point that you can resume, but you are not allowed to resume execution points you have previously resumed. You cannot, for example, implement backtracking search with just coroutines as you need to to return to previous execution points. (Look, you can implement anything with anything. Turing completeness etc. This is about implementing it in a natural way using the effect handlers.)
That's not what "resume multiple times" is referring to here. You can typically only resume a coroutine once per yield, while a continuation generally allows you to return to the same place multiple times.
One lets you save and return to an execution state (program counter and local environment), the other lets you create and call an execution state that is saved between calls to it.
There are obvious implementation differences but I'm not sure it makes any difference here, in both cases you can return to the same execution state multiple times.
The distinction between coroutines and delimited continuations is one-shot vs. multi-shot. The delimited continuation crowd use different language, but imagine an ordinary stackful asymmetric coroutine wrapped around a function call, except instead of just yield and resume, you have yield, resume, and reset. Call the coroutine, it yields from A, call resume, it yields from B, call reset, resume, it yields from B again. You can do that as often as you'd like.
This can in fact be emulated with a coroutine generator and some fancy footwork, but it's a subtly different primitive.
The difference is that resuming a coroutine mutates it, so that the next time you resume the same object it starts from wherever the coroutine next yielded. This may or may not be the same yield point as the last time, depending on the definition of the coroutine.
A continuation is immutable in that way, so it is either an error to invoke it multiple times, or else it will always resume at the same place. Implementing coroutines in terms of continuations would mean capturing a new continuation each time you yield.
Effects require 1) well-defined control flow (think of IO; you need to know in what order output occurs) and 2) manipulation of control flow (think of error handling or concurrency).
We can model effects as a back-and-forth between effect handlers, which carry out effects, and the user program. The user program passes control to the effect handler to carry out some effect, and the effect handler passes control back to the user program (potentially a different part of the user program; think error handling) when the effect has been performed. Continuations give complete control over control flow, so in their full generality effects require continuations (or some equivalent like monads). Coroutines are a slightly stilted form of continuations, that you can model much, but not all, control flow with.