## Summary
Gives dashboard integrators (plugin views, embedded panels, theming
tools) a supported way to match the dashboard's look and to layer
overlay UI correctly — instead of scraping computed styles and guessing
z-index values. This implements the CSS-token bridge slice of
`docs/proposals/2026-07-01-dashboard-theme-plugin-system.md`.
Two additions, both inert unless used:
1. **Documented theme-token contract.** A "Theme tokens" section in
`docs/dashboard-guide.md` (referenced from `docs/PLUGIN_AUTHORING.md`)
declares the stable set of CSS custom properties — colors, surfaces,
status colors — that integrators may read. Tokens resolve to raw color
strings (e.g. `#161b22`) in every theme, including the newer ones. A
sync test (`theme-token-contract-docs.test.ts`) parses the doc's token
table and asserts each documented token has a real definition in the
dashboard CSS, so the contract cannot silently drift from the code.
2. **Overlay layering surface.** Overlay-style UI (palettes, pickers,
floating panels) currently has no supported way to sit above the
floating-window stack — the effective max z-index is runtime state
inside `floatingWindowStack.ts`. This PR exposes it:
- `--fusion-max-z` on `:root` — kept in sync by `floatingWindowStack`
(written at module load and after every `nextFloatingZ()` claim), so it
always reflects the true top of the dashboard-managed stack. Boot/floor
value is `11001`, chosen to clear the highest statically-declared layer
(the body-portaled model-combobox dropdown at `z-index: 11000`).
- `#plugin-overlay-root` — an empty, `pointer-events: none` sibling of
`#root` stacked at `calc(var(--fusion-max-z) + 1)`. React never renders
into it, so it is hydration-safe; integrators portal into it and
re-enable pointer events on their own elements.
- The layer bands (base UI / floating windows / toasts / dropdown /
overlay root) are documented in `styles.css` and the guide, and a guard
test (`dashboard-max-z-guard.test.ts`) scans the structural + component
CSS and fails if any static `z-index` is ever introduced above the floor
— keeping the contract honest as the codebase evolves.
## Behavior
No visual or behavioral change for existing users: `floatingWindowStack`
still returns the same values from `nextFloatingZ()`; the overlay root
is empty and click-through; tokens were already defined — this only
documents and guards them.
## Tests
- `theme-token-contract-docs.test.ts` — docs ↔ CSS sync
(non-tautological: anchored matching against real definitions).
- `floatingWindowStack.max-z.test.ts` — `--fusion-max-z` boot value and
live tracking as the stack claims z-indexes.
- `dashboard-max-z-guard.test.ts` — no static dashboard z-index above
the floor (decorative `public/theme-data.css` INT_MAX scanline overlay
deliberately excluded; it's non-interactive grain, documented in the
test).
- Changeset included (`minor`, `category: feature`). Typecheck clean.
## Open question for maintainers
The token is named `--fusion-max-z`. The existing scale uses `--z-*`
names (`--z-dropdown`, `--z-modal`) on a lower band — happy to rename to
`--z-max` / `--z-plugin-overlay` or anything that fits your convention;
the name is the only bikeshed here, the sync mechanism is independent of
it.
## AI assistance disclosure
Parts of this change were authored with AI assistance (Anthropic's
Claude); the commit carries a `Co-authored-by` trailer accordingly.
Everything was human-reviewed before submission, and the test suite and
typecheck were run locally against the current `main`.
If squash-merging with a rewritten message, please keep the attribution:
```
Co-authored-by: Claude <noreply@anthropic.com>
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Added stable dashboard theme tokens for consistent plugin/integration
styling.
- Introduced a dedicated plugin overlay mount point with click-through
defaults and an overlay stacking ceiling.
- Overlay z-index now stays in sync with floating window layering
automatically.
- **Documentation**
- Added an explicit stable “theme token contract” and “overlay layering
contract,” including interaction and z-index usage rules and deprecation
expectations.
- **Bug Fixes**
- Improved reliability of plugin overlay stacking so overlay content
renders above intended dashboard layers.
- **Tests**
- Added guards validating CSS z-index ceilings and enforcing the
documented theme token contract.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: Claude <noreply@anthropic.com>
Fixes the workflow editor's fullscreen prompt overlay having an inert-looking mobile Expand button because a static z-index of 10000 sat below the mobile workflow editor's full-screen FloatingWindow sheet (10100+ shared floating-stack band).
- Have the fullscreen prompt overlay claim a fresh shared floating-stack z-index via nextFloatingZ() when opened, instead of relying on the static CSS z-index: 10000 fallback
- Track the claimed z-index in new promptFullscreenZ state, applying it as an inline style on the portaled overlay and clearing it on collapse/Escape
- Update FNXC comments in WorkflowNodeEditor.css and floatingWindowStack.ts documenting the shared z-index contract and why the static value is now only a fallback
- Add regression tests asserting the prompt fullscreen overlay's z-index exceeds the workflow editor's floating window z-index on desktop, mobile prompt nodes, mobile gate nodes, and after re-opening after collapse
Files changed:
.../app/components/WorkflowNodeEditor.css | 1 +
.../app/components/WorkflowNodeEditor.tsx | 25 ++++++-
.../__tests__/WorkflowNodeEditor.test.tsx | 81 ++++++++++++++++++++++
.../app/components/floatingWindowStack.ts | 2 +-
4 files changed, 106 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-7914
Fusion-Task-Lineage: e230309a-3b53-4e42-9e63-7516597b6c24
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Root causes of modals being overlapped + tap-to-front not working across types:
- Only FloatingWindow was portaled; the dock pop-out, terminal, and New Task rendered inline in their own stacking contexts, so the shared z-counter could not order them across types. Portal all three to document.body so all four floating modals share the one root stacking context.
- The floating band started at 4000, below page overlays/popovers at 10000-10001 (log viewer, workflow editor, selection popover, fullscreen overlay) which painted over the modals. Raise the shared band base to 10100. Toasts already sit at 200 (below), unaffected.
- Update RightDock dock-toggle test to the current behavior (popping out closes the dock; the floating modal survives) and fix NewTaskModal keyboard-vars test to query the portaled modal from document.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Floating modals (FloatingWindow, right-dock pop-out, terminal, New Task) now share one z-index stack (floatingWindowStack) — tapping any one raises it above all others regardless of type. Floating overlays reset to z-index:auto so panels interleave in the shared 4000+ band.
- TaskChatTab tests: the test i18n now resolves the entryCount/toolCallCount plural forms (production already had them) so '2 entries'/'7 tool calls' render; fixed stale 'Tool call → result/error' casing to match the rendered 'Result'/'Error'. All 179 pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>