:root {
	--mf-pointer-fade-out-opacity: 0.1;
	--mf-pointer-fade-out-speed: 3s;
	--mf-pointer-fade-in-speed: 0.3s;
	--mf-pointer-color: var(--mf-color-accent);
	--mf-pointer-dim-opacity: 0.25;
	--mf-pointer-grip-speed: 1.6s;
	--mf-pointer-grip-travel: 8px;
	--mf-pointer-rest-opacity: 0.55;
}

/* Scoped to the mounted crosshair: coarse pointers and forced-colors never mount
   one, and there the native cursor is all they have.
   Universal and !important on purpose: every control that sets its own `cursor` has
   to lose it, and inheritance cannot override a declaration. The class is toggled
   once per session, so the tree-wide restyle is not on any hot path. */
html.mf-pointer-active * {
	cursor: none !important;
}

/* The brace is the focus cue where a crosshair is mounted; a second rectangle at
   nearly the same offset only reads as a brace that failed to clear. */
html.mf-pointer-active :focus-visible {
	outline: none;
}

/* Out past the frame edge, then back in from the other side. --mf-grip-out is
   which way "out" is, which is all that separated the four sides. */
@keyframes mf-grip-y {
	0% { opacity: 1; transform: translateY(0) scale(1); }
	25% { opacity: 0; transform: translateY(var(--mf-grip-out)) scale(0.9); }
	26% { opacity: 0; transform: translateY(calc(-1 * var(--mf-grip-out))) scale(0.9); }
	55%, 100% { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes mf-grip-x {
	0% { opacity: 1; transform: translateX(0) scale(1); }
	25% { opacity: 0; transform: translateX(var(--mf-grip-out)) scale(0.9); }
	26% { opacity: 0; transform: translateX(calc(-1 * var(--mf-grip-out))) scale(0.9); }
	55%, 100% { opacity: 1; transform: translateX(0) scale(1); }
}

.mf-pointer {
	position: fixed;
	inset: 0;

	pointer-events: none;
	user-select: none;

	z-index: var(--mf-z-pointer);
	overflow: visible;

	.mf-pointer-line,
	.mf-pointer-brace,
	.mf-pointer-caret,
	.mf-pointer-grip,
	.mf-pointer-ring {
		fill: none;
		stroke: var(--mf-pointer-color);
		stroke-width: 1;
		vector-effect: non-scaling-stroke;
		shape-rendering: geometricPrecision;
		stroke-linecap: square;
	}

	.mf-pointer-grip {
		transform-box: fill-box;
		transform-origin: center;

		animation-duration: var(--mf-pointer-grip-speed);
		animation-iteration-count: infinite;
		animation-timing-function: linear;
	}

	.mf-pointer-grip-n,
	.mf-pointer-grip-w {
		--mf-grip-out: calc(-1 * var(--mf-pointer-grip-travel));
	}

	.mf-pointer-grip-e,
	.mf-pointer-grip-s {
		--mf-grip-out: var(--mf-pointer-grip-travel);
	}

	/* An inward chevron drifts the way it points, which is the other way. */
	.mf-pointer-grip-in.mf-pointer-grip-n,
	.mf-pointer-grip-in.mf-pointer-grip-w {
		--mf-grip-out: var(--mf-pointer-grip-travel);
	}

	.mf-pointer-grip-in.mf-pointer-grip-e,
	.mf-pointer-grip-in.mf-pointer-grip-s {
		--mf-grip-out: calc(-1 * var(--mf-pointer-grip-travel));
	}

	.mf-pointer-grip-n,
	.mf-pointer-grip-s {
		animation-name: mf-grip-y;
	}

	.mf-pointer-grip-e,
	.mf-pointer-grip-w {
		animation-name: mf-grip-x;
	}

	/* The stretch of each arm that lies outside the active container. */
	.mf-pointer-line-dim {
		opacity: var(--mf-pointer-dim-opacity);
	}

	.mf-pointer-hotspot {
		fill: var(--mf-pointer-color);
		stroke: none;
	}
}

.mf-pointer-hidden {
	display: none;
}

/* The crosshair rests; the grab cues, kept out of that group, rest less. */
.mf-pointer-fade,
.mf-pointer-grips {
	transition: opacity var(--mf-pointer-fade-out-speed);
}

html:not(.mf-pointer-moving) {
	.mf-pointer-fade {
		opacity: var(--mf-pointer-fade-out-opacity);
	}

	.mf-pointer-grips {
		opacity: var(--mf-pointer-rest-opacity);
	}
}

html.mf-pointer-moving {
	.mf-pointer-fade,
	.mf-pointer-grips {
		opacity: 1;
		transition-duration: var(--mf-pointer-fade-in-speed);
	}
}
