diff --git a/docs/slideouts.md b/docs/slideouts.md
index d39b666ea01..3b29c76652e 100644
--- a/docs/slideouts.md
+++ b/docs/slideouts.md
@@ -461,8 +461,9 @@ Two things to know if you touch this area:
- **Don't reuse legacy class names.** The legacy stylesheet owns `.slideout-shade` and hides it with
`:not(.visible) { display: none }`. The shared shade is `.cp-slideout-shade` for that reason, and
- it sits at `z-index: 99` — one below both kinds of panel, so it stays underneath them regardless
- of the order they were appended to `
` in.
+ it sits at `--c-z-slideout-shade` — one rung below `--c-z-slideout`, which both kinds of panel
+ use, so it stays underneath them regardless of the order they were appended to `` in. See
+ [z-layers.md](z-layers.md).
- The legacy payload's key order is pinned by `tests/Feature/Http/Responses/CpScreenSlideoutTest.php`.
If that test goes red, the jQuery slideout stack is broken.
diff --git a/docs/z-layers.md b/docs/z-layers.md
new file mode 100644
index 00000000000..8518baf9378
--- /dev/null
+++ b/docs/z-layers.md
@@ -0,0 +1,110 @@
+# Z-layers
+
+Every surface in the CP that escapes normal flow picks a **rung** from a shared ladder instead of
+inventing a number. The ladder is declared once, in two mirrored files:
+
+| File | For |
+| --- | --- |
+| [`packages/craftcms-ui/src/styles/shared/z-layers.css`](../packages/craftcms-ui/src/styles/shared/z-layers.css) | CSS (`var(--c-z-modal)`). The source of truth. |
+| [`packages/craftcms-ui/src/constants/z-layers.ts`](../packages/craftcms-ui/src/constants/z-layers.ts) | JS (`ZLayer.Modal`), for overlay configs and inline styles. |
+
+`src/styles/z-layers.test.ts` asserts the two agree, so a rung added or moved in one has to be added
+or moved in the other.
+
+The stylesheet is imported by `@craftcms/ui/styles/cp.css`, which `resources/css/cp.css` pulls in,
+which the CP's only layout (`resources/views/app.blade.php`) always loads. The tokens are therefore
+available on every CP page, including inside shadow roots — custom properties inherit through the
+shadow boundary.
+
+## The ladder
+
+### Local — within a component's own stacking context
+
+| Token | `ZLayer` | Value | Use for |
+| --- | --- | --- | --- |
+| `--c-z-behind` | `Behind` | `-1` | Decorative fill painted behind its own content |
+| `--c-z-base` | `Base` | `0` | Explicitly on the baseline — mostly to reset a lift |
+| `--c-z-raised` | `Raised` | `1` | Lifted above sibling content (a check overlay, a focus ring) |
+| `--c-z-floating` | `Floating` | `2` | Above a sibling that's already raised |
+| `--c-z-sticky` | `Sticky` | `10` | Sticky headers/footers/toolbars inside a scroll container |
+
+### Page-level — competing with the rest of the CP
+
+| Token | `ZLayer` | Value | Use for |
+| --- | --- | --- | --- |
+| `--c-z-page-header` | `PageHeader` | `2000` | Sticky page and editor headers |
+| `--c-z-nav` | `Nav` | `2100` | Persistent CP chrome — the global sidebar |
+| `--c-z-drag` | `Drag` | `3000` | Drag helpers and drop indicators |
+| `--c-z-slideout-shade` | `SlideoutShade` | `4000` | The shade behind a slideout |
+| `--c-z-slideout` | `Slideout` | `4100` | Slideout panels and their container |
+| `--c-z-modal-shade` | `ModalShade` | `5000` | The shade behind a modal |
+| `--c-z-modal` | `Modal` | `5100` | Modal panels |
+| `--c-z-overlay` | `Overlay` | `6000` | Menus, comboboxes, selects, popovers, HUDs |
+| `--c-z-notification` | `Notification` | `7000` | Toasts and notifications |
+| `--c-z-tooltip` | `Tooltip` | `8000` | Tooltips |
+| `--c-z-debug` | `Debug` | `9000` | Dev-only chrome (the debug toolbar) |
+
+Rungs are spaced by 1000 (100 within a shade/panel pair) so a new layer can be slotted between two
+existing ones without renumbering anything.
+
+## Rules
+
+**Pick local unless the thing is attached to ``.** A page-level rung only wins if no ancestor
+has created a stacking context, so using one from inside a component works right up until somebody
+adds a `transform`, an `opacity`, or a `filter` above it. If the surface renders in place, it's
+local; if it's teleported, portalled, or appended to ``, it's page-level.
+
+**Anchored overlays sit above modals on purpose.** `--c-z-overlay` is above `--c-z-modal` because an
+overlay is opened *from* a surface and has to paint above whichever surface opened it — a menu inside
+a modal is ordinary, and there's no reliable way for the menu to know what it was opened from.
+`--c-z-tooltip` is highest for the same reason: anything at all can have a tooltip.
+
+**Don't add a rung for one component.** Reach for `--c-z-raised` / `--c-z-floating` first. A new rung
+is warranted only when a surface genuinely has to be ordered against other page-level surfaces.
+
+## What the ladder doesn't cover
+
+### The top layer
+
+`craft-dialog` is a Lion modal dialog, which opens with `HTMLDialogElement.showModal()`. Top-layer
+content paints above every z-indexed element regardless of the number, so **no rung will ever cover
+it**, and ordering *between* top-layer elements is order-of-entry rather than z-index.
+
+Lion's non-modal overlays (`craft-popover` and everything built on it, `craft-tooltip`,
+`craft-select-rich`, `craft-combobox`) use a `