Background
The project has a documented z-index scale in docs/z-index-layering.md and a rule that every fixed/modal element must use <Teleport to="body"> to escape stacking contexts created by backdrop-filter or transform on ancestor elements. Several violations have already been fixed (AdvertModal z-50 → z-[300], TopBar System Status panel Teleport, NetworkMap raw z-index: 1000), but a systematic audit has never been done across the full codebase.
Why this matters
Violations cause real bugs: dropdowns render behind modals, modals render behind navigation overlays, map overlays cover fixed panels. They're also silent — everything looks fine in the happy path (desktop, light mode, no overlapping UI states) and only breaks in edge cases (mobile, sidebar open, overlapping panels).
The two failure modes are:
- Wrong z-index value — ad-hoc values (
z-50, z-[9999]) instead of the documented scale.
- Missing Teleport — a fixed/absolute overlay inside an ancestor that has
backdrop-filter or transform. The stacking context traps the element regardless of z-index value.
Audit scope
Every .vue file in src/ that renders a fixed, absolute, or modal-style overlay.
AI prompt — feed this into Claude Code to run the audit
Read docs/z-index-layering.md and docs/style-guide.md first.
Then run_pipeline with task: "audit z-index violations and missing Teleport across all Vue components"
For every .vue file in src/, identify elements that match ANY of these conditions:
1. Uses a z-index value that is NOT in the documented scale:
z-[100], z-[150], z-[200], z-[250], z-[300], z-[350], z-[400], z-[450], z-[500]
Report any z-50, z-[9999], z-index in scoped CSS that does not match the scale.
2. Uses `position: fixed` or is `absolute` and participates in a stacking context, BUT is NOT wrapped in `<Teleport to="body">`.
Focus on: modal backdrops, floating menus, notification panels, tooltips, dropdowns, sidebars.
Skip: inline absolute elements that only need to clear adjacent siblings (e.g. icon badges, input icons).
3. Has `backdrop-filter` or `transform` on itself or an ancestor that could trap a child overlay.
For each violation found, report:
- File path and line number
- The element and its current z-index / Teleport state
- Which rule it violates (wrong z-index value / missing Teleport / stacking context trap)
- Proposed fix (which scale value to use; whether Teleport is needed)
Do NOT fix anything yet — output a structured report only. Wait for approval before making changes.
Format:
## Violations
### src/path/to/Component.vue
- **Line N**: `<div class="fixed z-50 ...">` — wrong z-index. Should be `z-[300]` (primary modal tier). Missing `<Teleport to="body">`.
- **Line N**: `.some-css-rule { z-index: 1000 }` in scoped CSS — ad-hoc value. Should use `z-[200]` Tailwind class on the element instead.
## Summary
- N files affected
- N wrong z-index values
- N missing Teleports
- N stacking context traps
Acceptance criteria
Related
Fixes applied so far in this area:
- AdvertModal
z-50 → z-[300]
- TopBar System Status panel: added
<Teleport to="body"> + fixed positioning with getBoundingClientRect
- NetworkMap: moved
z-index: 1000 / z-index: 200 from scoped CSS to z-[200] Tailwind classes on template elements
Background
The project has a documented z-index scale in
docs/z-index-layering.mdand a rule that every fixed/modal element must use<Teleport to="body">to escape stacking contexts created bybackdrop-filterortransformon ancestor elements. Several violations have already been fixed (AdvertModalz-50→z-[300], TopBar System Status panel Teleport, NetworkMap rawz-index: 1000), but a systematic audit has never been done across the full codebase.Why this matters
Violations cause real bugs: dropdowns render behind modals, modals render behind navigation overlays, map overlays cover fixed panels. They're also silent — everything looks fine in the happy path (desktop, light mode, no overlapping UI states) and only breaks in edge cases (mobile, sidebar open, overlapping panels).
The two failure modes are:
z-50,z-[9999]) instead of the documented scale.backdrop-filterortransform. The stacking context traps the element regardless of z-index value.Audit scope
Every
.vuefile insrc/that renders a fixed, absolute, or modal-style overlay.AI prompt — feed this into Claude Code to run the audit
Acceptance criteria
z-50, raw CSSz-index: 1000,z-[9999]etc.)z-[200],z-[300]etc.)z-indexdeclarations in scoped CSS that duplicate or override Tailwind z-index classesdocs/z-index-layering.mdupdated if any new tiers are genuinely needednpm run test:unitpasses after fixesRelated
Fixes applied so far in this area:
z-50→z-[300]<Teleport to="body">+fixedpositioning withgetBoundingClientRectz-index: 1000/z-index: 200from scoped CSS toz-[200]Tailwind classes on template elements