How to slab model to surface?

I wanna make this placement script slab into target surface

robloxapp-20250302-2242085.wmv (3.7 MB)

local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local LocalInput = require(script.Parent.Parent.LocalInput)
local LocalPlayer = Players.LocalPlayer
local Mouse = LocalPlayer:GetMouse()

local Model = ReplicatedStorage:WaitForChild("Sellables").Structures.Part.Model

local OldCFrame = nil
local gridSize = 0.5 

--------------------------[[ Functions ]]--------------------------

function PrepareModel()
	local NewModel = Model:Clone()
	NewModel.Parent = workspace

	local Highlight = Instance.new("Highlight", NewModel)
	Highlight.Adornee = NewModel
	Highlight.Name = "StructureHighlight"

	for _, part in ipairs(NewModel:GetChildren()) do
		if part:IsA("Part") then
			part.CanCollide = false
			part.CanTouch = false
			part.CanQuery = false
		end
	end

	return NewModel
end

function ConvertToGridSize(mousePosition)
	local newX = math.round(mousePosition.X / gridSize) * gridSize
	local newZ = math.round(mousePosition.Z / gridSize) * gridSize
	local newY = math.round(mousePosition.Y / gridSize) * gridSize
	local newCFrame = CFrame.new(newX, newY, newZ)
	return newCFrame
end

function IsPositionValid(model, newCFrame)
	if not model.PrimaryPart then return false end
	
	local primaryPart = model.PrimaryPart
	local size = primaryPart.Size * 0.98 

	local region = Region3.new(newCFrame.Position - size / 2, newCFrame.Position + size / 2)

	local overlapParams = OverlapParams.new()
	overlapParams.FilterType = Enum.RaycastFilterType.Exclude
	overlapParams.FilterDescendantsInstances = {Players, model}

	local parts = game.Workspace:FindPartsInRegion3(region, overlapParams)

	return #parts == 0
end

function MoveStructure()
	local NewModel = PrepareModel()
	local modelHeight = NewModel.PrimaryPart.Size.Y 
	
	while true do
		local mousePosition = Mouse.Hit.Position
		local NewCFrame = ConvertToGridSize(mousePosition, modelHeight)
		
		if not (OldCFrame == NewCFrame) then
			NewModel:PivotTo(NewCFrame)
			OldCFrame = NewCFrame
		end
		
		if IsPositionValid(NewModel, NewCFrame) then
			NewModel.StructureHighlight.FillColor = Color3.fromRGB(0, 255, 0)
		else
			NewModel.StructureHighlight.FillColor = Color3.fromRGB(255, 0, 0)
		end

		RunService.RenderStepped:Wait()
	end
end

--------------------------[[ Inputs ]]--------------------------

LocalInput.moveStructure(MoveStructure)