/**
 * Desktop Mode — Window state visuals.
 *
 * Every rule that keys off a `--state` modifier class: the resize
 * handle + its overlay shield (drag/resize iframe-interception),
 * maximize, fullscreen, the opening animation, minimize + closing
 * fade-outs, reduced-motion scoped overrides, and the RTL cursor
 * flip on the resize corner.
 *
 * Base chrome lives in window-chrome.css; the zoom-out grid lives
 * in window-overview.css.
 *
 * @since 6.9.0
 */

/*
 * Resize handles — one per corner (NE / NW / SE / SW). Each is an
 * invisible square hit-target whose cursor telegraphs the resize
 * axis. SE keeps the legacy grip-lines glyph so the affordance is
 * visible even without hover; the other three remain transparent
 * (discoverable by cursor change only) to keep the window chrome
 * clean.
 *
 * Hit-area is `--desktop-mode-resize-size` (20 px by default). The
 * handles extend a few pixels OUTSIDE the window edge so a cursor
 * landing just past the border still activates them — matches how
 * native OS windows forgive edge-grabs.
 */
.desktop-mode-window__resize-handle {
	position: absolute;
	width: var(--desktop-mode-resize-size);
	height: var(--desktop-mode-resize-size);
	z-index: 999;
}

.desktop-mode-window__resize-handle--se {
	right: -3px;
	bottom: -3px;
	cursor: nwse-resize;
	background: linear-gradient(
		135deg,
		transparent 30%,
		var(--desktop-mode-resize-color) 30%,
		var(--desktop-mode-resize-color) 40%,
		transparent 40%,
		transparent 55%,
		var(--desktop-mode-resize-color) 55%,
		var(--desktop-mode-resize-color) 65%,
		transparent 65%,
		transparent 80%,
		var(--desktop-mode-resize-color) 80%
	);
}

.desktop-mode-window__resize-handle--sw {
	left: -3px;
	bottom: -3px;
	cursor: nesw-resize;
}

.desktop-mode-window__resize-handle--ne {
	right: -3px;
	top: -3px;
	cursor: nesw-resize;
}

.desktop-mode-window__resize-handle--nw {
	left: -3px;
	top: -3px;
	cursor: nwse-resize;
}

/*
 * During drag/resize, overlay the iframe to prevent it from
 * capturing pointer events and breaking the drag.
 */
.desktop-mode-window--dragging .desktop-mode-window__body::after,
.desktop-mode-window--resizing .desktop-mode-window__body::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 10;
}

/*
 * Maximized state: the pixel geometry is applied inline from JS
 * (matching the desktop area) so left/top/width/height can animate.
 * Only cosmetic overrides here.
 */
.desktop-mode-window--maximized {
	border-radius: 0;
}

.desktop-mode-window--maximized .desktop-mode-window__resize-handle {
	display: none;
}

/*
 * Fullscreen ("focus") state — the window escapes the desktop area and
 * covers the entire viewport, hiding the admin bar and dock behind
 * it. Uses position: fixed so no ancestor overflow clips it, and
 * a z-index above the admin bar (--desktop-mode-z-adminbar). Inline
 * geometry set by toggleMaximize() is overridden with !important because
 * we never want fullscreen to respect a saved x/y/width/height.
 */
.desktop-mode-window--fullscreen {
	position: fixed !important;
	left: 0 !important;
	top: 0 !important;
	width: 100vw !important;
	height: 100vh !important;
	z-index: var(--desktop-mode-z-fullscreen) !important;
	border-radius: 0 !important;
	border: none;
}

.desktop-mode-window--fullscreen .desktop-mode-window__resize-handle {
	display: none;
}

/*
 * Opening animation — subtle scale-up + fade-in.
 * The class is added on creation and removed after the animation ends.
 */
@keyframes desktop-mode-window-open {
	from {
		opacity: 0;
		transform: scale(0.92);
	}
	to {
		opacity: 1;
		transform: scale(1);
	}
}

.desktop-mode-window--opening {
	animation: desktop-mode-window-open 0.2s ease forwards;
}

/*
 * Shake animation — used by `Window.shake()` for nudge / attention-
 * grab affordances. The window briefly jiggles horizontally while
 * keeping its position. Composes via CSS variable so the inline
 * `left`/`top` written by the window manager keeps wining; the
 * shake is a translate ON TOP of that.
 *
 * Reduced-motion fallback: a static accent ring for the same
 * duration so users with prefers-reduced-motion still see the
 * affordance without movement.
 */
@keyframes desktop-mode-window-shake {
	0%, 100% { transform: translateX( 0 ); }
	8%       { transform: translateX( -10px ); }
	18%      { transform: translateX( 9px ); }
	28%      { transform: translateX( -8px ); }
	38%      { transform: translateX( 7px ); }
	48%      { transform: translateX( -5px ); }
	60%      { transform: translateX( 4px ); }
	72%      { transform: translateX( -3px ); }
	84%      { transform: translateX( 2px ); }
}

.desktop-mode-window--shaking {
	animation: desktop-mode-window-shake 0.6s cubic-bezier( 0.36, 0.07, 0.19, 0.97 ) both;
}

@media ( prefers-reduced-motion: reduce ) {
	.desktop-mode-window--shaking {
		animation: none;
		outline: 3px solid var( --wp-admin-theme-color, #2271b1 );
		outline-offset: 2px;
		transition: outline 0.6s ease;
	}
}

/*
 * Desktop-switch slide — applied to `.desktop-mode-area` (the windows
 * + widgets container) when the user moves between virtual desktops
 * via arrow keys or any other directional caller. The wallpaper lives
 * OUTSIDE this element (sibling under `.desktop-mode-shell`), so the
 * slide reveals the wallpaper as a backdrop — no black flash, no
 * awkward gap on the leading edge.
 *
 * `--sliding-from-right` plays when moving to the next desktop (the
 * rightward arrow press): the new desktop's content rushes in from
 * the right and settles to centre. `--sliding-from-left` mirrors it
 * for the previous-desktop direction. Wrap-around presses (rightmost
 * → first via ArrowRight) keep the direction the user perceived,
 * not the index delta.
 *
 * Opacity tapers from 0.35 → 1 so the moving content visibly arrives
 * rather than just sliding in at full strength, but the wallpaper
 * stays at full opacity behind it for an anchored sense of place.
 * Cubic-bezier ease-out lands cleanly without overshoot.
 *
 * `forwards` isn't needed — the JS strips the class on `animationend`
 * so the element returns to its natural transform / opacity state.
 */
@keyframes desktop-mode-area-slide-from-right {
	from {
		transform: translateX(64px);
		opacity: 0.35;
	}
	to {
		transform: translateX(0);
		opacity: 1;
	}
}

@keyframes desktop-mode-area-slide-from-left {
	from {
		transform: translateX(-64px);
		opacity: 0.35;
	}
	to {
		transform: translateX(0);
		opacity: 1;
	}
}

.desktop-mode-area--sliding-from-right {
	animation: desktop-mode-area-slide-from-right 0.28s cubic-bezier( 0.2, 0.7, 0.2, 1 );
}

.desktop-mode-area--sliding-from-left {
	animation: desktop-mode-area-slide-from-left 0.28s cubic-bezier( 0.2, 0.7, 0.2, 1 );
}

@media ( prefers-reduced-motion: reduce ) {
	.desktop-mode-area--sliding-from-right,
	.desktop-mode-area--sliding-from-left {
		animation: none;
	}
}

/*
 * Minimized state — fade + scale down.
 * Uses opacity + pointer-events instead of display: none so the
 * CSS transition can animate the change. The window is invisible
 * and non-interactive but stays in the DOM for a smooth restore.
 */
.desktop-mode-window--minimized {
	opacity: 0;
	transform: scale(0.92) translateY(16px);
	pointer-events: none;
	will-change: transform, opacity;
}

/*
 * `pointer-events: none` on the window root above is not enough on
 * its own: a number of descendants (most notably `.desktop-mode-
 * file-tile`, but also other tile renderers) explicitly set
 * `pointer-events: auto` so the wallpaper / folder layer doesn't
 * eat their clicks. That `auto` overrides the parent's `none`, and
 * after "Show Desktop" minimizes every window, hovering the empty
 * space where a tile used to sit would still trigger its tooltip
 * / dock peek — the invisible-but-still-interactive bug.
 *
 * The universal selector is scoped INSIDE the minimized window so
 * it doesn't touch anything else, and `!important` is required to
 * win over the per-tile `pointer-events: auto`.
 */
.desktop-mode-window--minimized *,
.desktop-mode-window--closing * {
	pointer-events: none !important;
}

/*
 * Closing animation — fade out + slight scale down.
 * The JS waits for transitionend then removes the element.
 */
.desktop-mode-window--closing {
	opacity: 0;
	transform: scale(0.95);
	pointer-events: none;
	will-change: transform, opacity;
}

/*
 * Respect prefers-reduced-motion: collapse all durations to near-zero
 * so state changes are instant but still technically transition
 * (avoids layout jumps from display: none).
 */
@media ( prefers-reduced-motion: reduce ) {
	.desktop-mode-window {
		transition-duration: 0.01ms !important;
	}
	.desktop-mode-window--opening {
		animation-duration: 0.01ms !important;
	}
}

/*
 * RTL note: resize handles use physical `left` / `right` anchors
 * (not logical `inset-inline-*`) so the four corners stay in the
 * same physical positions under RTL. Each handle already has the
 * correct cursor for its physical diagonal (SE + NW use
 * `nwse-resize`, NE + SW use `nesw-resize`); no RTL override
 * needed.
 */

/* ---------------------------------------------------------------
 * Snap zones — edge-snap preview rectangle + snapped-state chrome.
 *
 * Preview appears while the drag cursor is within SNAP_EDGE_THRESHOLD
 * of the left/right edge (see window-manager/snap-zones.ts). It's a
 * translucent accent-colored rectangle covering the target half, with
 * a bright border so the user sees exactly where the window will land.
 * --------------------------------------------------------------- */
.desktop-mode-snap-preview {
	position: absolute;
	background: color-mix(
		in srgb,
		var( --wp-admin-theme-color, #2271b1 ) 14%,
		transparent
	);
	border: 2px solid var( --wp-admin-theme-color, #2271b1 );
	border-radius: 12px;
	box-shadow:
		0 0 0 1px rgba( 255, 255, 255, 0.15 ) inset,
		0 12px 36px rgba( 0, 0, 0, 0.22 );
	pointer-events: none;
	z-index: 99; /* Just under windows (which start at 100) so a */
	             /* still-dragging window renders on top. */
	opacity: 0;
	transition:
		opacity 0.15s ease,
		left 0.18s cubic-bezier( 0.2, 0, 0.2, 1 ),
		top 0.18s cubic-bezier( 0.2, 0, 0.2, 1 ),
		width 0.18s cubic-bezier( 0.2, 0, 0.2, 1 ),
		height 0.18s cubic-bezier( 0.2, 0, 0.2, 1 );
}

.desktop-mode-snap-preview--visible {
	opacity: 1;
}

/*
 * Snapped window state — `--snapped-left` / `--snapped-right` carry
 * cosmetic tweaks only. Resize handles stay visible and functional:
 * the user can grab any corner to shrink the window back to floating
 * (the pointer layer drops the snapped-* class on first resize so
 * geometry stops pretending to be half-screen).
 *
 * Rounded-corner profile flattens the INNER edges (the ones that
 * butt against the partner window) to match macOS split-view
 * aesthetic.
 *
 * Shadows are dropped on both snapped variants. The default window
 * drop shadow would render inside the opposite half — a dark vertical
 * ghost line at the seam — and compete visually with the partner
 * window. Flat edges + no shadow gives the two-up feel of a native
 * split view: windows adjacent, no separator.
 */
.desktop-mode-window--snapped-left,
.desktop-mode-window--snapped-right {
	box-shadow: none;
}

/* Override the elevated shadow applied to `--focused` windows too —
   the focused selector runs at equal specificity, so without this
   rule the focus shadow would re-introduce the seam once the snapped
   window is active. */
.desktop-mode-window--focused.desktop-mode-window--snapped-left,
.desktop-mode-window--focused.desktop-mode-window--snapped-right {
	box-shadow: none;
}

.desktop-mode-window--snapped-left {
	/* Inner (right) edge flush; outer corners keep the radius. */
	border-top-right-radius: 0;
	border-bottom-right-radius: 0;
}

.desktop-mode-window--snapped-right {
	border-top-left-radius: 0;
	border-bottom-left-radius: 0;
}

/*
 * Split overview — a constrained variant of the full overview,
 * scoped to the half opposite a just-snapped window. Uses the same
 * thumbnail visuals as the main overview; only the backdrop tint is
 * lighter (the anchor window still takes the other half, so we want
 * the picker to feel "peripheral" not "modal").
 */
.desktop-mode-area--split-overview {
	background-color: rgba( 0, 0, 0, 0.28 );
	transition: background-color 0.24s ease;
}

/* Toast styling moved into `<wpd-toast-container>` and `<wpd-toast>`
 * (src/ui/components/wpd-toast/). The components own their shadow
 * DOM styling; nothing at host level needs to reach inside. */
