Doubling storage on overflow is how a dynamic array stays fast. When the underlying block fills up, the array allocates a new block, usually twice as large, copies every element over, and releases the old one.
That copy costs O(n), so a single resize is not cheap. The saving grace is that resizes get rarer as the array grows. Going from 8 to 16 to 32 slots means the gaps between resizes keep doubling.
Spread the total copy work across every append, and each one averages out to constant time. That is what amortized O(1) means: individual appends occasionally spike, but the long-run cost per append stays flat. Appending a million items in a row stays fast overall.
Rewriting in plainer words…
This answer doesn't lend itself to a diagram - it reads best . No credits were charged.