Callbacks and Callback Hell
In short: a callback is a function you hand to another function,
to be called later — often once some work finishes. It's how JavaScript
reacted to things before Promise existed, and it still shows up
everywhere (addEventListener, setTimeout, array methods). The trouble
starts when several async steps must run in order: nesting a callback
inside a callback inside a callback produces callback hell — a
staircase of indentation that's hard to read and harder to change.

Calling back once the work is done
A callback that runs synchronously, right when the work is ready:
onDone is the callback — a function processOrder calls once it has
something to report. The caller decides what happens with the result;
processOrder doesn't need to know or care.
A ticket you walk away with
Callbacks get more useful once the work actually takes time — you hand over a callback and move on, like leaving your name with a clerk:
orderCoffee returns immediately after placing the order — it doesn't
block waiting for the coffee. The callback is called later, once the
(simulated) work finishes, with the result. Wrapping the call in a
Promise and await-ing it here is just so every line prints before this
example ends — the pattern being shown is the plain callback itself.
Three steps, nested three levels deep
The problem callbacks create: running steps in order means nesting them, one inside the next.
Each step can only start once the one before it calls back, so the code has to nest to express that order — three steps, three levels deep. Real programs with five or six sequential async steps turn this into an unreadable staircase, sliding further right with every step, which is exactly the shape Promises (next lessons) were designed to flatten back out.
Quick practice
What is a callback, in plain terms?
Why does "callback hell" happen when you need several async steps in order?
What is the main problem with deeply nested callbacks, beyond how they look?
