/** * Window links — visual ties between related windows. * * The link layer sits inside `#desktop-mode-area`, absolutely * positioned over the whole desktop. At rest it stacks BETWEEN the * widget layer (z 1) and the windows (z 100+) — wires on the desk, * visible in the gaps. While a relation-group member is focused, the * render host lifts the layer to the group's z-ceiling via an inline * z-index so the ties draw over every window except the top one. * `pointer-events: none` throughout — the layer must never steal a * click from the desktop or a window. * * Tuning knobs live in `variables.css` as * `--desktop-mode-window-link-*`; the SVG structure comes from the * built-in `svg-splines` renderer (`src/window-links/renderers/`). * Third-party renderers mount their own children into the same layer * and are free to ignore all of this. * * @since 0.9.4 */ .desktop-mode-window-links { position: absolute; inset: 0; z-index: var(--desktop-mode-z-window-links, 50); pointer-events: none; opacity: 0; transition: opacity 0.25s ease; } /* * Toggled by the render host per the `windowLinkVisibility` OS * setting: always on under `always`, tracking group focus under * `focus`. The fade lives here so every renderer inherits it. */ .desktop-mode-window-links--visible { opacity: 1; } @media (prefers-reduced-motion: reduce) { .desktop-mode-window-links { transition: none; } } .desktop-mode-window-links__svg { display: block; width: 100%; height: 100%; } .desktop-mode-window-link__path { fill: none; /* Solid scheme color + opacity for the resting dimming. No color-mix() anywhere in this chain: when a custom property's value can't resolve, the consuming declaration goes invalid at computed-value time and an SVG stroke resets to `none` — invisible lines under floating black endpoint markers. The var() fallback covers a missing token outright. */ stroke: var(--desktop-mode-window-link-color, #2271b1); stroke-opacity: 0.55; stroke-width: var(--desktop-mode-window-link-width, 1.5px); stroke-linecap: round; } /* * Endpoint dots (inside ). Circles rather than * arrowheads — rotation-invariant, so a tie meeting a border at any * angle looks right. Two variants because a marker can't read the * class of the path referencing it — the renderer swaps * marker-end/-start between them on focus. Direction survives as * size: the larger dot sits on the root/referenced window; * bidirectional reference edges get large dots on both ends. */ .desktop-mode-window-link__endpoint { fill: var(--desktop-mode-window-link-color, #2271b1); fill-opacity: 0.55; } .desktop-mode-window-link__endpoint--active { fill: var(--desktop-mode-window-link-color-active, #2271b1); fill-opacity: 1; } /* Edges touching the focused window get the emphasized stroke. */ .desktop-mode-window-link--active .desktop-mode-window-link__path { stroke: var(--desktop-mode-window-link-color-active, #2271b1); stroke-opacity: 1; stroke-width: calc(var(--desktop-mode-window-link-width, 1.5px) + 0.5px); } /* * Related-window chrome cue — stamped by the render host on every * OTHER member of the focused window's relation group. Two parts: * * - an accent outline (follows the window's border-radius on every * modern engine); * - a soft halo. box-shadow is one property, so the window's * elevation shadow is re-declared behind the glow — dropping it * would flatten linked windows against the wallpaper. A linked * window is by definition not the focused one, so the unfocused * elevation token is the right one to compose with. * * The base window chrome already transitions box-shadow, so the halo * fades in and out with focus changes for free. */ .desktop-mode-window--linked { outline: 2px solid var(--desktop-mode-window-link-accent, var(--wp-admin-theme-color, #2271b1)); outline-offset: 1px; box-shadow: 0 0 18px 4px var(--desktop-mode-window-link-glow, rgba(34, 113, 177, 0.45)), var(--desktop-mode-window-shadow); }