MenuInput.cs
using Sandbox;
using SWB.Player;

// Frees the mouse cursor for menu UI.
//
// Mouse.Visible can't be set directly - the engine derives it each frame
// from whether the active input context is in UI mouse state:
//
//     MouseCursorVisible = !mouseCaptureMode &&
//       (activeMouse is not null && activeMouse.MouseState == InputState.UI);
//
// What actually holds it in gameplay mode is CameraMovement.FirstPerson()
// consuming Input.AnalogLook every frame for mouse-look. Switching that
// component off while a menu is open releases the pointer; switching it
// back on returns control to the player.
//
// Shared by the vendor and job board so they can't drift apart and leave
// the cursor stuck in whichever state the last one set.
public static class MenuInput
{
	public static void SetMenuOpen( bool open )
	{
		var player = PlayerBase.Local;

		if ( player is null )
			return;

		// PlayerBase caches this in OnAwake, which matters: component
		// lookups skip DISABLED components by default, so searching for it
		// here would find nothing once a menu had switched it off - and it
		// would never get switched back on. Using the cached reference
		// sidesteps that entirely.
		if ( player.CameraMovement is not Component look )
			return;

		// MissionPlayerState turns mouse-look off to hand the camera over
		// for spectating. Re-enabling it here would yank the view back off
		// whoever they're watching, so leave it alone once they're out.
		var outOfPlay = player.Components.Get<MissionPlayerState>()?.IsOut ?? false;

		if ( outOfPlay )
			return;

		look.Enabled = !open;
	}
}