It's pull from production, not push to production
If continuous integration is “developers push their work into the mainline”, then I’m more in the camp of “continuous deployment is developers pointing the DNS at their work”.
One interesting feature of the Serverless'n'CDN architecture is that you can have as many versions of the codebase ready to run at a moment's notice (and can run them all at the same time).
Every branch you're currently working on, and every version you ever had. That's because new deploys add but do not subtract.
Which version do users get experience? Whatever the DNS is pointing to at the moment.
It can be the latest feature branch. You can roll back to an older version. You can stay behind the latest because marketing wants to hold off on releasing a feature.
It's a different perspective on release management.
The old world is based on the push model: dev -> repo -> prod.
The new world is pull-based: you decide which git commit is currently production by pointing the DNS at it.
Fundamentally, every branch is a production candidate. Main is no longer that special.
Now, when other branches want the same features and bug fixes as your branch, they need to merge your branch in.
Merging a PR is basically an agreement that all the changes included in that PR will stick around to future deploys.
Since you don't want to keep track of “which is today's main branch”, everyone agrees to sync their work through one branch and we call that branch main.
Yet main is no longer the equivalent of production. Main is now the archive of code that made it to production and that we decided to keep around.
At first you deploy, and then if you deem the code good enough to stick around, you merge that PR.
It's pull from production, not push to production.
 For example, AWS Lambda. You don't push code into servers because there are no assigned servers. When AWS needs to spin up a server to execute your code, it loads an image. Which image it picks? That depends on the endpoint. An endpoint can be permanently tied to an image, or an alias you can change (eg current, next, featureX). Image storage is as cheap as S3, so unless you delete images they just stick around forever.
 Because of the packaging requirements of some languages (not PHP!) you can't run any arbitrary git commit. Something has to package a git commit into an image before it can run. But it's common to set it up to package every git push, which is almost as good.
 Maybe continuous deployment is not the right term because it implies that you need to keep doing something. Maybe we should think of it instead as “pulling production code into your machine to make changes and then returning it to production”.
 Other benefits of code that's always ready-to-run: production readiness is the default state of mind. At the same time, easier to experiment because you're not burdening the mainline. And you can involve people who usually can't run your code on their machines (PMs, designers, execs).
 And maybe we can all stop saying Works on My Machine.