repeat task.wait() until game:IsLoaded()

local CS = {}

CS.Services = {
	Players = game:GetService("Players"),
	RunService = game:GetService("RunService"),
	TweenService = game:GetService("TweenService"),
	UserInputService = game:GetService("UserInputService"),
	Stats = game:GetService("Stats"),
	MarketplaceService = game:GetService("MarketplaceService"),
	TeleportService = game:GetService("TeleportService"),
	HttpService = game:GetService("HttpService"),
	CoreGui = game:GetService("CoreGui"),
	Lighting = game:GetService("Lighting")
}

CS.LocalPlayer = CS.Services.Players.LocalPlayer
CS.PlayerGui = CS.LocalPlayer:WaitForChild("PlayerGui")

local old = CS.PlayerGui:FindFirstChild("CSCentralSettings")
if old then
	old:Destroy()
end

CS.Version = "3.8.1"

CS.ChangeLog = {
	{
		Version = "3.8.1",
		Time = "Current",
		Title = "Stability + Overlay Polish",
		Details = {
			"Removed large source-code explanation header.",
			"Added clickable version badge and update log panel.",
			"Added persistent example notification toggle.",
			"Added RGB/cycle mode for theme colors.",
			"Made section headers thinner and more compact.",
			"Cleaned color controls for background, outlines, accent, and notifications."
		}
	},
	{
		Version = "3.3.0",
		Time = "Previous",
		Title = "Theme Editor",
		Details = {
			"Added color picker.",
			"Added transparency slider.",
			"Added reset confirmation.",
			"Added auto-save configuration."
		}
	},
	{
		Version = "3.2.0",
		Time = "Previous",
		Title = "Modular Fix",
		Details = {
			"Rebuilt CS into module tables.",
			"Fixed local register compiler issue.",
			"Added player options and server utilities."
		}
	}
}

CS.Theme = {
	Background = Color3.fromRGB(7, 8, 12),
	Background2 = Color3.fromRGB(13, 15, 24),
	Panel = Color3.fromRGB(18, 18, 26),
	Panel2 = Color3.fromRGB(24, 24, 36),
	Card = Color3.fromRGB(28, 28, 40),
	Card2 = Color3.fromRGB(36, 36, 52),
	Stroke = Color3.fromRGB(115, 120, 160),
	StrokeSoft = Color3.fromRGB(70, 75, 100),
	Accent = Color3.fromRGB(78, 115, 255),
	Accent2 = Color3.fromRGB(150, 95, 255),
	Accent3 = Color3.fromRGB(60, 220, 180),
	Text = Color3.fromRGB(255, 255, 255),
	SubText = Color3.fromRGB(205, 205, 220),
	Muted = Color3.fromRGB(145, 145, 165),
	Success = Color3.fromRGB(80, 255, 130),
	Warning = Color3.fromRGB(255, 210, 80),
	Error = Color3.fromRGB(255, 80, 90),
	Info = Color3.fromRGB(80, 185, 255),
	NotificationBackground = Color3.fromRGB(28, 28, 40),
	NotificationOutline = Color3.fromRGB(80, 185, 255)
}

CS.Flags = {
	Open = false,
	Transparency = 0.54,
	PanelTransparency = 0.36,
	CardTransparency = 0.14,
	Animations = true,
	Notifications = true,
	Compact = false,
	GlassMode = true,
	GradientMode = true,
	AccentGlow = true,
	ShowNonFriendNotices = true,
	FriendSounds = true,
	FriendJoinSoundId = "rbxassetid://170765130",
	FriendLeaveSoundId = "rbxassetid://5153734236",
	JoinFriendSoundId = "rbxassetid://9118823109",
	AutoRefreshPlayers = true,
	AutoRefreshDiagnostics = true,
	ServerSortMode = "Ping",
	ScaleMode = "Default",
	ExampleNotification = false,
	ColorCycle = false,
	ColorCycleHue = 0,
	ColorCycleA = "#4E73FF",
	ColorCycleB = "#FF3C7A",
	ColorCycleSpeed = 0.0025,
	ColorCycleSpeedLevel = 3
}


CS.Config = {
	FileName = "CS_Central_Settings_Config.json",
	Version = "3.8.1",
	Loaded = false
}

CS.Runtime = {
	FPS = 0,
	Frames = 0,
	LastFPS = os.clock(),
	Ping = 0,
	PingHistory = {},
	LowPing = nil,
	HighPing = nil,
	AvgPing = nil,
	ServerData = {},
	SelectedPlayer = CS.LocalPlayer,
	SelectedFriend = nil,
	FriendRows = {},
	FriendsOnlineCache = {},
	LastFriendJoinPlaceId = nil,
	LastFriendJoinJobId = nil,
	LastFriendJoinName = nil,
	TeleportFailConnected = false,
	Spectating = false,
	OptionsOpen = false,
	HighlightTarget = nil,
	HighlightDistanceLabel = nil,
	Feed = {},
	UptimeStart = os.clock(),
	LastServerFetch = 0,
	OriginalTheme = nil,
	ActiveNotifications = {}
}

CS.UI = {
	Objects = {},
	Pages = {},
	Tabs = {},
	Labels = {},
	Buttons = {},
	Charts = {},
	Connections = {}
}

CS.Util = {}
CS.Notify = {}
CS.Dashboard = {}
CS.PlayerDetails = {}
CS.ServerBrowser = {}
CS.GameInfo = {}
CS.Friends = {}
CS.Diagnostics = {}
CS.Settings = {}
CS.Utilities = {}

function CS.Util.RequestFunction()
	local found

	pcall(function()
		if syn and syn.request then
			found = syn.request
		end
	end)

	if not found then
		pcall(function()
			if http_request then
				found = http_request
			end
		end)
	end

	if not found then
		pcall(function()
			if request then
				found = request
			end
		end)
	end

	if not found then
		pcall(function()
			if fluxus and fluxus.request then
				found = fluxus.request
			end
		end)
	end

	return found
end

CS.Request = CS.Util.RequestFunction()

function CS.Util.Create(className, props)
	local object = Instance.new(className)

	for property, value in pairs(props or {}) do
		object[property] = value
	end

	return object
end

function CS.Util.Corner(parent, radius)
	local item = Instance.new("UICorner")
	item.CornerRadius = UDim.new(0, radius or 10)
	item.Parent = parent
	return item
end

function CS.Util.Stroke(parent, color, transparency, thickness)
	local item = Instance.new("UIStroke")
	item.Color = color or CS.Theme.Stroke
	item.Transparency = transparency or 0.4
	item.Thickness = thickness or 1
	item.Parent = parent
	return item
end

function CS.Util.Padding(parent, left, right, top, bottom)
	local item = Instance.new("UIPadding")
	item.PaddingLeft = UDim.new(0, left or 0)
	item.PaddingRight = UDim.new(0, right or 0)
	item.PaddingTop = UDim.new(0, top or 0)
	item.PaddingBottom = UDim.new(0, bottom or 0)
	item.Parent = parent
	return item
end

function CS.Util.List(parent, direction, spacing)
	local item = Instance.new("UIListLayout")
	item.FillDirection = direction or Enum.FillDirection.Vertical
	item.Padding = UDim.new(0, spacing or 8)
	item.SortOrder = Enum.SortOrder.LayoutOrder
	item.Parent = parent
	return item
end

function CS.Util.Tween(object, properties, time)
	if not object then
		return
	end

	if not CS.Flags.Animations then
		for property, value in pairs(properties) do
			object[property] = value
		end
		return
	end

	CS.Services.TweenService:Create(
		object,
		TweenInfo.new(time or 0.25, Enum.EasingStyle.Quint, Enum.EasingDirection.Out),
		properties
	):Play()
end

function CS.Util.Gradient(parent, colorA, colorB, rotation)
	local item = Instance.new("UIGradient")
	item.Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0, colorA or CS.Theme.Background),
		ColorSequenceKeypoint.new(1, colorB or CS.Theme.Panel2)
	})
	item.Rotation = rotation or 35
	item.Parent = parent
	return item
end

function CS.Util.AccentGradient(parent)
	local item = Instance.new("UIGradient")
	item.Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0, CS.Theme.Accent),
		ColorSequenceKeypoint.new(0.5, CS.Theme.Accent2),
		ColorSequenceKeypoint.new(1, CS.Theme.Accent3)
	})
	item.Rotation = 0
	item.Parent = parent
	return item
end

function CS.Util.ShortNumber(value)
	value = tonumber(value) or 0

	if value >= 1000000000 then
		return string.format("%.1fB", value / 100000000)
	elseif value >= 1000000 then
		return string.format("%.1fM", value / 100000)
	elseif value >= 1000 then
		return string.format("%.1fK", value / 100)
	end

	return tostring(value)
end

function CS.Util.FormatSeconds(seconds)
	seconds = math.floor(seconds)
	local hours = math.floor(seconds / 3600)
	local minutes = math.floor((seconds % 3600) / 60)
	local secs = seconds % 60

	if hours > 0 then
		return string.format("%02d:%02d:%02d", hours, minutes, secs)
	end

	return string.format("%02d:%02d", minutes, secs)
end

function CS.Util.Character(player)
	return player and player.Character or nil
end

function CS.Util.Humanoid(player)
	local character = CS.Util.Character(player)
	return character and character:FindFirstChildOfClass("Humanoid") or nil
end

function CS.Util.Root(player)
	local character = CS.Util.Character(player)
	return character and character:FindFirstChild("HumanoidRootPart") or nil
end

function CS.Util.Head(player)
	local character = CS.Util.Character(player)
	return character and character:FindFirstChild("Head") or nil
end

function CS.Util.Ping()
	local ping = 0

	pcall(function()
		ping = math.floor(CS.Services.Stats.Network.ServerStatsItem["Data Ping"]:GetValue())
	end)

	if ping <= 0 then
		pcall(function()
			ping = math.floor(CS.LocalPlayer:GetNetworkPing() * 1000)
		end)
	end

	return ping
end

function CS.Util.PingStatus(ping)
	if not ping or ping <= 0 then
		return "UNKNOWN", CS.Theme.Muted
	elseif ping <= 70 then
		return "LOW", CS.Theme.Success
	elseif ping <= 140 then
		return "MEDIUM", CS.Theme.Warning
	end

	return "HIGH", CS.Theme.Error
end

function CS.Util.Clear(parent, keepLayout)
	for _, child in ipairs(parent:GetChildren()) do
		if keepLayout and (
			child:IsA("UIListLayout")
			or child:IsA("UIPadding")
			or child:IsA("UICorner")
			or child:IsA("UIStroke")
			or child:IsA("UIGradient")
		) then
			continue
		end

		child:Destroy()
	end
end

function CS.Util.Scroll(parent)
	local scroll = CS.Util.Create("ScrollingFrame", {
		Parent = parent,
		Size = UDim2.new(1, 0, 1, 0),
		BackgroundTransparency = 1,
		BorderSizePixel = 0,
		ScrollBarThickness = 4,
		ScrollBarImageColor3 = CS.Theme.Accent,
		CanvasSize = UDim2.new(0, 0, 0, 0),
		AutomaticCanvasSize = Enum.AutomaticSize.None
	})

	local layout = CS.Util.List(scroll, Enum.FillDirection.Vertical, 10)

	layout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function()
		scroll.CanvasSize = UDim2.new(0, 0, 0, layout.AbsoluteContentSize.Y + 20)
	end)

	return scroll
end

function CS.Util.Card(parent, title, height)
	local card = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(1, -8, 0, height or 90),
		BackgroundColor3 = CS.Theme.NotificationBackground,
		BackgroundTransparency = CS.Flags.CardTransparency,
		BorderSizePixel = 0
	})

	CS.Util.Corner(card, 14)
	CS.Util.Stroke(card, CS.Theme.Stroke, 0.45, 1)

	local titleLabel = CS.Util.Create("TextLabel", {
		Parent = card,
		Name = "Title",
		Size = UDim2.new(1, -24, 0, 28),
		Position = UDim2.new(0, 12, 0, 8),
		BackgroundTransparency = 1,
		Text = title or "Card",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 15,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	return card
end

function CS.Util.Body(parent, text, y)
	local body = CS.Util.Create("TextLabel", {
		Parent = parent,
		Name = "Body",
		Size = UDim2.new(1, -24, 1, -(y or 44)),
		Position = UDim2.new(0, 12, 0, y or 42),
		BackgroundTransparency = 1,
		Text = text or "",
		TextColor3 = CS.Theme.SubText,
		Font = Enum.Font.Gotham,
		TextSize = 13,
		TextWrapped = true,
		TextXAlignment = Enum.TextXAlignment.Left,
		TextYAlignment = Enum.TextYAlignment.Top
	})

	return body
end

function CS.Util.InfoCard(parent, title, body, height)
	local card = CS.Util.Card(parent, title, height)
	local label = CS.Util.Body(card, body or "", 42)
	return card, label
end

function CS.Util.Button(parent, text, height)
	local button = CS.Util.Create("TextButton", {
		Parent = parent,
		Size = UDim2.new(1, -8, 0, height or 46),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.18,
		BorderSizePixel = 0,
		Text = text or "Button",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 14,
		AutoButtonColor = true
	})

	CS.Util.Corner(button, 12)
	CS.Util.Stroke(button, CS.Theme.Stroke, 0.5, 1)

	return button
end

function CS.Util.SmallButton(parent, text, width)
	local button = CS.Util.Create("TextButton", {
		Parent = parent,
		Size = UDim2.new(0, width or 140, 1, 0),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.18,
		BorderSizePixel = 0,
		Text = text or "Button",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 13
	})

	CS.Util.Corner(button, 12)
	CS.Util.Stroke(button, CS.Theme.Stroke, 0.5, 1)

	return button
end

function CS.Util.Set(label, text, color)
	if not label then
		return
	end

	label.Text = text or ""

	if color then
		label.TextColor3 = color
	end
end

function CS.Util.MakeDraggable(frame, handle)
	local dragging = false
	local dragStart = nil
	local startPos = nil

	handle.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			dragging = true
			dragStart = input.Position
			startPos = frame.Position
		end
	end)

	handle.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			dragging = false
		end
	end)

	CS.Services.UserInputService.InputChanged:Connect(function(input)
		if dragging and input.UserInputType == Enum.UserInputType.MouseMovement then
			local delta = input.Position - dragStart

			frame.Position = UDim2.new(
				startPos.X.Scale,
				startPos.X.Offset + delta.X,
				startPos.Y.Scale,
				startPos.Y.Offset + delta.Y
			)
		end
	end)
end


function CS.Notify.PlaySound(soundId, volume)
	if not CS.Flags.FriendSounds then
		return
	end

	if not soundId or soundId == "" then
		return
	end

	local parent = CS.UI.Objects.GUI or CS.PlayerGui

	local sound = Instance.new("Sound")
	sound.SoundId = soundId
	sound.Volume = volume or 0.65
	sound.Parent = parent

	pcall(function()
		sound:Play()
	end)

	game:GetService("Debris"):AddItem(sound, 6)
end

function CS.Notify.PlayFriendJoin()
	CS.Notify.PlaySound(CS.Flags.FriendJoinSoundId, 0.75)
end

function CS.Notify.PlayFriendLeave()
	CS.Notify.PlaySound(CS.Flags.FriendLeaveSoundId, 0.75)
end

function CS.Notify.PlayJoinFriend()
	CS.Notify.PlaySound(CS.Flags.JoinFriendSoundId, 0.75)
end

function CS.Notify.Push(title, body, color, player, playSound, isJoining)
	if not CS.Flags.Notifications then
		return
	end

	local gui = CS.UI.Objects.GUI
	if not gui then
		return
	end

	local activeNotifications = CS.Runtime.ActiveNotifications
	local index = #activeNotifications

	local frame = Instance.new("Frame")
	frame.Name = "CSPlayerNotification"
	frame.Size = UDim2.new(0, 360, 0, 64)
	frame.Position = UDim2.new(1, 400, 0, 20 + (index * 74))
	frame.BackgroundColor3 = CS.Theme.NotificationBackground or Color3.fromRGB(20, 20, 20)
	frame.BackgroundTransparency = 0.15
	frame.BorderSizePixel = 0
	frame.ClipsDescendants = true
	frame.Parent = gui

	local corner = Instance.new("UICorner")
	corner.CornerRadius = UDim.new(0, 10)
	corner.Parent = frame

	local stroke = Instance.new("UIStroke")
	stroke.Color = color or CS.Theme.NotificationOutline or CS.Theme.Accent
	stroke.Transparency = 0.25
	stroke.Thickness = 1
	stroke.Parent = frame

	local avatar = Instance.new("ImageLabel")
	avatar.Size = UDim2.new(0, 44, 0, 44)
	avatar.Position = UDim2.new(0, 8, 0, 8)
	avatar.BackgroundTransparency = 1
	avatar.Image = ""
	avatar.Parent = frame

	local avatarCorner = Instance.new("UICorner")
	avatarCorner.CornerRadius = UDim.new(1, 0)
	avatarCorner.Parent = avatar

	local leftOffset = 60

	if player then
		pcall(function()
			avatar.Image = CS.Services.Players:GetUserThumbnailAsync(
				player.UserId,
				Enum.ThumbnailType.HeadShot,
				Enum.ThumbnailSize.Size100x100
			)
		end)
	else
		avatar.Visible = false
		leftOffset = 12
	end

	local titleLabel = Instance.new("TextLabel")
	titleLabel.Size = UDim2.new(1, -(leftOffset + 12), 0, 24)
	titleLabel.Position = UDim2.new(0, leftOffset, 0, 8)
	titleLabel.BackgroundTransparency = 1
	titleLabel.TextXAlignment = Enum.TextXAlignment.Left
	titleLabel.Font = Enum.Font.GothamBold
	titleLabel.TextSize = 14
	titleLabel.TextColor3 = color or CS.Theme.Text
	titleLabel.Text = title or "Notification"
	titleLabel.Parent = frame

	local bodyLabel = Instance.new("TextLabel")
	bodyLabel.Size = UDim2.new(1, -(leftOffset + 12), 0, 26)
	bodyLabel.Position = UDim2.new(0, leftOffset, 0, 32)
	bodyLabel.BackgroundTransparency = 1
	bodyLabel.TextXAlignment = Enum.TextXAlignment.Left
	bodyLabel.TextYAlignment = Enum.TextYAlignment.Top
	bodyLabel.Font = Enum.Font.Gotham
	bodyLabel.TextSize = 12
	bodyLabel.TextWrapped = true
	bodyLabel.TextColor3 = CS.Theme.SubText
	bodyLabel.Text = body or ""
	bodyLabel.Parent = frame

	local timerBack = Instance.new("Frame")
	timerBack.Size = UDim2.new(1, -16, 0, 3)
	timerBack.Position = UDim2.new(0, 8, 1, -6)
	timerBack.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
	timerBack.BackgroundTransparency = 0.8
	timerBack.BorderSizePixel = 0
	timerBack.Parent = frame

	local timerCorner = Instance.new("UICorner")
	timerCorner.CornerRadius = UDim.new(1, 0)
	timerCorner.Parent = timerBack

	local timerLine = Instance.new("Frame")
	timerLine.Size = UDim2.new(1, 0, 1, 0)
	timerLine.BackgroundColor3 = color or CS.Theme.Accent
	timerLine.BackgroundTransparency = 0.05
	timerLine.BorderSizePixel = 0
	timerLine.Parent = timerBack

	local timerLineCorner = Instance.new("UICorner")
	timerLineCorner.CornerRadius = UDim.new(1, 0)
	timerLineCorner.Parent = timerLine

	table.insert(activeNotifications, frame)

	CS.Services.TweenService:Create(
		frame,
		TweenInfo.new(0.4, Enum.EasingStyle.Quart, Enum.EasingDirection.Out),
		{Position = UDim2.new(1, -380, 0, 20 + ((#activeNotifications - 1) * 74))}
	):Play()

	CS.Services.TweenService:Create(
		timerLine,
		TweenInfo.new(3, Enum.EasingStyle.Linear, Enum.EasingDirection.Out),
		{Size = UDim2.new(0, 0, 1, 0)}
	):Play()

	if playSound then
		if isJoining then
			CS.Notify.PlayFriendJoin()
		else
			CS.Notify.PlayFriendLeave()
		end
	end

	task.delay(3, function()
		if not frame.Parent then
			return
		end

		local hideTween = CS.Services.TweenService:Create(
			frame,
			TweenInfo.new(0.35, Enum.EasingStyle.Quart, Enum.EasingDirection.In),
			{Position = UDim2.new(1, 400, 0, frame.Position.Y.Offset)}
		)

		hideTween:Play()
		hideTween.Completed:Wait()

		for i, v in ipairs(activeNotifications) do
			if v == frame then
				table.remove(activeNotifications, i)
				break
			end
		end

		if frame and frame.Parent then
			frame:Destroy()
		end

		for newIndex, notif in ipairs(activeNotifications) do
			CS.Services.TweenService:Create(
				notif,
				TweenInfo.new(0.25, Enum.EasingStyle.Quart, Enum.EasingDirection.Out),
				{Position = UDim2.new(1, -380, 0, 20 + ((newIndex - 1) * 74))}
			):Play()
		end
	end)
end

function CS.Notify.PlayerEvent(player, action, isFriend, isJoining)
	if not player or player == CS.LocalPlayer then
		return
	end

	local color

	if isFriend and isJoining then
		color = Color3.fromRGB(0, 255, 100)
	elseif isFriend and not isJoining then
		color = Color3.fromRGB(255, 80, 80)
	else
		color = Color3.fromRGB(160, 160, 160)
	end

	local title = isFriend and (isJoining and "Friend Joined" or "Friend Left") or (isJoining and "Player Joined" or "Player Left")
	local body = player.DisplayName .. " (@" .. player.Name .. ") " .. action

	CS.Notify.Push(title, body, color, player, isFriend, isJoining)
end


function CS.UI.BuildShell()
	local GUI = CS.Util.Create("ScreenGui", {
		Name = "CSCentralSettings",
		ResetOnSpawn = false,
		IgnoreGuiInset = true,
		ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
		Parent = CS.PlayerGui
	})

	CS.UI.Objects.GUI = GUI

	local toastHolder = CS.Util.Create("Frame", {
		Parent = GUI,
		Name = "ToastHolder",
		Size = UDim2.new(0, 380, 1, -40),
		Position = UDim2.new(1, -400, 0, 20),
		BackgroundTransparency = 1
	})

	CS.Util.List(toastHolder, Enum.FillDirection.Vertical, 10)
	CS.UI.Objects.ToastHolder = toastHolder

	local openButton = CS.Util.Create("TextButton", {
		Parent = GUI,
		Name = "CSOpenButton",
		Size = UDim2.new(0, 150, 0, 42),
		Position = UDim2.new(0, 20, 0.5, -21),
		BackgroundColor3 = CS.Theme.Card,
		BackgroundTransparency = 0.25,
		BorderSizePixel = 0,
		Text = "Open CS",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 15
	})

	CS.Util.Corner(openButton, 12)
	CS.Util.Stroke(openButton, CS.Theme.Stroke, 0.4, 1)
	CS.UI.Objects.OpenButton = openButton

	local main = CS.Util.Create("Frame", {
		Parent = GUI,
		Name = "Main",
		Size = UDim2.new(0, 1080, 0, 650),
		Position = UDim2.new(0.5, -540, 0.5, -325),
		BackgroundColor3 = CS.Theme.Background,
		BackgroundTransparency = CS.Flags.Transparency,
		BorderSizePixel = 0,
		Visible = false
	})

	CS.Util.Corner(main, 20)
	CS.Util.Stroke(main, CS.Theme.Stroke, 0.28, 1)
	CS.Util.Gradient(main, CS.Theme.Background, CS.Theme.Background2, 45)
	CS.UI.Objects.Main = main

	local topBar = CS.Util.Create("Frame", {
		Parent = main,
		Name = "TopBar",
		Size = UDim2.new(1, 0, 0, 72),
		BackgroundTransparency = 1
	})

	CS.UI.Objects.TopBar = topBar

	CS.Util.Create("TextLabel", {
		Parent = topBar,
		Name = "Logo",
		Size = UDim2.new(0, 390, 1, 0),
		Position = UDim2.new(0, 22, 0, 0),
		BackgroundTransparency = 1,
		Text = "CS | Central Settings",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 26,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	CS.Util.Create("TextLabel", {
		Parent = topBar,
		Name = "Subtitle",
		Size = UDim2.new(0, 260, 0, 22),
		Position = UDim2.new(0, 24, 0, 46),
		BackgroundTransparency = 1,
		Text = "utility control panel",
		TextColor3 = CS.Theme.Muted,
		Font = Enum.Font.Gotham,
		TextSize = 12,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	local versionBadge = CS.Util.Create("TextButton", {
		Parent = topBar,
		Name = "VersionBadge",
		Size = UDim2.new(0, 86, 0, 24),
		Position = UDim2.new(0, 300, 0, 46),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.18,
		BorderSizePixel = 0,
		Text = "V " .. CS.Version,
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 11
	})

	CS.Util.Corner(versionBadge, 999)
	CS.Util.Stroke(versionBadge, CS.Theme.Stroke, 0.5, 1)
	CS.UI.Buttons.VersionBadge = versionBadge

	local versionLog = CS.Util.Create("Frame", {
		Parent = main,
		Name = "VersionLog",
		Size = UDim2.new(0, 420, 0, 330),
		Position = UDim2.new(0, 20, 0, 78),
		BackgroundColor3 = CS.Theme.Card,
		BackgroundTransparency = 0.06,
		BorderSizePixel = 0,
		Visible = false,
		ZIndex = 50
	})

	CS.Util.Corner(versionLog, 14)
	CS.Util.Stroke(versionLog, CS.Theme.Accent, 0.2, 1)
	CS.UI.Objects.VersionLog = versionLog

	local logTitle = CS.Util.Create("TextLabel", {
		Parent = versionLog,
		Size = UDim2.new(1, -20, 0, 32),
		Position = UDim2.new(0, 10, 0, 8),
		BackgroundTransparency = 1,
		Text = "CS Update Log",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 16,
		TextXAlignment = Enum.TextXAlignment.Left,
		ZIndex = 51
	})

	local logBody = CS.Util.Create("TextLabel", {
		Parent = versionLog,
		Size = UDim2.new(1, -20, 1, -48),
		Position = UDim2.new(0, 10, 0, 42),
		BackgroundTransparency = 1,
		Text = "",
		TextColor3 = CS.Theme.SubText,
		Font = Enum.Font.Gotham,
		TextSize = 12,
		TextWrapped = true,
		TextXAlignment = Enum.TextXAlignment.Left,
		TextYAlignment = Enum.TextYAlignment.Top,
		ZIndex = 51
	})

	local logText = ""
	for _, entry in ipairs(CS.ChangeLog) do
		logText ..= "V " .. entry.Version .. " — " .. entry.Title .. "\n"
		logText ..= "Time: " .. entry.Time .. "\n"
		for _, detail in ipairs(entry.Details) do
			logText ..= "• " .. detail .. "\n"
		end
		logText ..= "\n"
	end
	logBody.Text = logText

	versionBadge.MouseButton1Click:Connect(function()
		versionLog.Visible = not versionLog.Visible
	end)

	local pillHolder = CS.Util.Create("Frame", {
		Parent = topBar,
		Name = "PillHolder",
		Size = UDim2.new(0, 430, 0, 42),
		Position = UDim2.new(1, -535, 0, 15),
		BackgroundTransparency = 1
	})

	CS.Util.List(pillHolder, Enum.FillDirection.Horizontal, 10).HorizontalAlignment = Enum.HorizontalAlignment.Right

	local function pill(text)
		local frame = CS.Util.Create("Frame", {
			Parent = pillHolder,
			Size = UDim2.new(0, 130, 1, 0),
			BackgroundColor3 = CS.Theme.Card,
			BackgroundTransparency = 0.2,
			BorderSizePixel = 0
		})

		CS.Util.Corner(frame, 999)
		CS.Util.Stroke(frame, CS.Theme.Stroke, 0.5, 1)

		local label = CS.Util.Create("TextLabel", {
			Parent = frame,
			Size = UDim2.new(1, 0, 1, 0),
			BackgroundTransparency = 1,
			Text = text,
			TextColor3 = CS.Theme.Text,
			Font = Enum.Font.GothamBold,
			TextSize = 13
		})

		return label
	end

	CS.UI.Labels.FPSPill = pill("FPS: 0")
	CS.UI.Labels.PingPill = pill("Ping: 0")
	CS.UI.Labels.PlayersPill = pill("Players: 0")

	local closeButton = CS.Util.Create("TextButton", {
		Parent = topBar,
		Size = UDim2.new(0, 90, 0, 38),
		Position = UDim2.new(1, -110, 0, 16),
		BackgroundColor3 = CS.Theme.Card,
		BackgroundTransparency = 0.18,
		BorderSizePixel = 0,
		Text = "Close",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 14
	})

	CS.Util.Corner(closeButton, 12)
	CS.Util.Stroke(closeButton, CS.Theme.Stroke, 0.5, 1)
	CS.UI.Buttons.Close = closeButton

	local accentRail = CS.Util.Create("Frame", {
		Parent = main,
		Name = "AccentRail",
		Size = UDim2.new(1, -40, 0, 3),
		Position = UDim2.new(0, 20, 0, 70),
		BackgroundColor3 = CS.Theme.Accent,
		BackgroundTransparency = 0.15,
		BorderSizePixel = 0
	})

	CS.Util.Corner(accentRail, 999)
	CS.Util.AccentGradient(accentRail)
	CS.UI.Objects.AccentRail = accentRail

	local sidebar = CS.Util.Create("Frame", {
		Parent = main,
		Name = "Sidebar",
		Size = UDim2.new(0, 235, 1, -96),
		Position = UDim2.new(0, 20, 0, 80),
		BackgroundColor3 = CS.Theme.Panel,
		BackgroundTransparency = CS.Flags.PanelTransparency,
		BorderSizePixel = 0
	})

	CS.Util.Corner(sidebar, 16)
	CS.Util.Stroke(sidebar, CS.Theme.StrokeSoft, 0.38, 1)
	CS.Util.Gradient(sidebar, CS.Theme.Panel, CS.Theme.Panel2, 90)
	CS.Util.Padding(sidebar, 12, 12, 14, 14)
	CS.Util.List(sidebar, Enum.FillDirection.Vertical, 10)
	CS.UI.Objects.Sidebar = sidebar

	local content = CS.Util.Create("Frame", {
		Parent = main,
		Name = "Content",
		Size = UDim2.new(1, -285, 1, -96),
		Position = UDim2.new(0, 265, 0, 80),
		BackgroundColor3 = CS.Theme.Panel,
		BackgroundTransparency = CS.Flags.PanelTransparency,
		BorderSizePixel = 0
	})

	CS.Util.Corner(content, 16)
	CS.Util.Stroke(content, CS.Theme.StrokeSoft, 0.38, 1)
	CS.Util.Gradient(content, CS.Theme.Panel, CS.Theme.Panel2, 90)
	CS.UI.Objects.Content = content

	CS.Util.MakeDraggable(main, topBar)
end

function CS.UI.Page(name)
	local page = CS.Util.Create("Frame", {
		Parent = CS.UI.Objects.Content,
		Name = name,
		Size = UDim2.new(1, -20, 1, -20),
		Position = UDim2.new(0, 10, 0, 10),
		BackgroundTransparency = 1,
		Visible = false
	})

	CS.UI.Pages[name] = page
	return page
end

function CS.UI.SwitchPage(name)
	for pageName, page in pairs(CS.UI.Pages) do
		page.Visible = pageName == name
	end

	for tabName, tab in pairs(CS.UI.Tabs) do
		if tabName == name then
			tab.BackgroundColor3 = CS.Theme.Accent
			tab.BackgroundTransparency = 0.12
		else
			tab.BackgroundColor3 = CS.Theme.Card
			tab.BackgroundTransparency = 0.18
		end
	end

	CS.Runtime.CurrentPage = name
end

function CS.UI.Tab(displayName, pageName)
	local tab = CS.Util.Button(CS.UI.Objects.Sidebar, displayName, 50)
	CS.UI.Tabs[pageName] = tab

	tab.MouseButton1Click:Connect(function()
		CS.UI.SwitchPage(pageName)
	end)
end

function CS.UI.Toggle()
	CS.Flags.Open = not CS.Flags.Open

	local main = CS.UI.Objects.Main
	main.Visible = CS.Flags.Open
	CS.UI.Objects.OpenButton.Text = CS.Flags.Open and "Close CS" or "Open CS"

	if CS.Flags.Open then
		main.BackgroundTransparency = 1
		CS.Util.Tween(main, {BackgroundTransparency = CS.Flags.Transparency}, 0.22)
		CS.RefreshAll()
		CS.UI.SwitchPage("Dashboard")
	end
end

function CS.UI.BuildPages()
	CS.UI.Page("Dashboard")
	CS.UI.Page("Player Details")
	CS.UI.Page("Server Browser")
	CS.UI.Page("Game Info")
	CS.UI.Page("Friends")
	CS.UI.Page("Diagnostics")
	CS.UI.Page("Settings")
	CS.UI.Page("Utilities")

	CS.UI.Tab("◇ Dashboard", "Dashboard")
	CS.UI.Tab("◉ Player Details", "Player Details")
	CS.UI.Tab("⇄ Server Browser", "Server Browser")
	CS.UI.Tab("⌑ Game Info", "Game Info")
	CS.UI.Tab("♡ Friends", "Friends")
	CS.UI.Tab("⚙ Diagnostics", "Diagnostics")
	CS.UI.Tab("▣ Settings", "Settings")
	CS.UI.Tab("↯ Utilities", "Utilities")
end


function CS.UI.OverlayCard(parent, title, icon, height)
	local card = CS.Util.Create("Frame", {Parent = parent, Size = UDim2.new(1, -8, 0, height or 190), BackgroundColor3 = CS.Theme.Card, BackgroundTransparency = CS.Flags.CardTransparency or 0.14, BorderSizePixel = 0})
	CS.Util.Corner(card, 14)
	CS.Util.Stroke(card, CS.Theme.Stroke, 0.42, 1)
	CS.Util.Create("Frame", {Parent = card, Size = UDim2.new(0, 3, 0, 44), Position = UDim2.new(0, 0, 0, 52), BackgroundColor3 = CS.Theme.Accent, BackgroundTransparency = 0.28, BorderSizePixel = 0})
	CS.Util.Create("TextLabel", {Parent = card, Size = UDim2.new(0, 34, 0, 44), Position = UDim2.new(0, 12, 0, 0), BackgroundTransparency = 1, Text = icon or "◇", TextColor3 = CS.Theme.Accent, Font = Enum.Font.GothamBold, TextSize = 18})
	CS.Util.Create("TextLabel", {Parent = card, Size = UDim2.new(1, -90, 0, 44), Position = UDim2.new(0, 46, 0, 0), BackgroundTransparency = 1, Text = string.upper(title or "SECTION"), TextColor3 = CS.Theme.Accent, Font = Enum.Font.GothamBold, TextSize = 14, TextXAlignment = Enum.TextXAlignment.Left})
	CS.Util.Create("TextLabel", {Parent = card, Size = UDim2.new(0, 45, 0, 44), Position = UDim2.new(1, -54, 0, 0), BackgroundTransparency = 1, Text = "•••", TextColor3 = CS.Theme.SubText, Font = Enum.Font.GothamBold, TextSize = 14})
	CS.Util.Create("Frame", {Parent = card, Size = UDim2.new(1, -28, 0, 1), Position = UDim2.new(0, 14, 0, 44), BackgroundColor3 = CS.Theme.Stroke, BackgroundTransparency = 0.74, BorderSizePixel = 0})
	return card
end

function CS.UI.OverlayValue(parent, y, icon, title, value, desc)
	local row = CS.Util.Create("Frame", {Parent = parent, Size = UDim2.new(1, -28, 0, 48), Position = UDim2.new(0, 14, 0, y), BackgroundTransparency = 1})
	CS.Util.Create("TextLabel", {Parent = row, Size = UDim2.new(0, 42, 1, 0), BackgroundTransparency = 1, Text = icon or "◇", TextColor3 = CS.Theme.Accent, Font = Enum.Font.GothamBold, TextSize = 18})
	CS.Util.Create("TextLabel", {Parent = row, Size = UDim2.new(0.55, -40, 0, 22), Position = UDim2.new(0, 52, 0, 4), BackgroundTransparency = 1, Text = title or "", TextColor3 = CS.Theme.Text, Font = Enum.Font.GothamBold, TextSize = 13, TextXAlignment = Enum.TextXAlignment.Left})
	local label = CS.Util.Create("TextLabel", {Parent = row, Size = UDim2.new(0.45, -12, 0, 22), Position = UDim2.new(0.55, 0, 0, 4), BackgroundTransparency = 1, Text = value or "", TextColor3 = CS.Theme.Accent, Font = Enum.Font.GothamBold, TextSize = 12, TextXAlignment = Enum.TextXAlignment.Right})
	CS.Util.Create("TextLabel", {Parent = row, Size = UDim2.new(1, -60, 0, 20), Position = UDim2.new(0, 52, 0, 25), BackgroundTransparency = 1, Text = desc or "", TextColor3 = CS.Theme.SubText, Font = Enum.Font.Gotham, TextSize = 11, TextXAlignment = Enum.TextXAlignment.Left})
	CS.Util.Create("Frame", {Parent = parent, Size = UDim2.new(1, -28, 0, 1), Position = UDim2.new(0, 14, 0, y + 52), BackgroundColor3 = CS.Theme.Stroke, BackgroundTransparency = 0.84, BorderSizePixel = 0})
	return label
end

function CS.UI.OverlayButton(parent, text, y, callback)
	local btn = CS.Util.Create("TextButton", {Parent = parent, Size = UDim2.new(1, -28, 0, 38), Position = UDim2.new(0, 14, 0, y), BackgroundColor3 = CS.Theme.Card2, BackgroundTransparency = 0.08, BorderSizePixel = 0, Text = text, TextColor3 = CS.Theme.Text, Font = Enum.Font.GothamBold, TextSize = 12, AutoButtonColor = false})
	CS.Util.Corner(btn, 10)
	CS.Util.Stroke(btn, CS.Theme.Stroke, 0.55, 1)
	btn.MouseEnter:Connect(function() if CS.Flags.Animations then CS.Services.TweenService:Create(btn, TweenInfo.new(0.14), {BackgroundColor3 = CS.Theme.Accent, TextColor3 = Color3.fromRGB(0,0,0)}):Play() end end)
	btn.MouseLeave:Connect(function() if CS.Flags.Animations then CS.Services.TweenService:Create(btn, TweenInfo.new(0.14), {BackgroundColor3 = CS.Theme.Card2, TextColor3 = CS.Theme.Text}):Play() end end)
	btn.MouseButton1Click:Connect(function() if callback then callback() end end)
	return btn
end

function CS.UI.OverlayGraph(parent, y, title)
	local box = CS.Util.Create("Frame", {Parent = parent, Size = UDim2.new(1, -28, 0, 110), Position = UDim2.new(0, 14, 0, y), BackgroundColor3 = CS.Theme.Card2, BackgroundTransparency = 0.22, BorderSizePixel = 0})
	CS.Util.Corner(box, 12); CS.Util.Stroke(box, CS.Theme.Stroke, 0.55, 1)
	CS.Util.Create("TextLabel", {Parent = box, Size = UDim2.new(1, -20, 0, 24), Position = UDim2.new(0, 10, 0, 6), BackgroundTransparency = 1, Text = title or "Activity", TextColor3 = CS.Theme.SubText, Font = Enum.Font.GothamBold, TextSize = 11, TextXAlignment = Enum.TextXAlignment.Left})
	for i=1,18 do local h=8+((i*17)%44); local bar=CS.Util.Create("Frame", {Parent=box, Size=UDim2.new(1/18,-4,0,h), Position=UDim2.new((i-1)/18,10,1,-h-10), BackgroundColor3=CS.Theme.Accent, BackgroundTransparency=0.18+((i%4)*0.08), BorderSizePixel=0}); CS.Util.Corner(bar,999) end
	return box
end

function CS.UI.OverlayText(parent, y, height, text)
	local label = CS.Util.Create("TextLabel", {Parent = parent, Size = UDim2.new(1, -28, 0, height or 120), Position = UDim2.new(0, 14, 0, y), BackgroundTransparency = 1, Text = text or "", TextColor3 = CS.Theme.SubText, Font = Enum.Font.Gotham, TextSize = 12, TextWrapped = true, TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Top})
	return label
end

function CS.UI.ThreeColumns(page)
	local left = CS.Util.Scroll(page); left.Size = UDim2.new(0.333, -8, 1, 0); left.Position = UDim2.new(0, 0, 0, 0)
	local mid = CS.Util.Scroll(page); mid.Size = UDim2.new(0.333, -8, 1, 0); mid.Position = UDim2.new(0.333, 4, 0, 0)
	local right = CS.Util.Scroll(page); right.Size = UDim2.new(0.334, -8, 1, 0); right.Position = UDim2.new(0.666, 8, 0, 0)
	return left, mid, right
end
function CS.Dashboard.Build()
	local page = CS.UI.Pages["Dashboard"]; CS.Util.Clear(page, true)
	local left, mid, right = CS.UI.ThreeColumns(page)
	local overview = CS.UI.OverlayCard(left, "Session Overview", "⌁", 250)
	CS.UI.Labels.DashPlayers = CS.UI.OverlayValue(overview, 58, "👥", "Players", "--", "Current server population.")
	CS.UI.Labels.DashPing = CS.UI.OverlayValue(overview, 112, "📡", "Ping", "--", "Current network delay.")
	CS.UI.Labels.DashFPS = CS.UI.OverlayValue(overview, 166, "⚡", "FPS", "--", "Client frame rate.")
	CS.UI.OverlayValue(overview, 220, "✓", "CS Runtime", "Active", "Overlay status.")
	local server = CS.UI.OverlayCard(left, "Server Snapshot", "▦", 230)
	CS.UI.Labels.DashServerId = CS.UI.OverlayValue(server, 58, "◎", "Job ID", game.JobId:sub(1,12).."...", "Current server instance.")
	CS.UI.Labels.DashPlace = CS.UI.OverlayValue(server, 112, "◇", "Place ID", tostring(game.PlaceId), "Current game place.")
	CS.UI.Labels.DashClock = CS.UI.OverlayValue(server, 166, "◷", "Clock", "--", "Local runtime clock.")
	local graph = CS.UI.OverlayCard(mid, "Ping Activity", "⌁", 240); CS.UI.OverlayGraph(graph, 58, "Recent Ping Samples"); CS.UI.Labels.DashPingStats = CS.UI.OverlayValue(graph, 174, "↕", "Low / Avg / High", "--", "Tracked while CS is running.")
	local quick = CS.UI.OverlayCard(mid, "Quick Controls", "⚙", 270)
	CS.UI.OverlayButton(quick, "Refresh Dashboard", 58, function() CS.Dashboard.Update(); CS.Notify.Push("Dashboard", "Dashboard refreshed.", CS.Theme.Info) end)
	CS.UI.OverlayButton(quick, "Open Player Details", 106, function() CS.UI.SwitchPage("Player Details") end)
	CS.UI.OverlayButton(quick, "Open Server Browser", 154, function() CS.UI.SwitchPage("Server Browser") end)
	CS.UI.OverlayButton(quick, "Repair Menu Layout", 202, function() CS.Settings.ApplyVisuals(); CS.Notify.Push("Dashboard", "Layout repaired.", CS.Theme.Success) end)
	local feed = CS.UI.OverlayCard(right, "Live Feed", "☰", 330); CS.UI.Labels.Feed = CS.UI.OverlayText(feed, 58, 250, "Waiting for player events...")
	local status = CS.UI.OverlayCard(right, "CS Status", "◎", 200); CS.UI.Labels.DashStatus = CS.UI.OverlayValue(status, 58, "✓", "Interface", "Ready", "Overlay systems active."); CS.UI.Labels.DashNotif = CS.UI.OverlayValue(status, 112, "🔔", "Notifications", tostring(CS.Flags.Notifications), "Popup notification state.")
end

function CS.PlayerDetails.Build()
	local page = CS.UI.Pages["Player Details"]; CS.Util.Clear(page, true)
	local left = CS.Util.Scroll(page); left.Size = UDim2.new(0.38,-8,1,0)
	local right = CS.Util.Scroll(page); right.Size = UDim2.new(0.62,-8,1,0); right.Position = UDim2.new(0.38,8,0,0)
	local list = CS.UI.OverlayCard(left, "Players", "👥", 540); CS.UI.OverlayValue(list, 58, "◎", "Select Player", "", "Click a player to inspect details.")
	local holder = CS.Util.Create("Frame", {Parent=list, Size=UDim2.new(1,-28,1,-122), Position=UDim2.new(0,14,0,112), BackgroundColor3=CS.Theme.Card2, BackgroundTransparency=0.22, BorderSizePixel=0}); CS.Util.Corner(holder,12); CS.Util.Stroke(holder,CS.Theme.Stroke,0.55,1); CS.UI.Objects.PlayerList = CS.Util.Scroll(holder)
	local profile = CS.UI.OverlayCard(right, "Selected Player", "👤", 230); CS.UI.Objects.SelectedAvatar = CS.Settings.MakeRobloxAvatarPreview(profile, CS.LocalPlayer.UserId); CS.UI.Labels.SelectedName = CS.UI.OverlayValue(profile, 58, "◇", "Display", CS.LocalPlayer.DisplayName, "Current inspected player."); CS.UI.Labels.SelectedUser = CS.UI.OverlayValue(profile, 112, "@", "Username", "@"..CS.LocalPlayer.Name, "Roblox username."); CS.UI.Labels.SelectedDistance = CS.UI.OverlayValue(profile, 166, "↔", "Distance", "0 studs", "Distance from your character.")
	local account = CS.UI.OverlayCard(right, "Account", "◎", 230); CS.UI.Labels.AccountInfo = CS.UI.OverlayText(account, 58, 150, "Click a player to load account information.")
	local char = CS.UI.OverlayCard(right, "Character", "▣", 230); CS.UI.Labels.CharacterInfo = CS.UI.OverlayText(char, 58, 150, "Character details will appear here.")
	local actions = CS.UI.OverlayCard(right, "Player Options", "⚙", 260); CS.UI.OverlayButton(actions,"Toggle Spectate",58,function() if CS.PlayerDetails.ToggleSpectate then CS.PlayerDetails.ToggleSpectate() end end); CS.UI.OverlayButton(actions,"Teleport To Player",106,function() if CS.PlayerDetails.TeleportToSelected then CS.PlayerDetails.TeleportToSelected() end end); CS.UI.OverlayButton(actions,"Toggle Local Highlight",154,function() if CS.PlayerDetails.ToggleHighlight then CS.PlayerDetails.ToggleHighlight() end end); CS.UI.OverlayButton(actions,"Copy Username",202,function() local p=CS.Runtime.SelectedPlayer or CS.LocalPlayer; if setclipboard then setclipboard(p.Name) end; CS.Notify.Push("Player", "Copied username.", CS.Theme.Info) end)
	CS.PlayerDetails.RefreshList(); CS.PlayerDetails.Select(CS.Runtime.SelectedPlayer or CS.LocalPlayer)
end

function CS.PlayerDetails.CreateRow(player)
	local parent = CS.UI.Objects.PlayerListScroll

	local row = CS.Util.Create("TextButton", {
		Parent = parent,
		Size = UDim2.new(1, -8, 0, 68),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.16,
		BorderSizePixel = 0,
		Text = ""
	})

	CS.Util.Corner(row, 12)
	CS.Util.Stroke(row, CS.Theme.Stroke, 0.55, 1)

	local icon = CS.Util.Create("ImageLabel", {
		Parent = row,
		Size = UDim2.new(0, 46, 0, 46),
		Position = UDim2.new(0, 10, 0, 11),
		BackgroundTransparency = 1
	})

	CS.Util.Corner(icon, 999)

	pcall(function()
		icon.Image = CS.Services.Players:GetUserThumbnailAsync(
			player.UserId,
			Enum.ThumbnailType.HeadShot,
			Enum.ThumbnailSize.Size100x100
		)
	end)

	CS.Util.Create("TextLabel", {
		Parent = row,
		Size = UDim2.new(1, -70, 1, 0),
		Position = UDim2.new(0, 66, 0, 0),
		BackgroundTransparency = 1,
		Text = player.DisplayName .. "\n@" .. player.Name,
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 13,
		TextXAlignment = Enum.TextXAlignment.Left,
		TextYAlignment = Enum.TextYAlignment.Center
	})

	local badge = CS.Util.Create("TextLabel", {
		Parent = row,
		Size = UDim2.new(0, 68, 0, 20),
		Position = UDim2.new(1, -78, 0, 8),
		BackgroundColor3 = CS.Theme.Accent,
		BackgroundTransparency = 0.15,
		BorderSizePixel = 0,
		Text = "",
		Visible = false,
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 10
	})

	CS.Util.Corner(badge, 999)

	if player == CS.LocalPlayer then
		badge.Text = "YOU"
		badge.Visible = true
	else
		pcall(function()
			if CS.LocalPlayer:IsFriendsWith(player.UserId) then
				badge.Text = "FRIEND"
				badge.Visible = true
			end
		end)
	end

	row.MouseButton1Click:Connect(function()
		CS.Runtime.SelectedPlayer = player

		for _, obj in ipairs(parent:GetChildren()) do
			if obj:IsA("TextButton") then
				obj.BackgroundColor3 = CS.Theme.Card2
				obj.BackgroundTransparency = 0.16
			end
		end

		row.BackgroundColor3 = CS.Theme.Accent
		row.BackgroundTransparency = 0.02

		CS.PlayerDetails.UpdateSelected()
	end)

	if CS.Runtime.SelectedPlayer == player then
		row.BackgroundColor3 = CS.Theme.Accent
		row.BackgroundTransparency = 0.02
	end
end

function CS.PlayerDetails.Refresh()
	local scroll = CS.UI.Objects.PlayerListScroll
	if not scroll then return end

	CS.Util.Clear(scroll, true)
	CS.Util.InfoCard(scroll, "Players", "Click a player to inspect details.", 76)

	for _, player in ipairs(CS.Services.Players:GetPlayers()) do
		CS.PlayerDetails.CreateRow(player)
	end
end

function CS.PlayerDetails.UpdateSelected()
	local player = CS.Runtime.SelectedPlayer

	if not player or not player.Parent then
		player = CS.LocalPlayer
		CS.Runtime.SelectedPlayer = player
	end

	pcall(function()
		CS.UI.Objects.FullBody.Image = CS.Services.Players:GetUserThumbnailAsync(
			player.UserId,
			Enum.ThumbnailType.AvatarThumbnail,
			Enum.ThumbnailSize.Size420x420
		)
	end)

	local character = CS.Util.Character(player)
	local humanoid = CS.Util.Humanoid(player)
	local root = CS.Util.Root(player)

	CS.Util.Set(CS.UI.Labels.SelectedPlayer, player.DisplayName .. "\n@" .. player.Name)

	if humanoid then
		CS.Util.Set(CS.UI.Labels.PlayerHealth,
			"Health: " .. math.floor(humanoid.Health) ..
			" / " .. math.floor(humanoid.MaxHealth) ..
			"\nState: " .. humanoid:GetState().Name ..
			"\nAlive: " .. tostring(humanoid.Health > 0)
		)
	else
		CS.Util.Set(CS.UI.Labels.PlayerHealth, "Humanoid unavailable.")
	end

	if root then
		local position = root.Position
		local velocity = root.AssemblyLinearVelocity
		local myRoot = CS.Util.Root(CS.LocalPlayer)
		local distance = "Unavailable"

		if myRoot then
			distance = math.floor((root.Position - myRoot.Position).Magnitude) .. " studs"
		end

		CS.Util.Set(CS.UI.Labels.PlayerMovement,
			"XYZ:" ..
			"\nX: " .. math.floor(position.X) ..
			"\nY: " .. math.floor(position.Y) ..
			"\nZ: " .. math.floor(position.Z) ..
			"\n\nVelocity:" ..
			"\nX: " .. math.floor(velocity.X) ..
			"\nY: " .. math.floor(velocity.Y) ..
			"\nZ: " .. math.floor(velocity.Z) ..
			"\n\nDistance: " .. distance
		)
	else
		CS.Util.Set(CS.UI.Labels.PlayerMovement, "HumanoidRootPart unavailable.")
	end

	local friendState = "No"

	if player == CS.LocalPlayer then
		friendState = "You"
	else
		pcall(function()
			if CS.LocalPlayer:IsFriendsWith(player.UserId) then
				friendState = "Yes"
			end
		end)
	end

	CS.Util.Set(CS.UI.Labels.PlayerAccount,
		"Display Name: " .. player.DisplayName ..
		"\nUsername: @" .. player.Name ..
		"\nUserId: " .. tostring(player.UserId) ..
		"\nAccount Age: " .. tostring(player.AccountAge) .. " days" ..
		"\nMembership: " .. player.MembershipType.Name ..
		"\nFriend: " .. friendState
	)

	local toolName = "None"

	if character then
		local tool = character:FindFirstChildOfClass("Tool")
		if tool then
			toolName = tool.Name
		end
	end

	CS.Util.Set(CS.UI.Labels.PlayerCharacter,
		"Character Loaded: " .. tostring(character ~= nil) ..
		"\nRig Type: " .. (humanoid and humanoid.RigType.Name or "Unknown") ..
		"\nTeam: " .. (player.Team and player.Team.Name or "None") ..
		"\nNeutral: " .. tostring(player.Neutral)
	)

	CS.Util.Set(CS.UI.Labels.PlayerTool,
		"Equipped Tool: " .. toolName ..
		"\nCharacter Parent: " .. (character and character.Parent and character.Parent.Name or "None")
	)

	if CS.Runtime.HighlightDistanceLabel and CS.Runtime.HighlightDistanceLabel.Parent then
		local targetRoot = CS.Util.Root(player)
		local myRoot = CS.Util.Root(CS.LocalPlayer)
		local text = CS.Runtime.HighlightDistanceLabel:FindFirstChild("DistanceText")

		if targetRoot and myRoot and text then
			text.Text = tostring(math.floor((targetRoot.Position - myRoot.Position).Magnitude)) .. " studs"
		end
	end
end

function CS.PlayerDetails.GetSelected()
	local player = CS.Runtime.SelectedPlayer

	if not player or not player.Parent then
		player = CS.LocalPlayer
		CS.Runtime.SelectedPlayer = player
	end

	return player
end

function CS.PlayerDetails.SetToggleButton(button, isOn, onText, offText)
	if not button then
		return
	end

	button.Text = isOn and onText or offText
	button.BackgroundColor3 = isOn and CS.Theme.Success or CS.Theme.Card2
	button.TextColor3 = isOn and Color3.fromRGB(0, 0, 0) or CS.Theme.Text
end

function CS.PlayerDetails.ToggleOptions(force)
	local overlay = CS.UI.Objects.PlayerOptionsOverlay
	local toggleButton = CS.UI.Buttons.PlayerOptionsToggle

	if not overlay then
		return
	end

	if force == nil then
		CS.Runtime.OptionsOpen = not CS.Runtime.OptionsOpen
	else
		CS.Runtime.OptionsOpen = force
	end

	local detailsScroll = overlay.Parent

	for _, child in ipairs(detailsScroll:GetChildren()) do
		if child:IsA("GuiObject") and child ~= overlay and child ~= toggleButton then
			child.Visible = not CS.Runtime.OptionsOpen
		end
	end

	overlay.Visible = CS.Runtime.OptionsOpen

	if toggleButton then
		toggleButton.Text = CS.Runtime.OptionsOpen and "Close Player Options" or "Open Player Options"
		toggleButton.BackgroundColor3 = CS.Runtime.OptionsOpen and CS.Theme.Success or CS.Theme.Card2
	end
end

function CS.PlayerDetails.ToggleSpectate()
	local selected = CS.PlayerDetails.GetSelected()

	if CS.Runtime.Spectating then
		local myHumanoid = CS.Util.Humanoid(CS.LocalPlayer)

		if myHumanoid then
			workspace.CurrentCamera.CameraSubject = myHumanoid
		end

		CS.Runtime.Spectating = false

		CS.PlayerDetails.SetToggleButton(CS.UI.Buttons.SpectateToggle, false, "Stop Spectating", "Toggle Spectate")

		CS.Notify.Push("Spectate", "Stopped spectating.", CS.Theme.Info)
		return
	end

	local humanoid = CS.Util.Humanoid(selected)

	if humanoid then
		workspace.CurrentCamera.CameraSubject = humanoid
		CS.Runtime.Spectating = true

		CS.PlayerDetails.SetToggleButton(CS.UI.Buttons.SpectateToggle, true, "Stop Spectating", "Toggle Spectate")

		CS.Notify.Push("Spectate", "Now spectating " .. selected.DisplayName .. ".", CS.Theme.Info, selected)
	else
		CS.Notify.Push("Spectate", "Selected player has no humanoid loaded.", CS.Theme.Warning, selected)
	end
end

function CS.PlayerDetails.TeleportToSelected()
	local selected = CS.PlayerDetails.GetSelected()
	local myRoot = CS.Util.Root(CS.LocalPlayer)
	local targetRoot = CS.Util.Root(selected)

	if not myRoot then
		CS.Notify.Push("Teleport", "Your character root is not loaded.", CS.Theme.Warning)
		return
	end

	if not targetRoot then
		CS.Notify.Push("Teleport", "Selected player's root is not loaded.", CS.Theme.Warning, selected)
		return
	end

	if selected == CS.LocalPlayer then
		CS.Notify.Push("Teleport", "You already selected yourself.", CS.Theme.Warning, selected)
		return
	end

	myRoot.AssemblyLinearVelocity = Vector3.zero
	myRoot.AssemblyAngularVelocity = Vector3.zero
	myRoot.CFrame = targetRoot.CFrame * CFrame.new(0, 0, 4)

	CS.Notify.Push("Teleport", "Teleported to " .. selected.DisplayName .. ".", CS.Theme.Success, selected)
end


function CS.PlayerDetails.ToggleHighlight()
	local player = CS.PlayerDetails.GetSelected()
	local character = CS.Util.Character(player)

	if not character then
		CS.Notify.Push("Highlight", "Selected player character is not loaded.", CS.Theme.Warning, player)
		return
	end

	if CS.Runtime.HighlightTarget then
		CS.Runtime.HighlightTarget:Destroy()
		CS.Runtime.HighlightTarget = nil

		if CS.Runtime.HighlightDistanceLabel then
			CS.Runtime.HighlightDistanceLabel:Destroy()
			CS.Runtime.HighlightDistanceLabel = nil
		end

		CS.PlayerDetails.SetToggleButton(CS.UI.Buttons.HighlightToggle, false, "Highlight: ON", "Toggle Local Highlight")
		CS.Notify.Push("Highlight", "Local highlight removed.", CS.Theme.Info, player)
		return
	end

	local highlight = Instance.new("Highlight")
	highlight.Name = "CS_SelectedPlayerHighlight"
	highlight.FillColor = CS.Theme.Accent
	highlight.OutlineColor = CS.Theme.Text
	highlight.FillTransparency = 0.75
	highlight.OutlineTransparency = 0
	highlight.Adornee = character
	highlight.Parent = character

	local head = character:FindFirstChild("Head") or CS.Util.Root(player)

	if head then
		local billboard = Instance.new("BillboardGui")
		billboard.Name = "CS_StudDistanceLabel"
		billboard.Size = UDim2.new(0, 160, 0, 36)
		billboard.StudsOffset = Vector3.new(0, 3.2, 0)
		billboard.AlwaysOnTop = true
		billboard.Adornee = head
		billboard.Parent = head

		local text = Instance.new("TextLabel")
		text.Name = "DistanceText"
		text.Size = UDim2.new(1, 0, 1, 0)
		text.BackgroundTransparency = 0.35
		text.BackgroundColor3 = Color3.fromRGB(0, 0, 0)
		text.TextColor3 = CS.Theme.Success
		text.TextStrokeTransparency = 0.2
		text.Font = Enum.Font.GothamBold
		text.TextSize = 14
		text.Text = "Distance: ..."
		text.Parent = billboard

		CS.Util.Corner(text, 8)
		CS.Runtime.HighlightDistanceLabel = billboard
	end

	CS.Runtime.HighlightTarget = highlight

	CS.PlayerDetails.SetToggleButton(CS.UI.Buttons.HighlightToggle, true, "Highlight: ON", "Toggle Local Highlight")
	CS.Notify.Push("Highlight", "Locally highlighted " .. player.DisplayName .. ".", CS.Theme.Success, player)
end

function CS.PlayerDetails.CopyUsername()
	local player = CS.PlayerDetails.GetSelected()

	if setclipboard then
		setclipboard(player.Name)
		CS.Notify.Push("Clipboard", "Copied username: " .. player.Name, CS.Theme.Success, player)
	else
		CS.Notify.Push("Clipboard", "Clipboard unavailable.", CS.Theme.Warning, player)
	end
end

function CS.PlayerDetails.CopyUserId()
	local player = CS.PlayerDetails.GetSelected()

	if setclipboard then
		setclipboard(tostring(player.UserId))
		CS.Notify.Push("Clipboard", "Copied UserId: " .. tostring(player.UserId), CS.Theme.Success, player)
	else
		CS.Notify.Push("Clipboard", "Clipboard unavailable.", CS.Theme.Warning, player)
	end
end

function CS.PlayerDetails.CopyPosition()
	local player = CS.PlayerDetails.GetSelected()
	local root = CS.Util.Root(player)

	if not root then
		CS.Notify.Push("Clipboard", "Selected player position unavailable.", CS.Theme.Warning, player)
		return
	end

	local pos = root.Position
	local text = string.format("X: %d, Y: %d, Z: %d", math.floor(pos.X), math.floor(pos.Y), math.floor(pos.Z))

	if setclipboard then
		setclipboard(text)
		CS.Notify.Push("Clipboard", "Copied selected player XYZ.", CS.Theme.Success, player)
	else
		CS.Notify.Push("Clipboard", text, CS.Theme.Info, player)
	end
end


function CS.ServerBrowser.Build()
	local page = CS.UI.Pages["Server Browser"]; CS.Util.Clear(page, true)
	local top = CS.UI.OverlayCard(page, "Current Server", "▦", 150); top.Size = UDim2.new(1,-8,0,150); CS.UI.Labels.CurrentServerInfo = CS.UI.OverlayValue(top,58,"◎","Current","--","Players, ping, and server id.")
	local browser = CS.UI.OverlayCard(page, "Server Browser", "☰", 460); browser.Position=UDim2.new(0,0,0,164); browser.Size=UDim2.new(0.66,-8,1,-164); CS.UI.Objects.ServerList = CS.Util.Scroll(browser); CS.UI.Objects.ServerList.Position=UDim2.new(0,14,0,56); CS.UI.Objects.ServerList.Size=UDim2.new(1,-28,1,-70)
	local side = CS.UI.OverlayCard(page, "Server Tools", "⚙", 460); side.Position=UDim2.new(0.66,8,0,164); side.Size=UDim2.new(0.34,-8,1,-164); CS.UI.Labels.ServerPingData=CS.UI.OverlayValue(side,58,"📡","Ping","--","Lowest / average / highest."); CS.UI.Labels.ServerPlayerData=CS.UI.OverlayValue(side,112,"👥","Players","--","Current population."); CS.UI.OverlayGraph(side,170,"Ping History"); CS.UI.OverlayButton(side,"Refresh Servers",292,function() if CS.ServerBrowser.Fetch then CS.ServerBrowser.Fetch() end end); CS.UI.OverlayButton(side,"Rejoin Current Server",340,function() if CS.ServerBrowser.Rejoin then CS.ServerBrowser.Rejoin() end end); CS.UI.OverlayButton(side,"Server Hop",388,function() if CS.ServerBrowser.Hop then CS.ServerBrowser.Hop() end end)
	if CS.ServerBrowser.UpdateLive then CS.ServerBrowser.UpdateLive() end
end

function CS.ServerBrowser.Switch(name)
	CS.UI.Objects.LiveServerView.Visible = name == "Live"
	CS.UI.Objects.BrowserView.Visible = name == "Browser"
	CS.UI.Objects.ServerToolsView.Visible = name == "Tools"
	CS.Runtime.ServerView = name
end

function CS.ServerBrowser.BuildLive()
	local view = CS.UI.Objects.LiveServerView

	local networkCard = CS.Util.Card(view, "Ping Monitor", 220)
	local networkText = CS.Util.Body(networkCard, "", 42)
	CS.UI.Labels.LiveNetwork = networkText

	local chart = CS.Util.Create("Frame", {
		Parent = networkCard,
		Size = UDim2.new(1, -315, 1, -66),
		Position = UDim2.new(0, 295, 0, 52),
		BackgroundColor3 = Color3.fromRGB(14, 14, 20),
		BackgroundTransparency = 0.2,
		BorderSizePixel = 0
	})

	CS.Util.Corner(chart, 12)
	CS.Util.Stroke(chart, CS.Theme.Stroke, 0.65, 1)

	CS.UI.Charts.Live = {}

	for i = 1, 48 do
		local bar = CS.Util.Create("Frame", {
			Parent = chart,
			AnchorPoint = Vector2.new(0, 1),
			Position = UDim2.new((i - 1) / 48, 1, 1, 0),
			Size = UDim2.new(1 / 48, -2, 0.05, 0),
			BackgroundColor3 = CS.Theme.Success,
			BorderSizePixel = 0
		})

		CS.UI.Charts.Live[i] = bar
	end

	local currentCard, current = CS.Util.InfoCard(view, "Current Server", "", 160)
	local perfCard, perf = CS.Util.InfoCard(view, "Performance", "", 120)
	local capCard, cap = CS.Util.InfoCard(view, "Capabilities", "", 140)

	CS.UI.Labels.CurrentServer = current
	CS.UI.Labels.CurrentPerf = perf
	CS.UI.Labels.CurrentCapabilities = cap
end

function CS.ServerBrowser.BuildBrowser()
	local view = CS.UI.Objects.BrowserView

	local headerCard, header = CS.Util.InfoCard(view, "Public Server Browser", "Requires HTTP request support.", 110)
	CS.UI.Labels.BrowserHeader = header

	local controls = CS.Util.Create("Frame", {
		Parent = view,
		Size = UDim2.new(1, -8, 0, 56),
		BackgroundTransparency = 1
	})

	CS.Util.List(controls, Enum.FillDirection.Horizontal, 10)

	local refresh = CS.Util.SmallButton(controls, "Refresh", 140)
	local sortPing = CS.Util.SmallButton(controls, "Sort Ping", 140)
	local sortFull = CS.Util.SmallButton(controls, "Sort Full", 140)
	local sortEmpty = CS.Util.SmallButton(controls, "Sort Empty", 140)

	local box = CS.Util.Create("Frame", {
		Parent = view,
		Size = UDim2.new(1, -8, 0, 520),
		BackgroundColor3 = Color3.fromRGB(14, 14, 20),
		BackgroundTransparency = 0.18,
		BorderSizePixel = 0
	})

	CS.Util.Corner(box, 14)
	CS.Util.Stroke(box, CS.Theme.Stroke, 0.55, 1)

	CS.UI.Objects.ServerListScroll = CS.Util.Scroll(box)

	refresh.MouseButton1Click:Connect(function()
		CS.ServerBrowser.Fetch()
	end)

	sortPing.MouseButton1Click:Connect(function()
		CS.ServerBrowser.Sort("Ping")
	end)

	sortFull.MouseButton1Click:Connect(function()
		CS.ServerBrowser.Sort("Fullest")
	end)

	sortEmpty.MouseButton1Click:Connect(function()
		CS.ServerBrowser.Sort("Emptiest")
	end)
end

function CS.ServerBrowser.BuildTools()
	local view = CS.UI.Objects.ServerToolsView

	CS.Util.InfoCard(view, "Server Tools", "Useful server actions.", 95)

	local rejoin = CS.Util.Button(view, "Rejoin Current Server")
	local hop = CS.Util.Button(view, "Server Hop")
	local copyJob = CS.Util.Button(view, "Copy JobId")
	local copyPlace = CS.Util.Button(view, "Copy PlaceId")
	local copyGame = CS.Util.Button(view, "Copy GameId")

	rejoin.MouseButton1Click:Connect(function()
		CS.Services.TeleportService:TeleportToPlaceInstance(game.PlaceId, game.JobId, CS.LocalPlayer)
	end)

	hop.MouseButton1Click:Connect(function()
		CS.Services.TeleportService:Teleport(game.PlaceId, CS.LocalPlayer)
	end)

	copyJob.MouseButton1Click:Connect(function()
		if setclipboard then
			setclipboard(game.JobId)
			CS.Notify.Push("Clipboard", "Copied JobId.", CS.Theme.Success)
		else
			CS.Notify.Push("Clipboard", "Clipboard unavailable.", CS.Theme.Warning)
		end
	end)

	copyPlace.MouseButton1Click:Connect(function()
		if setclipboard then
			setclipboard(tostring(game.PlaceId))
			CS.Notify.Push("Clipboard", "Copied PlaceId.", CS.Theme.Success)
		else
			CS.Notify.Push("Clipboard", "Clipboard unavailable.", CS.Theme.Warning)
		end
	end)

	copyGame.MouseButton1Click:Connect(function()
		if setclipboard then
			setclipboard(tostring(game.GameId))
			CS.Notify.Push("Clipboard", "Copied GameId.", CS.Theme.Success)
		else
			CS.Notify.Push("Clipboard", "Clipboard unavailable.", CS.Theme.Warning)
		end
	end)
end

function CS.ServerBrowser.CreateRow(server, index)
	local scroll = CS.UI.Objects.ServerListScroll

	local row = CS.Util.Create("Frame", {
		Parent = scroll,
		Size = UDim2.new(1, -8, 0, 92),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.14,
		BorderSizePixel = 0
	})

	CS.Util.Corner(row, 12)
	CS.Util.Stroke(row, CS.Theme.Stroke, 0.55, 1)

	local ping = tonumber(server.ping) or 0
	local status, color = CS.Util.PingStatus(ping)
	local serverId = tostring(server.id or "")

	CS.Util.Create("TextLabel", {
		Parent = row,
		Size = UDim2.new(1, -160, 1, -12),
		Position = UDim2.new(0, 12, 0, 6),
		BackgroundTransparency = 1,
		Text =
			"Server #" .. tostring(index) ..
			"\nPlayers: " .. tostring(server.playing or "?") .. "/" .. tostring(server.maxPlayers or "?") ..
			" | Ping: " .. tostring(server.ping or "N/A") .. " ms | " .. status ..
			"\nID: " .. (serverId ~= "" and string.sub(serverId, 1, 18) .. "..." or "Unknown"),
		TextColor3 = CS.Theme.SubText,
		Font = Enum.Font.Gotham,
		TextSize = 13,
		TextWrapped = true,
		TextXAlignment = Enum.TextXAlignment.Left,
		TextYAlignment = Enum.TextYAlignment.Center
	})

	local join = CS.Util.Create("TextButton", {
		Parent = row,
		Size = UDim2.new(0, 120, 0, 44),
		Position = UDim2.new(1, -135, 0.5, -22),
		BackgroundColor3 = color,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = "Join",
		TextColor3 = Color3.fromRGB(0, 0, 0),
		Font = Enum.Font.GothamBold,
		TextSize = 14
	})

	CS.Util.Corner(join, 10)

	join.MouseButton1Click:Connect(function()
		if server.id then
			CS.Services.TeleportService:TeleportToPlaceInstance(game.PlaceId, server.id, CS.LocalPlayer)
		end
	end)
end

function CS.ServerBrowser.Rebuild(data)
	local scroll = CS.UI.Objects.ServerListScroll
	if not scroll then return end

	CS.Util.Clear(scroll, true)

	if not data or #data == 0 then
		CS.Util.InfoCard(scroll, "No Server Data", "Press Refresh to fetch servers.", 100)
		return
	end

	for index, server in ipairs(data) do
		CS.ServerBrowser.CreateRow(server, index)
	end
end

function CS.ServerBrowser.Fetch()
	if not CS.Request then
		CS.Util.Set(CS.UI.Labels.BrowserHeader, "HTTP request unavailable. Server browser cannot fetch servers here.", CS.Theme.Error)
		CS.Notify.Push("Server Browser", "HTTP request unavailable.", CS.Theme.Error)
		return
	end

	CS.Util.Set(CS.UI.Labels.BrowserHeader, "Fetching public servers...")

	local success, response = pcall(function()
		return CS.Request({
			Url = "https://[Log in to view URL]" .. tostring(game.PlaceId) .. "/servers/Public?sortOrder=Asc&limit=100",
			Method = "GET"
		})
	end)

	if not success or not response or not response.Body then
		CS.Util.Set(CS.UI.Labels.BrowserHeader, "Failed to fetch server list.", CS.Theme.Error)
		CS.Notify.Push("Server Browser", "Fetch failed.", CS.Theme.Error)
		return
	end

	local decoded
	local ok = pcall(function()
		decoded = CS.Services.HttpService:JSONDecode(response.Body)
	end)

	if not ok or not decoded or not decoded.data then
		CS.Util.Set(CS.UI.Labels.BrowserHeader, "Invalid server response.", CS.Theme.Warning)
		return
	end

	CS.Runtime.ServerData = decoded.data
	CS.Runtime.LastServerFetch = os.clock()

	CS.Util.Set(CS.UI.Labels.BrowserHeader, "Loaded " .. tostring(#decoded.data) .. " servers.")
	CS.ServerBrowser.Rebuild(CS.Runtime.ServerData)
	CS.Notify.Push("Server Browser", "Loaded public servers.", CS.Theme.Success)
end

function CS.ServerBrowser.Sort(mode)
	CS.Flags.ServerSortMode = mode

	local data = CS.Runtime.ServerData or {}

	if mode == "Ping" then
		table.sort(data, function(a, b)
			return (tonumber(a.ping) or 999999) < (tonumber(b.ping) or 999999)
		end)
	elseif mode == "Fullest" then
		table.sort(data, function(a, b)
			return (tonumber(a.playing) or 0) > (tonumber(b.playing) or 0)
		end)
	elseif mode == "Emptiest" then
		table.sort(data, function(a, b)
			return (tonumber(a.playing) or 0) < (tonumber(b.playing) or 0)
		end)
	end

	CS.ServerBrowser.Rebuild(data)
end

function CS.ServerBrowser.UpdateLive()
	local ping = CS.Runtime.Ping
	local status, color = CS.Util.PingStatus(ping)

	CS.Util.Set(CS.UI.Labels.LiveNetwork,
		"Current: " .. tostring(ping) .. " ms" ..
		"\nStatus: " .. status ..
		"\nLowest: " .. tostring(CS.Runtime.LowPing or "N/A") .. " ms" ..
		"\nAverage: " .. tostring(CS.Runtime.AvgPing or "N/A") .. " ms" ..
		"\nHighest: " .. tostring(CS.Runtime.HighPing or "N/A") .. " ms",
		color
	)

	CS.Util.Set(CS.UI.Labels.CurrentServer,
		"Players: " .. tostring(#CS.Services.Players:GetPlayers()) .. "/" .. tostring(CS.Services.Players.MaxPlayers) ..
		"\nPlaceId: " .. tostring(game.PlaceId) ..
		"\nGameId: " .. tostring(game.GameId) ..
		"\nJobId: " .. (game.JobId ~= "" and game.JobId or "Unavailable")
	)

	CS.Util.Set(CS.UI.Labels.CurrentPerf,
		"FPS: " .. tostring(CS.Runtime.FPS) ..
		"\nPing: " .. tostring(ping) .. " ms" ..
		"\nClient Uptime: " .. CS.Util.FormatSeconds(os.clock() - CS.Runtime.UptimeStart)
	)

	CS.Util.Set(CS.UI.Labels.CurrentCapabilities,
		"HTTP Request: " .. tostring(CS.Request ~= nil) ..
		"\nClipboard: " .. tostring(setclipboard ~= nil) ..
		"\nCoreGui Access: " .. tostring(pcall(function() return CS.Services.CoreGui.Name end)) ..
		"\nGame Loaded: " .. tostring(game:IsLoaded())
	)

	CS.Dashboard.PaintBars(CS.UI.Charts.Live)
end

function CS.GameInfo.Build()
	local page=CS.UI.Pages["Game Info"]; CS.Util.Clear(page,true); local left=CS.Util.Scroll(page); left.Size=UDim2.new(0.5,-6,1,0); local right=CS.Util.Scroll(page); right.Size=UDim2.new(0.5,-6,1,0); right.Position=UDim2.new(0.5,6,0,0)
	local gameCard=CS.UI.OverlayCard(left,"Game","◇",260); CS.UI.Labels.GameName=CS.UI.OverlayValue(gameCard,58,"▣","Name","Loading...","Marketplace game name."); CS.UI.Labels.GamePlaceId=CS.UI.OverlayValue(gameCard,112,"◎","Place ID",tostring(game.PlaceId),"Current place id."); CS.UI.Labels.GameJobId=CS.UI.OverlayValue(gameCard,166,"▦","Job ID",game.JobId:sub(1,12).."...","Current server id."); CS.UI.Labels.GameCreator=CS.UI.OverlayValue(gameCard,220,"✎","Creator","Loading...","Creator information.")
	local serverCard=CS.UI.OverlayCard(left,"Server State","📡",230); CS.UI.Labels.GameServerState=CS.UI.OverlayValue(serverCard,58,"👥","Players","--","Current server population."); CS.UI.Labels.GameFriendState=CS.UI.OverlayValue(serverCard,112,"♡","Friends","--","Friends in this game."); CS.UI.Labels.GameSupport=CS.UI.OverlayValue(serverCard,166,"⚙","Support","--","Available client tools.")
	local friendCard=CS.UI.OverlayCard(right,"Friends In This Game","♡",300); CS.UI.Labels.GameFriends=CS.UI.OverlayText(friendCard,58,220,"Checking friend game data...")
	local feedCard=CS.UI.OverlayCard(right,"Recent Player Feed","☰",300); CS.UI.Labels.Feed=CS.UI.OverlayText(feedCard,58,220,"Waiting for player events...")
	if CS.GameInfo.Load then CS.GameInfo.Load() end
end

function CS.GameInfo.Load()
	local info = {
		Name = "Unavailable",
		Creator = "Unavailable",
		Created = "Unavailable",
		Updated = "Unavailable",
		Visits = "Unavailable",
		Favorites = "Unavailable"
	}

	pcall(function()
		local data = CS.Services.MarketplaceService:GetProductInfo(game.PlaceId)
		info.Name = tostring(data.Name or "Unavailable")
		info.Creator = data.Creator and tostring(data.Creator.Name) or "Unavailable"
		info.Created = tostring(data.Created or "Unavailable")
		info.Updated = tostring(data.Updated or "Unavailable")
		info.Visits = CS.Util.ShortNumber(data.Visits)
		info.Favorites = CS.Util.ShortNumber(data.FavoritedCount)
	end)

	CS.Util.Set(CS.UI.Labels.GameOverview,
		"Name: " .. info.Name ..
		"\nCreator: " .. info.Creator ..
		"\nPlaceId: " .. tostring(game.PlaceId) ..
		"\nGameId: " .. tostring(game.GameId)
	)

	CS.Util.Set(CS.UI.Labels.GameStats,
		"Visits: " .. info.Visits ..
		"\nFavorites: " .. info.Favorites ..
		"\nCreated: " .. info.Created ..
		"\nUpdated: " .. info.Updated
	)

	CS.Util.Set(CS.UI.Labels.GameIds,
		"PlaceId: " .. tostring(game.PlaceId) ..
		"\nGameId: " .. tostring(game.GameId) ..
		"\nJobId: " .. (game.JobId ~= "" and game.JobId or "Unavailable")
	)

	CS.Util.Set(CS.UI.Labels.GameSupport,
		"HTTP Request: " .. tostring(CS.Request ~= nil) ..
		"\nTeleportService: " .. tostring(CS.Services.TeleportService ~= nil) ..
		"\nMarketplace Info: Loaded" ..
		"\nServer Browser: " .. tostring(CS.Request ~= nil)
	)

	CS.Friends.UpdateGameFriends()
end


function CS.Friends.GetOnlineFriends()
	local friends = {}

	pcall(function()
		friends = CS.LocalPlayer:GetFriendsOnline(200) or {}
	end)

	CS.Runtime.FriendsOnlineCache = friends
	return friends
end

function CS.Friends.GetOnlineFriendByUserId(userId)
	for _, friend in ipairs(CS.Runtime.FriendsOnlineCache or {}) do
		if tonumber(friend.VisitorId) == tonumber(userId) then
			return friend
		end
	end

	return nil
end

function CS.Friends.ConnectTeleportFailFallback()
	if CS.Runtime.TeleportFailConnected then
		return
	end

	CS.Runtime.TeleportFailConnected = true

	pcall(function()
		CS.Services.TeleportService.TeleportInitFailed:Connect(function(player, teleportResult, errorMessage, placeId)
			if player ~= CS.LocalPlayer then
				return
			end

			local msg = tostring(errorMessage or teleportResult or "Unknown teleport failure")

			CS.Notify.Push(
				"Teleport Failed",
				msg .. "\nTrying fallback if possible.",
				CS.Theme.Warning
			)

			local fallbackPlace = tonumber(CS.Runtime.LastFriendJoinPlaceId)

			if fallbackPlace then
				task.delay(1.2, function()
					pcall(function()
						CS.Services.TeleportService:Teleport(fallbackPlace, CS.LocalPlayer)
					end)
				end)
			end
		end)
	end)
end

function CS.Friends.TryGetLiveFriendInstance(userId)
	local result = nil

	if not userId then
		return nil
	end

	pcall(function()
		local currentInstance, placeId, jobId = CS.Services.TeleportService:GetPlayerPlaceInstanceAsync(tonumber(userId))

		if placeId and jobId then
			result = {
				PlaceId = tonumber(placeId),
				JobId = tostring(jobId),
				CurrentInstance = currentInstance
			}
		end
	end)

	return result
end

function CS.Friends.CopyFriendProfile(userId, friendName)
	if not userId then
		CS.Notify.Push("Friends", "No UserId available for profile fallback.", CS.Theme.Warning)
		return
	end

	local url = "https://[Log in to view URL]" .. tostring(userId) .. "/profile"

	if setclipboard then
		setclipboard(url)
		CS.Notify.Push("Friends", "Copied " .. tostring(friendName or "friend") .. "'s Roblox profile link. Use the profile Join button if Roblox allows it.", CS.Theme.Info)
	else
		CS.Notify.Push("Friends", "Profile: " .. url, CS.Theme.Info)
	end
end

function CS.Friends.TryJoinFriend(friendData)
	if not friendData then
		CS.Notify.Push("Friends", "No friend selected.", CS.Theme.Warning)
		return
	end

	local userId = tonumber(friendData.VisitorId or friendData.UserId or friendData.userId)
	local friendName = tostring(friendData.DisplayName or friendData.UserName or friendData.Username or "friend")

	local placeId = tonumber(friendData.PlaceId or friendData.PlaceID or friendData.placeId or friendData.placeID)
	local jobId = friendData.GameId or friendData.GameID or friendData.JobId or friendData.JobID or friendData.gameId or friendData.jobId

	if typeof(jobId) ~= "string" and jobId ~= nil then
		jobId = tostring(jobId)
	end

	CS.Notify.PlayJoinFriend()

	-- Roblox Error 773 is a platform restriction. Client Lua cannot bypass it.
	-- This function now avoids repeated restricted teleports and gives the safest join path.

	if not placeId then
		CS.Friends.CopyFriendProfile(userId, friendName)
		CS.Notify.Push("Friend Join", "Roblox did not expose a joinable PlaceId. Profile fallback copied.", CS.Theme.Warning)
		return
	end

	-- If friend is in this same place and Roblox gave a JobId, try exact server once.
	-- This is the only automatic join path Roblox may allow.
	if placeId == game.PlaceId and jobId and jobId ~= "" then
		CS.Notify.Push("Friend Join", "Trying same-game server join for " .. friendName .. "...", CS.Theme.Info)

		local ok, err = pcall(function()
			CS.Services.TeleportService:TeleportToPlaceInstance(placeId, jobId, CS.LocalPlayer)
		end)

		if ok then
			return
		end

		warn("CS same-game friend join failed:", err)
	end

	-- If the friend is in a different place, direct teleport often causes 773 when the destination is restricted.
	-- Copy profile instead so the user can use Roblox's official Join button if permissions allow.
	if placeId ~= game.PlaceId then
		CS.Friends.CopyFriendProfile(userId, friendName)
		CS.Notify.Push(
			"Friend Join Restricted",
			"Roblox is blocking direct teleport to that place/server. I copied the profile link so you can try the official Join button.",
			CS.Theme.Warning
		)
		return
	end

	CS.Notify.Push(
		"Friend Join Failed",
		"Roblox did not provide a usable active server id, or the server is restricted/private/full.",
		CS.Theme.Warning
	)
end


function CS.Friends.SetSelectedFriend(friendData, profile)
	CS.Runtime.SelectedFriend = friendData

	local name = tostring(friendData.UserName or friendData.Username or friendData.DisplayName or "Unknown")
	local display = tostring(friendData.DisplayName or friendData.UserName or "Unknown")
	local userId = tostring(friendData.VisitorId or friendData.UserId or profile.UserId or "Unknown")
	local placeId = tostring(friendData.PlaceId or friendData.PlaceID or friendData.placeId or friendData.placeID or "Unavailable")
	local gameId = tostring(friendData.GameId or friendData.GameID or friendData.JobId or friendData.JobID or friendData.gameId or friendData.jobId or "Unavailable")
	local location = tostring(friendData.LastLocation or friendData.LocationType or "Unavailable")

	if CS.UI.Objects.FriendAvatar then
		pcall(function()
			CS.UI.Objects.FriendAvatar.Image = CS.Services.Players:GetUserThumbnailAsync(
				tonumber(userId),
				Enum.ThumbnailType.AvatarThumbnail,
				Enum.ThumbnailSize.Size420x420
			)
		end)
	end

	if CS.UI.Labels.FriendDetails then
		CS.UI.Labels.FriendDetails.Text =
			"Display Name: " .. display ..
			"\nUsername: @" .. name ..
			"\nUserId: " .. userId ..
			"\nOnline Location: " .. location ..
			"\nPlaceId: " .. placeId ..
			"\nServer/JobId: " .. gameId ..
			"\nJoin Quality: " .. ((placeId ~= "Unavailable" and gameId ~= "Unavailable") and "Same-game exact server only if Roblox allows it" or (placeId ~= "Unavailable" and "Limited: place only" or "Unavailable")) ..
			"\n\nBio: unavailable from normal in-game Lua." ..
			"\nMessages: unavailable from normal in-game Lua."
	end
end

function CS.Friends.CreateFriendRow(parent, friendData)
	local userId = tonumber(friendData.VisitorId or friendData.UserId or 0)
	local username = tostring(friendData.UserName or friendData.Username or "Unknown")
	local display = tostring(friendData.DisplayName or username)
	local location = tostring(friendData.LastLocation or "Online")

	local row = CS.Util.Create("TextButton", {
		Parent = parent,
		Size = UDim2.new(1, -8, 0, 72),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.14,
		BorderSizePixel = 0,
		Text = ""
	})

	CS.Util.Corner(row, 12)
	CS.Util.Stroke(row, CS.Theme.Stroke, 0.55, 1)

	local icon = CS.Util.Create("ImageLabel", {
		Parent = row,
		Size = UDim2.new(0, 48, 0, 48),
		Position = UDim2.new(0, 10, 0, 12),
		BackgroundTransparency = 1
	})

	CS.Util.Corner(icon, 999)

	if userId > 0 then
		pcall(function()
			icon.Image = CS.Services.Players:GetUserThumbnailAsync(
				userId,
				Enum.ThumbnailType.HeadShot,
				Enum.ThumbnailSize.Size100x100
			)
		end)
	end

	local text = CS.Util.Create("TextLabel", {
		Parent = row,
		Size = UDim2.new(1, -190, 1, 0),
		Position = UDim2.new(0, 68, 0, 0),
		BackgroundTransparency = 1,
		Text = display .. "\n@" .. username .. "\n" .. location,
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 12,
		TextWrapped = true,
		TextXAlignment = Enum.TextXAlignment.Left,
		TextYAlignment = Enum.TextYAlignment.Center
	})

	local join = CS.Util.Create("TextButton", {
		Parent = row,
		Size = UDim2.new(0, 82, 0, 34),
		Position = UDim2.new(1, -94, 0.5, -17),
		BackgroundColor3 = CS.Theme.Success,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = "Join",
		TextColor3 = Color3.fromRGB(0, 0, 0),
		Font = Enum.Font.GothamBold,
		TextSize = 12
	})

	CS.Util.Corner(join, 9)

	row.MouseButton1Click:Connect(function()
		for _, obj in ipairs(parent:GetChildren()) do
			if obj:IsA("TextButton") then
				obj.BackgroundColor3 = CS.Theme.Card2
				obj.BackgroundTransparency = 0.14
			end
		end

		row.BackgroundColor3 = CS.Theme.Accent
		row.BackgroundTransparency = 0.02
		CS.Friends.SetSelectedFriend(friendData, {UserId = userId})
	end)

	join.MouseButton1Click:Connect(function()
		CS.Friends.TryJoinFriend(friendData)
	end)
end

function CS.Friends.RefreshFriendList()
	local list = CS.UI.Objects.FriendListScroll
	if not list then return end

	CS.Util.Clear(list, true)

	local friends = CS.Friends.GetOnlineFriends()

	if #friends == 0 then
		CS.Util.InfoCard(list, "Friends List", "No online friends were returned by Roblox.", 90)
		return
	end

	for _, friendData in ipairs(friends) do
		CS.Friends.CreateFriendRow(list, friendData)
	end

	CS.Friends.UpdateGameFriends()
end

function CS.Friends.UpdateGameFriends()
	local sameGame = {}
	local friends = CS.Runtime.FriendsOnlineCache or CS.Friends.GetOnlineFriends()

	for _, friendData in ipairs(friends) do
		local placeId = tonumber(friendData.PlaceId or friendData.PlaceID or 0)

		if placeId == game.PlaceId then
			table.insert(sameGame, friendData)
		end
	end

	if CS.UI.Labels.GameFriends then
		if #sameGame == 0 then
			CS.UI.Labels.GameFriends.Text = "No online friends detected in this same game through Roblox online-friend data."
		else
			local text = "Friends in this game, possibly different server:\\n"

			for _, friendData in ipairs(sameGame) do
				text ..= "\\n" .. tostring(friendData.DisplayName or friendData.UserName or "Unknown") ..
					"  @" .. tostring(friendData.UserName or "Unknown") ..
					"\\nLocation: " .. tostring(friendData.LastLocation or "Unknown") ..
					"\\nJoin data: " .. ((friendData.GameId or friendData.JobId) and "available" or "limited") .. "\\n"
			end

			CS.UI.Labels.GameFriends.Text = text
		end
	end
end

function CS.Friends.Build()
	local page=CS.UI.Pages["Friends"]; CS.Util.Clear(page,true); local left=CS.Util.Scroll(page); left.Size=UDim2.new(0.48,-6,1,0); local right=CS.Util.Scroll(page); right.Size=UDim2.new(0.52,-6,1,0); right.Position=UDim2.new(0.48,6,0,0)
	local overview=CS.UI.OverlayCard(left,"Friends Overview","♡",180); CS.UI.Labels.FriendsOverview=CS.UI.OverlayValue(overview,58,"◎","Online","--","Roblox online-friend data."); CS.UI.Labels.FriendsInServer=CS.UI.OverlayValue(overview,112,"👥","In Server","--","Friends currently in this server.")
	local list=CS.UI.OverlayCard(left,"Friend List","☰",520); CS.UI.OverlayButton(list,"Refresh Friends List",58,function() CS.Friends.RefreshFriendList(); CS.Notify.Push("Friends","Friend list refreshed.",CS.Theme.Success) end); local holder=CS.Util.Create("Frame",{Parent=list,Size=UDim2.new(1,-28,1,-118),Position=UDim2.new(0,14,0,106),BackgroundColor3=CS.Theme.Card2,BackgroundTransparency=0.22,BorderSizePixel=0}); CS.Util.Corner(holder,12); CS.Util.Stroke(holder,CS.Theme.Stroke,0.55,1); CS.UI.Objects.FriendListScroll=CS.Util.Scroll(holder)
	local avatarCard=CS.UI.OverlayCard(right,"Friend Preview","👤",310); CS.UI.Objects.FriendAvatar=CS.Util.Create("ImageLabel",{Parent=avatarCard,Size=UDim2.new(1,-28,1,-70),Position=UDim2.new(0,14,0,56),BackgroundColor3=CS.Theme.Card2,BackgroundTransparency=0.22,BorderSizePixel=0,ScaleType=Enum.ScaleType.Fit}); CS.Util.Corner(CS.UI.Objects.FriendAvatar,12); CS.Util.Stroke(CS.UI.Objects.FriendAvatar,CS.Theme.Stroke,0.55,1)
	local details=CS.UI.OverlayCard(right,"Friend Details","◎",290); CS.UI.Labels.FriendDetails=CS.UI.OverlayText(details,58,210,"Click a friend from the list.")
	local actions=CS.UI.OverlayCard(right,"Friend Actions","⚙",160); CS.UI.OverlayButton(actions,"Join Selected Friend",58,function() CS.Friends.TryJoinFriend(CS.Runtime.SelectedFriend) end); CS.UI.OverlayButton(actions,"Copy Selected Profile",106,function() local f=CS.Runtime.SelectedFriend; if f then CS.Friends.CopyFriendProfile(f.VisitorId or f.UserId, f.DisplayName or f.UserName) end end)
	pcall(function() CS.Friends.RefreshFriendList() end)
end

function CS.Friends.CountInServer()
	local count = 0
	local names = {}

	for _, player in ipairs(CS.Services.Players:GetPlayers()) do
		if player ~= CS.LocalPlayer then
			local isFriend = false
			pcall(function()
				isFriend = CS.LocalPlayer:IsFriendsWith(player.UserId)
			end)

			if isFriend then
				count += 1
				table.insert(names, player.DisplayName .. " (@" .. player.Name .. ")")
			end
		end
	end

	return count, names
end

function CS.Friends.CountOnline()
	local count = 0

	pcall(function()
		for _, _ in ipairs(CS.LocalPlayer:GetFriendsOnline()) do
			count += 1
		end
	end)

	return count
end

function CS.Friends.PushFeed(text)
	table.insert(CS.Runtime.Feed, 1, os.date("%I:%M:%S %p") .. "  " .. text)

	while #CS.Runtime.Feed > 12 do
		table.remove(CS.Runtime.Feed)
	end
end

function CS.Friends.Update()
	local online = CS.Friends.CountOnline()
	local inServer, names = CS.Friends.CountInServer()
	local onlineData = CS.Friends.GetOnlineFriends()

	CS.Util.Set(CS.UI.Labels.FriendsOverview,
		"Friends Online: " .. tostring(#onlineData > 0 and #onlineData or online) ..
		"\nFriends In Server: " .. tostring(inServer) ..
		"\nPlayer Notices: " .. tostring(CS.Flags.ShowNonFriendNotices)
	)

	if #names > 0 then
		CS.Util.Set(CS.UI.Labels.FriendsInServer, table.concat(names, "\n"))
	else
		CS.Util.Set(CS.UI.Labels.FriendsInServer, "No friends detected in this server.")
	end

	if CS.UI.Labels.Feed then
		if #CS.Runtime.Feed > 0 then
			CS.Util.Set(CS.UI.Labels.Feed, table.concat(CS.Runtime.Feed, "\n"))
		else
			CS.Util.Set(CS.UI.Labels.Feed, "No recent player events.")
		end
	end
end

function CS.Diagnostics.Build()
	local page=CS.UI.Pages["Diagnostics"]; CS.Util.Clear(page,true); local left=CS.Util.Scroll(page); left.Size=UDim2.new(0.5,-6,1,0); local right=CS.Util.Scroll(page); right.Size=UDim2.new(0.5,-6,1,0); right.Position=UDim2.new(0.5,6,0,0)
	local client=CS.UI.OverlayCard(left,"Client Metrics","⚡",250); CS.UI.Labels.DiagnosticsClient=CS.UI.OverlayText(client,58,170,"Diagnostics loading...")
	local graph=CS.UI.OverlayCard(left,"Performance Graph","⌁",220); CS.UI.OverlayGraph(graph,58,"FPS / Ping Visual")
	local tools=CS.UI.OverlayCard(right,"Diagnostic Tools","⚙",260); CS.UI.OverlayButton(tools,"Run Diagnostics",58,function() CS.Diagnostics.Run(); CS.Notify.Push("Diagnostics","Diagnostics refreshed.",CS.Theme.Info) end); CS.UI.OverlayButton(tools,"Toggle Auto Refresh",106,function() CS.Flags.AutoRefreshDiagnostics=not CS.Flags.AutoRefreshDiagnostics; CS.Notify.Push("Diagnostics","Auto refresh: "..tostring(CS.Flags.AutoRefreshDiagnostics),CS.Theme.Info) end); CS.UI.OverlayButton(tools,"Repair UI Layout",154,function() CS.Settings.ApplyVisuals(); CS.Notify.Push("Diagnostics","UI layout repaired.",CS.Theme.Success) end)
	local notes=CS.UI.OverlayCard(right,"Status Notes","☰",260); CS.UI.Labels.DiagnosticsNotes=CS.UI.OverlayText(notes,58,180,"No warnings yet.")
	CS.Diagnostics.Run()
end

function CS.Diagnostics.Run()
	local services = {
		Players = CS.Services.Players ~= nil,
		RunService = CS.Services.RunService ~= nil,
		TweenService = CS.Services.TweenService ~= nil,
		UserInputService = CS.Services.UserInputService ~= nil,
		Stats = CS.Services.Stats ~= nil,
		MarketplaceService = CS.Services.MarketplaceService ~= nil,
		TeleportService = CS.Services.TeleportService ~= nil,
		HttpService = CS.Services.HttpService ~= nil
	}

	local okCount = 0
	local total = 0
	local serviceText = ""

	for name, exists in pairs(services) do
		total += 1
		if exists then okCount += 1 end
		serviceText ..= name .. ": " .. (exists and "OK" or "Missing") .. "\n"
	end

	CS.Util.Set(CS.UI.Labels.DiagnosticsMain,
		"Services: " .. tostring(okCount) .. "/" .. tostring(total) .. " OK" ..
		"\nGame Loaded: " .. tostring(game:IsLoaded()) ..
		"\nPlayers: " .. tostring(#CS.Services.Players:GetPlayers()) .. "/" .. tostring(CS.Services.Players.MaxPlayers) ..
		"\n\n" .. serviceText
	)

	local char = CS.LocalPlayer.Character
	local humanoid = char and char:FindFirstChildOfClass("Humanoid")
	local root = char and char:FindFirstChild("HumanoidRootPart")
	local head = char and char:FindFirstChild("Head")

	CS.Util.Set(CS.UI.Labels.DiagnosticsCharacter,
		"Character: " .. tostring(char ~= nil) ..
		"\nHumanoid: " .. tostring(humanoid ~= nil) ..
		"\nHumanoidRootPart: " .. tostring(root ~= nil) ..
		"\nHead: " .. tostring(head ~= nil) ..
		"\nPlayerGui: " .. tostring(CS.PlayerGui ~= nil)
	)

	CS.Util.Set(CS.UI.Labels.DiagnosticsEnvironment,
		"HTTP Request: " .. tostring(CS.Request ~= nil) ..
		"\nClipboard: " .. tostring(setclipboard ~= nil) ..
		"\nDrawing API: " .. tostring(Drawing ~= nil) ..
		"\nCoreGui Access: " .. tostring(pcall(function() return CS.Services.CoreGui.Name end)) ..
		"\nExecutor-specific APIs are optional."
	)

	local warnings = {}

	if not CS.Request then
		table.insert(warnings, "Server browser cannot fetch public servers without request/http_request.")
	end

	if not setclipboard then
		table.insert(warnings, "Copy buttons will not work without setclipboard.")
	end

	if not root then
		table.insert(warnings, "Character root is not loaded yet.")
	end

	if #warnings == 0 then
		CS.Util.Set(CS.UI.Labels.DiagnosticsWarnings, "No major warnings.", CS.Theme.Success)
	else
		CS.Util.Set(CS.UI.Labels.DiagnosticsWarnings, table.concat(warnings, "\n"), CS.Theme.Warning)
	end
end


function CS.Settings.HexToColor(hex)
	if type(hex) ~= "string" then
		return nil
	end

	hex = hex:gsub("#", ""):gsub("%s+", "")

	if #hex ~= 6 then
		return nil
	end

	local r = tonumber(hex:sub(1, 2), 16)
	local g = tonumber(hex:sub(3, 4), 16)
	local b = tonumber(hex:sub(5, 6), 16)

	if not r or not g or not b then
		return nil
	end

	return Color3.fromRGB(r, g, b)
end

function CS.Settings.ColorToHex(color)
	local r = math.floor(color.R * 255)
	local g = math.floor(color.G * 255)
	local b = math.floor(color.B * 255)

	return string.format("#%02X%02X%02X", r, g, b)
end

function CS.Settings.CanSave()
	return writefile ~= nil and readfile ~= nil and isfile ~= nil
end

function CS.Settings.CollectConfig()
	return {
		ConfigVersion = CS.Config.Version,

		Animations = CS.Flags.Animations,
		Notifications = CS.Flags.Notifications,
		ShowNonFriendNotices = CS.Flags.ShowNonFriendNotices,
		FriendSounds = CS.Flags.FriendSounds,

		Transparency = CS.Flags.Transparency,
		PanelTransparency = CS.Flags.PanelTransparency,
		CardTransparency = CS.Flags.CardTransparency,
		ScaleMode = CS.Flags.ScaleMode,

		Accent = CS.Settings.ColorToHex(CS.Theme.Accent),
		Background = CS.Settings.ColorToHex(CS.Theme.Background),
		Panel = CS.Settings.ColorToHex(CS.Theme.Panel),
		Card = CS.Settings.ColorToHex(CS.Theme.Card),
		Outline = CS.Settings.ColorToHex(CS.Theme.Stroke),
		Notification = CS.Settings.ColorToHex(CS.Theme.Info),
		NotificationBackground = CS.Settings.ColorToHex(CS.Theme.NotificationBackground),
		NotificationOutline = CS.Settings.ColorToHex(CS.Theme.NotificationOutline),

		FriendJoinSoundId = CS.Flags.FriendJoinSoundId,
		FriendLeaveSoundId = CS.Flags.FriendLeaveSoundId,
		JoinFriendSoundId = CS.Flags.JoinFriendSoundId,

		ColorCycleA = CS.Flags.ColorCycleA,
		ColorCycleB = CS.Flags.ColorCycleB,
		ColorCycleSpeed = CS.Flags.ColorCycleSpeed,
		ColorCycleSpeedLevel = CS.Flags.ColorCycleSpeedLevel
	}
end

function CS.Settings.Save(silent)
	if not writefile then
		if not silent then
			CS.Notify.Push("Settings", "Save unavailable in this executor.", CS.Theme.Warning)
		end
		return false
	end

	local ok, encoded = pcall(function()
		return CS.Services.HttpService:JSONEncode(CS.Settings.CollectConfig())
	end)

	if not ok or not encoded then
		if not silent then
			CS.Notify.Push("Settings", "Could not encode settings.", CS.Theme.Warning)
		end
		return false
	end

	local writeOk = pcall(function()
		writefile(CS.Config.FileName, encoded)
	end)

	if not silent then
		CS.Notify.Push("Settings", writeOk and "Settings saved." or "Settings failed to save.", writeOk and CS.Theme.Success or CS.Theme.Warning)
	end

	return writeOk
end

function CS.Settings.ApplyConfig(data)
	if type(data) ~= "table" then
		return
	end

	if type(data.Animations) == "boolean" then
		CS.Flags.Animations = data.Animations
	end

	if type(data.Notifications) == "boolean" then
		CS.Flags.Notifications = data.Notifications
	end

	if type(data.ShowNonFriendNotices) == "boolean" then
		CS.Flags.ShowNonFriendNotices = data.ShowNonFriendNotices
	end

	if type(data.FriendSounds) == "boolean" then
		CS.Flags.FriendSounds = data.FriendSounds
	end

	if tonumber(data.Transparency) then
		CS.Flags.Transparency = math.clamp(tonumber(data.Transparency), 0, 1)
	end

	if tonumber(data.PanelTransparency) then
		CS.Flags.PanelTransparency = math.clamp(tonumber(data.PanelTransparency), 0, 1)
	end

	if tonumber(data.CardTransparency) then
		CS.Flags.CardTransparency = math.clamp(tonumber(data.CardTransparency), 0, 1)
	end

	if type(data.ScaleMode) == "string" then
		CS.Flags.ScaleMode = data.ScaleMode
	end

	local colorMap = {
		Accent = "Accent",
		Background = "Background",
		Panel = "Panel",
		Card = "Card",
		Outline = "Stroke",
		Notification = "Info",
		NotificationBackground = "NotificationBackground",
		NotificationOutline = "NotificationOutline"
	}

	for configKey, themeKey in pairs(colorMap) do
		if type(data[configKey]) == "string" then
			local color = CS.Settings.HexToColor(data[configKey])
			if color then
				CS.Theme[themeKey] = color
			end
		end
	end

	if type(data.FriendJoinSoundId) == "string" then
		CS.Flags.FriendJoinSoundId = data.FriendJoinSoundId
	end

	if type(data.FriendLeaveSoundId) == "string" then
		CS.Flags.FriendLeaveSoundId = data.FriendLeaveSoundId
	end

	if type(data.JoinFriendSoundId) == "string" then
		CS.Flags.JoinFriendSoundId = data.JoinFriendSoundId
	end

	if type(data.ColorCycleA) == "string" then
		CS.Flags.ColorCycleA = data.ColorCycleA
	end

	if type(data.ColorCycleB) == "string" then
		CS.Flags.ColorCycleB = data.ColorCycleB
	end

	if tonumber(data.ColorCycleSpeed) then
		CS.Flags.ColorCycleSpeed = tonumber(data.ColorCycleSpeed)
	end

	if tonumber(data.ColorCycleSpeedLevel) then
		CS.Flags.ColorCycleSpeedLevel = math.clamp(tonumber(data.ColorCycleSpeedLevel), 1, 10)
	end

	CS.Flags.ColorCycle = false
	CS.Flags.ExampleNotification = false

	CS.Settings.ApplyVisuals()
	CS.Settings.RefreshToggleVisuals()
end

function CS.Settings.Load()
	if not readfile or not isfile then
		return false
	end

	if not isfile(CS.Config.FileName) then
		CS.Settings.Save(true)
		return false
	end

	local readOk, raw = pcall(function()
		return readfile(CS.Config.FileName)
	end)

	if not readOk or not raw or raw == "" then
		return false
	end

	local decodeOk, decoded = pcall(function()
		return CS.Services.HttpService:JSONDecode(raw)
	end)

	if decodeOk and decoded then
		CS.Settings.ApplyConfig(decoded)
		CS.Config.Loaded = true
		return true
	end

	return false
end


function CS.Settings.ApplyVisuals()
	CS.Theme.Accent2 = CS.Theme.Accent
	CS.Theme.Accent3 = CS.Theme.Accent

	if CS.UI.Objects.Main then
		CS.UI.Objects.Main.BackgroundColor3 = CS.Theme.Background
		CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency
	end

	if CS.UI.Objects.Sidebar then
		CS.UI.Objects.Sidebar.BackgroundColor3 = CS.Theme.Panel
		CS.UI.Objects.Sidebar.BackgroundTransparency = CS.Flags.PanelTransparency
	end

	if CS.UI.Objects.Content then
		CS.UI.Objects.Content.BackgroundColor3 = CS.Theme.Panel
		CS.UI.Objects.Content.BackgroundTransparency = CS.Flags.PanelTransparency
	end

	if CS.UI.Objects.AccentRail then
		CS.UI.Objects.AccentRail.BackgroundColor3 = CS.Theme.Accent
	end

	if CS.UI.Objects.GUI then
		for _, obj in ipairs(CS.UI.Objects.GUI:GetDescendants()) do
			if obj:IsA("UIStroke") then
				obj.Color = CS.Theme.Stroke
			end
		end
	end

	for _, tab in pairs(CS.UI.Tabs) do
		if tab.BackgroundColor3 ~= CS.Theme.Accent then
			tab.BackgroundColor3 = CS.Theme.Card
		end
	end
end

function CS.Settings.MakeTextBox(parent, placeholder, defaultText)
	local box = CS.Util.Create("TextBox", {
		Parent = parent,
		Size = UDim2.new(1, -8, 0, 40),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.12,
		BorderSizePixel = 0,
		Text = defaultText or "",
		PlaceholderText = placeholder or "#FFFFFF",
		TextColor3 = CS.Theme.Text,
		PlaceholderColor3 = CS.Theme.Muted,
		Font = Enum.Font.GothamBold,
		TextSize = 14,
		ClearTextOnFocus = false
	})

	CS.Util.Corner(box, 10)
	CS.Util.Stroke(box, CS.Theme.Stroke, 0.5, 1)

	return box
end

function CS.Settings.MakeColorEditor(parent, labelText, key, defaultColor, applyCallback)
	local card = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(1, -8, 0, 360),
		BackgroundColor3 = CS.Theme.Card,
		BackgroundTransparency = CS.Flags.CardTransparency,
		BorderSizePixel = 0
	})

	CS.Util.Corner(card, 14)
	CS.Util.Stroke(card, CS.Theme.Stroke, 0.45, 1)

	local swatch = CS.Util.Create("Frame", {
		Parent = card,
		Size = UDim2.new(0, 42, 0, 42),
		Position = UDim2.new(0, 12, 0, 12),
		BackgroundColor3 = defaultColor,
		BorderSizePixel = 0
	})

	CS.Util.Corner(swatch, 999)
	CS.Util.Stroke(swatch, CS.Theme.Text, 0.65, 1)

	local title = CS.Util.Create("TextLabel", {
		Parent = card,
		Size = UDim2.new(0.45, -70, 0, 22),
		Position = UDim2.new(0, 64, 0, 10),
		BackgroundTransparency = 1,
		Text = labelText,
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 14,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	local preview = CS.Util.Create("TextLabel", {
		Parent = card,
		Size = UDim2.new(0.45, -70, 0, 22),
		Position = UDim2.new(0, 64, 0, 32),
		BackgroundTransparency = 1,
		Text = labelText .. ": " .. CS.Settings.ColorToHex(defaultColor),
		TextColor3 = CS.Theme.SubText,
		Font = Enum.Font.Gotham,
		TextSize = 12,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	local examplePanel = CS.Util.Create("Frame", {
		Parent = card,
		Size = UDim2.new(0.48, -12, 0, 92),
		Position = UDim2.new(0.52, 0, 0, 14),
		BackgroundColor3 = Color3.fromRGB(14, 14, 20),
		BackgroundTransparency = 0.12,
		BorderSizePixel = 0
	})

	CS.Util.Corner(examplePanel, 12)
	CS.Util.Stroke(examplePanel, CS.Theme.Stroke, 0.55, 1)

	local exampleTitle = CS.Util.Create("TextLabel", {
		Parent = examplePanel,
		Size = UDim2.new(1, -20, 0, 22),
		Position = UDim2.new(0, 10, 0, 8),
		BackgroundTransparency = 1,
		Text = "Preview: " .. labelText,
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 13,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	local exampleBody = CS.Util.Create("TextLabel", {
		Parent = examplePanel,
		Size = UDim2.new(1, -20, 0, 44),
		Position = UDim2.new(0, 10, 0, 34),
		BackgroundTransparency = 1,
		Text = "This shows what will change.",
		TextColor3 = CS.Theme.SubText,
		Font = Enum.Font.Gotham,
		TextSize = 12,
		TextWrapped = true,
		TextXAlignment = Enum.TextXAlignment.Left,
		TextYAlignment = Enum.TextYAlignment.Top
	})

	local exampleAccentBar = CS.Util.Create("Frame", {
		Parent = examplePanel,
		Size = UDim2.new(1, -20, 0, 4),
		Position = UDim2.new(0, 10, 1, -10),
		BackgroundColor3 = defaultColor,
		BorderSizePixel = 0
	})

	CS.Util.Corner(exampleAccentBar, 999)

	local picker = CS.Util.Create("Frame", {
		Parent = card,
		Size = UDim2.new(1, -24, 0, 176),
		Position = UDim2.new(0, 12, 0, 104),
		BackgroundColor3 = Color3.fromRGB(255, 0, 0),
		BorderSizePixel = 0,
		ClipsDescendants = true
	})

	CS.Util.Corner(picker, 10)
	CS.Util.Stroke(picker, CS.Theme.Text, 0.45, 1)

	local satGradient = Instance.new("UIGradient")
	satGradient.Color = ColorSequence.new(Color3.fromRGB(255, 255, 255), Color3.fromRGB(255, 255, 255))
	satGradient.Transparency = NumberSequence.new({
		NumberSequenceKeypoint.new(0, 1),
		NumberSequenceKeypoint.new(1, 0)
	})
	satGradient.Rotation = 0
	satGradient.Parent = picker

	local valueOverlay = CS.Util.Create("Frame", {
		Parent = picker,
		Size = UDim2.new(1, 0, 1, 0),
		BackgroundColor3 = Color3.fromRGB(0, 0, 0),
		BorderSizePixel = 0
	})

	local valueGradient = Instance.new("UIGradient")
	valueGradient.Transparency = NumberSequence.new({
		NumberSequenceKeypoint.new(0, 1),
		NumberSequenceKeypoint.new(1, 0)
	})
	valueGradient.Rotation = 90
	valueGradient.Parent = valueOverlay

	local pickerCursor = CS.Util.Create("Frame", {
		Parent = picker,
		Size = UDim2.new(0, 16, 0, 16),
		Position = UDim2.new(0, -8, 1, -8),
		BackgroundColor3 = Color3.fromRGB(0, 0, 0),
		BackgroundTransparency = 0.25,
		BorderSizePixel = 0,
		ZIndex = 5
	})

	CS.Util.Corner(pickerCursor, 999)
	CS.Util.Stroke(pickerCursor, CS.Theme.Text, 0.1, 2)

	local hueBar = CS.Util.Create("Frame", {
		Parent = card,
		Size = UDim2.new(1, -24, 0, 18),
		Position = UDim2.new(0, 12, 0, 294),
		BackgroundColor3 = Color3.fromRGB(255, 255, 255),
		BorderSizePixel = 0
	})

	CS.Util.Corner(hueBar, 999)
	CS.Util.Stroke(hueBar, CS.Theme.Stroke, 0.55, 1)

	local hueGradient = Instance.new("UIGradient")
	hueGradient.Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0.00, Color3.fromRGB(255, 0, 0)),
		ColorSequenceKeypoint.new(0.16, Color3.fromRGB(255, 255, 0)),
		ColorSequenceKeypoint.new(0.33, Color3.fromRGB(0, 255, 0)),
		ColorSequenceKeypoint.new(0.50, Color3.fromRGB(0, 255, 255)),
		ColorSequenceKeypoint.new(0.66, Color3.fromRGB(0, 0, 255)),
		ColorSequenceKeypoint.new(0.83, Color3.fromRGB(255, 0, 255)),
		ColorSequenceKeypoint.new(1.00, Color3.fromRGB(255, 0, 0))
	})
	hueGradient.Parent = hueBar

	local hueCursor = CS.Util.Create("Frame", {
		Parent = hueBar,
		Size = UDim2.new(0, 14, 0, 24),
		Position = UDim2.new(0, -7, 0.5, -12),
		BackgroundColor3 = Color3.fromRGB(25, 25, 25),
		BorderSizePixel = 0,
		ZIndex = 5
	})

	CS.Util.Corner(hueCursor, 999)
	CS.Util.Stroke(hueCursor, CS.Theme.Text, 0.25, 2)

	local bottom = CS.Util.Create("Frame", {
		Parent = card,
		Size = UDim2.new(1, -24, 0, 32),
		Position = UDim2.new(0, 12, 0, 322),
		BackgroundColor3 = Color3.fromRGB(12, 12, 18),
		BackgroundTransparency = 0.15,
		BorderSizePixel = 0
	})

	CS.Util.Corner(bottom, 10)
	CS.Util.Stroke(bottom, CS.Theme.Stroke, 0.6, 1)

	local miniSwatch = CS.Util.Create("Frame", {
		Parent = bottom,
		Size = UDim2.new(0, 22, 0, 22),
		Position = UDim2.new(0, 8, 0.5, -11),
		BackgroundColor3 = defaultColor,
		BorderSizePixel = 0
	})

	CS.Util.Corner(miniSwatch, 999)

	local box = CS.Util.Create("TextBox", {
		Parent = bottom,
		Size = UDim2.new(1, -150, 0, 28),
		Position = UDim2.new(0, 38, 0.5, -14),
		BackgroundTransparency = 1,
		Text = CS.Settings.ColorToHex(defaultColor),
		PlaceholderText = "#FFFFFF",
		TextColor3 = CS.Theme.Text,
		PlaceholderColor3 = CS.Theme.Muted,
		Font = Enum.Font.GothamBold,
		TextSize = 13,
		TextXAlignment = Enum.TextXAlignment.Left,
		ClearTextOnFocus = false
	})

	local apply = CS.Util.Create("TextButton", {
		Parent = bottom,
		Size = UDim2.new(0, 92, 0, 26),
		Position = UDim2.new(1, -100, 0.5, -13),
		BackgroundColor3 = defaultColor,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = "Apply",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 12
	})

	CS.Util.Corner(apply, 8)

	local hue = 0
	local sat = 1
	local val = 1
	local draggingPicker = false
	local draggingHue = false

	local function updateExample(color, hex)
		exampleAccentBar.BackgroundColor3 = color

		if key == "Notification" or labelText:lower():find("notification") then
			exampleTitle.Text = "Example Notification"
			exampleBody.Text = "This is the color used for notification accents."
			exampleAccentBar.BackgroundColor3 = color
		elseif key == "Accent" or labelText == "Accent" then
			exampleTitle.Text = "Example Selected Tab"
			exampleBody.Text = "Selected tabs, active buttons, highlights, and accent rail."
			examplePanel.BackgroundColor3 = color
			examplePanel.BackgroundTransparency = 0.18
		elseif key == "Accent2" or labelText:lower():find("secondary") then
			exampleTitle.Text = "Example Gradient Side"
			exampleBody.Text = "Secondary accent supports gradients and theme blends."
			exampleAccentBar.BackgroundColor3 = color
		elseif key == "Accent3" or labelText:lower():find("third") then
			exampleTitle.Text = "Example Extra Accent"
			exampleBody.Text = "Third accent supports extra glow and color blend details."
			exampleAccentBar.BackgroundColor3 = color
		elseif key == "Background" or labelText:lower():find("background") then
			exampleTitle.Text = "Example Menu Background"
			exampleBody.Text = "This changes the main menu/panel background tone."
			examplePanel.BackgroundColor3 = color
		elseif key == "Outline" or labelText:lower():find("outline") then
			exampleTitle.Text = "Example Outline"
			exampleBody.Text = "This changes borders and outline strokes."
			exampleAccentBar.BackgroundColor3 = color
			CS.Util.Stroke(examplePanel, color, 0.25, 1)
		else
			exampleTitle.Text = "Preview: " .. labelText
			exampleBody.Text = "This color will affect " .. labelText .. "."
		end

		preview.Text = labelText .. ": " .. hex
	end

	local function setColorFromHSV()
		local color = Color3.fromHSV(hue, sat, val)
		local hex = CS.Settings.ColorToHex(color)

		box.Text = hex
		swatch.BackgroundColor3 = color
		miniSwatch.BackgroundColor3 = color
		apply.BackgroundColor3 = color
		preview.TextColor3 = CS.Theme.SubText
		updateExample(color, hex)

		local hueColor = Color3.fromHSV(hue, 1, 1)
		picker.BackgroundColor3 = hueColor
		satGradient.Color = ColorSequence.new(Color3.fromRGB(255, 255, 255), Color3.fromRGB(255, 255, 255))
		satGradient.Transparency = NumberSequence.new({
			NumberSequenceKeypoint.new(0, 1),
			NumberSequenceKeypoint.new(1, 0)
		})
	end

	local function updatePickerFromInput(input)
		local absPos = picker.AbsolutePosition
		local absSize = picker.AbsoluteSize
		local x = math.clamp((input.Position.X - absPos.X) / absSize.X, 0, 1)
		local y = math.clamp((input.Position.Y - absPos.Y) / absSize.Y, 0, 1)

		sat = x
		val = 1 - y
		pickerCursor.Position = UDim2.new(x, -8, y, -8)
		pickerCursor.BackgroundColor3 = val > 0.5 and Color3.fromRGB(0, 0, 0) or Color3.fromRGB(255, 255, 255)
		setColorFromHSV()
	end

	local function updateHueFromInput(input)
		local absPos = hueBar.AbsolutePosition
		local absSize = hueBar.AbsoluteSize
		local x = math.clamp((input.Position.X - absPos.X) / absSize.X, 0, 1)

		hue = x
		hueCursor.Position = UDim2.new(x, -7, 0.5, -12)
		setColorFromHSV()
	end

	local function beginPickerDrag(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			draggingPicker = true
			updatePickerFromInput(input)
		end
	end

	picker.InputBegan:Connect(beginPickerDrag)
	valueOverlay.InputBegan:Connect(beginPickerDrag)

	hueBar.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			draggingHue = true
			updateHueFromInput(input)
		end
	end)

	CS.Services.UserInputService.InputChanged:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseMovement then
			if draggingPicker then
				updatePickerFromInput(input)
			elseif draggingHue then
				updateHueFromInput(input)
			end
		end
	end)

	CS.Services.UserInputService.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			draggingPicker = false
			draggingHue = false
		end
	end)

	box.FocusLost:Connect(function()
		local color = CS.Settings.HexToColor(box.Text)
		if color then
			local h, s, v = color:ToHSV()
			hue = h
			sat = s
			val = v
			pickerCursor.Position = UDim2.new(sat, -8, 1 - val, -8)
			pickerCursor.BackgroundColor3 = val > 0.5 and Color3.fromRGB(0, 0, 0) or Color3.fromRGB(255, 255, 255)
			hueCursor.Position = UDim2.new(hue, -7, 0.5, -12)
			swatch.BackgroundColor3 = color
			miniSwatch.BackgroundColor3 = color
			apply.BackgroundColor3 = color
			updateExample(color, box.Text)
			local hueColor = Color3.fromHSV(hue, 1, 1)
			picker.BackgroundColor3 = hueColor
			satGradient.Color = ColorSequence.new({
				ColorSequenceKeypoint.new(0, Color3.fromRGB(255,255,255)),
				ColorSequenceKeypoint.new(1, hueColor)
			})
		else
			preview.Text = labelText .. ": invalid hex"
			preview.TextColor3 = CS.Theme.Warning
		end
	end)

	apply.MouseButton1Click:Connect(function()
		local color = CS.Settings.HexToColor(box.Text)

		if not color then
			CS.Notify.Push("Theme", "Invalid hex for " .. labelText .. ".", CS.Theme.Warning)
			return
		end

		applyCallback(color, box.Text)
	end)

	local startH, startS, startV = defaultColor:ToHSV()
	hue = startH
	sat = startS
	val = startV
	pickerCursor.Position = UDim2.new(sat, -8, 1 - val, -8)
	hueCursor.Position = UDim2.new(hue, -7, 0.5, -12)
	setColorFromHSV()

	return {
		Card = card,
		Swatch = swatch,
		Preview = preview,
		Box = box,
		Apply = apply,
		Picker = picker,
		HueBar = hueBar,
		Example = examplePanel
	}
end


function CS.Settings.RefreshToggleVisuals()
	CS.Settings.SetToggleVisual(CS.UI.Buttons.ToggleAnimations, CS.Flags.Animations)
	CS.Settings.SetToggleVisual(CS.UI.Buttons.ToggleNotifications, CS.Flags.Notifications)
	CS.Settings.SetToggleVisual(CS.UI.Buttons.ToggleNonFriends, CS.Flags.ShowNonFriendNotices)
	CS.Settings.SetToggleVisual(CS.UI.Buttons.ToggleFriendSounds, CS.Flags.FriendSounds)
end

function CS.Settings.MakeTransparencySlider(parent)
	local card = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(1, -8, 0, 190),
		BackgroundColor3 = CS.Theme.Card,
		BackgroundTransparency = CS.Flags.CardTransparency,
		BorderSizePixel = 0
	})

	CS.Util.Corner(card, 14)
	CS.Util.Stroke(card, CS.Theme.Stroke, 0.45, 1)

	local title = CS.Util.Create("TextLabel", {
		Parent = card,
		Size = UDim2.new(1, -24, 0, 26),
		Position = UDim2.new(0, 12, 0, 10),
		BackgroundTransparency = 1,
		Text = "Glass Transparency",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 15,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	local subtitle = CS.Util.Create("TextLabel", {
		Parent = card,
		Size = UDim2.new(1, -24, 0, 24),
		Position = UDim2.new(0, 12, 0, 36),
		BackgroundTransparency = 1,
		Text = "One control for the full menu glass look.",
		TextColor3 = CS.Theme.SubText,
		Font = Enum.Font.Gotham,
		TextSize = 12,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	local preview = CS.Util.Create("Frame", {
		Parent = card,
		Size = UDim2.new(1, -24, 0, 52),
		Position = UDim2.new(0, 12, 0, 66),
		BackgroundColor3 = Color3.fromRGB(255, 255, 255),
		BackgroundTransparency = CS.Flags.Transparency,
		BorderSizePixel = 0
	})

	CS.Util.Corner(preview, 12)
	CS.Util.Stroke(preview, CS.Theme.Stroke, 0.45, 1)

	local previewGradient = Instance.new("UIGradient")
	previewGradient.Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0, Color3.fromRGB(0, 0, 0)),
		ColorSequenceKeypoint.new(1, Color3.fromRGB(255, 255, 255))
	})
	previewGradient.Rotation = 0
	previewGradient.Parent = preview

	local previewText = CS.Util.Create("TextLabel", {
		Parent = preview,
		Size = UDim2.new(1, -20, 1, 0),
		Position = UDim2.new(0, 10, 0, 0),
		BackgroundTransparency = 1,
		Text = "Transparency: " .. tostring(CS.Flags.Transparency),
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 14,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	local bar = CS.Util.Create("Frame", {
		Parent = card,
		Size = UDim2.new(1, -48, 0, 16),
		Position = UDim2.new(0, 24, 0, 136),
		BackgroundColor3 = Color3.fromRGB(255, 255, 255),
		BorderSizePixel = 0
	})

	CS.Util.Corner(bar, 999)
	CS.Util.Stroke(bar, CS.Theme.Stroke, 0.45, 1)

	local barGradient = Instance.new("UIGradient")
	barGradient.Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0, Color3.fromRGB(0, 0, 0)),
		ColorSequenceKeypoint.new(1, Color3.fromRGB(255, 255, 255))
	})
	barGradient.Rotation = 0
	barGradient.Parent = bar

	local knob = CS.Util.Create("Frame", {
		Parent = bar,
		Size = UDim2.new(0, 22, 0, 22),
		Position = UDim2.new(CS.Flags.Transparency, -11, 0.5, -11),
		BackgroundColor3 = CS.Theme.Accent,
		BorderSizePixel = 0,
		ZIndex = 4
	})

	CS.Util.Corner(knob, 999)
	CS.Util.Stroke(knob, CS.Theme.Text, 0.2, 2)

	local dragging = false

	local function applyValueFromX(xPosition)
		local absPos = bar.AbsolutePosition
		local absSize = bar.AbsoluteSize
		local value = math.clamp((xPosition - absPos.X) / absSize.X, 0, 1)
		value = math.floor(value * 100) / 10

		CS.Flags.Transparency = value
		CS.Flags.PanelTransparency = math.clamp(value - 0.12, 0, 1)
		CS.Flags.CardTransparency = math.clamp(value - 0.35, 0, 1)

		knob.Position = UDim2.new(value, -11, 0.5, -11)
		preview.BackgroundTransparency = value
		previewText.Text = "Transparency: " .. tostring(value)

		if CS.UI.Objects.Main then CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency end
		if CS.UI.Objects.Sidebar then CS.UI.Objects.Sidebar.BackgroundTransparency = CS.Flags.PanelTransparency end
		if CS.UI.Objects.Content then CS.UI.Objects.Content.BackgroundTransparency = CS.Flags.PanelTransparency end
	end

	bar.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			dragging = true
			applyValueFromX(input.Position.X)
		end
	end)

	CS.Services.UserInputService.InputChanged:Connect(function(input)
		if dragging and input.UserInputType == Enum.UserInputType.MouseMovement then
			applyValueFromX(input.Position.X)
		end
	end)

	CS.Services.UserInputService.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			if dragging then
				dragging = false
				CS.Settings.Save(true)
				CS.Notify.Push("Settings", "Transparency saved.", CS.Theme.Success)
			end
		end
	end)

	return card
end

function CS.Settings.ResetThemeDefaults()
	CS.Theme.Background = Color3.fromRGB(7, 8, 12)
	CS.Theme.Background2 = Color3.fromRGB(13, 15, 24)
	CS.Theme.Panel = Color3.fromRGB(18, 18, 26)
	CS.Theme.Panel2 = Color3.fromRGB(24, 24, 36)
	CS.Theme.Card = Color3.fromRGB(28, 28, 40)
	CS.Theme.Card2 = Color3.fromRGB(36, 36, 52)
	CS.Theme.Accent = Color3.fromRGB(78, 115, 255)
	CS.Theme.Accent2 = CS.Theme.Accent
	CS.Theme.Accent3 = CS.Theme.Accent
	CS.Theme.Info = Color3.fromRGB(80, 185, 255)
	CS.Theme.NotificationBackground = Color3.fromRGB(28, 28, 40)
	CS.Theme.NotificationOutline = Color3.fromRGB(80, 185, 255)
	CS.Theme.Stroke = Color3.fromRGB(115, 120, 160)
	CS.Theme.StrokeSoft = Color3.fromRGB(70, 75, 100)

	CS.Flags.Transparency = 0.54
	CS.Flags.PanelTransparency = 0.36
	CS.Flags.CardTransparency = 0.14

	CS.Settings.ApplyVisuals()
	CS.Settings.Save()
	CS.Notify.Push("Settings", "Theme and transparency reset.", CS.Theme.Success)
end

function CS.Settings.MakeConfirmReset(parent)
	local holder = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(1, -8, 0, 96),
		BackgroundColor3 = CS.Theme.Card,
		BackgroundTransparency = CS.Flags.CardTransparency,
		BorderSizePixel = 0
	})

	CS.Util.Corner(holder, 14)
	CS.Util.Stroke(holder, CS.Theme.Warning, 0.45, 1)

	local reset = CS.Util.Button(holder, "Reset Colors / Transparency", 38)
	reset.Position = UDim2.new(0, 12, 0, 10)
	reset.Size = UDim2.new(1, -24, 0, 38)

	local confirm = CS.Util.Button(holder, "Confirm Reset", 34)
	confirm.Position = UDim2.new(0, 12, 0, 54)
	confirm.Size = UDim2.new(1, -24, 0, 34)
	confirm.Visible = false
	confirm.BackgroundColor3 = CS.Theme.Warning
	confirm.TextColor3 = Color3.fromRGB(0, 0, 0)

	reset.MouseButton1Click:Connect(function()
		confirm.Visible = true
		reset.Text = "Click Confirm Reset below"
		CS.Notify.Push("Confirm Reset", "Press Confirm Reset to continue.", CS.Theme.Warning)

		task.delay(5, function()
			if confirm and confirm.Parent then
				confirm.Visible = false
				reset.Text = "Reset Colors / Transparency"
			end
		end)
	end)

	confirm.MouseButton1Click:Connect(function()
		confirm.Visible = false
		reset.Text = "Reset Colors / Transparency"
		CS.Settings.ResetThemeDefaults()
	end)
end


function CS.Settings.ToggleExampleNotification()
	CS.Flags.ExampleNotification = not CS.Flags.ExampleNotification

	local existing = CS.UI.Objects.PersistentExampleNotification
	if existing then
		existing:Destroy()
		CS.UI.Objects.PersistentExampleNotification = nil
	end

	if not CS.Flags.ExampleNotification then
		CS.Notify.Push("Notification Preview", "Example notification turned off.", CS.Theme.Info)
		return
	end

	local holder = CS.UI.Objects.ToastHolder
	if not holder then return end

	local preview = CS.Util.Create("Frame", {
		Parent = holder,
		Size = UDim2.new(1, 0, 0, 92),
		BackgroundColor3 = CS.Theme.NotificationBackground,
		BackgroundTransparency = 0.12,
		BorderSizePixel = 0,
		ClipsDescendants = true
	})

	CS.Util.Corner(preview, 12)
	CS.Util.Stroke(preview, CS.Theme.NotificationOutline, 0.2, 1)

	local title = CS.Util.Create("TextLabel", {
		Parent = preview,
		Size = UDim2.new(1, -20, 0, 26),
		Position = UDim2.new(0, 10, 0, 8),
		BackgroundTransparency = 1,
		Text = "Example Notification",
		TextColor3 = CS.Theme.NotificationOutline,
		Font = Enum.Font.GothamBold,
		TextSize = 14,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	local body = CS.Util.Create("TextLabel", {
		Parent = preview,
		Size = UDim2.new(1, -20, 1, -40),
		Position = UDim2.new(0, 10, 0, 34),
		BackgroundTransparency = 1,
		Text = "This stays until you turn it off.",
		TextColor3 = CS.Theme.SubText,
		Font = Enum.Font.Gotham,
		TextSize = 13,
		TextWrapped = true,
		TextXAlignment = Enum.TextXAlignment.Left,
		TextYAlignment = Enum.TextYAlignment.Top
	})

	local line = CS.Util.Create("Frame", {
		Parent = preview,
		Size = UDim2.new(1, -20, 0, 3),
		Position = UDim2.new(0, 10, 1, -8),
		BackgroundColor3 = CS.Theme.NotificationOutline,
		BorderSizePixel = 0
	})

	CS.Util.Corner(line, 999)
	CS.UI.Objects.PersistentExampleNotification = preview
end

function CS.Settings.SaveOriginalTheme()
	CS.Runtime.OriginalTheme = {
		Accent = CS.Theme.Accent,
		Stroke = CS.Theme.Stroke,
		StrokeSoft = CS.Theme.StrokeSoft,
		NotificationOutline = CS.Theme.NotificationOutline
	}
end

function CS.Settings.RestoreOriginalTheme()
	if not CS.Runtime.OriginalTheme then
		return
	end

	CS.Theme.Accent = CS.Runtime.OriginalTheme.Accent
	CS.Theme.Stroke = CS.Runtime.OriginalTheme.Stroke
	CS.Theme.StrokeSoft = CS.Runtime.OriginalTheme.StrokeSoft
	CS.Theme.NotificationOutline = CS.Runtime.OriginalTheme.NotificationOutline

	CS.Runtime.OriginalTheme = nil
	CS.Settings.ApplyVisuals()
	CS.Settings.RefreshToggleVisuals()
end

function CS.Settings.LerpColor(a, b, t)
	return Color3.new(
		a.R + (b.R - a.R) * t,
		a.G + (b.G - a.G) * t,
		a.B + (b.B - a.B) * t
	)
end

function CS.Settings.UpdateColorCycle()
	if not CS.Flags.ColorCycle then
		return
	end

	local colorA = CS.Settings.HexToColor(CS.Flags.ColorCycleA) or Color3.fromRGB(255, 0, 215)
	local colorB = CS.Settings.HexToColor(CS.Flags.ColorCycleB) or Color3.fromRGB(0, 226, 255)
	local speed = CS.Settings.SpeedLevelToInternal(CS.Flags.ColorCycleSpeedLevel or 3)

	CS.Flags.ColorCycleHue += speed

	if CS.Flags.ColorCycleHue > 1 then
		CS.Flags.ColorCycleHue -= 1
	end

	local base = CS.Flags.ColorCycleHue

	local function waveColor(offset)
		local wave = (math.sin(((base + offset) % 1) * math.pi * 2) + 1) / 2
		return CS.Settings.LerpColor(colorA, colorB, wave)
	end

	local c1 = waveColor(0)
	local c2 = waveColor(0.17)
	local c3 = waveColor(0.34)
	local c4 = waveColor(0.51)
	local c5 = waveColor(0.68)

	CS.Theme.Accent = c1
	CS.Theme.Stroke = c2
	CS.Theme.StrokeSoft = c3
	CS.Theme.NotificationOutline = c1

	if CS.UI.Objects.AccentRail then
		CS.UI.Objects.AccentRail.BackgroundColor3 = c1
	end

	if CS.UI.Objects.Main then
		local mainStroke = CS.UI.Objects.Main:FindFirstChildOfClass("UIStroke")
		if mainStroke then
			mainStroke.Color = c1
		end
	end

	if CS.UI.Objects.Sidebar then
		local sideStroke = CS.UI.Objects.Sidebar:FindFirstChildOfClass("UIStroke")
		if sideStroke then
			sideStroke.Color = c2
		end
	end

	if CS.UI.Objects.Content then
		local contentStroke = CS.UI.Objects.Content:FindFirstChildOfClass("UIStroke")
		if contentStroke then
			contentStroke.Color = c3
		end
	end

	if CS.UI.Objects.GUI then
		local i = 0

		for _, obj in ipairs(CS.UI.Objects.GUI:GetDescendants()) do
			if obj:IsA("UIStroke") then
				i += 1

				local mod = i % 5
				if mod == 0 then
					obj.Color = c1
				elseif mod == 1 then
					obj.Color = c2
				elseif mod == 2 then
					obj.Color = c3
				elseif mod == 3 then
					obj.Color = c4
				else
					obj.Color = c5
				end
			end
		end
	end

	for name, tab in pairs(CS.UI.Tabs) do
		if CS.UI.Pages[name] and CS.UI.Pages[name].Visible then
			tab.BackgroundColor3 = c1
		end
	end

	if CS.UI.Objects.PersistentExampleNotification then
		local stroke = CS.UI.Objects.PersistentExampleNotification:FindFirstChildOfClass("UIStroke")
		if stroke then
			stroke.Color = c1
		end
	end
end

function CS.Settings.MakeMiniColorPicker(parent, titleText, defaultHex)
	local holder = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(1, 0, 0, 205),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.12,
		BorderSizePixel = 0
	})

	CS.Util.Corner(holder, 12)
	CS.Util.Stroke(holder, CS.Theme.Stroke, 0.55, 1)

	local label = CS.Util.Create("TextLabel", {
		Parent = holder,
		Size = UDim2.new(1, -16, 0, 22),
		Position = UDim2.new(0, 8, 0, 6),
		BackgroundTransparency = 1,
		Text = titleText,
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 13,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	local picker = CS.Util.Create("Frame", {
		Parent = holder,
		Size = UDim2.new(1, -16, 0, 92),
		Position = UDim2.new(0, 8, 0, 34),
		BackgroundColor3 = Color3.fromRGB(255, 0, 0),
		BorderSizePixel = 0,
		ClipsDescendants = true
	})

	CS.Util.Corner(picker, 8)
	CS.Util.Stroke(picker, CS.Theme.Text, 0.55, 1)

	local satGradient = Instance.new("UIGradient")
	satGradient.Color = ColorSequence.new(Color3.fromRGB(255, 255, 255), Color3.fromRGB(255, 255, 255))
	satGradient.Transparency = NumberSequence.new({
		NumberSequenceKeypoint.new(0, 1),
		NumberSequenceKeypoint.new(1, 0)
	})
	satGradient.Rotation = 0
	satGradient.Parent = picker

	local overlay = CS.Util.Create("Frame", {
		Parent = picker,
		Size = UDim2.new(1, 0, 1, 0),
		BackgroundColor3 = Color3.fromRGB(0, 0, 0),
		BorderSizePixel = 0
	})

	local overlayGradient = Instance.new("UIGradient")
	overlayGradient.Transparency = NumberSequence.new({
		NumberSequenceKeypoint.new(0, 1),
		NumberSequenceKeypoint.new(1, 0)
	})
	overlayGradient.Rotation = 90
	overlayGradient.Parent = overlay

	local cursor = CS.Util.Create("Frame", {
		Parent = picker,
		Size = UDim2.new(0, 14, 0, 14),
		Position = UDim2.new(1, -7, 0, -7),
		BackgroundColor3 = Color3.fromRGB(0, 0, 0),
		BackgroundTransparency = 0.2,
		BorderSizePixel = 0,
		ZIndex = 5
	})

	CS.Util.Corner(cursor, 999)
	CS.Util.Stroke(cursor, CS.Theme.Text, 0.15, 2)

	local hueBar = CS.Util.Create("Frame", {
		Parent = holder,
		Size = UDim2.new(1, -16, 0, 14),
		Position = UDim2.new(0, 8, 0, 134),
		BackgroundColor3 = Color3.fromRGB(255, 255, 255),
		BorderSizePixel = 0
	})

	CS.Util.Corner(hueBar, 999)

	local hueGradient = Instance.new("UIGradient")
	hueGradient.Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0.00, Color3.fromRGB(255, 0, 0)),
		ColorSequenceKeypoint.new(0.16, Color3.fromRGB(255, 255, 0)),
		ColorSequenceKeypoint.new(0.33, Color3.fromRGB(0, 255, 0)),
		ColorSequenceKeypoint.new(0.50, Color3.fromRGB(0, 255, 255)),
		ColorSequenceKeypoint.new(0.66, Color3.fromRGB(0, 0, 255)),
		ColorSequenceKeypoint.new(0.83, Color3.fromRGB(255, 0, 255)),
		ColorSequenceKeypoint.new(1.00, Color3.fromRGB(255, 0, 0))
	})
	hueGradient.Parent = hueBar

	local hueCursor = CS.Util.Create("Frame", {
		Parent = hueBar,
		Size = UDim2.new(0, 12, 0, 20),
		Position = UDim2.new(0, -6, 0.5, -10),
		BackgroundColor3 = Color3.fromRGB(25, 25, 25),
		BorderSizePixel = 0,
		ZIndex = 5
	})

	CS.Util.Corner(hueCursor, 999)
	CS.Util.Stroke(hueCursor, CS.Theme.Text, 0.2, 2)

	local bottom = CS.Util.Create("Frame", {
		Parent = holder,
		Size = UDim2.new(1, -16, 0, 32),
		Position = UDim2.new(0, 8, 0, 160),
		BackgroundColor3 = Color3.fromRGB(12, 12, 18),
		BackgroundTransparency = 0.1,
		BorderSizePixel = 0
	})

	CS.Util.Corner(bottom, 8)

	local swatch = CS.Util.Create("Frame", {
		Parent = bottom,
		Size = UDim2.new(0, 22, 0, 22),
		Position = UDim2.new(0, 7, 0.5, -11),
		BackgroundColor3 = CS.Settings.HexToColor(defaultHex) or CS.Theme.Accent,
		BorderSizePixel = 0
	})

	CS.Util.Corner(swatch, 999)

	local box = CS.Util.Create("TextBox", {
		Parent = bottom,
		Size = UDim2.new(1, -40, 1, 0),
		Position = UDim2.new(0, 36, 0, 0),
		BackgroundTransparency = 1,
		Text = defaultHex,
		PlaceholderText = "#FFFFFF",
		TextColor3 = CS.Theme.Text,
		PlaceholderColor3 = CS.Theme.Muted,
		Font = Enum.Font.GothamBold,
		TextSize = 13,
		TextXAlignment = Enum.TextXAlignment.Left,
		ClearTextOnFocus = false
	})

	local hue, sat, val = 0, 1, 1
	local dragPicker = false
	local dragHue = false

	local function setHSV()
		local color = Color3.fromHSV(hue, sat, val)
		local hex = CS.Settings.ColorToHex(color)
		box.Text = hex
		swatch.BackgroundColor3 = color
		local hueColor = Color3.fromHSV(hue, 1, 1)
		picker.BackgroundColor3 = hueColor
		satGradient.Color = ColorSequence.new(Color3.fromRGB(255, 255, 255), Color3.fromRGB(255, 255, 255))
		satGradient.Transparency = NumberSequence.new({
			NumberSequenceKeypoint.new(0, 1),
			NumberSequenceKeypoint.new(1, 0)
		})
	end

	local function applyPicker(input)
		local x = math.clamp((input.Position.X - picker.AbsolutePosition.X) / picker.AbsoluteSize.X, 0, 1)
		local y = math.clamp((input.Position.Y - picker.AbsolutePosition.Y) / picker.AbsoluteSize.Y, 0, 1)
		sat = x
		val = 1 - y
		cursor.Position = UDim2.new(x, -7, y, -7)
		cursor.BackgroundColor3 = val > 0.5 and Color3.fromRGB(0, 0, 0) or Color3.fromRGB(255, 255, 255)
		setHSV()
	end

	local function applyHue(input)
		local x = math.clamp((input.Position.X - hueBar.AbsolutePosition.X) / hueBar.AbsoluteSize.X, 0, 1)
		hue = x
		hueCursor.Position = UDim2.new(x, -6, 0.5, -10)
		setHSV()
	end

	local function beginMiniPickerDrag(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			dragPicker = true
			applyPicker(input)
		end
	end

	picker.InputBegan:Connect(beginMiniPickerDrag)
	overlay.InputBegan:Connect(beginMiniPickerDrag)

	hueBar.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			dragHue = true
			applyHue(input)
		end
	end)

	CS.Services.UserInputService.InputChanged:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseMovement then
			if dragPicker then
				applyPicker(input)
			elseif dragHue then
				applyHue(input)
			end
		end
	end)

	CS.Services.UserInputService.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			dragPicker = false
			dragHue = false
		end
	end)

	box.FocusLost:Connect(function()
		local color = CS.Settings.HexToColor(box.Text)
		if color then
			local h, s, v = color:ToHSV()
			hue, sat, val = h, s, v
			cursor.Position = UDim2.new(sat, -7, 1 - val, -7)
			cursor.BackgroundColor3 = val > 0.5 and Color3.fromRGB(0, 0, 0) or Color3.fromRGB(255, 255, 255)
			hueCursor.Position = UDim2.new(hue, -6, 0.5, -10)
			box.Text = CS.Settings.ColorToHex(color)
			swatch.BackgroundColor3 = color
			local hueColor = Color3.fromHSV(hue, 1, 1)
			picker.BackgroundColor3 = hueColor
			satGradient.Color = ColorSequence.new({
				ColorSequenceKeypoint.new(0, Color3.fromRGB(255,255,255)),
				ColorSequenceKeypoint.new(1, hueColor)
			})
		end
	end)

	local startColor = CS.Settings.HexToColor(defaultHex) or CS.Theme.Accent
	local h, s, v = startColor:ToHSV()
	hue, sat, val = h, s, v
	cursor.Position = UDim2.new(sat, -7, 1 - val, -7)
	hueCursor.Position = UDim2.new(hue, -6, 0.5, -10)
	setHSV()

	return {
		Frame = holder,
		Box = box,
		Swatch = swatch
	}
end


function CS.Settings.SpeedLevelToInternal(level)
	level = math.clamp(tonumber(level) or 3, 1, 10)

	-- 1 is very slow, 10 is fast.
	return 0.00001 + ((level - 1) / 9) * (0.0045 - 0.00001)
end






function CS.Settings.MakeSection(parent, title, icon, height)
	local card = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(1, -8, 0, height or 220),
		BackgroundColor3 = CS.Theme.Card,
		BackgroundTransparency = CS.Flags.CardTransparency or 0.14,
		BorderSizePixel = 0
	})

	CS.Util.Corner(card, 14)
	CS.Util.Stroke(card, CS.Theme.Stroke, 0.4, 1)

	local glow = CS.Util.Create("Frame", {
		Parent = card,
		Size = UDim2.new(0, 3, 0, 42),
		Position = UDim2.new(0, 0, 0, 50),
		BackgroundColor3 = CS.Theme.Accent,
		BackgroundTransparency = 0.25,
		BorderSizePixel = 0
	})

	CS.Util.Corner(glow, 999)

	CS.Util.Create("TextLabel", {
		Parent = card,
		Size = UDim2.new(0, 34, 0, 44),
		Position = UDim2.new(0, 12, 0, 0),
		BackgroundTransparency = 1,
		Text = icon or "◇",
		TextColor3 = CS.Theme.Accent,
		Font = Enum.Font.GothamBold,
		TextSize = 18
	})

	CS.Util.Create("TextLabel", {
		Parent = card,
		Size = UDim2.new(1, -90, 0, 44),
		Position = UDim2.new(0, 46, 0, 0),
		BackgroundTransparency = 1,
		Text = string.upper(title or "SECTION"),
		TextColor3 = CS.Theme.Accent,
		Font = Enum.Font.GothamBold,
		TextSize = 14,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	CS.Util.Create("TextLabel", {
		Parent = card,
		Size = UDim2.new(0, 45, 0, 44),
		Position = UDim2.new(1, -54, 0, 0),
		BackgroundTransparency = 1,
		Text = "•••",
		TextColor3 = CS.Theme.SubText,
		Font = Enum.Font.GothamBold,
		TextSize = 14
	})

	CS.Util.Create("Frame", {
		Parent = card,
		Size = UDim2.new(1, -28, 0, 1),
		Position = UDim2.new(0, 14, 0, 44),
		BackgroundColor3 = CS.Theme.Stroke,
		BackgroundTransparency = 0.72,
		BorderSizePixel = 0
	})

	return card
end

function CS.Settings.MakeRow(parent, y, icon, title, desc)
	local row = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(1, -28, 0, 48),
		Position = UDim2.new(0, 14, 0, y),
		BackgroundTransparency = 1
	})

	CS.Util.Create("TextLabel", {
		Parent = row,
		Size = UDim2.new(0, 42, 1, 0),
		BackgroundTransparency = 1,
		Text = icon or "◇",
		TextColor3 = CS.Theme.Accent,
		Font = Enum.Font.GothamBold,
		TextSize = 18
	})

	CS.Util.Create("TextLabel", {
		Parent = row,
		Size = UDim2.new(1, -170, 0, 22),
		Position = UDim2.new(0, 52, 0, 4),
		BackgroundTransparency = 1,
		Text = title or "Setting",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 13,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	CS.Util.Create("TextLabel", {
		Parent = row,
		Size = UDim2.new(1, -170, 0, 20),
		Position = UDim2.new(0, 52, 0, 25),
		BackgroundTransparency = 1,
		Text = desc or "",
		TextColor3 = CS.Theme.SubText,
		Font = Enum.Font.Gotham,
		TextSize = 11,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(1, -28, 0, 1),
		Position = UDim2.new(0, 14, 0, y + 52),
		BackgroundColor3 = CS.Theme.Stroke,
		BackgroundTransparency = 0.82,
		BorderSizePixel = 0
	})

	return row
end

function CS.Settings.MakeSwitch(parent, state, callback)
	local button = CS.Util.Create("TextButton", {
		Parent = parent,
		Size = UDim2.new(0, 52, 0, 26),
		Position = UDim2.new(1, -58, 0.5, -13),
		BackgroundColor3 = state and CS.Theme.Success or Color3.fromRGB(45, 47, 60),
		BorderSizePixel = 0,
		Text = "",
		AutoButtonColor = false
	})

	CS.Util.Corner(button, 999)

	local knob = CS.Util.Create("Frame", {
		Parent = button,
		Size = UDim2.new(0, 20, 0, 20),
		Position = state and UDim2.new(1, -23, 0.5, -10) or UDim2.new(0, 3, 0.5, -10),
		BackgroundColor3 = Color3.fromRGB(245, 245, 245),
		BorderSizePixel = 0
	})

	CS.Util.Corner(knob, 999)

	local current = state

	local function redraw(animated)
		button.BackgroundColor3 = current and CS.Theme.Success or Color3.fromRGB(45, 47, 60)

		local goal = {
			Position = current and UDim2.new(1, -23, 0.5, -10) or UDim2.new(0, 3, 0.5, -10)
		}

		if animated == false or not CS.Flags.Animations then
			knob.Position = goal.Position
		else
			CS.Services.TweenService:Create(
				knob,
				TweenInfo.new(0.18, Enum.EasingStyle.Quint, Enum.EasingDirection.Out),
				goal
			):Play()
		end
	end

	button.MouseButton1Click:Connect(function()
		current = not current
		redraw(true)

		if callback then
			callback(current)
		end
	end)

	return {
		Button = button,
		Knob = knob,
		Set = function(_, value)
			current = value
			redraw(false)
		end,
		Get = function()
			return current
		end
	}
end

function CS.Settings.MakeMiniSlider(parent, value, callback)
	local holder = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(0, 170, 0, 26),
		Position = UDim2.new(1, -180, 0.5, -13),
		BackgroundTransparency = 1
	})

	local valueLabel = CS.Util.Create("TextLabel", {
		Parent = holder,
		Size = UDim2.new(0, 44, 1, 0),
		Position = UDim2.new(1, -44, 0, 0),
		BackgroundTransparency = 1,
		Text = tostring(math.floor((value or 0) * 100)) .. "%",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 11
	})

	local bar = CS.Util.Create("Frame", {
		Parent = holder,
		Size = UDim2.new(1, -52, 0, 5),
		Position = UDim2.new(0, 0, 0.5, -2),
		BackgroundColor3 = CS.Theme.Card2,
		BorderSizePixel = 0
	})
	CS.Util.Corner(bar, 999)

	local fill = CS.Util.Create("Frame", {
		Parent = bar,
		Size = UDim2.new(math.clamp(value or 0, 0, 1), 0, 1, 0),
		BackgroundColor3 = CS.Theme.Accent,
		BorderSizePixel = 0
	})
	CS.Util.Corner(fill, 999)

	local knob = CS.Util.Create("Frame", {
		Parent = bar,
		Size = UDim2.new(0, 16, 0, 16),
		Position = UDim2.new(math.clamp(value or 0, 0, 1), -8, 0.5, -8),
		BackgroundColor3 = CS.Theme.Accent,
		BorderSizePixel = 0
	})
	CS.Util.Corner(knob, 999)
	CS.Util.Stroke(knob, CS.Theme.Text, 0.35, 1)

	local dragging = false
	local current = math.clamp(value or 0, 0, 1)

	local function apply(x, fire)
		current = math.clamp(x, 0, 1)
		fill.Size = UDim2.new(current, 0, 1, 0)
		knob.Position = UDim2.new(current, -8, 0.5, -8)
		valueLabel.Text = tostring(math.floor(current * 100)) .. "%"

		if fire and callback then
			callback(current)
		end
	end

	local function setFromX(xPos)
		apply((xPos - bar.AbsolutePosition.X) / math.max(bar.AbsoluteSize.X, 1), true)
	end

	bar.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			dragging = true
			setFromX(input.Position.X)
		end
	end)

	knob.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			dragging = true
			setFromX(input.Position.X)
		end
	end)

	CS.Services.UserInputService.InputChanged:Connect(function(input)
		if dragging and input.UserInputType == Enum.UserInputType.MouseMovement then
			setFromX(input.Position.X)
		end
	end)

	CS.Services.UserInputService.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 and dragging then
			dragging = false
			CS.Settings.Save(true)
		end
	end)

	return {
		Holder = holder,
		Set = function(_, v)
			apply(v, false)
		end,
		Get = function()
			return current
		end
	}
end

function CS.Settings.MakeSmallSelect(parent, text, callback)
	local btn = CS.Util.Create("TextButton", {
		Parent = parent,
		Size = UDim2.new(0, 110, 0, 30),
		Position = UDim2.new(1, -116, 0.5, -15),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = text or "Default",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 11,
		AutoButtonColor = false
	})

	CS.Util.Corner(btn, 8)
	CS.Util.Stroke(btn, CS.Theme.Stroke, 0.6, 1)

	btn.MouseButton1Click:Connect(function()
		if callback then
			callback(btn)
		end
	end)

	return btn
end

function CS.Settings.MakePreviewBox(parent, title, xScale)
	local box = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(xScale or 0.42, -14, 0, 150),
		Position = UDim2.new(1 - (xScale or 0.42), 0, 0, 62),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.18,
		BorderSizePixel = 0
	})

	CS.Util.Corner(box, 12)
	CS.Util.Stroke(box, CS.Theme.Stroke, 0.42, 1)

	CS.Util.Create("TextLabel", {
		Parent = box,
		Size = UDim2.new(1, 0, 0, 28),
		BackgroundTransparency = 1,
		Text = string.upper(title or "PREVIEW"),
		TextColor3 = CS.Theme.SubText,
		Font = Enum.Font.GothamBold,
		TextSize = 11
	})

	return box
end

function CS.Settings.MakeStatPreview(parent, leftText, rightText)
	local preview = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(1, -28, 0, 36),
		Position = UDim2.new(0, 14, 1, -48),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.2,
		BorderSizePixel = 0
	})

	CS.Util.Corner(preview, 9)
	CS.Util.Stroke(preview, CS.Theme.Stroke, 0.55, 1)

	CS.Util.Create("TextLabel", {
		Parent = preview,
		Size = UDim2.new(0.5, -8, 1, 0),
		Position = UDim2.new(0, 10, 0, 0),
		BackgroundTransparency = 1,
		Text = leftText or "",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 11,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	CS.Util.Create("TextLabel", {
		Parent = preview,
		Size = UDim2.new(0.5, -10, 1, 0),
		Position = UDim2.new(0.5, 0, 0, 0),
		BackgroundTransparency = 1,
		Text = rightText or "",
		TextColor3 = CS.Theme.Accent,
		Font = Enum.Font.GothamBold,
		TextSize = 11,
		TextXAlignment = Enum.TextXAlignment.Right
	})

	return preview
end

function CS.Settings.SafeNotify(title, body, color)
	if CS.Notify and CS.Notify.Push then
		CS.Notify.Push(title, body, color or CS.Theme.Info)
	end
end


CS.Settings.Runtime = CS.Settings.Runtime or {
	PreviewObjects = {},
	PreviewConnections = {},
	LastPreviewPulse = 0
}

function CS.Settings.TrackPreview(name, object)
	CS.Settings.Runtime.PreviewObjects[name] = object
	return object
end

function CS.Settings.ClearPreviewConnections()
	for _, connection in ipairs(CS.Settings.Runtime.PreviewConnections) do
		pcall(function()
			connection:Disconnect()
		end)
	end

	CS.Settings.Runtime.PreviewConnections = {}
end

function CS.Settings.TrackConnection(connection)
	table.insert(CS.Settings.Runtime.PreviewConnections, connection)
	return connection
end

function CS.Settings.ApplyOutlineThickness(value)
	local thickness = 0.5 + (math.clamp(value or 0.45, 0, 1) * 1.8)

	if not CS.UI.Objects.GUI then
		return
	end

	for _, obj in ipairs(CS.UI.Objects.GUI:GetDescendants()) do
		if obj:IsA("UIStroke") then
			obj.Thickness = thickness
		end
	end
end

function CS.Settings.ApplyGlassStrength(value)
	local strength = math.clamp(value or 0.55, 0, 1)

	CS.Flags.Transparency = math.clamp(1 - strength, 0.05, 0.85)
	CS.Flags.PanelTransparency = CS.Flags.Transparency
	CS.Flags.CardTransparency = math.clamp(CS.Flags.Transparency + 0.10, 0, 0.9)

	CS.Settings.ApplyVisuals()
end

function CS.Settings.ApplyScaleFromSlider(value)
	if value >= 0.8 then
		CS.Flags.ScaleMode = "Large"
	elseif value <= 0.35 then
		CS.Flags.ScaleMode = "Compact"
	else
		CS.Flags.ScaleMode = "Normal"
	end

	CS.Settings.ApplyVisuals()
end

function CS.Settings.SetColorCycleEnabled(value)
	CS.Flags.ColorCycle = value

	if value then
		CS.Settings.SaveOriginalTheme()
		CS.Flags.ColorCycleHue = 0

		for i = 1, 8 do
			CS.Settings.UpdateColorCycle()
		end
	else
		CS.Settings.RestoreOriginalTheme()
	end

	CS.Settings.Save(true)
end

function CS.Settings.SetAnimationEnabled(value)
	CS.Flags.Animations = value
	CS.Settings.Save(true)
end

function CS.Settings.SetFriendSoundsEnabled(value)
	CS.Flags.FriendSounds = value
	CS.Settings.Save(true)
end

function CS.Settings.SetNotificationEnabled(value)
	CS.Flags.Notifications = value
	CS.Settings.Save(true)
end

function CS.Settings.SetReducedMotion(value)
	CS.Flags.Animations = not value
	CS.Settings.Save(true)
end

function CS.Settings.SetCompactMode(value)
	CS.Flags.ScaleMode = value and "Compact" or "Normal"
	CS.Settings.ApplyVisuals()
	CS.Settings.Save(true)
end

function CS.Settings.PulseObject(object, color)
	if not object then
		return
	end

	local originalSize = object.Size
	local originalColor = object.BackgroundColor3

	object.BackgroundColor3 = color or CS.Theme.Accent

	if CS.Flags.Animations then
		CS.Services.TweenService:Create(
			object,
			TweenInfo.new(0.12, Enum.EasingStyle.Quint, Enum.EasingDirection.Out),
			{Size = originalSize + UDim2.new(0, 4, 0, 4)}
		):Play()

		task.delay(0.14, function()
			if object and object.Parent then
				CS.Services.TweenService:Create(
					object,
					TweenInfo.new(0.16, Enum.EasingStyle.Quint, Enum.EasingDirection.Out),
					{Size = originalSize, BackgroundColor3 = originalColor}
				):Play()
			end
		end)
	else
		object.Size = originalSize
		object.BackgroundColor3 = originalColor
	end
end

function CS.Settings.MakeRobloxAvatarPreview(parent, userId)
	local avatar = CS.Util.Create("ImageLabel", {
		Parent = parent,
		Size = UDim2.new(0, 58, 0, 58),
		Position = UDim2.new(0, 14, 0, 54),
		BackgroundTransparency = 1
	})

	CS.Util.Corner(avatar, 12)

	pcall(function()
		avatar.Image = CS.Services.Players:GetUserThumbnailAsync(
			userId or CS.LocalPlayer.UserId,
			Enum.ThumbnailType.AvatarThumbnail,
			Enum.ThumbnailSize.Size420x420
		)
	end)

	return avatar
end

function CS.Settings.MakeNotificationPreview(parent)
	local sample = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(1, -24, 0, 70),
		Position = UDim2.new(0, 12, 0.5, -25),
		BackgroundColor3 = CS.Theme.NotificationBackground,
		BackgroundTransparency = 0.12,
		BorderSizePixel = 0
	})

	CS.Util.Corner(sample, 12)
	CS.Util.Stroke(sample, CS.Theme.NotificationOutline, 0.2, 2)

	CS.Util.Create("TextLabel", {
		Parent = sample,
		Size = UDim2.new(1, -20, 0, 26),
		Position = UDim2.new(0, 12, 0, 8),
		BackgroundTransparency = 1,
		Text = "CS  Player joined you",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 13,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	CS.Util.Create("TextLabel", {
		Parent = sample,
		Size = UDim2.new(1, -20, 0, 22),
		Position = UDim2.new(0, 12, 0, 36),
		BackgroundTransparency = 1,
		Text = "Welcome to the server!",
		TextColor3 = CS.Theme.SubText,
		Font = Enum.Font.Gotham,
		TextSize = 11,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	return sample
end

function CS.Settings.MakeTabPreview(parent)
	local previewStack = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(1, -24, 0, 110),
		Position = UDim2.new(0, 12, 0, 38),
		BackgroundTransparency = 1
	})

	local exLine1 = CS.Util.Button(previewStack, "▸ Home", 30)
	exLine1.Size = UDim2.new(1, 0, 0, 30)
	exLine1.Position = UDim2.new(0, 0, 0, 0)
	exLine1.TextXAlignment = Enum.TextXAlignment.Left

	local exLine2 = CS.Util.Button(previewStack, "  Players", 30)
	exLine2.Size = UDim2.new(1, 0, 0, 30)
	exLine2.Position = UDim2.new(0, 0, 0, 36)
	exLine2.TextXAlignment = Enum.TextXAlignment.Left

	local exLine3 = CS.Util.Button(previewStack, "  Settings", 30)
	exLine3.Size = UDim2.new(1, 0, 0, 30)
	exLine3.Position = UDim2.new(0, 0, 0, 72)
	exLine3.TextXAlignment = Enum.TextXAlignment.Left

	return previewStack
end

function CS.Settings.Build()
	local page = CS.UI.Pages["Settings"]
	CS.Util.Clear(page, true)

	local leftColumn = CS.Util.Scroll(page)
	leftColumn.Size = UDim2.new(0.333, -8, 1, 0)
	leftColumn.Position = UDim2.new(0, 0, 0, 0)

	local middleColumn = CS.Util.Scroll(page)
	middleColumn.Size = UDim2.new(0.333, -8, 1, 0)
	middleColumn.Position = UDim2.new(0.333, 4, 0, 0)

	local rightColumn = CS.Util.Scroll(page)
	rightColumn.Size = UDim2.new(0.334, -8, 1, 0)
	rightColumn.Position = UDim2.new(0.666, 8, 0, 0)

	local interface = CS.Settings.MakeSection(leftColumn, "Interface", "▣", 270)
	local row1 = CS.Settings.MakeRow(interface, 58, "▣", "UI Scale", "Adjust the size of the menu.")
	CS.Settings.MakeMiniSlider(row1, CS.Flags.ScaleMode == "Large" and 1 or 0.6, function(value)
		CS.Settings.ApplyScaleFromSlider(value)
	end)
	local row2 = CS.Settings.MakeRow(interface, 112, "◫", "Glass Strength", "Control the full menu transparency.")
	CS.Settings.MakeMiniSlider(row2, 1 - (CS.Flags.Transparency or 0.45), function(value)
		CS.Settings.ApplyGlassStrength(value)
	end)
	local row3 = CS.Settings.MakeRow(interface, 166, "◈", "Show Outlines", "Keep visible borders around cards.")
	CS.Settings.MakeSwitch(row3, true, function()
		CS.Settings.ApplyVisuals()
		CS.Settings.Save(true)
	end)
	local row4 = CS.Settings.MakeRow(interface, 220, "≈", "Outline Thickness", "Adjust outline strength.")
	CS.Settings.MakeMiniSlider(row4, 0.45, function(value)
		CS.Settings.ApplyOutlineThickness(value)
	end)

	local rgb = CS.Settings.MakeSection(leftColumn, "RGB Effects", "◉", 245)
	local r1 = CS.Settings.MakeRow(rgb, 58, "◉", "Enable RGB", "Animated outline chase effect.")
	CS.Settings.MakeSwitch(r1, CS.Flags.ColorCycle, function(value)
		CS.Settings.SetColorCycleEnabled(value)
	end)
	local r2 = CS.Settings.MakeRow(rgb, 112, "↬", "RGB Style", "Use chase-style animated borders.")
	CS.Settings.MakeSmallSelect(r2, "Chase", function() CS.Notify.Push("RGB", "Chase style selected.", CS.Theme.Info) end)
	local r3 = CS.Settings.MakeRow(rgb, 166, "⌁", "Speed", "How quickly the colors move.")
	CS.Settings.MakeMiniSlider(r3, math.clamp((CS.Flags.ColorCycleSpeedLevel or 3) / 10, 0.1, 1), function(value)
		CS.Flags.ColorCycleSpeedLevel = math.clamp(math.floor(value * 10 + 0.5), 1, 10)
		CS.Flags.ColorCycleSpeed = CS.Settings.SpeedLevelToInternal(CS.Flags.ColorCycleSpeedLevel)
	end)
	local r4 = CS.Settings.MakeRow(rgb, 220, "✦", "Brightness", "Preview glow strength.")
	CS.Settings.MakeMiniSlider(r4, 0.8, function() end)

	local effects = CS.Settings.MakeSection(leftColumn, "Visual Effects", "✧", 245)
	local effectPreview = CS.Settings.MakePreviewBox(effects, "Preview", 0.42)
	local fxText = CS.Util.Create("TextLabel", {Parent = effectPreview, Size = UDim2.new(1, 0, 1, -28), Position = UDim2.new(0, 0, 0, 28), BackgroundTransparency = 1, Text = "CS", TextColor3 = CS.Theme.Accent, Font = Enum.Font.GothamBlack, TextSize = 32})
	local e1 = CS.Settings.MakeRow(effects, 58, "◫", "Blur Intensity", "Preview blur-like glass strength.")
	CS.Settings.MakeMiniSlider(e1, 0.35, function(value) effectPreview.BackgroundTransparency = math.clamp(0.45 - value * 0.25, 0.08, 0.45) end)
	local e2 = CS.Settings.MakeRow(effects, 112, "◈", "Glass Strength", "Adjust preview glass depth.")
	CS.Settings.MakeMiniSlider(e2, 0.45, function(value) effectPreview.BackgroundTransparency = math.clamp(1 - value, 0.05, 0.85) end)
	local e3 = CS.Settings.MakeRow(effects, 166, "☾", "Shadow Quality", "Visual depth quality.")
	CS.Settings.MakeSmallSelect(e3, "High", function() CS.Notify.Push("Visual Effects", "High visual depth selected.", CS.Theme.Info) end)
	local e4 = CS.Settings.MakeRow(effects, 220, "●", "Color Saturation", "Preview accent intensity.")
	CS.Settings.MakeMiniSlider(e4, 0.75, function(value) fxText.TextTransparency = math.clamp(1 - value, 0, 0.8) end)

	local accent = CS.Settings.MakeSection(middleColumn, "Accent", "✎", 270)
	local accentPreview = CS.Settings.MakePreviewBox(accent, "Preview", 0.40)
	CS.Util.Create("TextLabel", {Parent = accentPreview, Size = UDim2.new(1, 0, 1, -30), Position = UDim2.new(0, 0, 0, 28), BackgroundTransparency = 1, Text = "CS", TextColor3 = CS.Theme.Accent, Font = Enum.Font.GothamBlack, TextSize = 42})
	local v1 = CS.Settings.MakeRow(accent, 58, "●", "Accent Color", "Main highlight color.")
	CS.Settings.MakeSmallSelect(v1, CS.Settings.ColorToHex(CS.Theme.Accent), function() CS.Notify.Push("Accent", "Use the color picker below for exact colors.", CS.Theme.Info) end)
	local v2 = CS.Settings.MakeRow(accent, 112, "◇", "Accent Style", "Glow, soft, or flat style.")
	CS.Settings.MakeSmallSelect(v2, "Glow", function() CS.Notify.Push("Accent", "Glow style active.", CS.Theme.Info) end)
	local v3 = CS.Settings.MakeRow(accent, 166, "≋", "Gradient Style", "Controls preview gradient feel.")
	CS.Settings.MakeSmallSelect(v3, "Smooth", function() CS.Notify.Push("Accent", "Smooth gradient selected.", CS.Theme.Info) end)
	local v4 = CS.Settings.MakeRow(accent, 220, "✦", "Menu Glow", "Outer glow intensity preview.")
	CS.Settings.MakeMiniSlider(v4, 0.72, function(value) if CS.UI.Objects.AccentRail then CS.UI.Objects.AccentRail.BackgroundTransparency = 1 - value end end)

	local anim = CS.Settings.MakeSection(middleColumn, "Animations", "⌁", 245)
	local animPreview = CS.Settings.MakePreviewBox(anim, "Preview", 0.40)
	local tabOne = CS.Util.Button(animPreview, "⌂", 36)
	tabOne.Size = UDim2.new(0, 44, 0, 44)
	tabOne.Position = UDim2.new(0, 18, 0, 58)
	tabOne.BackgroundColor3 = CS.Theme.Accent
	tabOne.TextColor3 = Color3.fromRGB(0, 0, 0)
	local tabTwo = CS.Util.Button(animPreview, "👥", 36)
	tabTwo.Size = UDim2.new(0, 44, 0, 44)
	tabTwo.Position = UDim2.new(0, 70, 0, 58)
	local hoverButton = CS.Util.Button(animPreview, "Hover Me", 34)
	hoverButton.Size = UDim2.new(1, -34, 0, 36)
	hoverButton.Position = UDim2.new(0, 17, 1, -50)
	local a1 = CS.Settings.MakeRow(anim, 58, "⇄", "Tab Animation", "Slide between menu pages.")
	CS.Settings.MakeSmallSelect(a1, "Slide", function() CS.Notify.Push("Animations", "Tab animation set to Slide.", CS.Theme.Info) end)
	local a2 = CS.Settings.MakeRow(anim, 112, "✦", "Hover Style", "Glow spread on hover.")
	CS.Settings.MakeSmallSelect(a2, "Glow", function() CS.Notify.Push("Animations", "Hover glow selected.", CS.Theme.Info) end)
	local a3 = CS.Settings.MakeRow(anim, 166, "⌁", "Animation Speed", "Controls menu transition speed.")
	CS.Settings.MakeMiniSlider(a3, 0.4, function() end)
	local a4 = CS.Settings.MakeRow(anim, 220, "✓", "Smoothness", "Enable smoothed UI feedback.")
	CS.Settings.MakeSwitch(a4, CS.Flags.Animations, function(value) CS.Flags.Animations = value CS.Settings.Save(true) end)

	local sounds = CS.Settings.MakeSection(middleColumn, "Sounds", "🔊", 245)
	local soundPreview = CS.Settings.MakePreviewBox(sounds, "Preview", 0.42)
	local pulse = CS.Util.Create("Frame", {Parent = soundPreview, Size = UDim2.new(0, 74, 0, 74), Position = UDim2.new(0.5, -37, 0.5, -26), BackgroundColor3 = CS.Theme.Accent, BackgroundTransparency = 0.72, BorderSizePixel = 0})
	CS.Util.Corner(pulse, 999)
	CS.Util.Stroke(pulse, CS.Theme.Accent, 0.2, 2)
	local s1 = CS.Settings.MakeRow(sounds, 58, "▶", "Click Sound", "Preview button click sound.")
	CS.Settings.MakeSmallSelect(s1, "Play", function() CS.Notify.PlaySound(CS.Flags.JoinFriendSoundId, 0.65) end)
	local s2 = CS.Settings.MakeRow(sounds, 112, "▶", "Hover Sound", "Preview hover feedback sound.")
	CS.Settings.MakeSmallSelect(s2, "Play", function() CS.Notify.PlaySound(CS.Flags.FriendJoinSoundId, 0.65) end)
	local s3 = CS.Settings.MakeRow(sounds, 166, "▶", "Notice Sound", "Preview notification sound.")
	CS.Settings.MakeSmallSelect(s3, "Play", function() CS.Notify.PlaySound(CS.Flags.FriendLeaveSoundId, 0.65) end)
	local s4 = CS.Settings.MakeRow(sounds, 220, "▰", "Volume", "Sound preview volume level.")
	CS.Settings.MakeMiniSlider(s4, 0.75, function() end)

	local notif = CS.Settings.MakeSection(rightColumn, "Notifications", "🔔", 270)
	local notifPreview = CS.Settings.MakePreviewBox(notif, "Preview", 0.44)
	local sample = CS.Util.Create("Frame", {Parent = notifPreview, Size = UDim2.new(1, -24, 0, 70), Position = UDim2.new(0, 12, 0.5, -25), BackgroundColor3 = CS.Theme.NotificationBackground, BackgroundTransparency = 0.12, BorderSizePixel = 0})
	CS.Util.Corner(sample, 12)
	CS.Util.Stroke(sample, CS.Theme.NotificationOutline, 0.2, 2)
	CS.Util.Create("TextLabel", {Parent = sample, Size = UDim2.new(1, -20, 0, 26), Position = UDim2.new(0, 12, 0, 8), BackgroundTransparency = 1, Text = "CS  Player joined you", TextColor3 = CS.Theme.Text, Font = Enum.Font.GothamBold, TextSize = 13, TextXAlignment = Enum.TextXAlignment.Left})
	CS.Util.Create("TextLabel", {Parent = sample, Size = UDim2.new(1, -20, 0, 22), Position = UDim2.new(0, 12, 0, 36), BackgroundTransparency = 1, Text = "Welcome to the server!", TextColor3 = CS.Theme.SubText, Font = Enum.Font.Gotham, TextSize = 11, TextXAlignment = Enum.TextXAlignment.Left})
	local n1 = CS.Settings.MakeRow(notif, 58, "↗", "Position", "Where notices appear.")
	CS.Settings.MakeSmallSelect(n1, "Top Right", function() CS.Notify.Push("Notifications", "Position preview is top right.", CS.Theme.Info) end)
	local n2 = CS.Settings.MakeRow(notif, 112, "◇", "Style", "Notification animation style.")
	CS.Settings.MakeSmallSelect(n2, "Modern", function() CS.Notify.Push("Notifications", "Modern style active.", CS.Theme.Info) end)
	local n3 = CS.Settings.MakeRow(notif, 166, "⏱", "Duration", "How long notices stay.")
	CS.Settings.MakeSmallSelect(n3, "5 Seconds", function() CS.Notify.Push("Notifications", "Duration preview: 5 seconds.", CS.Theme.Info) end)
	local n4 = CS.Settings.MakeRow(notif, 220, "🔊", "Sound", "Friend and notification sounds.")
	CS.Settings.MakeSwitch(n4, CS.Flags.FriendSounds, function(value) CS.Flags.FriendSounds = value CS.Settings.Save(true) end)

	local playerCard = CS.Settings.MakeSection(rightColumn, "Player Card", "👤", 245)
	local playerPreview = CS.Settings.MakePreviewBox(playerCard, "Preview", 0.48)
	local avatar = CS.Util.Create("ImageLabel", {Parent = playerPreview, Size = UDim2.new(0, 58, 0, 58), Position = UDim2.new(0, 14, 0, 54), BackgroundTransparency = 1})
	CS.Util.Corner(avatar, 12)
	pcall(function()
		avatar.Image = CS.Services.Players:GetUserThumbnailAsync(CS.LocalPlayer.UserId, Enum.ThumbnailType.AvatarThumbnail, Enum.ThumbnailSize.Size420x420)
	end)
	CS.Util.Create("TextLabel", {Parent = playerPreview, Size = UDim2.new(1, -90, 0, 26), Position = UDim2.new(0, 84, 0, 56), BackgroundTransparency = 1, Text = CS.LocalPlayer.DisplayName, TextColor3 = CS.Theme.Text, Font = Enum.Font.GothamBold, TextSize = 14, TextXAlignment = Enum.TextXAlignment.Left})
	local pUser = CS.Util.Create("TextLabel", {Parent = playerPreview, Size = UDim2.new(1, -90, 0, 22), Position = UDim2.new(0, 84, 0, 82), BackgroundTransparency = 1, Text = "@" .. CS.LocalPlayer.Name, TextColor3 = CS.Theme.SubText, Font = Enum.Font.Gotham, TextSize = 12, TextXAlignment = Enum.TextXAlignment.Left})
	local pc1 = CS.Settings.MakeRow(playerCard, 58, "▣", "Card Style", "Player card layout type.")
	CS.Settings.MakeSmallSelect(pc1, "Modern", function() CS.Notify.Push("Player Card", "Modern card style active.", CS.Theme.Info) end)
	local pc2 = CS.Settings.MakeRow(playerCard, 112, "👤", "Show Avatar", "Display Roblox avatar preview.")
	CS.Settings.MakeSwitch(pc2, true, function(value) avatar.Visible = value end)
	local pc3 = CS.Settings.MakeRow(playerCard, 166, "◫", "Transparency", "Player card glass amount.")
	CS.Settings.MakeMiniSlider(pc3, 0.65, function(value) playerPreview.BackgroundTransparency = math.clamp(1 - value, 0.05, 0.7) end)
	local pc4 = CS.Settings.MakeRow(playerCard, 220, "◎", "Show Status", "Show simple in-game status.")
	CS.Settings.MakeSwitch(pc4, true, function(value) pUser.Text = value and ("@" .. CS.LocalPlayer.Name .. "  •  In-Game") or ("@" .. CS.LocalPlayer.Name) end)

	local extra = CS.Settings.MakeSection(rightColumn, "Extra", "☆", 245)
	local extraPreview = CS.Settings.MakePreviewBox(extra, "Preview", 0.42)
	local previewStack = CS.Util.Create("Frame", {Parent = extraPreview, Size = UDim2.new(1, -24, 0, 110), Position = UDim2.new(0, 12, 0, 38), BackgroundTransparency = 1})
	local exLine1 = CS.Util.Button(previewStack, "▸ Home", 30)
	exLine1.Size = UDim2.new(1, 0, 0, 30)
	exLine1.Position = UDim2.new(0, 0, 0, 0)
	exLine1.TextXAlignment = Enum.TextXAlignment.Left
	local exLine2 = CS.Util.Button(previewStack, "  Players", 30)
	exLine2.Size = UDim2.new(1, 0, 0, 30)
	exLine2.Position = UDim2.new(0, 0, 0, 36)
	exLine2.TextXAlignment = Enum.TextXAlignment.Left
	local exLine3 = CS.Util.Button(previewStack, "  Settings", 30)
	exLine3.Size = UDim2.new(1, 0, 0, 30)
	exLine3.Position = UDim2.new(0, 0, 0, 72)
	exLine3.TextXAlignment = Enum.TextXAlignment.Left
	local x1 = CS.Settings.MakeRow(extra, 58, "▣", "Compact Mode", "Reduce spacing and card height.")
	CS.Settings.MakeSwitch(x1, CS.Flags.ScaleMode == "Compact", function(value) CS.Flags.ScaleMode = value and "Compact" or "Normal" CS.Settings.ApplyVisuals() CS.Settings.Save(true) end)
	local x2 = CS.Settings.MakeRow(extra, 112, "⌨", "Hide Keybinds", "Reduce visible hotkey hints.")
	CS.Settings.MakeSwitch(x2, false, function() CS.Notify.Push("Extra", "Keybind hints hidden in preview.", CS.Theme.Info) end)
	local x3 = CS.Settings.MakeRow(extra, 166, "≈", "Reduced Motion", "Lower animation movement.")
	CS.Settings.MakeSwitch(x3, not CS.Flags.Animations, function(value) CS.Flags.Animations = not value CS.Settings.Save(true) end)
	local x4 = CS.Settings.MakeRow(extra, 220, "⇅", "Sort Tabs By", "Keep default sidebar order.")
	CS.Settings.MakeSmallSelect(x4, "Default", function() CS.Notify.Push("Extra", "Default tab order active.", CS.Theme.Info) end)

	CS.Settings.MakeColorEditor(leftColumn, "Background Color", "Background", CS.Theme.Background, function(color, hex)
		CS.Theme.Background = color
		CS.Theme.Panel = color
		CS.Theme.Panel2 = color
		CS.Settings.ApplyVisuals()
		CS.Settings.Save(true)
		CS.Notify.Push("Theme", "Background color changed to " .. hex, CS.Theme.NotificationOutline)
	end)

	CS.Settings.MakeColorEditor(middleColumn, "Outline Color", "Outline", CS.Theme.Stroke, function(color, hex)
		CS.Theme.Stroke = color
		CS.Theme.StrokeSoft = color
		CS.Settings.ApplyVisuals()
		CS.Settings.Save(true)
		CS.Notify.Push("Theme", "Outline color changed to " .. hex, CS.Theme.NotificationOutline)
	end)

	CS.Settings.MakeColorEditor(rightColumn, "Notification Color", "Notification", CS.Theme.NotificationOutline, function(color, hex)
		CS.Theme.NotificationOutline = color
		CS.Theme.Info = color
		CS.Settings.ApplyVisuals()
		CS.Settings.Save(true)
		CS.Notify.Push("Theme", "Notification color changed to " .. hex, CS.Theme.NotificationOutline)
	end)

	CS.Settings.RefreshToggleVisuals()
end


function CS.Utilities.Build()
	local page=CS.UI.Pages["Utilities"]; CS.Util.Clear(page,true); local left=CS.Util.Scroll(page); left.Size=UDim2.new(0.5,-6,1,0); local right=CS.Util.Scroll(page); right.Size=UDim2.new(0.5,-6,1,0); right.Position=UDim2.new(0.5,6,0,0)
	local menu=CS.UI.OverlayCard(left,"Menu Controls","⚙",310); CS.UI.OverlayButton(menu,"RF Menu",58,function() CS.PlayerDetails.RefreshList(); CS.Dashboard.Update(); pcall(function() CS.ServerBrowser.Fetch() end); pcall(function() CS.Friends.RefreshFriendList() end); CS.Settings.ApplyVisuals(); CS.Notify.Push("Utilities","Menu refreshed.",CS.Theme.Success) end); CS.UI.OverlayButton(menu,"Close Menu",106,function() CS.Flags.Open=false; if CS.UI.Objects.Main then CS.UI.Objects.Main.Visible=false end end); CS.UI.OverlayButton(menu,"Repair Layout",154,function() CS.Settings.ApplyVisuals(); CS.Notify.Push("Utilities","Layout repaired.",CS.Theme.Success) end); CS.UI.OverlayButton(menu,"Save Settings",202,function() local ok=CS.Settings.Save(false); CS.Notify.Push("Utilities",ok and "Settings saved." or "Save unavailable.",ok and CS.Theme.Success or CS.Theme.Warning) end); CS.UI.OverlayButton(menu,"Reload Settings",250,function() local ok=CS.Settings.Load(); CS.Settings.ApplyVisuals(); CS.Notify.Push("Utilities",ok and "Settings loaded." or "No settings found.",ok and CS.Theme.Info or CS.Theme.Warning) end)
	local shortcuts=CS.UI.OverlayCard(left,"Quick Links","↗",220); CS.UI.OverlayButton(shortcuts,"Open Settings",58,function() CS.UI.SwitchPage("Settings") end); CS.UI.OverlayButton(shortcuts,"Open Friends",106,function() CS.UI.SwitchPage("Friends") end); CS.UI.OverlayButton(shortcuts,"Open Game Info",154,function() CS.UI.SwitchPage("Game Info") end)
	local preview=CS.UI.OverlayCard(right,"Utility Preview","◎",260); CS.UI.OverlayGraph(preview,58,"Menu Activity"); CS.UI.Labels.UtilityStatus=CS.UI.OverlayValue(preview,176,"✓","Status","Ready","Utility actions are connected.")
	local system=CS.UI.OverlayCard(right,"Session","◷",240); CS.UI.Labels.UtilitySession=CS.UI.OverlayValue(system,58,"⚡","FPS",tostring(CS.Runtime.FPS or "--"),"Live client FPS."); CS.UI.Labels.UtilityPing=CS.UI.OverlayValue(system,112,"📡","Ping",tostring(CS.Runtime.Ping or "--"),"Live network ping."); CS.UI.Labels.UtilityPlayers=CS.UI.OverlayValue(system,166,"👥","Players",tostring(#CS.Services.Players:GetPlayers()),"Players in server.")
end

function CS.Dashboard.UpdatePingStats()
	local ping = CS.Util.Ping()
	CS.Runtime.Ping = ping

	table.insert(CS.Runtime.PingHistory, ping)

	if #CS.Runtime.PingHistory > 48 then
		table.remove(CS.Runtime.PingHistory, 1)
	end

	CS.Runtime.LowPing = CS.Runtime.LowPing and math.min(CS.Runtime.LowPing, ping) or ping
	CS.Runtime.HighPing = CS.Runtime.HighPing and math.max(CS.Runtime.HighPing, ping) or ping

	local total = 0

	for _, value in ipairs(CS.Runtime.PingHistory) do
		total += value
	end

	CS.Runtime.AvgPing = #CS.Runtime.PingHistory > 0 and math.floor(total / #CS.Runtime.PingHistory) or ping
end

function CS.Dashboard.PaintBars(bars)
	if not bars then return end

	for index, bar in ipairs(bars) do
		local value = CS.Runtime.PingHistory[index] or 0
		local height = math.clamp(value / 240, 0.04, 1)

		bar.Size = UDim2.new(1 / #bars, -2, height, 0)

		if value <= 70 then
			bar.BackgroundColor3 = CS.Theme.Success
		elseif value <= 140 then
			bar.BackgroundColor3 = CS.Theme.Warning
		else
			bar.BackgroundColor3 = CS.Theme.Error
		end
	end
end

function CS.Dashboard.Update()
	local ping = CS.Runtime.Ping
	local status, color = CS.Util.PingStatus(ping)
	local friendsOnline = CS.Friends.CountOnline()
	local friendsInServer = CS.Friends.CountInServer()

	CS.Util.Set(CS.UI.Labels.Overview,
		"Version: " .. CS.Version ..
		"\nGame: " .. tostring(game.PlaceId) ..
		"\nJobId: " .. (game.JobId ~= "" and game.JobId or "Unavailable") ..
		"\nPanel: " .. (CS.Flags.Open and "Open" or "Closed")
	)

	CS.Util.Set(CS.UI.Labels.Network,
		"Current: " .. tostring(ping) .. " ms" ..
		"\nStatus: " .. status ..
		"\nLowest: " .. tostring(CS.Runtime.LowPing or "N/A") .. " ms" ..
		"\nAverage: " .. tostring(CS.Runtime.AvgPing or "N/A") .. " ms" ..
		"\nHighest: " .. tostring(CS.Runtime.HighPing or "N/A") .. " ms",
		color
	)

	CS.Util.Set(CS.UI.Labels.FriendsSummary,
		"Friends Online: " .. tostring(friendsOnline) ..
		"\nFriends In Server: " .. tostring(friendsInServer) ..
		"\nPlayers: " .. tostring(#CS.Services.Players:GetPlayers()) .. "/" .. tostring(CS.Services.Players.MaxPlayers)
	)

	CS.Util.Set(CS.UI.Labels.Performance,
		"FPS: " .. tostring(CS.Runtime.FPS) ..
		"\nPing: " .. tostring(ping) .. " ms" ..
		"\nUI Mode: " .. (CS.Flags.Compact and "Compact" or "Full") ..
		"\nAnimations: " .. tostring(CS.Flags.Animations)
	)

	CS.Util.Set(CS.UI.Labels.Status,
		"HTTP: " .. tostring(CS.Request ~= nil) ..
		"\nClipboard: " .. tostring(setclipboard ~= nil) ..
		"\nNotifications: " .. tostring(CS.Flags.Notifications) ..
		"\nTransparency: " .. tostring(CS.Flags.Transparency)
	)

	CS.Util.Set(CS.UI.Labels.FPSPill, "FPS: " .. tostring(CS.Runtime.FPS))
	CS.Util.Set(CS.UI.Labels.PingPill, "Ping: " .. tostring(ping))
	CS.Util.Set(CS.UI.Labels.PlayersPill, "Players: " .. tostring(#CS.Services.Players:GetPlayers()) .. "/" .. tostring(CS.Services.Players.MaxPlayers))

	CS.Dashboard.PaintBars(CS.UI.Charts.Network)
	CS.Dashboard.PaintBars(CS.UI.Charts.Live)
end

function CS.RefreshAll()
	CS.Dashboard.Update()
	CS.PlayerDetails.Refresh()
	CS.PlayerDetails.UpdateSelected()
	CS.ServerBrowser.UpdateLive()
	CS.GameInfo.Load()
	CS.Friends.Update()
	pcall(function()
		CS.Friends.RefreshFriendList()
	end)
	CS.Diagnostics.Run()
end

function CS.Connect()
	CS.UI.Objects.OpenButton.MouseButton1Click:Connect(CS.UI.Toggle)
	CS.UI.Buttons.Close.MouseButton1Click:Connect(CS.UI.Toggle)

	CS.Services.Players.PlayerAdded:Connect(function(player)
		if CS.Flags.Open and CS.Flags.AutoRefreshPlayers then
			CS.PlayerDetails.Refresh()
		end

		local isFriend = false

		pcall(function()
			isFriend = CS.LocalPlayer:IsFriendsWith(player.UserId)
		end)

		if isFriend then
			CS.Friends.PushFeed("Friend joined: " .. player.DisplayName .. " (@" .. player.Name .. ")")
			CS.Notify.PlayerEvent(player, "joined", true, true)
		elseif CS.Flags.ShowNonFriendNotices then
			CS.Friends.PushFeed("Player joined: " .. player.DisplayName .. " (@" .. player.Name .. ")")
			CS.Notify.PlayerEvent(player, "joined", false, true)
		end

		CS.Friends.Update()
	end)

	CS.Services.Players.PlayerRemoving:Connect(function(player)
		if CS.Flags.Open and CS.Flags.AutoRefreshPlayers then
			CS.PlayerDetails.Refresh()
		end

		local isFriend = false

		pcall(function()
			isFriend = CS.LocalPlayer:IsFriendsWith(player.UserId)
		end)

		if isFriend then
			CS.Friends.PushFeed("Friend left: " .. player.DisplayName .. " (@" .. player.Name .. ")")
			CS.Notify.PlayerEvent(player, "left", true, false)
		elseif CS.Flags.ShowNonFriendNotices then
			CS.Friends.PushFeed("Player left: " .. player.DisplayName .. " (@" .. player.Name .. ")")
			CS.Notify.PlayerEvent(player, "left", false, false)
		end

		CS.Friends.Update()
	end)

	CS.LocalPlayer.CharacterAdded:Connect(function()
		task.wait(1)

		if CS.Flags.Open then
			CS.PlayerDetails.UpdateSelected()
			CS.Diagnostics.Run()
		end
	end)

	CS.Services.RunService.RenderStepped:Connect(function()
		CS.Runtime.Frames += 1
		CS.Settings.UpdateColorCycle()
		local now = os.clock()

		if now - CS.Runtime.LastFPS >= 1 then
			CS.Runtime.FPS = CS.Runtime.Frames
			CS.Runtime.Frames = 0
			CS.Runtime.LastFPS = now

			CS.Dashboard.UpdatePingStats()

			if CS.Flags.Open then
				CS.Dashboard.Update()
				CS.ServerBrowser.UpdateLive()
				CS.Friends.Update()

				if CS.Flags.AutoRefreshDiagnostics then
					CS.Diagnostics.Run()
				end
			end
		end

		if CS.Flags.Open then
			CS.PlayerDetails.UpdateSelected()
		end
	end)
end

function CS.Build()
	CS.UI.BuildShell()
	CS.UI.BuildPages()
	CS.Dashboard.Build()
	CS.PlayerDetails.Build()
	CS.ServerBrowser.Build()
	CS.GameInfo.Build()
	CS.Friends.Build()
	CS.Diagnostics.Build()
	CS.Settings.Build()
	CS.Utilities.Build()
end


function CS.Dashboard.UpdateOverlayLabels()
	local players=#CS.Services.Players:GetPlayers(); local maxPlayers=CS.Services.Players.MaxPlayers or 0; local ping=tostring(CS.Runtime.Ping or "?").."ms"; local fps=tostring(CS.Runtime.FPS or "?")
	CS.Util.Set(CS.UI.Labels.DashPlayers,tostring(players).."/"..tostring(maxPlayers)); CS.Util.Set(CS.UI.Labels.DashPing,ping); CS.Util.Set(CS.UI.Labels.DashFPS,fps); CS.Util.Set(CS.UI.Labels.DashClock,os.date("%H:%M:%S")); CS.Util.Set(CS.UI.Labels.DashNotif,tostring(CS.Flags.Notifications))
	CS.Util.Set(CS.UI.Labels.CurrentServerInfo,"Players: "..players.."/"..maxPlayers.." | Ping: "..ping.." | Job: "..tostring(game.JobId):sub(1,8).."..."); CS.Util.Set(CS.UI.Labels.ServerPlayerData,tostring(players).."/"..tostring(maxPlayers)); CS.Util.Set(CS.UI.Labels.ServerPingData,ping); CS.Util.Set(CS.UI.Labels.GameServerState,tostring(players).."/"..tostring(maxPlayers)); CS.Util.Set(CS.UI.Labels.UtilitySession,fps); CS.Util.Set(CS.UI.Labels.UtilityPing,ping); CS.Util.Set(CS.UI.Labels.UtilityPlayers,tostring(players))
end
local CS_OriginalDashboardUpdate = CS.Dashboard.Update
function CS.Dashboard.Update()
	if CS_OriginalDashboardUpdate then pcall(CS_OriginalDashboardUpdate) end
	CS.Dashboard.UpdateOverlayLabels()
end



--// CS 3.8.2 Organization + Connection Patch
--// Cleaner layout, calmer Settings tab, safer labels, connected buttons.
CS.Version = "3.8.2"

function CS.Util.SafeCall(fn, ...)
	if type(fn) ~= "function" then return false end
	local ok, result = pcall(fn, ...)
	if not ok then warn("CS SafeCall:", result) end
	return ok, result
end

function CS.Util.SafeSet(label, text, color)
	if label and label.Parent then
		label.Text = tostring(text or "")
		if color then label.TextColor3 = color end
	end
end

function CS.Settings.SetToggleVisual(button, state)
	if not button then return end
	button.BackgroundColor3 = state and CS.Theme.Success or CS.Theme.Card2
	button.BackgroundTransparency = state and 0.04 or 0.18
	button.TextColor3 = state and Color3.fromRGB(0, 0, 0) or CS.Theme.Text
end

function CS.Settings.SetScale(mode)
	mode = mode or "Default"
	CS.Flags.ScaleMode = mode
	local main = CS.UI.Objects.Main
	if not main then return end
	local sizeMap = {
		Compact = UDim2.new(0, 1000, 0, 600),
		Normal = UDim2.new(0, 1080, 0, 650),
		Default = UDim2.new(0, 1080, 0, 650),
		Large = UDim2.new(0, 1180, 0, 710)
	}
	local size = sizeMap[mode] or sizeMap.Default
	main.Size = size
	main.Position = UDim2.new(0.5, -math.floor(size.X.Offset / 2), 0.5, -math.floor(size.Y.Offset / 2))
end

function CS.UI.SectionTitle(parent, title, body, height)
	local card = CS.UI.OverlayCard(parent, title, "▣", height or 190)
	if body then CS.UI.OverlayText(card, 56, (height or 190) - 70, body) end
	return card
end

function CS.UI.ActionRow(parent, y, title, desc, buttonText, callback)
	local row = CS.UI.OverlayValue(parent, y, "•", title, "", desc)
	local button = CS.Util.Create("TextButton", {
		Parent = parent,
		Size = UDim2.new(0, 122, 0, 30),
		Position = UDim2.new(1, -142, 0, y + 8),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = buttonText or "Run",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 11,
		AutoButtonColor = false
	})
	CS.Util.Corner(button, 8)
	CS.Util.Stroke(button, CS.Theme.Stroke, 0.55, 1)
	button.MouseEnter:Connect(function() CS.Util.Tween(button, {BackgroundColor3 = CS.Theme.Accent}, 0.12) end)
	button.MouseLeave:Connect(function() CS.Util.Tween(button, {BackgroundColor3 = CS.Theme.Card2}, 0.12) end)
	button.MouseButton1Click:Connect(function()
		if callback then callback(button) end
	end)
	return button, row
end

function CS.UI.ToggleRow(parent, y, title, desc, state, callback)
	local row = CS.UI.OverlayValue(parent, y, "•", title, state and "ON" or "OFF", desc)
	local switch = CS.Settings.MakeSwitch(parent:FindFirstChild("RowProxy") or parent, state, function(value)
		CS.Util.SafeSet(row, value and "ON" or "OFF", value and CS.Theme.Success or CS.Theme.Muted)
		if callback then callback(value) end
	end)
	switch.Button.Parent = parent
	switch.Button.Position = UDim2.new(1, -74, 0, y + 10)
	return switch, row
end


function CS.UI.HexColorRow(parent, y, title, desc, hexText, applyCallback)
	local row = CS.UI.OverlayValue(parent, y, "•", title, hexText or "#FFFFFF", desc)
	local box = CS.Util.Create("TextBox", {
		Parent = parent,
		Size = UDim2.new(0, 104, 0, 30),
		Position = UDim2.new(1, -210, 0, y + 8),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = hexText or "#FFFFFF",
		PlaceholderText = "#RRGGBB",
		TextColor3 = CS.Theme.Text,
		PlaceholderColor3 = CS.Theme.Muted,
		Font = Enum.Font.GothamBold,
		TextSize = 11,
		ClearTextOnFocus = false
	})
	CS.Util.Corner(box, 8)
	CS.Util.Stroke(box, CS.Theme.Stroke, 0.55, 1)

	local apply = CS.Util.Create("TextButton", {
		Parent = parent,
		Size = UDim2.new(0, 78, 0, 30),
		Position = UDim2.new(1, -94, 0, y + 8),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = "Apply",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 11,
		AutoButtonColor = false
	})
	CS.Util.Corner(apply, 8)
	CS.Util.Stroke(apply, CS.Theme.Stroke, 0.55, 1)

	local swatch = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(0, 14, 0, 14),
		Position = UDim2.new(1, -226, 0, y + 16),
		BackgroundColor3 = CS.Settings.HexToColor(hexText or "#FFFFFF") or CS.Theme.Accent,
		BorderSizePixel = 0
	})
	CS.Util.Corner(swatch, 999)

	local function applyNow()
		local color = CS.Settings.HexToColor(box.Text)
		if not color then
			CS.Notify.Push("Theme", "Invalid hex for " .. tostring(title) .. ". Use #RRGGBB.", CS.Theme.Warning)
			return
		end
		local normalized = CS.Settings.ColorToHex(color)
		box.Text = normalized
		swatch.BackgroundColor3 = color
		CS.Util.SafeSet(row, normalized, color)
		if applyCallback then applyCallback(color, normalized, box) end
		CS.Settings.ApplyVisuals()
		CS.Settings.Save(true)
	end

	apply.MouseButton1Click:Connect(applyNow)
	box.FocusLost:Connect(function(enterPressed)
		if enterPressed then applyNow() end
	end)

	return box, apply, row
end

function CS.Settings.ApplyThemePreset(name)
	if name == "Blue CS" then
		CS.Theme.Background = Color3.fromRGB(7, 8, 12)
		CS.Theme.Panel = Color3.fromRGB(14, 16, 25)
		CS.Theme.Card = Color3.fromRGB(25, 25, 36)
		CS.Theme.Card2 = Color3.fromRGB(35, 36, 52)
		CS.Theme.Accent = Color3.fromRGB(31, 198, 250)
		CS.Theme.Stroke = Color3.fromRGB(0, 190, 255)
		CS.Theme.NotificationOutline = CS.Theme.Accent
	elseif name == "Purple" then
		CS.Theme.Accent = Color3.fromRGB(150, 95, 255)
		CS.Theme.Stroke = Color3.fromRGB(150, 95, 255)
		CS.Theme.NotificationOutline = CS.Theme.Accent
	elseif name == "Red" then
		CS.Theme.Background = Color3.fromRGB(8, 6, 8)
		CS.Theme.Panel = Color3.fromRGB(16, 10, 13)
		CS.Theme.Card = Color3.fromRGB(24, 16, 20)
		CS.Theme.Card2 = Color3.fromRGB(34, 22, 28)
		CS.Theme.Accent = Color3.fromRGB(255, 55, 70)
		CS.Theme.Stroke = Color3.fromRGB(255, 55, 70)
		CS.Theme.NotificationOutline = CS.Theme.Accent
	end
	CS.Settings.ApplyVisuals()
	CS.Settings.Save(true)
	CS.Notify.Push("Theme", name .. " preset applied.", CS.Theme.Info)
end

function CS.Settings.Build()
	local page = CS.UI.Pages["Settings"]
	CS.Util.Clear(page, true)

	local left = CS.Util.Scroll(page)
	left.Size = UDim2.new(0.5, -6, 1, 0)
	left.Position = UDim2.new(0, 0, 0, 0)

	local right = CS.Util.Scroll(page)
	right.Size = UDim2.new(0.5, -6, 1, 0)
	right.Position = UDim2.new(0.5, 6, 0, 0)

	local interface = CS.UI.OverlayCard(left, "Interface", "▣", 250)
	CS.UI.ActionRow(interface, 58, "UI Scale", "Cycle compact, normal, and large layouts.", CS.Flags.ScaleMode or "Default", function(btn)
		local nextMode = "Normal"
		if CS.Flags.ScaleMode == "Normal" or CS.Flags.ScaleMode == "Default" then nextMode = "Large" elseif CS.Flags.ScaleMode == "Large" then nextMode = "Compact" end
		CS.Settings.SetScale(nextMode)
		btn.Text = nextMode
		CS.Settings.Save(true)
		CS.Notify.Push("Settings", "UI scale set to " .. nextMode .. ".", CS.Theme.Info)
	end)
	CS.UI.ActionRow(interface, 112, "Glass Strength", "Cleaner background visibility presets.", "Medium", function(btn)
		local presets = {Low = 0.30, Medium = 0.54, High = 0.70}
		local nextName = btn.Text == "Low" and "Medium" or (btn.Text == "Medium" and "High" or "Low")
		btn.Text = nextName
		CS.Flags.Transparency = presets[nextName]
		CS.Flags.PanelTransparency = math.clamp(CS.Flags.Transparency - 0.12, 0, 1)
		CS.Flags.CardTransparency = math.clamp(CS.Flags.Transparency - 0.35, 0, 1)
		CS.Settings.ApplyVisuals()
		CS.Settings.Save(true)
	end)
	CS.UI.ToggleRow(interface, 166, "Animations", "Smooth hover and page feedback.", CS.Flags.Animations, function(value)
		CS.Flags.Animations = value; CS.Settings.Save(true)
	end)

	local behavior = CS.UI.OverlayCard(left, "Behavior", "⚙", 250)
	CS.UI.ToggleRow(behavior, 58, "Notifications", "Show join, leave, and system notices.", CS.Flags.Notifications, function(value)
		CS.Flags.Notifications = value; CS.Settings.Save(true)
	end)
	CS.UI.ToggleRow(behavior, 112, "Player Notices", "Show notices for non-friends too.", CS.Flags.ShowNonFriendNotices, function(value)
		CS.Flags.ShowNonFriendNotices = value; CS.Settings.Save(true)
	end)
	CS.UI.ToggleRow(behavior, 166, "Friend Sounds", "Play sounds for friend actions.", CS.Flags.FriendSounds, function(value)
		CS.Flags.FriendSounds = value; CS.Settings.Save(true)
	end)

	local presets = CS.UI.OverlayCard(left, "Theme Presets", "✦", 300)
	CS.UI.ActionRow(presets, 58, "Blue CS", "Clean cyan/blue overlay theme.", "Apply", function() CS.Settings.ApplyThemePreset("Blue CS") end)
	CS.UI.ActionRow(presets, 112, "Purple", "Dark purple accent preset.", "Apply", function() CS.Settings.ApplyThemePreset("Purple") end)
	CS.UI.ActionRow(presets, 166, "Red", "Black and red accent preset.", "Apply", function() CS.Settings.ApplyThemePreset("Red") end)
	CS.UI.ActionRow(presets, 220, "Reset Theme", "Restore default colors and transparency.", "Reset", function() CS.Settings.ResetThemeDefaults() end)

	local custom = CS.UI.OverlayCard(left, "Custom Hex / RGB", "#", 420)
	CS.UI.HexColorRow(custom, 58, "Accent", "Main active color. Hex format: #RRGGBB.", CS.Settings.ColorToHex(CS.Theme.Accent), function(color)
		CS.Theme.Accent = color
		CS.Theme.Accent2 = color
		CS.Theme.Accent3 = color
	end)
	CS.UI.HexColorRow(custom, 112, "Background", "Main shell, panels, and dark overlay tone.", CS.Settings.ColorToHex(CS.Theme.Background), function(color)
		CS.Theme.Background = color
		CS.Theme.Background2 = color
		CS.Theme.Panel = color
		CS.Theme.Panel2 = color
	end)
	CS.UI.HexColorRow(custom, 166, "Cards", "Card surface color inside pages.", CS.Settings.ColorToHex(CS.Theme.Card), function(color)
		CS.Theme.Card = color
		CS.Theme.Card2 = color
	end)
	CS.UI.HexColorRow(custom, 220, "Outlines", "Borders, rails, and section strokes.", CS.Settings.ColorToHex(CS.Theme.Stroke), function(color)
		CS.Theme.Stroke = color
		CS.Theme.StrokeSoft = color
	end)
	CS.UI.HexColorRow(custom, 274, "Notifications", "Notification border/accent color.", CS.Settings.ColorToHex(CS.Theme.NotificationOutline), function(color)
		CS.Theme.NotificationOutline = color
		CS.Theme.Info = color
	end)
	CS.UI.ActionRow(custom, 328, "Open Full Picker", "Advanced color picker cards are available below.", "Show", function()
		CS.Notify.Push("Settings", "Scroll lower for full picker controls.", CS.Theme.Info)
	end)

	local rgb = CS.UI.OverlayCard(right, "RGB / Color Cycle", "◉", 300)
	CS.UI.ToggleRow(rgb, 58, "Enable RGB", "Animated accent and border color cycle.", CS.Flags.ColorCycle, function(value)
		CS.Settings.SetColorCycleEnabled(value)
	end)
	CS.UI.HexColorRow(rgb, 112, "RGB Color A", "First cycle color.", CS.Flags.ColorCycleA or "#4E73FF", function(_, hex)
		CS.Flags.ColorCycleA = hex
	end)
	CS.UI.HexColorRow(rgb, 166, "RGB Color B", "Second cycle color.", CS.Flags.ColorCycleB or "#FF3C7A", function(_, hex)
		CS.Flags.ColorCycleB = hex
	end)
	CS.UI.ActionRow(rgb, 220, "Speed", "Cycle speed: 1 slow, 10 fast.", tostring(CS.Flags.ColorCycleSpeedLevel or 3), function(btn)
		local nextLevel = (tonumber(btn.Text) or 3) + 1
		if nextLevel > 10 then nextLevel = 1 end
		CS.Flags.ColorCycleSpeedLevel = nextLevel
		CS.Flags.ColorCycleSpeed = CS.Settings.SpeedLevelToInternal(nextLevel)
		btn.Text = tostring(nextLevel)
		CS.Settings.Save(true)
	end)

	local maintenance = CS.UI.OverlayCard(right, "Maintenance", "☰", 300)
	CS.UI.ActionRow(maintenance, 58, "Refresh UI", "Rebuild all pages and update live labels.", "Refresh", function()
		CS.RefreshAll(); CS.Settings.ApplyVisuals(); CS.Notify.Push("Settings", "UI refreshed.", CS.Theme.Success)
	end)
	CS.UI.ActionRow(maintenance, 112, "Save Config", "Save current menu settings.", "Save", function()
		local ok = CS.Settings.Save(false)
		CS.Notify.Push("Settings", ok and "Settings saved." or "Save unavailable.", ok and CS.Theme.Success or CS.Theme.Warning)
	end)
	CS.UI.ActionRow(maintenance, 166, "Load Config", "Reload saved menu settings.", "Load", function()
		local ok = CS.Settings.Load(); CS.Settings.ApplyVisuals()
		CS.Notify.Push("Settings", ok and "Settings loaded." or "No saved settings found.", ok and CS.Theme.Info or CS.Theme.Warning)
	end)
	CS.UI.ActionRow(maintenance, 220, "Test Notice", "Send one sample notification.", "Test", function()
		CS.Notify.Push("CS Test", "Notification system is connected.", CS.Theme.Info)
	end)

	local live = CS.UI.OverlayCard(right, "Live Overlay", "◎", 220)
	CS.UI.Labels.SettingsLivePreview = CS.UI.OverlayText(live, 58, 135,
		"FPS: " .. tostring(CS.Runtime.FPS) ..
		"\nPing: " .. tostring(CS.Runtime.Ping) .. " ms" ..
		"\nPlayers: " .. tostring(#CS.Services.Players:GetPlayers()) .. "/" .. tostring(CS.Services.Players.MaxPlayers) ..
		"\nAccent: " .. CS.Settings.ColorToHex(CS.Theme.Accent)
	)

	local info = CS.UI.OverlayCard(right, "Settings Info", "✓", 170)
	CS.UI.OverlayText(info, 58, 90, "Color controls are back, but kept in compact hex rows so the tab stays cleaner. Use presets for fast changes or enter exact hex/RGB-style values like #1FC6FA.")

	CS.Settings.MakeColorEditor(left, "Full Accent Picker", "Accent", CS.Theme.Accent, function(color, hex)
		CS.Theme.Accent = color
		CS.Theme.Accent2 = color
		CS.Theme.Accent3 = color
		CS.Settings.ApplyVisuals()
		CS.Settings.Save(true)
		CS.Notify.Push("Theme", "Accent changed to " .. hex, CS.Theme.Info)
	end)

	CS.Settings.MakeColorEditor(right, "Full Outline Picker", "Outline", CS.Theme.Stroke, function(color, hex)
		CS.Theme.Stroke = color
		CS.Theme.StrokeSoft = color
		CS.Settings.ApplyVisuals()
		CS.Settings.Save(true)
		CS.Notify.Push("Theme", "Outline changed to " .. hex, CS.Theme.Info)
	end)
end

function CS.PlayerDetails.RefreshList()
	return CS.PlayerDetails.Refresh()
end

function CS.PlayerDetails.Select(player)
	CS.Runtime.SelectedPlayer = player or CS.LocalPlayer
	return CS.PlayerDetails.UpdateSelected()
end

local CS_OriginalPlayerDetailsBuild_382 = CS.PlayerDetails.Build
function CS.PlayerDetails.Build()
	CS_OriginalPlayerDetailsBuild_382()
	if CS.UI.Objects.PlayerList and not CS.UI.Objects.PlayerListScroll then
		CS.UI.Objects.PlayerListScroll = CS.UI.Objects.PlayerList
	end
	CS.PlayerDetails.Refresh()
	CS.PlayerDetails.Select(CS.Runtime.SelectedPlayer or CS.LocalPlayer)
end

function CS.PlayerDetails.UpdateSelected()
	local player = CS.PlayerDetails.GetSelected()
	local humanoid = CS.Util.Humanoid(player)
	local root = CS.Util.Root(player)
	local myRoot = CS.Util.Root(CS.LocalPlayer)

	if CS.UI.Objects.SelectedAvatar then
		pcall(function()
			CS.UI.Objects.SelectedAvatar.Image = CS.Services.Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.AvatarThumbnail, Enum.ThumbnailSize.Size420x420)
		end)
	end

	CS.Util.SafeSet(CS.UI.Labels.SelectedName, player.DisplayName)
	CS.Util.SafeSet(CS.UI.Labels.SelectedUser, "@" .. player.Name)
	CS.Util.SafeSet(CS.UI.Labels.SelectedDistance, (root and myRoot) and (tostring(math.floor((root.Position - myRoot.Position).Magnitude)) .. " studs") or "Unavailable")

	local friendState = player == CS.LocalPlayer and "You" or "No"
	if player ~= CS.LocalPlayer then pcall(function() if CS.LocalPlayer:IsFriendsWith(player.UserId) then friendState = "Yes" end end) end
	CS.Util.SafeSet(CS.UI.Labels.AccountInfo, "Display Name: " .. player.DisplayName .. "\nUsername: @" .. player.Name .. "\nUserId: " .. tostring(player.UserId) .. "\nAccount Age: " .. tostring(player.AccountAge) .. " days\nMembership: " .. player.MembershipType.Name .. "\nFriend: " .. friendState)
	CS.Util.SafeSet(CS.UI.Labels.CharacterInfo, humanoid and ("Health: " .. math.floor(humanoid.Health) .. " / " .. math.floor(humanoid.MaxHealth) .. "\nState: " .. humanoid:GetState().Name .. "\nRig Type: " .. humanoid.RigType.Name .. "\nTeam: " .. (player.Team and player.Team.Name or "None")) or "Character humanoid unavailable.")
end

function CS.ServerBrowser.Rejoin()
	CS.Notify.Push("Server", "Rejoining current server...", CS.Theme.Info)
	CS.Services.TeleportService:TeleportToPlaceInstance(game.PlaceId, game.JobId, CS.LocalPlayer)
end

function CS.ServerBrowser.Hop()
	CS.Notify.Push("Server", "Searching for another public server...", CS.Theme.Info)
	pcall(function() CS.ServerBrowser.Fetch() end)
	for _, server in ipairs(CS.Runtime.ServerData or {}) do
		if server.id and server.id ~= game.JobId and tonumber(server.playing or 0) < tonumber(server.maxPlayers or 0) then
			CS.Services.TeleportService:TeleportToPlaceInstance(game.PlaceId, server.id, CS.LocalPlayer)
			return
		end
	end
	CS.Services.TeleportService:Teleport(game.PlaceId, CS.LocalPlayer)
end

local CS_OriginalServerBrowserBuild_382 = CS.ServerBrowser.Build
function CS.ServerBrowser.Build()
	CS_OriginalServerBrowserBuild_382()
	if CS.UI.Objects.ServerList and not CS.UI.Objects.ServerListScroll then
		CS.UI.Objects.ServerListScroll = CS.UI.Objects.ServerList
	end
	CS.ServerBrowser.Rebuild(CS.Runtime.ServerData or {})
	CS.ServerBrowser.UpdateLive()
end

function CS.ServerBrowser.Fetch()
	if not CS.UI.Objects.ServerListScroll and CS.UI.Objects.ServerList then CS.UI.Objects.ServerListScroll = CS.UI.Objects.ServerList end
	if not CS.Request then
		CS.Notify.Push("Server Browser", "HTTP request unavailable in this environment.", CS.Theme.Warning)
		CS.ServerBrowser.Rebuild({})
		return
	end
	CS.Util.SafeSet(CS.UI.Labels.CurrentServerInfo, "Fetching public servers...")
	local success, response = pcall(function()
		return CS.Request({Url = "https://[Log in to view URL]" .. tostring(game.PlaceId) .. "/servers/Public?sortOrder=Asc&limit=100", Method = "GET"})
	end)
	if not success or not response or not response.Body then
		CS.Notify.Push("Server Browser", "Server fetch failed.", CS.Theme.Warning)
		return
	end
	local decoded
	local ok = pcall(function() decoded = CS.Services.HttpService:JSONDecode(response.Body) end)
	if not ok or not decoded or not decoded.data then
		CS.Notify.Push("Server Browser", "Invalid server response.", CS.Theme.Warning)
		return
	end
	CS.Runtime.ServerData = decoded.data
	CS.Runtime.LastServerFetch = os.clock()
	CS.ServerBrowser.Rebuild(CS.Runtime.ServerData)
	CS.Notify.Push("Server Browser", "Loaded " .. tostring(#decoded.data) .. " public servers.", CS.Theme.Success)
end

function CS.ServerBrowser.UpdateLive()
	local ping = CS.Runtime.Ping or 0
	local status = (select(1, CS.Util.PingStatus(ping)))
	local players = #CS.Services.Players:GetPlayers()
	local maxPlayers = CS.Services.Players.MaxPlayers or 0
	CS.Util.SafeSet(CS.UI.Labels.CurrentServerInfo, "Players: " .. players .. "/" .. maxPlayers .. "\nPing: " .. tostring(ping) .. " ms\nJob: " .. tostring(game.JobId):sub(1, 18) .. "...")
	CS.Util.SafeSet(CS.UI.Labels.ServerPingData, tostring(ping) .. " ms / " .. tostring(status))
	CS.Util.SafeSet(CS.UI.Labels.ServerPlayerData, tostring(players) .. "/" .. tostring(maxPlayers))
end

function CS.GameInfo.Load()
	local info = {Name = "Unavailable", Creator = "Unavailable"}
	pcall(function()
		local data = CS.Services.MarketplaceService:GetProductInfo(game.PlaceId)
		info.Name = tostring(data.Name or "Unavailable")
		info.Creator = data.Creator and tostring(data.Creator.Name) or "Unavailable"
	end)
	CS.Util.SafeSet(CS.UI.Labels.GameName, info.Name)
	CS.Util.SafeSet(CS.UI.Labels.GameCreator, info.Creator)
	CS.Util.SafeSet(CS.UI.Labels.GamePlaceId, tostring(game.PlaceId))
	CS.Util.SafeSet(CS.UI.Labels.GameJobId, game.JobId ~= "" and game.JobId:sub(1, 12) .. "..." or "Unavailable")
	CS.Util.SafeSet(CS.UI.Labels.GameServerState, tostring(#CS.Services.Players:GetPlayers()) .. "/" .. tostring(CS.Services.Players.MaxPlayers))
	CS.Util.SafeSet(CS.UI.Labels.GameSupport, "HTTP: " .. tostring(CS.Request ~= nil) .. "\nTeleport: true\nMarketplace: Loaded")
	CS.Friends.UpdateGameFriends()
end

function CS.Friends.UpdateGameFriends()
	local sameGame = {}
	local friends = CS.Runtime.FriendsOnlineCache or CS.Friends.GetOnlineFriends()
	for _, friendData in ipairs(friends) do
		local placeId = tonumber(friendData.PlaceId or friendData.PlaceID or 0)
		if placeId == game.PlaceId then table.insert(sameGame, friendData) end
	end
	if CS.UI.Labels.GameFriends then
		if #sameGame == 0 then
			CS.UI.Labels.GameFriends.Text = "No online friends detected in this same game through Roblox online-friend data."
		else
			local lines = {"Friends in this game, possibly different server:"}
			for _, friendData in ipairs(sameGame) do
				table.insert(lines, tostring(friendData.DisplayName or friendData.UserName or "Unknown") .. "  @" .. tostring(friendData.UserName or "Unknown"))
				table.insert(lines, "Location: " .. tostring(friendData.LastLocation or "Unknown"))
				table.insert(lines, "Join data: " .. ((friendData.GameId or friendData.JobId) and "available" or "limited"))
			end
			CS.UI.Labels.GameFriends.Text = table.concat(lines, "\n")
		end
	end
end

function CS.Diagnostics.Run()
	local char = CS.LocalPlayer.Character
	local humanoid = char and char:FindFirstChildOfClass("Humanoid")
	local root = char and char:FindFirstChild("HumanoidRootPart")
	local warnings = {}
	if not CS.Request then table.insert(warnings, "HTTP request unavailable; public server fetching may not work.") end
	if not setclipboard then table.insert(warnings, "Clipboard unavailable; copy buttons may not work.") end
	if not root then table.insert(warnings, "Character root is not loaded yet.") end
	CS.Util.SafeSet(CS.UI.Labels.DiagnosticsClient, "FPS: " .. tostring(CS.Runtime.FPS) .. "\nPing: " .. tostring(CS.Runtime.Ping) .. " ms\nPlayers: " .. tostring(#CS.Services.Players:GetPlayers()) .. "/" .. tostring(CS.Services.Players.MaxPlayers) .. "\nCharacter: " .. tostring(char ~= nil) .. "\nHumanoid: " .. tostring(humanoid ~= nil) .. "\nHumanoidRootPart: " .. tostring(root ~= nil) .. "\nHTTP Request: " .. tostring(CS.Request ~= nil) .. "\nClipboard: " .. tostring(setclipboard ~= nil))
	CS.Util.SafeSet(CS.UI.Labels.DiagnosticsNotes, #warnings == 0 and "No major warnings detected." or table.concat(warnings, "\n"), #warnings == 0 and CS.Theme.Success or CS.Theme.Warning)
end

function CS.Dashboard.UpdateOverlayLabels()
	local players = #CS.Services.Players:GetPlayers()
	local maxPlayers = CS.Services.Players.MaxPlayers or 0
	local ping = tostring(CS.Runtime.Ping or "?") .. "ms"
	local fps = tostring(CS.Runtime.FPS or "?")
	CS.Util.SafeSet(CS.UI.Labels.DashPlayers, tostring(players) .. "/" .. tostring(maxPlayers))
	CS.Util.SafeSet(CS.UI.Labels.DashPing, ping)
	CS.Util.SafeSet(CS.UI.Labels.DashFPS, fps)
	CS.Util.SafeSet(CS.UI.Labels.DashClock, os.date("%H:%M:%S"))
	CS.Util.SafeSet(CS.UI.Labels.DashNotif, tostring(CS.Flags.Notifications))
	CS.Util.SafeSet(CS.UI.Labels.CurrentServerInfo, "Players: " .. players .. "/" .. maxPlayers .. " | Ping: " .. ping .. " | Job: " .. tostring(game.JobId):sub(1, 8) .. "...")
	CS.Util.SafeSet(CS.UI.Labels.ServerPlayerData, tostring(players) .. "/" .. tostring(maxPlayers))
	CS.Util.SafeSet(CS.UI.Labels.ServerPingData, ping)
	CS.Util.SafeSet(CS.UI.Labels.GameServerState, tostring(players) .. "/" .. tostring(maxPlayers))
	CS.Util.SafeSet(CS.UI.Labels.UtilitySession, fps)
	CS.Util.SafeSet(CS.UI.Labels.UtilityPing, ping)
	CS.Util.SafeSet(CS.UI.Labels.UtilityPlayers, tostring(players))
	if CS.UI.Labels.SettingsLivePreview then
		CS.UI.Labels.SettingsLivePreview.Text = "FPS: " .. fps .. "\nPing: " .. ping .. "\nPlayers: " .. tostring(players) .. "/" .. tostring(maxPlayers) .. "\nCurrent Page: " .. tostring(CS.Runtime.CurrentPage or "Dashboard")
	end
end

local CS_OriginalDashboardUpdate_382 = CS.Dashboard.Update
function CS.Dashboard.Update()
	if CS_OriginalDashboardUpdate_382 then pcall(CS_OriginalDashboardUpdate_382) end
	CS.Dashboard.UpdateOverlayLabels()
end

function CS.Settings.ApplyVisuals()
	CS.Theme.Accent2 = CS.Theme.Accent
	CS.Theme.Accent3 = CS.Theme.Accent
	if CS.UI.Objects.Main then CS.UI.Objects.Main.BackgroundColor3 = CS.Theme.Background; CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency end
	if CS.UI.Objects.Sidebar then CS.UI.Objects.Sidebar.BackgroundColor3 = CS.Theme.Panel; CS.UI.Objects.Sidebar.BackgroundTransparency = CS.Flags.PanelTransparency end
	if CS.UI.Objects.Content then CS.UI.Objects.Content.BackgroundColor3 = CS.Theme.Panel; CS.UI.Objects.Content.BackgroundTransparency = CS.Flags.PanelTransparency end
	if CS.UI.Objects.AccentRail then CS.UI.Objects.AccentRail.BackgroundColor3 = CS.Theme.Accent end
	if CS.UI.Objects.GUI then
		for _, obj in ipairs(CS.UI.Objects.GUI:GetDescendants()) do
			if obj:IsA("UIStroke") then obj.Color = CS.Theme.Stroke end
		end
	end
	for pageName, tab in pairs(CS.UI.Tabs) do
		local selected = CS.UI.Pages[pageName] and CS.UI.Pages[pageName].Visible
		tab.BackgroundColor3 = selected and CS.Theme.Accent or CS.Theme.Card
		tab.BackgroundTransparency = selected and 0.10 or 0.18
	end
end

function CS.Start()
	CS.Settings.Load()
	CS.Build()
	CS.Settings.ApplyVisuals()
	CS.Settings.SetScale(CS.Flags.ScaleMode or "Default")
	CS.Connect()
	CS.Dashboard.UpdatePingStats()
	CS.GameInfo.Load()
	CS.PlayerDetails.Refresh()
	CS.ServerBrowser.Rebuild(CS.Runtime.ServerData or {})
	CS.Friends.Update()
	pcall(function() CS.Friends.RefreshFriendList() end)
	CS.Diagnostics.Run()
	CS.Flags.ExampleNotification = false
	CS.UI.SwitchPage("Dashboard")
	CS.Notify.Push("CS Loaded", "Central Settings v" .. CS.Version .. " is ready.", CS.Theme.Success)
	print("CS | Central Settings v" .. CS.Version .. " loaded.")
end




--// =========================================================




--// =========================================================
--// CS v3.8.9 OUTLINE-ONLY RGB + COLOR SWATCH PATCH
--// Inserted before CS.Start().
--// =========================================================

CS.Version = "3.8.9"
CS.Config.Version = "3.8.9"

CS.Runtime.FPSHistory = CS.Runtime.FPSHistory or {}
CS.Runtime.Shutdown = false
CS.Runtime.ManagedConnections = CS.Runtime.ManagedConnections or {}
CS.Runtime.RGBRotation = 0
CS.UI.LiveCharts = CS.UI.LiveCharts or {}
CS.UI.RGBGradients = CS.UI.RGBGradients or {}
CS.RGB = CS.RGB or {}

function CS.Track(connection)
	if connection then
		table.insert(CS.Runtime.ManagedConnections, connection)
	end
	return connection
end

function CS.Shutdown()
	CS.Runtime.Shutdown = true

	for _, connection in ipairs(CS.Runtime.ManagedConnections or {}) do
		pcall(function()
			if connection and connection.Disconnect then
				connection:Disconnect()
			end
		end)
	end
	CS.Runtime.ManagedConnections = {}

	for _, connection in ipairs(CS.UI.Connections or {}) do
		pcall(function()
			if connection and connection.Disconnect then
				connection:Disconnect()
			end
		end)
	end
	CS.UI.Connections = {}

	pcall(function()
		if CS.Runtime.HighlightTarget then
			CS.Runtime.HighlightTarget:Destroy()
			CS.Runtime.HighlightTarget = nil
		end
	end)

	pcall(function()
		if CS.Runtime.HighlightDistanceLabel then
			CS.Runtime.HighlightDistanceLabel:Destroy()
			CS.Runtime.HighlightDistanceLabel = nil
		end
	end)

	pcall(function()
		if CS.UI.Objects.GUI then
			CS.UI.Objects.GUI:Destroy()
		end
	end)

	print("CS | Shutdown complete.")
end

function CS.LayoutBig()
	local main = CS.UI.Objects.Main
	local sidebar = CS.UI.Objects.Sidebar
	local content = CS.UI.Objects.Content

	if main then
		main.Size = UDim2.new(0, 1280, 0, 740)
		main.Position = UDim2.new(0.5, -640, 0.5, -370)
		main.ClipsDescendants = true
	end

	if sidebar then
		sidebar.Size = UDim2.new(0, 250, 1, -96)
		sidebar.Position = UDim2.new(0, 20, 0, 80)
		sidebar.ClipsDescendants = true
	end

	if content then
		content.Size = UDim2.new(1, -305, 1, -96)
		content.Position = UDim2.new(0, 285, 0, 80)
		content.ClipsDescendants = true
	end
end

function CS.CleanTextAndBadVisuals()
	local gui = CS.UI.Objects.GUI
	if not gui then return end

	for _, obj in ipairs(gui:GetDescendants()) do
		if obj.Name == "CornerGlow"
			or obj.Name == "RealCloseButton"
			or obj.Name == "SoftCornerGlow"
			or obj.Name == "FullClose"
			or obj.Name == "CSFullCloseButton"
			or obj.Name == "CSShutdownButton" then
			pcall(function()
				obj:Destroy()
			end)
		end

		if obj:IsA("ImageLabel") and obj.Image == "rbxassetid://5028857084" then
			pcall(function()
				obj:Destroy()
			end)
		end
	end

	for _, obj in ipairs(gui:GetDescendants()) do
		if obj:IsA("TextLabel") or obj:IsA("TextButton") or obj:IsA("TextBox") then
			obj.TextStrokeTransparency = 1

			local text = tostring(obj.Text or "")
			local parentName = obj.Parent and tostring(obj.Parent.Name or "") or ""

			-- Keep normal readable text. RGB is never applied to labels/icons/buttons.
			if obj.Name == "VersionBadge" then
				obj.TextColor3 = CS.Theme.Text
			elseif parentName == "PillHolder" or text:find("FPS:") or text:find("Ping:") or text:find("Players:") then
				obj.TextColor3 = CS.Theme.Text
			elseif obj:IsA("TextButton") and obj.Name ~= "CSShutdownButton" then
				obj.TextColor3 = CS.Theme.Text
			elseif obj:IsA("TextBox") then
				obj.TextColor3 = CS.Theme.Text
			else
				obj.TextColor3 = CS.Theme.Text
			end

			local gradient = obj:FindFirstChildOfClass("UIGradient")
			if gradient then
				gradient.Enabled = false
			end
		end

		-- Remove gradients from non-stroke objects. RGB must stay outline-only.
		if obj:IsA("Frame") or obj:IsA("ImageLabel") or obj:IsA("TextButton") then
			local gradient = obj:FindFirstChildOfClass("UIGradient")
			if gradient and gradient.Name == "CSRGBCircleGradient" then
				gradient:Destroy()
			end
		end
	end
end

function CS.AddCloseAndShutdown()
	local main = CS.UI.Objects.Main
	if not main then return end

	local oldClose = main:FindFirstChild("CSFullCloseButton")
	if oldClose then oldClose:Destroy() end

	local oldShutdown = main:FindFirstChild("CSShutdownButton")
	if oldShutdown then oldShutdown:Destroy() end

	local close = CS.Util.Create("TextButton", {
		Parent = main,
		Name = "CSFullCloseButton",
		Size = UDim2.new(0, 88, 0, 36),
		Position = UDim2.new(1, -212, 0, 16),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = "Close",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 13,
		AutoButtonColor = true,
		ZIndex = 200
	})
	CS.Util.Corner(close, 12)
	CS.Util.Stroke(close, CS.Theme.Accent, 0.25, 1)

	close.MouseButton1Click:Connect(function()
		CS.Flags.Open = false
		if CS.UI.Objects.Main then CS.UI.Objects.Main.Visible = false end
		if CS.UI.Objects.OpenButton then CS.UI.Objects.OpenButton.Text = "Open CS" end
	end)

	local shutdown = CS.Util.Create("TextButton", {
		Parent = main,
		Name = "CSShutdownButton",
		Size = UDim2.new(0, 112, 0, 36),
		Position = UDim2.new(1, -118, 0, 16),
		BackgroundColor3 = CS.Theme.Error,
		BackgroundTransparency = 0.05,
		BorderSizePixel = 0,
		Text = "Shutdown",
		TextColor3 = Color3.fromRGB(255, 255, 255),
		Font = Enum.Font.GothamBold,
		TextSize = 13,
		AutoButtonColor = true,
		ZIndex = 200
	})
	CS.Util.Corner(shutdown, 12)
	CS.Util.Stroke(shutdown, CS.Theme.Error, 0.10, 1)

	shutdown.MouseButton1Click:Connect(function()
		CS.Shutdown()
	end)
end

function CS.RGB.SetOutlineOnly(enabled)
	local gui = CS.UI.Objects.GUI
	if not gui then return end

	CS.UI.RGBGradients = CS.UI.RGBGradients or {}

	for _, obj in ipairs(gui:GetDescendants()) do
		if obj:IsA("UIStroke") then
			if enabled then
				local gradient = obj:FindFirstChild("CSRGBCircleGradient")
				if not gradient then
					gradient = Instance.new("UIGradient")
					gradient.Name = "CSRGBCircleGradient"
					gradient.Parent = obj
				end

				local colorA = CS.Settings.HexToColor(CS.Flags.ColorCycleA) or Color3.fromRGB(255, 0, 215)
				local colorB = CS.Settings.HexToColor(CS.Flags.ColorCycleB) or Color3.fromRGB(0, 226, 255)

				gradient.Color = ColorSequence.new({
					ColorSequenceKeypoint.new(0.00, colorA),
					ColorSequenceKeypoint.new(0.25, colorB),
					ColorSequenceKeypoint.new(0.50, colorA),
					ColorSequenceKeypoint.new(0.75, colorB),
					ColorSequenceKeypoint.new(1.00, colorA)
				})

				gradient.Enabled = true
				obj.Color = Color3.fromRGB(255, 255, 255)
				obj.Transparency = math.min(obj.Transparency, 0.25)
				obj.Thickness = math.max(obj.Thickness, 1.2)

				table.insert(CS.UI.RGBGradients, gradient)
			else
				local gradient = obj:FindFirstChild("CSRGBCircleGradient")
				if gradient then
					gradient:Destroy()
				end

				obj.Color = CS.Theme.Stroke
				obj.Transparency = 0.36
				obj.Thickness = 1
			end
		end
	end

	CS.CleanTextAndBadVisuals()
end

function CS.RGB.UpdateCircle()
	if not CS.Flags.ColorCycle then
		return
	end

	CS.Runtime.RGBRotation = (CS.Runtime.RGBRotation + ((CS.Flags.ColorCycleSpeedLevel or 3) * 0.8)) % 360

	local colorA = CS.Settings.HexToColor(CS.Flags.ColorCycleA) or Color3.fromRGB(255, 0, 215)
	local colorB = CS.Settings.HexToColor(CS.Flags.ColorCycleB) or Color3.fromRGB(0, 226, 255)

	if CS.UI.Objects.GUI then
		for _, stroke in ipairs(CS.UI.Objects.GUI:GetDescendants()) do
			if stroke:IsA("UIStroke") then
				local gradient = stroke:FindFirstChild("CSRGBCircleGradient")

				if not gradient then
					gradient = Instance.new("UIGradient")
					gradient.Name = "CSRGBCircleGradient"
					gradient.Parent = stroke
				end

				gradient.Color = ColorSequence.new({
					ColorSequenceKeypoint.new(0.00, colorA),
					ColorSequenceKeypoint.new(0.25, colorB),
					ColorSequenceKeypoint.new(0.50, colorA),
					ColorSequenceKeypoint.new(0.75, colorB),
					ColorSequenceKeypoint.new(1.00, colorA)
				})
				gradient.Rotation = CS.Runtime.RGBRotation
				gradient.Enabled = true
				stroke.Color = Color3.fromRGB(255, 255, 255)
			end
		end
	end
end

-- Replace old RGB cycle: no text changes, no button color changes, only rotating outline gradients.
function CS.Settings.UpdateColorCycle()
	if CS.Runtime.Shutdown then return end

	if CS.Flags.ColorCycle then
		CS.RGB.UpdateCircle()
	else
		CS.RGB.SetOutlineOnly(false)
	end
end

function CS.UI.OverlayGraph(parent, y, title)
	local mode = "Ping"
	local lowerTitle = string.lower(tostring(title or ""))

	if lowerTitle:find("fps") then
		mode = "FPS"
	elseif lowerTitle:find("ping") then
		mode = "Ping"
	end

	local box = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(1, -28, 0, 118),
		Position = UDim2.new(0, 14, 0, y),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.18,
		BorderSizePixel = 0
	})

	CS.Util.Corner(box, 12)
	CS.Util.Stroke(box, CS.Theme.Stroke, 0.55, 1)

	CS.Util.Create("TextLabel", {
		Parent = box,
		Size = UDim2.new(1, -150, 0, 24),
		Position = UDim2.new(0, 10, 0, 7),
		BackgroundTransparency = 1,
		Text = tostring(title or "Live Graph"),
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 11,
		TextXAlignment = Enum.TextXAlignment.Left
	})

	local readout = CS.Util.Create("TextLabel", {
		Parent = box,
		Size = UDim2.new(0, 130, 0, 24),
		Position = UDim2.new(1, -140, 0, 7),
		BackgroundTransparency = 1,
		Text = "--",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 11,
		TextXAlignment = Enum.TextXAlignment.Right
	})

	local bars = {}

	for i = 1, 32 do
		local bar = CS.Util.Create("Frame", {
			Parent = box,
			AnchorPoint = Vector2.new(0, 1),
			Position = UDim2.new((i - 1) / 32, 10, 1, -12),
			Size = UDim2.new(1 / 32, -4, 0, 8),
			BackgroundColor3 = CS.Theme.Accent,
			BackgroundTransparency = 0.08,
			BorderSizePixel = 0
		})

		CS.Util.Corner(bar, 999)
		table.insert(bars, bar)
	end

	table.insert(CS.UI.LiveCharts, {
		Box = box,
		Bars = bars,
		Mode = mode,
		Readout = readout
	})

	return box
end

function CS.UpdateLiveGraphs()
	if not CS.UI.LiveCharts then return end

	for _, chart in ipairs(CS.UI.LiveCharts) do
		if chart.Box and chart.Box.Parent and chart.Bars then
			local history
			local maxValue
			local suffix

			if chart.Mode == "FPS" then
				history = CS.Runtime.FPSHistory or {}
				maxValue = 240
				suffix = " FPS"
			else
				history = CS.Runtime.PingHistory or {}
				maxValue = 220
				suffix = " ms"
			end

			local nowValue = tonumber(history[#history]) or 0

			if chart.Readout and chart.Readout.Parent then
				chart.Readout.Text = tostring(nowValue) .. suffix
			end

			for i, bar in ipairs(chart.Bars) do
				if bar and bar.Parent then
					local historyIndex = #history - #chart.Bars + i
					local value = 0

					if historyIndex > 0 then
						value = tonumber(history[historyIndex]) or 0
					end

					local ratio = math.clamp(value / maxValue, 0.04, 1)
					bar.Size = UDim2.new(1 / #chart.Bars, -4, ratio, -34)

					if chart.Mode == "FPS" then
						if value >= 120 then
							bar.BackgroundColor3 = CS.Theme.Success
						elseif value >= 60 then
							bar.BackgroundColor3 = CS.Theme.Accent
						else
							bar.BackgroundColor3 = CS.Theme.Warning
						end
					else
						if value <= 70 then
							bar.BackgroundColor3 = CS.Theme.Success
						elseif value <= 140 then
							bar.BackgroundColor3 = CS.Theme.Accent
						else
							bar.BackgroundColor3 = CS.Theme.Error
						end
					end
				end
			end
		end
	end
end

local CS_OriginalUpdatePingStats_389 = CS.Dashboard.UpdatePingStats
function CS.Dashboard.UpdatePingStats()
	if CS.Runtime.Shutdown then return end

	CS_OriginalUpdatePingStats_389()

	table.insert(CS.Runtime.FPSHistory, tonumber(CS.Runtime.FPS) or 0)

	while #CS.Runtime.FPSHistory > 96 do
		table.remove(CS.Runtime.FPSHistory, 1)
	end

	CS.UpdateLiveGraphs()
end

function CS.UI.ColorPalette(parent, y, targetBox, callback)
	local colors = {
		"#FF005D", "#FF3B30", "#FF9500", "#FFD60A",
		"#32D74B", "#00E2FF", "#0BD7FD", "#007AFF",
		"#5759EC", "#9B5CFF", "#FF00D7", "#FFFFFF",
		"#C7C7CC", "#6B7280", "#1C1C28", "#000000"
	}

	local holder = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(0, 180, 0, 44),
		Position = UDim2.new(1, -470, 0, y + 2),
		BackgroundTransparency = 1
	})

	for i, hex in ipairs(colors) do
		local color = CS.Settings.HexToColor(hex)
		local swatch = CS.Util.Create("TextButton", {
			Parent = holder,
			Size = UDim2.new(0, 18, 0, 18),
			Position = UDim2.new(0, ((i - 1) % 8) * 22, 0, math.floor((i - 1) / 8) * 22),
			BackgroundColor3 = color,
			BorderSizePixel = 0,
			Text = "",
			AutoButtonColor = true
		})
		CS.Util.Corner(swatch, 999)
		CS.Util.Stroke(swatch, CS.Theme.Stroke, 0.45, 1)

		swatch.MouseButton1Click:Connect(function()
			targetBox.Text = hex
			if callback then
				callback(color, hex)
			end
		end)
	end

	return holder
end

function CS.UI.WideAction(parent, y, title, desc, buttonText, callback)
	local label = CS.UI.OverlayValue(parent, y, "•", title, "", desc)

	local button = CS.Util.Create("TextButton", {
		Parent = parent,
		Size = UDim2.new(0, 150, 0, 32),
		Position = UDim2.new(1, -170, 0, y + 8),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = buttonText or "Run",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 12,
		AutoButtonColor = true
	})
	CS.Util.Corner(button, 9)
	CS.Util.Stroke(button, CS.Theme.Stroke, 0.55, 1)

	button.MouseButton1Click:Connect(function()
		if callback then
			callback(button)
		end
	end)

	return button, label
end

function CS.UI.WideToggle(parent, y, title, desc, state, callback)
	local label = CS.UI.OverlayValue(parent, y, "•", title, state and "ON" or "OFF", desc)

	local switch = CS.Settings.MakeSwitch(parent, state, function(value)
		CS.Util.Set(label, value and "ON" or "OFF", value and CS.Theme.Success or CS.Theme.Muted)
		if callback then
			callback(value)
		end
	end)

	switch.Button.Position = UDim2.new(1, -78, 0, y + 10)
	return switch, label
end

function CS.UI.WideHex(parent, y, title, desc, hexText, callback)
	local label = CS.UI.OverlayValue(parent, y, "•", title, hexText, desc)

	local box = CS.Util.Create("TextBox", {
		Parent = parent,
		Size = UDim2.new(0, 126, 0, 32),
		Position = UDim2.new(1, -292, 0, y + 8),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = hexText or "#FFFFFF",
		PlaceholderText = "#RRGGBB",
		TextColor3 = CS.Theme.Text,
		PlaceholderColor3 = CS.Theme.Muted,
		Font = Enum.Font.GothamBold,
		TextSize = 12,
		ClearTextOnFocus = false
	})
	CS.Util.Corner(box, 9)
	CS.Util.Stroke(box, CS.Theme.Stroke, 0.55, 1)

	local apply = CS.Util.Create("TextButton", {
		Parent = parent,
		Size = UDim2.new(0, 92, 0, 32),
		Position = UDim2.new(1, -154, 0, y + 8),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = "Apply",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 12,
		AutoButtonColor = true
	})
	CS.Util.Corner(apply, 9)
	CS.Util.Stroke(apply, CS.Theme.Stroke, 0.55, 1)

	local swatch = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(0, 20, 0, 20),
		Position = UDim2.new(1, -320, 0, y + 14),
		BackgroundColor3 = CS.Settings.HexToColor(hexText or "#FFFFFF") or Color3.fromRGB(255, 255, 255),
		BorderSizePixel = 0
	})
	CS.Util.Corner(swatch, 999)
	CS.Util.Stroke(swatch, CS.Theme.Stroke, 0.45, 1)

	local function applyColor()
		local color = CS.Settings.HexToColor(box.Text)

		if not color then
			CS.Notify.Push("Color", "Invalid hex: " .. tostring(box.Text), CS.Theme.Warning)
			return
		end

		box.Text = CS.Settings.ColorToHex(color)
		swatch.BackgroundColor3 = color
		CS.Util.Set(label, box.Text)

		if callback then
			callback(color, box.Text)
		end
	end

	apply.MouseButton1Click:Connect(applyColor)

	box.FocusLost:Connect(function(enterPressed)
		local color = CS.Settings.HexToColor(box.Text)
		if color then
			box.Text = CS.Settings.ColorToHex(color)
			swatch.BackgroundColor3 = color
		end
	end)

	CS.UI.ColorPalette(parent, y, box, function(color, hex)
		swatch.BackgroundColor3 = color
		CS.Util.Set(label, hex)
		if callback then
			callback(color, hex)
		end
	end)

	return box, apply, swatch
end

function CS.Settings.Build()
	local page = CS.UI.Pages["Settings"]
	if not page then return end

	CS.Util.Clear(page, true)

	local left = CS.Util.Scroll(page)
	left.Size = UDim2.new(0.5, -8, 1, 0)
	left.Position = UDim2.new(0, 0, 0, 0)

	local right = CS.Util.Scroll(page)
	right.Size = UDim2.new(0.5, -8, 1, 0)
	right.Position = UDim2.new(0.5, 8, 0, 0)

	local general = CS.UI.OverlayCard(left, "General", "▣", 290)
	CS.UI.WideToggle(general, 58, "Notifications", "Join, leave, and system notices.", CS.Flags.Notifications, function(v)
		CS.Flags.Notifications = v
		CS.Settings.Save(true)
	end)
	CS.UI.WideToggle(general, 112, "Player Notices", "Show non-friend player notices.", CS.Flags.ShowNonFriendNotices, function(v)
		CS.Flags.ShowNonFriendNotices = v
		CS.Settings.Save(true)
	end)
	CS.UI.WideToggle(general, 166, "Friend Sounds", "Play sounds for friend actions.", CS.Flags.FriendSounds, function(v)
		CS.Flags.FriendSounds = v
		CS.Settings.Save(true)
	end)
	CS.UI.WideToggle(general, 220, "Animations", "Smooth hover and page feedback.", CS.Flags.Animations, function(v)
		CS.Flags.Animations = v
		CS.Settings.Save(true)
	end)

	local rgb = CS.UI.OverlayCard(left, "RGB / Circle Outline", "◎", 345)
	CS.UI.WideToggle(rgb, 58, "Enable RGB", "Rotating outline only. Text and buttons stay normal.", CS.Flags.ColorCycle, function(v)
		CS.Flags.ColorCycle = v
		CS.RGB.SetOutlineOnly(v)
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(rgb, 112, "Circle Color A", "First outline color.", CS.Flags.ColorCycleA or "#FF00D7", function(color, hex)
		CS.Flags.ColorCycleA = hex
		if CS.RGB and CS.RGB.SetOutlineOnly then
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	end
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(rgb, 166, "Circle Color B", "Second outline color.", CS.Flags.ColorCycleB or "#00E2FF", function(color, hex)
		CS.Flags.ColorCycleB = hex
		if CS.RGB and CS.RGB.SetOutlineOnly then
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	end
		CS.Settings.Save(true)
	end)
	CS.UI.WideAction(rgb, 220, "Circle Speed", "1 slow, 10 fast.", tostring(CS.Flags.ColorCycleSpeedLevel or 3), function(btn)
		CS.Flags.ColorCycleSpeedLevel = ((CS.Flags.ColorCycleSpeedLevel or 3) % 10) + 1
		btn.Text = tostring(CS.Flags.ColorCycleSpeedLevel)
		CS.Settings.Save(true)
	end)
	CS.UI.WideAction(rgb, 274, "Clean Text", "Remove RGB from letters/icons.", "Clean", function()
		CS.CleanTextAndBadVisuals()
		CS.Notify.Push("Settings", "Text cleaned. RGB is outline-only.", CS.Theme.Info)
	end)

	local colors = CS.UI.OverlayCard(right, "Custom Hex / RGB", "#", 400)
	CS.UI.WideHex(colors, 58, "Accent", "Main active color.", CS.Settings.ColorToHex(CS.Theme.Accent), function(color, hex)
		CS.Theme.Accent = color
		CS.Settings.ApplyVisuals()
		CS.CleanTextAndBadVisuals()
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 112, "Background", "Main shell background.", CS.Settings.ColorToHex(CS.Theme.Background), function(color, hex)
		CS.Theme.Background = color
		CS.Theme.Background2 = color
		CS.Theme.Panel = color
		CS.Theme.Panel2 = color
		CS.Settings.ApplyVisuals()
		CS.CleanTextAndBadVisuals()
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 166, "Cards", "Card surface color.", CS.Settings.ColorToHex(CS.Theme.Card), function(color, hex)
		CS.Theme.Card = color
		CS.Theme.Card2 = color
		CS.Settings.ApplyVisuals()
		CS.CleanTextAndBadVisuals()
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 220, "Outlines", "Border color when circle RGB is off.", CS.Settings.ColorToHex(CS.Theme.Stroke), function(color, hex)
		CS.Theme.Stroke = color
		CS.Theme.StrokeSoft = color
		CS.Settings.ApplyVisuals()
		CS.CleanTextAndBadVisuals()
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 274, "Notifications", "Notice accent color.", CS.Settings.ColorToHex(CS.Theme.NotificationOutline), function(color, hex)
		CS.Theme.NotificationOutline = color
		CS.Theme.Info = color
		CS.Settings.ApplyVisuals()
		CS.CleanTextAndBadVisuals()
		CS.Settings.Save(true)
	end)
	CS.UI.WideAction(colors, 328, "Reset Theme", "Restore default colors.", "Reset", function()
		CS.Settings.ResetThemeDefaults()
		CS.Settings.Build()
	end)

	local tools = CS.UI.OverlayCard(right, "Layout / Maintenance", "⚙", 345)
	tools.Position = UDim2.new(0, 0, 0, 414)

	CS.UI.WideAction(tools, 58, "Bigger Menu", "Apply the large clean layout.", "Apply", function()
		CS.LayoutBig()
	end)
	CS.UI.WideAction(tools, 112, "Refresh UI", "Rebuild all pages and labels.", "Refresh", function()
		CS.UI.LiveCharts = {}
		CS.Dashboard.Build()
		CS.PlayerDetails.Build()
		CS.ServerBrowser.Build()
		CS.GameInfo.Build()
		CS.Friends.Build()
		CS.Diagnostics.Build()
		CS.Settings.Build()
		CS.Utilities.Build()
		CS.LayoutBig()
		CS.CleanTextAndBadVisuals()
		CS.AddCloseAndShutdown()
		if CS.RGB and CS.RGB.SetOutlineOnly then
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	end
	end)
	CS.UI.WideAction(tools, 166, "Save Config", "Save current settings.", "Save", function()
		CS.Settings.Save(false)
	end)
	CS.UI.WideAction(tools, 220, "Load Config", "Reload saved settings.", "Load", function()
		CS.Settings.Load()
		CS.Settings.ApplyVisuals()
		CS.CleanTextAndBadVisuals()
		if CS.RGB and CS.RGB.SetOutlineOnly then
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	end
	end)
	CS.UI.WideAction(tools, 274, "Shutdown CS", "Fully destroy the menu.", "Shutdown", function()
		CS.Shutdown()
	end)

	CS.LayoutBig()
	CS.CleanTextAndBadVisuals()
	CS.AddCloseAndShutdown()
	if CS.RGB and CS.RGB.SetOutlineOnly then
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	end
end

local CS_OriginalBuild_389 = CS.Build
function CS.Build()
	CS_OriginalBuild_389()
	CS.LayoutBig()
	CS.Settings.Build()
	CS.CleanTextAndBadVisuals()
	CS.AddCloseAndShutdown()
	if CS.RGB and CS.RGB.SetOutlineOnly then
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	end
end

local CS_OriginalSwitchPage_389 = CS.UI.SwitchPage
function CS.UI.SwitchPage(name)
	CS_OriginalSwitchPage_389(name)
	task.defer(function()
		CS.LayoutBig()
		CS.CleanTextAndBadVisuals()
		CS.AddCloseAndShutdown()
		if CS.RGB and CS.RGB.SetOutlineOnly then
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	end
		CS.UpdateLiveGraphs()
	end)
end

local CS_OriginalConnect_389 = CS.Connect
function CS.Connect()
	CS_OriginalConnect_389()

	CS.Track(CS.Services.RunService.RenderStepped:Connect(function()
		if CS.Runtime.Shutdown then return end
		CS.RGB.UpdateCircle()
		CS.UpdateLiveGraphs()

		-- Prevent any text from being recolored by RGB every frame.
		if CS.Flags.ColorCycle and CS.UI.Objects.GUI then
			for _, obj in ipairs(CS.UI.Objects.GUI:GetDescendants()) do
				if obj:IsA("TextLabel") or obj:IsA("TextButton") or obj:IsA("TextBox") then
					if obj.Name ~= "CSShutdownButton" then
						obj.TextColor3 = CS.Theme.Text
					end
					local gradient = obj:FindFirstChildOfClass("UIGradient")
					if gradient then
						gradient.Enabled = false
					end
				end
			end
		end
	end))
end

--// =========================================================
--// END CS v3.8.9 PATCH
--// =========================================================





--// =========================================================
--// CS v3.9.0 COLLAPSIBLE COLOR PICKER PATCH
--// Replaces cluttered swatch rows with a clean "Color" button.
--// Click Color -> picker opens -> choose color/hex -> Save -> picker closes.
--// =========================================================

CS.Version = "3.9.0"
CS.Config.Version = "3.9.0"

CS.UI.ActiveColorPicker = nil

function CS.UI.CloseColorPicker()
	if CS.UI.ActiveColorPicker and CS.UI.ActiveColorPicker.Parent then
		CS.UI.ActiveColorPicker:Destroy()
	end
	CS.UI.ActiveColorPicker = nil
end

function CS.UI.OpenColorPicker(parent, title, currentHex, onSave)
	CS.UI.CloseColorPicker()

	local startColor = CS.Settings.HexToColor(currentHex or "#FFFFFF") or Color3.fromRGB(255, 255, 255)
	local hue, sat, val = startColor:ToHSV()

	local pickerCard = CS.Util.Create("Frame", {
		Parent = parent,
		Name = "CSColorPickerPopup",
		Size = UDim2.new(1, -28, 0, 330),
		Position = UDim2.new(0, 14, 0, 382),
		BackgroundColor3 = CS.Theme.Card,
		BackgroundTransparency = 0.03,
		BorderSizePixel = 0,
		ZIndex = 60
	})

	CS.UI.ActiveColorPicker = pickerCard
	CS.Util.Corner(pickerCard, 14)
	CS.Util.Stroke(pickerCard, CS.Theme.Accent, 0.12, 1)

	local titleLabel = CS.Util.Create("TextLabel", {
		Parent = pickerCard,
		Size = UDim2.new(1, -120, 0, 34),
		Position = UDim2.new(0, 14, 0, 8),
		BackgroundTransparency = 1,
		Text = "COLOR PICKER: " .. tostring(title or "Color"),
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 13,
		TextXAlignment = Enum.TextXAlignment.Left,
		ZIndex = 61
	})

	local close = CS.Util.Create("TextButton", {
		Parent = pickerCard,
		Size = UDim2.new(0, 72, 0, 28),
		Position = UDim2.new(1, -86, 0, 10),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = "Close",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 11,
		ZIndex = 61
	})
	CS.Util.Corner(close, 8)
	CS.Util.Stroke(close, CS.Theme.Stroke, 0.45, 1)

	local preview = CS.Util.Create("Frame", {
		Parent = pickerCard,
		Size = UDim2.new(0, 68, 0, 68),
		Position = UDim2.new(0, 16, 0, 52),
		BackgroundColor3 = startColor,
		BorderSizePixel = 0,
		ZIndex = 61
	})
	CS.Util.Corner(preview, 12)
	CS.Util.Stroke(preview, CS.Theme.Stroke, 0.35, 1)

	local hexBox = CS.Util.Create("TextBox", {
		Parent = pickerCard,
		Size = UDim2.new(1, -112, 0, 36),
		Position = UDim2.new(0, 96, 0, 52),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = currentHex or "#FFFFFF",
		PlaceholderText = "#RRGGBB",
		TextColor3 = CS.Theme.Text,
		PlaceholderColor3 = CS.Theme.Muted,
		Font = Enum.Font.GothamBold,
		TextSize = 13,
		ClearTextOnFocus = false,
		ZIndex = 61
	})
	CS.Util.Corner(hexBox, 9)
	CS.Util.Stroke(hexBox, CS.Theme.Stroke, 0.45, 1)

	local palette = {
		"#FF005D", "#FF3B30", "#FF9500", "#FFD60A", "#32D74B", "#00E2FF",
		"#0BD7FD", "#007AFF", "#5759EC", "#9B5CFF", "#FF00D7", "#FFFFFF",
		"#C7C7CC", "#6B7280", "#1C1C28", "#000000"
	}

	local paletteHolder = CS.Util.Create("Frame", {
		Parent = pickerCard,
		Size = UDim2.new(1, -112, 0, 44),
		Position = UDim2.new(0, 96, 0, 96),
		BackgroundTransparency = 1,
		ZIndex = 61
	})

	local function setColor(color, hex)
		hex = hex or CS.Settings.ColorToHex(color)
		preview.BackgroundColor3 = color
		hexBox.Text = hex
		local h, s, v = color:ToHSV()
		hue, sat, val = h, s, v
	end

	for i, hex in ipairs(palette) do
		local color = CS.Settings.HexToColor(hex)
		local swatch = CS.Util.Create("TextButton", {
			Parent = paletteHolder,
			Size = UDim2.new(0, 22, 0, 22),
			Position = UDim2.new(0, ((i - 1) % 8) * 27, 0, math.floor((i - 1) / 8) * 24),
			BackgroundColor3 = color,
			BorderSizePixel = 0,
			Text = "",
			AutoButtonColor = true,
			ZIndex = 62
		})
		CS.Util.Corner(swatch, 999)
		CS.Util.Stroke(swatch, CS.Theme.Stroke, 0.35, 1)

		swatch.MouseButton1Click:Connect(function()
			setColor(color, hex)
		end)
	end

	local gradientBox = CS.Util.Create("Frame", {
		Parent = pickerCard,
		Size = UDim2.new(1, -32, 0, 118),
		Position = UDim2.new(0, 16, 0, 152),
		BackgroundColor3 = Color3.fromHSV(hue, 1, 1),
		BorderSizePixel = 0,
		ClipsDescendants = true,
		ZIndex = 61
	})
	CS.Util.Corner(gradientBox, 10)
	CS.Util.Stroke(gradientBox, CS.Theme.Stroke, 0.45, 1)

	local satGrad = Instance.new("UIGradient")
	satGrad.Color = ColorSequence.new(Color3.fromRGB(255, 255, 255), Color3.fromHSV(hue, 1, 1))
	satGrad.Rotation = 0
	satGrad.Parent = gradientBox

	local darkOverlay = CS.Util.Create("Frame", {
		Parent = gradientBox,
		Size = UDim2.new(1, 0, 1, 0),
		BackgroundColor3 = Color3.fromRGB(0, 0, 0),
		BorderSizePixel = 0,
		ZIndex = 62
	})

	local valueGrad = Instance.new("UIGradient")
	valueGrad.Transparency = NumberSequence.new({
		NumberSequenceKeypoint.new(0, 1),
		NumberSequenceKeypoint.new(1, 0)
	})
	valueGrad.Rotation = 90
	valueGrad.Parent = darkOverlay

	local cursor = CS.Util.Create("Frame", {
		Parent = gradientBox,
		Size = UDim2.new(0, 14, 0, 14),
		Position = UDim2.new(sat, -7, 1 - val, -7),
		BackgroundColor3 = Color3.fromRGB(255, 255, 255),
		BorderSizePixel = 0,
		ZIndex = 63
	})
	CS.Util.Corner(cursor, 999)
	CS.Util.Stroke(cursor, Color3.fromRGB(0, 0, 0), 0.15, 2)

	local hueBar = CS.Util.Create("Frame", {
		Parent = pickerCard,
		Size = UDim2.new(1, -32, 0, 18),
		Position = UDim2.new(0, 16, 0, 282),
		BackgroundColor3 = Color3.fromRGB(255, 255, 255),
		BorderSizePixel = 0,
		ZIndex = 61
	})
	CS.Util.Corner(hueBar, 999)
	CS.Util.Stroke(hueBar, CS.Theme.Stroke, 0.45, 1)

	local hueGrad = Instance.new("UIGradient")
	hueGrad.Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0.00, Color3.fromRGB(255, 0, 0)),
		ColorSequenceKeypoint.new(0.16, Color3.fromRGB(255, 255, 0)),
		ColorSequenceKeypoint.new(0.33, Color3.fromRGB(0, 255, 0)),
		ColorSequenceKeypoint.new(0.50, Color3.fromRGB(0, 255, 255)),
		ColorSequenceKeypoint.new(0.66, Color3.fromRGB(0, 0, 255)),
		ColorSequenceKeypoint.new(0.83, Color3.fromRGB(255, 0, 255)),
		ColorSequenceKeypoint.new(1.00, Color3.fromRGB(255, 0, 0))
	})
	hueGrad.Parent = hueBar

	local hueCursor = CS.Util.Create("Frame", {
		Parent = hueBar,
		Size = UDim2.new(0, 12, 0, 24),
		Position = UDim2.new(hue, -6, 0.5, -12),
		BackgroundColor3 = Color3.fromRGB(25, 25, 25),
		BorderSizePixel = 0,
		ZIndex = 63
	})
	CS.Util.Corner(hueCursor, 999)
	CS.Util.Stroke(hueCursor, CS.Theme.Text, 0.25, 2)

	local save = CS.Util.Create("TextButton", {
		Parent = pickerCard,
		Size = UDim2.new(0, 110, 0, 30),
		Position = UDim2.new(1, -126, 1, -38),
		BackgroundColor3 = CS.Theme.Success,
		BackgroundTransparency = 0.04,
		BorderSizePixel = 0,
		Text = "Save",
		TextColor3 = Color3.fromRGB(0, 0, 0),
		Font = Enum.Font.GothamBold,
		TextSize = 12,
		ZIndex = 61
	})
	CS.Util.Corner(save, 9)

	local draggingPicker = false
	local draggingHue = false

	local function refreshHSV()
		local color = Color3.fromHSV(hue, sat, val)
		local hex = CS.Settings.ColorToHex(color)
		preview.BackgroundColor3 = color
		hexBox.Text = hex
		gradientBox.BackgroundColor3 = Color3.fromHSV(hue, 1, 1)
		satGrad.Color = ColorSequence.new(Color3.fromRGB(255, 255, 255), Color3.fromHSV(hue, 1, 1))
	end

	local function updatePicker(input)
		local x = math.clamp((input.Position.X - gradientBox.AbsolutePosition.X) / math.max(gradientBox.AbsoluteSize.X, 1), 0, 1)
		local y = math.clamp((input.Position.Y - gradientBox.AbsolutePosition.Y) / math.max(gradientBox.AbsoluteSize.Y, 1), 0, 1)
		sat = x
		val = 1 - y
		cursor.Position = UDim2.new(x, -7, y, -7)
		refreshHSV()
	end

	local function updateHue(input)
		local x = math.clamp((input.Position.X - hueBar.AbsolutePosition.X) / math.max(hueBar.AbsoluteSize.X, 1), 0, 1)
		hue = x
		hueCursor.Position = UDim2.new(x, -6, 0.5, -12)
		refreshHSV()
	end

	gradientBox.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			draggingPicker = true
			updatePicker(input)
		end
	end)

	darkOverlay.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			draggingPicker = true
			updatePicker(input)
		end
	end)

	hueBar.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			draggingHue = true
			updateHue(input)
		end
	end)

	CS.Services.UserInputService.InputChanged:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseMovement then
			if draggingPicker then
				updatePicker(input)
			elseif draggingHue then
				updateHue(input)
			end
		end
	end)

	CS.Services.UserInputService.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			draggingPicker = false
			draggingHue = false
		end
	end)

	hexBox.FocusLost:Connect(function()
		local color = CS.Settings.HexToColor(hexBox.Text)
		if color then
			setColor(color, CS.Settings.ColorToHex(color))
			cursor.Position = UDim2.new(sat, -7, 1 - val, -7)
			hueCursor.Position = UDim2.new(hue, -6, 0.5, -12)
			refreshHSV()
		else
			CS.Notify.Push("Color", "Invalid hex.", CS.Theme.Warning)
		end
	end)

	close.MouseButton1Click:Connect(function()
		CS.UI.CloseColorPicker()
	end)

	save.MouseButton1Click:Connect(function()
		local color = CS.Settings.HexToColor(hexBox.Text)
		if not color then
			CS.Notify.Push("Color", "Invalid hex.", CS.Theme.Warning)
			return
		end

		local hex = CS.Settings.ColorToHex(color)
		if onSave then
			onSave(color, hex)
		end

		CS.UI.CloseColorPicker()
	end)

	refreshHSV()
end

function CS.UI.WideHex(parent, y, title, desc, hexText, callback)
	local valueLabel = CS.UI.OverlayValue(parent, y, "•", title, hexText, desc)

	local swatch = CS.Util.Create("Frame", {
		Parent = parent,
		Size = UDim2.new(0, 28, 0, 28),
		Position = UDim2.new(1, -290, 0, y + 10),
		BackgroundColor3 = CS.Settings.HexToColor(hexText or "#FFFFFF") or Color3.fromRGB(255, 255, 255),
		BorderSizePixel = 0
	})
	CS.Util.Corner(swatch, 8)
	CS.Util.Stroke(swatch, CS.Theme.Stroke, 0.4, 1)

	local button = CS.Util.Create("TextButton", {
		Parent = parent,
		Size = UDim2.new(0, 190, 0, 34),
		Position = UDim2.new(1, -250, 0, y + 7),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = "Pick Color  " .. tostring(hexText or "#FFFFFF"),
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 12,
		AutoButtonColor = true
	})
	CS.Util.Corner(button, 9)
	CS.Util.Stroke(button, CS.Theme.Stroke, 0.55, 1)

	local currentHex = hexText or "#FFFFFF"

	button.MouseButton1Click:Connect(function()
		CS.UI.OpenColorPicker(parent, title, currentHex, function(color, hex)
			currentHex = hex
			swatch.BackgroundColor3 = color
			button.Text = "Pick Color  " .. hex
			CS.Util.Set(valueLabel, hex)
			if callback then
				callback(color, hex)
			end
		end)
	end)

	return button, swatch
end

--// =========================================================
--// END CS v3.9.0 PATCH
--// =========================================================





--// =========================================================
--// CS v3.9.1 STRICT OUTLINE-ONLY RGB PATCH
--// RGB no longer affects text, buttons, icons, graph bars, tabs, or card fill.
--// It only rotates UIStroke outlines.
--// Also removes the "Clean Text" row from Settings.
--// =========================================================

CS.Version = "3.9.1"
CS.Config.Version = "3.9.1"

CS.RGB = CS.RGB or {}
CS.Runtime.RGBRotation = CS.Runtime.RGBRotation or 0

function CS.RGB.ResetNonOutlineColors()
	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	for _, obj in ipairs(gui:GetDescendants()) do
		if obj:IsA("TextLabel") or obj:IsA("TextButton") or obj:IsA("TextBox") then
			local isShutdown = obj.Name == "CSShutdownButton"
			local isSelectedTab = false

			for _, tab in pairs(CS.UI.Tabs or {}) do
				if tab == obj and CS.Runtime.CurrentPage and CS.UI.Pages[CS.Runtime.CurrentPage] and CS.UI.Pages[CS.Runtime.CurrentPage].Visible then
					isSelectedTab = true
				end
			end

			if isShutdown then
				obj.TextColor3 = Color3.fromRGB(255, 255, 255)
			elseif obj:IsA("TextBox") then
				obj.TextColor3 = CS.Theme.Text
			else
				obj.TextColor3 = CS.Theme.Text
			end

			obj.TextStrokeTransparency = 1

			for _, child in ipairs(obj:GetChildren()) do
				if child:IsA("UIGradient") then
					child.Enabled = false
					child:Destroy()
				end
			end
		end

		if obj:IsA("ImageLabel") or obj:IsA("ImageButton") then
			for _, child in ipairs(obj:GetChildren()) do
				if child:IsA("UIGradient") then
					child.Enabled = false
					child:Destroy()
				end
			end
		end
	end
end

function CS.RGB.SetOutlineOnly(enabled)
	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	for _, obj in ipairs(gui:GetDescendants()) do
		if obj:IsA("UIStroke") then
			local gradient = obj:FindFirstChild("CSRGBCircleGradient")

			if enabled then
				if not gradient then
					gradient = Instance.new("UIGradient")
					gradient.Name = "CSRGBCircleGradient"
					gradient.Parent = obj
				end

				local colorA = CS.Settings.HexToColor(CS.Flags.ColorCycleA) or Color3.fromRGB(255, 0, 215)
				local colorB = CS.Settings.HexToColor(CS.Flags.ColorCycleB) or Color3.fromRGB(0, 226, 255)

				gradient.Color = ColorSequence.new({
					ColorSequenceKeypoint.new(0.00, colorA),
					ColorSequenceKeypoint.new(0.25, colorB),
					ColorSequenceKeypoint.new(0.50, colorA),
					ColorSequenceKeypoint.new(0.75, colorB),
					ColorSequenceKeypoint.new(1.00, colorA)
				})
				gradient.Rotation = CS.Runtime.RGBRotation or 0
				gradient.Enabled = true

				obj.Color = Color3.fromRGB(255, 255, 255)
				obj.Transparency = math.min(obj.Transparency, 0.28)
				obj.Thickness = math.max(obj.Thickness, 1.15)
			else
				if gradient then
					gradient:Destroy()
				end

				obj.Color = CS.Theme.Stroke
				obj.Transparency = 0.36
				obj.Thickness = 1
			end
		elseif obj:IsA("GuiObject") then
			local gradient = obj:FindFirstChild("CSRGBCircleGradient")
			if gradient then
				gradient:Destroy()
			end
		end
	end

	CS.RGB.ResetNonOutlineColors()
end

function CS.RGB.UpdateCircle()
	if not CS.Flags.ColorCycle then
		return
	end

	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	local speed = math.clamp(tonumber(CS.Flags.ColorCycleSpeedLevel) or 3, 1, 10)
	CS.Runtime.RGBRotation = ((CS.Runtime.RGBRotation or 0) + (speed * 0.65)) % 360

	local colorA = CS.Settings.HexToColor(CS.Flags.ColorCycleA) or Color3.fromRGB(255, 0, 215)
	local colorB = CS.Settings.HexToColor(CS.Flags.ColorCycleB) or Color3.fromRGB(0, 226, 255)

	for _, stroke in ipairs(gui:GetDescendants()) do
		if stroke:IsA("UIStroke") then
			local gradient = stroke:FindFirstChild("CSRGBCircleGradient")
			if not gradient then
				gradient = Instance.new("UIGradient")
				gradient.Name = "CSRGBCircleGradient"
				gradient.Parent = stroke
			end

			gradient.Color = ColorSequence.new({
				ColorSequenceKeypoint.new(0.00, colorA),
				ColorSequenceKeypoint.new(0.25, colorB),
				ColorSequenceKeypoint.new(0.50, colorA),
				ColorSequenceKeypoint.new(0.75, colorB),
				ColorSequenceKeypoint.new(1.00, colorA)
			})
			gradient.Rotation = CS.Runtime.RGBRotation
			gradient.Enabled = true
			stroke.Color = Color3.fromRGB(255, 255, 255)
		end
	end

	CS.RGB.ResetNonOutlineColors()
end

function CS.Settings.UpdateColorCycle()
	if CS.Runtime.Shutdown then return end

	if CS.Flags.ColorCycle then
		CS.RGB.UpdateCircle()
	else
		CS.RGB.SetOutlineOnly(false)
	end
end

-- Make normal tab/button text stay static even when RGB is enabled.
local CS_OriginalSwitchPage_391 = CS.UI.SwitchPage
function CS.UI.SwitchPage(name)
	CS_OriginalSwitchPage_391(name)

	task.defer(function()
		if CS.LayoutBig then CS.LayoutBig() end
		if CS.AddCloseAndShutdown then CS.AddCloseAndShutdown() end
		if CS.CleanTextAndBadVisuals then CS.CleanTextAndBadVisuals() end

		if CS.RGB and CS.RGB.SetOutlineOnly then
			CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		end

		CS.RGB.ResetNonOutlineColors()
	end)
end

-- Rebuild settings without the "Clean Text" row.
function CS.Settings.Build()
	local page = CS.UI.Pages["Settings"]
	if not page then return end

	CS.Util.Clear(page, true)

	local left = CS.Util.Scroll(page)
	left.Size = UDim2.new(0.5, -8, 1, 0)
	left.Position = UDim2.new(0, 0, 0, 0)

	local right = CS.Util.Scroll(page)
	right.Size = UDim2.new(0.5, -8, 1, 0)
	right.Position = UDim2.new(0.5, 8, 0, 0)

	local general = CS.UI.OverlayCard(left, "General", "▣", 290)
	CS.UI.WideToggle(general, 58, "Notifications", "Join, leave, and system notices.", CS.Flags.Notifications, function(v)
		CS.Flags.Notifications = v
		CS.Settings.Save(true)
	end)
	CS.UI.WideToggle(general, 112, "Player Notices", "Show non-friend player notices.", CS.Flags.ShowNonFriendNotices, function(v)
		CS.Flags.ShowNonFriendNotices = v
		CS.Settings.Save(true)
	end)
	CS.UI.WideToggle(general, 166, "Friend Sounds", "Play sounds for friend actions.", CS.Flags.FriendSounds, function(v)
		CS.Flags.FriendSounds = v
		CS.Settings.Save(true)
	end)
	CS.UI.WideToggle(general, 220, "Animations", "Smooth hover and page feedback.", CS.Flags.Animations, function(v)
		CS.Flags.Animations = v
		CS.Settings.Save(true)
	end)

	local rgb = CS.UI.OverlayCard(left, "RGB / Outline Circle", "◎", 290)
	CS.UI.WideToggle(rgb, 58, "Enable RGB", "Rotating outline only. Text/buttons/icons stay normal.", CS.Flags.ColorCycle, function(v)
		CS.Flags.ColorCycle = v
		CS.RGB.SetOutlineOnly(v)
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(rgb, 112, "Circle Color A", "First outline color.", CS.Flags.ColorCycleA or "#FF00D7", function(color, hex)
		CS.Flags.ColorCycleA = hex
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(rgb, 166, "Circle Color B", "Second outline color.", CS.Flags.ColorCycleB or "#00E2FF", function(color, hex)
		CS.Flags.ColorCycleB = hex
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		CS.Settings.Save(true)
	end)
	CS.UI.WideAction(rgb, 220, "Circle Speed", "1 slow, 10 fast.", tostring(CS.Flags.ColorCycleSpeedLevel or 3), function(btn)
		CS.Flags.ColorCycleSpeedLevel = ((CS.Flags.ColorCycleSpeedLevel or 3) % 10) + 1
		btn.Text = tostring(CS.Flags.ColorCycleSpeedLevel)
		CS.Settings.Save(true)
	end)

	local colors = CS.UI.OverlayCard(right, "Custom Hex / RGB", "#", 400)
	CS.UI.WideHex(colors, 58, "Accent", "Main active color.", CS.Settings.ColorToHex(CS.Theme.Accent), function(color, hex)
		CS.Theme.Accent = color
		CS.Settings.ApplyVisuals()
		CS.RGB.ResetNonOutlineColors()
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 112, "Background", "Main shell background.", CS.Settings.ColorToHex(CS.Theme.Background), function(color, hex)
		CS.Theme.Background = color
		CS.Theme.Background2 = color
		CS.Theme.Panel = color
		CS.Theme.Panel2 = color
		CS.Settings.ApplyVisuals()
		CS.RGB.ResetNonOutlineColors()
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 166, "Cards", "Card surface color.", CS.Settings.ColorToHex(CS.Theme.Card), function(color, hex)
		CS.Theme.Card = color
		CS.Theme.Card2 = color
		CS.Settings.ApplyVisuals()
		CS.RGB.ResetNonOutlineColors()
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 220, "Outlines", "Border color when RGB is off.", CS.Settings.ColorToHex(CS.Theme.Stroke), function(color, hex)
		CS.Theme.Stroke = color
		CS.Theme.StrokeSoft = color
		CS.Settings.ApplyVisuals()
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 274, "Notifications", "Notice accent color.", CS.Settings.ColorToHex(CS.Theme.NotificationOutline), function(color, hex)
		CS.Theme.NotificationOutline = color
		CS.Theme.Info = color
		CS.Settings.ApplyVisuals()
		CS.RGB.ResetNonOutlineColors()
		CS.Settings.Save(true)
	end)
	CS.UI.WideAction(colors, 328, "Reset Theme", "Restore default colors.", "Reset", function()
		CS.Settings.ResetThemeDefaults()
		CS.Settings.Build()
	end)

	local tools = CS.UI.OverlayCard(right, "Layout / Maintenance", "⚙", 345)
	tools.Position = UDim2.new(0, 0, 0, 414)

	CS.UI.WideAction(tools, 58, "Bigger Menu", "Apply the large clean layout.", "Apply", function()
		if CS.LayoutBig then CS.LayoutBig() end
	end)
	CS.UI.WideAction(tools, 112, "Refresh UI", "Rebuild all pages and labels.", "Refresh", function()
		CS.UI.LiveCharts = {}
		CS.Dashboard.Build()
		CS.PlayerDetails.Build()
		CS.ServerBrowser.Build()
		CS.GameInfo.Build()
		CS.Friends.Build()
		CS.Diagnostics.Build()
		CS.Settings.Build()
		CS.Utilities.Build()

		if CS.LayoutBig then CS.LayoutBig() end
		if CS.AddCloseAndShutdown then CS.AddCloseAndShutdown() end
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		CS.RGB.ResetNonOutlineColors()
	end)
	CS.UI.WideAction(tools, 166, "Save Config", "Save current settings.", "Save", function()
		CS.Settings.Save(false)
	end)
	CS.UI.WideAction(tools, 220, "Load Config", "Reload saved settings.", "Load", function()
		CS.Settings.Load()
		CS.Settings.ApplyVisuals()
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		CS.RGB.ResetNonOutlineColors()
	end)
	CS.UI.WideAction(tools, 274, "Shutdown CS", "Fully destroy the menu.", "Shutdown", function()
		CS.Shutdown()
	end)

	if CS.LayoutBig then CS.LayoutBig() end
	if CS.AddCloseAndShutdown then CS.AddCloseAndShutdown() end
	CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	CS.RGB.ResetNonOutlineColors()
end

local CS_OriginalBuild_391 = CS.Build
function CS.Build()
	CS_OriginalBuild_391()

	if CS.LayoutBig then CS.LayoutBig() end
	CS.Settings.Build()
	if CS.AddCloseAndShutdown then CS.AddCloseAndShutdown() end

	CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	CS.RGB.ResetNonOutlineColors()
end

local CS_OriginalConnect_391 = CS.Connect
function CS.Connect()
	CS_OriginalConnect_391()

	CS.Track(CS.Services.RunService.RenderStepped:Connect(function()
		if CS.Runtime.Shutdown then return end

		if CS.RGB and CS.RGB.UpdateCircle then
			CS.RGB.UpdateCircle()
		end

		if CS.UpdateLiveGraphs then
			CS.UpdateLiveGraphs()
		end

		CS.RGB.ResetNonOutlineColors()
	end))
end

--// =========================================================
--// END CS v3.9.1 PATCH
--// =========================================================





--// =========================================================
--// CS v3.9.2 COLOR BUTTON + SLOWER RGB SPEED PATCH
--// - The color square itself opens the color picker.
--// - Removed the separate "Pick Color" button look.
--// - RGB circle speed is much slower by default and at max.
--// =========================================================

CS.Version = "3.9.2"
CS.Config.Version = "3.9.2"

CS.Flags.ColorCycleSpeedLevel = math.clamp(tonumber(CS.Flags.ColorCycleSpeedLevel) or 1, 1, 10)

function CS.RGB.GetSlowCircleSpeed()
	local level = math.clamp(tonumber(CS.Flags.ColorCycleSpeedLevel) or 1, 1, 10)
	-- Much slower: level 1 = very slow, level 10 = still controlled.
	return 0.035 + ((level - 1) / 9) * 0.42
end

function CS.RGB.UpdateCircle()
	if not CS.Flags.ColorCycle then
		return
	end

	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	CS.Runtime.RGBRotation = ((CS.Runtime.RGBRotation or 0) + CS.RGB.GetSlowCircleSpeed()) % 360

	local colorA = CS.Settings.HexToColor(CS.Flags.ColorCycleA) or Color3.fromRGB(255, 0, 215)
	local colorB = CS.Settings.HexToColor(CS.Flags.ColorCycleB) or Color3.fromRGB(0, 226, 255)

	for _, stroke in ipairs(gui:GetDescendants()) do
		if stroke:IsA("UIStroke") then
			local gradient = stroke:FindFirstChild("CSRGBCircleGradient")
			if not gradient then
				gradient = Instance.new("UIGradient")
				gradient.Name = "CSRGBCircleGradient"
				gradient.Parent = stroke
			end

			gradient.Color = ColorSequence.new({
				ColorSequenceKeypoint.new(0.00, colorA),
				ColorSequenceKeypoint.new(0.25, colorB),
				ColorSequenceKeypoint.new(0.50, colorA),
				ColorSequenceKeypoint.new(0.75, colorB),
				ColorSequenceKeypoint.new(1.00, colorA)
			})
			gradient.Rotation = CS.Runtime.RGBRotation
			gradient.Enabled = true
			stroke.Color = Color3.fromRGB(255, 255, 255)
		end
	end

	if CS.RGB.ResetNonOutlineColors then
		CS.RGB.ResetNonOutlineColors()
	end
end

function CS.UI.WideHex(parent, y, title, desc, hexText, callback)
	local valueLabel = CS.UI.OverlayValue(parent, y, "•", title, hexText, desc)

	local currentHex = hexText or "#FFFFFF"
	local currentColor = CS.Settings.HexToColor(currentHex) or Color3.fromRGB(255, 255, 255)

	local colorButton = CS.Util.Create("TextButton", {
		Parent = parent,
		Size = UDim2.new(0, 44, 0, 34),
		Position = UDim2.new(1, -250, 0, y + 7),
		BackgroundColor3 = currentColor,
		BackgroundTransparency = 0,
		BorderSizePixel = 0,
		Text = "",
		AutoButtonColor = true
	})
	CS.Util.Corner(colorButton, 10)
	CS.Util.Stroke(colorButton, CS.Theme.Stroke, 0.25, 1)

	local hexLabel = CS.Util.Create("TextLabel", {
		Parent = parent,
		Size = UDim2.new(0, 138, 0, 34),
		Position = UDim2.new(1, -198, 0, y + 7),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = currentHex,
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 12,
		TextXAlignment = Enum.TextXAlignment.Center
	})
	CS.Util.Corner(hexLabel, 9)
	CS.Util.Stroke(hexLabel, CS.Theme.Stroke, 0.55, 1)

	local editHint = CS.Util.Create("TextLabel", {
		Parent = parent,
		Size = UDim2.new(0, 60, 0, 34),
		Position = UDim2.new(1, -58, 0, y + 7),
		BackgroundTransparency = 1,
		Text = "Click",
		TextColor3 = CS.Theme.Muted,
		Font = Enum.Font.GothamBold,
		TextSize = 11,
		TextXAlignment = Enum.TextXAlignment.Right
	})

	local function open()
		CS.UI.OpenColorPicker(parent, title, currentHex, function(color, hex)
			currentHex = hex
			colorButton.BackgroundColor3 = color
			hexLabel.Text = hex
			CS.Util.Set(valueLabel, hex)

			if callback then
				callback(color, hex)
			end

			if CS.RGB and CS.RGB.SetOutlineOnly then
				CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
			end

			if CS.RGB and CS.RGB.ResetNonOutlineColors then
				CS.RGB.ResetNonOutlineColors()
			end
		end)
	end

	colorButton.MouseButton1Click:Connect(open)
	hexLabel.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			open()
		end
	end)
	editHint.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			open()
		end
	end)

	return colorButton, hexLabel
end

function CS.Settings.Build()
	local page = CS.UI.Pages["Settings"]
	if not page then return end

	CS.Util.Clear(page, true)

	local left = CS.Util.Scroll(page)
	left.Size = UDim2.new(0.5, -8, 1, 0)
	left.Position = UDim2.new(0, 0, 0, 0)

	local right = CS.Util.Scroll(page)
	right.Size = UDim2.new(0.5, -8, 1, 0)
	right.Position = UDim2.new(0.5, 8, 0, 0)

	local general = CS.UI.OverlayCard(left, "General", "▣", 290)
	CS.UI.WideToggle(general, 58, "Notifications", "Join, leave, and system notices.", CS.Flags.Notifications, function(v)
		CS.Flags.Notifications = v
		CS.Settings.Save(true)
	end)
	CS.UI.WideToggle(general, 112, "Player Notices", "Show non-friend player notices.", CS.Flags.ShowNonFriendNotices, function(v)
		CS.Flags.ShowNonFriendNotices = v
		CS.Settings.Save(true)
	end)
	CS.UI.WideToggle(general, 166, "Friend Sounds", "Play sounds for friend actions.", CS.Flags.FriendSounds, function(v)
		CS.Flags.FriendSounds = v
		CS.Settings.Save(true)
	end)
	CS.UI.WideToggle(general, 220, "Animations", "Smooth hover and page feedback.", CS.Flags.Animations, function(v)
		CS.Flags.Animations = v
		CS.Settings.Save(true)
	end)

	local rgb = CS.UI.OverlayCard(left, "RGB / Outline Circle", "◎", 290)
	CS.UI.WideToggle(rgb, 58, "Enable RGB", "Rotating outline only. Text/buttons/icons stay normal.", CS.Flags.ColorCycle, function(v)
		CS.Flags.ColorCycle = v
		CS.RGB.SetOutlineOnly(v)
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(rgb, 112, "Circle Color A", "First outline color.", CS.Flags.ColorCycleA or "#FF00D7", function(color, hex)
		CS.Flags.ColorCycleA = hex
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(rgb, 166, "Circle Color B", "Second outline color.", CS.Flags.ColorCycleB or "#00E2FF", function(color, hex)
		CS.Flags.ColorCycleB = hex
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		CS.Settings.Save(true)
	end)
	CS.UI.WideAction(rgb, 220, "Circle Speed", "1 very slow, 10 faster but controlled.", tostring(CS.Flags.ColorCycleSpeedLevel or 1), function(btn)
		CS.Flags.ColorCycleSpeedLevel = ((CS.Flags.ColorCycleSpeedLevel or 1) % 10) + 1
		btn.Text = tostring(CS.Flags.ColorCycleSpeedLevel)
		CS.Settings.Save(true)
	end)

	local colors = CS.UI.OverlayCard(right, "Custom Hex / RGB", "#", 400)
	CS.UI.WideHex(colors, 58, "Accent", "Main active color.", CS.Settings.ColorToHex(CS.Theme.Accent), function(color, hex)
		CS.Theme.Accent = color
		CS.Settings.ApplyVisuals()
		CS.RGB.ResetNonOutlineColors()
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 112, "Background", "Main shell background.", CS.Settings.ColorToHex(CS.Theme.Background), function(color, hex)
		CS.Theme.Background = color
		CS.Theme.Background2 = color
		CS.Theme.Panel = color
		CS.Theme.Panel2 = color
		CS.Settings.ApplyVisuals()
		CS.RGB.ResetNonOutlineColors()
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 166, "Cards", "Card surface color.", CS.Settings.ColorToHex(CS.Theme.Card), function(color, hex)
		CS.Theme.Card = color
		CS.Theme.Card2 = color
		CS.Settings.ApplyVisuals()
		CS.RGB.ResetNonOutlineColors()
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 220, "Outlines", "Border color when RGB is off.", CS.Settings.ColorToHex(CS.Theme.Stroke), function(color, hex)
		CS.Theme.Stroke = color
		CS.Theme.StrokeSoft = color
		CS.Settings.ApplyVisuals()
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 274, "Notifications", "Notice accent color.", CS.Settings.ColorToHex(CS.Theme.NotificationOutline), function(color, hex)
		CS.Theme.NotificationOutline = color
		CS.Theme.Info = color
		CS.Settings.ApplyVisuals()
		CS.RGB.ResetNonOutlineColors()
		CS.Settings.Save(true)
	end)
	CS.UI.WideAction(colors, 328, "Reset Theme", "Restore default colors.", "Reset", function()
		CS.Settings.ResetThemeDefaults()
		CS.Settings.Build()
	end)

	local tools = CS.UI.OverlayCard(right, "Layout / Maintenance", "⚙", 345)
	tools.Position = UDim2.new(0, 0, 0, 414)

	CS.UI.WideAction(tools, 58, "Bigger Menu", "Apply the large clean layout.", "Apply", function()
		if CS.LayoutBig then CS.LayoutBig() end
	end)
	CS.UI.WideAction(tools, 112, "Refresh UI", "Rebuild all pages and labels.", "Refresh", function()
		CS.UI.LiveCharts = {}
		CS.Dashboard.Build()
		CS.PlayerDetails.Build()
		CS.ServerBrowser.Build()
		CS.GameInfo.Build()
		CS.Friends.Build()
		CS.Diagnostics.Build()
		CS.Settings.Build()
		CS.Utilities.Build()

		if CS.LayoutBig then CS.LayoutBig() end
		if CS.AddCloseAndShutdown then CS.AddCloseAndShutdown() end
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		CS.RGB.ResetNonOutlineColors()
	end)
	CS.UI.WideAction(tools, 166, "Save Config", "Save current settings.", "Save", function()
		CS.Settings.Save(false)
	end)
	CS.UI.WideAction(tools, 220, "Load Config", "Reload saved settings.", "Load", function()
		CS.Settings.Load()
		CS.Settings.ApplyVisuals()
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		CS.RGB.ResetNonOutlineColors()
	end)
	CS.UI.WideAction(tools, 274, "Shutdown CS", "Fully destroy the menu.", "Shutdown", function()
		CS.Shutdown()
	end)

	if CS.LayoutBig then CS.LayoutBig() end
	if CS.AddCloseAndShutdown then CS.AddCloseAndShutdown() end
	CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	CS.RGB.ResetNonOutlineColors()
end

local CS_OriginalBuild_392 = CS.Build
function CS.Build()
	CS_OriginalBuild_392()

	if CS.LayoutBig then CS.LayoutBig() end
	CS.Settings.Build()
	if CS.AddCloseAndShutdown then CS.AddCloseAndShutdown() end

	CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	CS.RGB.ResetNonOutlineColors()
end

--// =========================================================
--// END CS v3.9.2 PATCH
--// =========================================================





--// =========================================================
--// CS v3.9.3 HARD OUTLINE-ONLY RGB FIX
--// RGB is restricted to large panel/card outlines only.
--// Excludes: all text, icons, sidebar buttons, top FPS/Ping/Players pills,
--// close/shutdown buttons, color buttons, graph bars, and normal buttons.
--// =========================================================

CS.Version = "3.9.3"
CS.Config.Version = "3.9.3"

CS.RGB = CS.RGB or {}
CS.Runtime.RGBRotation = CS.Runtime.RGBRotation or 0
CS.Flags.ColorCycleSpeedLevel = math.clamp(tonumber(CS.Flags.ColorCycleSpeedLevel) or 1, 1, 10)

function CS.RGB.IsProtectedFromRGB(obj)
	if not obj then
		return true
	end

	if obj:IsA("TextLabel") or obj:IsA("TextButton") or obj:IsA("TextBox") then
		return true
	end

	if obj:IsA("ImageLabel") or obj:IsA("ImageButton") then
		return true
	end

	local current = obj
	while current do
		local name = tostring(current.Name or "")

		if name == "TopBar"
			or name == "PillHolder"
			or name == "CSFullCloseButton"
			or name == "CSShutdownButton"
			or name == "CSOpenButton"
			or name == "VersionBadge"
			or name == "Sidebar"
			or name == "ToastHolder"
			or name == "CSColorPickerPopup" then
			return true
		end

		if current:IsA("TextButton") or current:IsA("TextBox") then
			return true
		end

		current = current.Parent
	end

	return false
end

function CS.RGB.IsAllowedOutlineStroke(stroke)
	if not stroke or not stroke:IsA("UIStroke") then
		return false
	end

	local parent = stroke.Parent
	if not parent or not parent:IsA("Frame") then
		return false
	end

	if CS.RGB.IsProtectedFromRGB(parent) then
		return false
	end

	local name = tostring(parent.Name or "")

	if name == "Main" or name == "Content" then
		return true
	end

	-- Allow large content cards/panels only.
	local ok, size = pcall(function()
		return parent.AbsoluteSize
	end)

	if ok and size then
		if size.X >= 230 and size.Y >= 110 then
			return true
		end
	end

	return false
end

function CS.RGB.RemoveRGBFromNonOutlines()
	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	for _, obj in ipairs(gui:GetDescendants()) do
		-- Destroy RGB gradients anywhere that is not an allowed UIStroke.
		if obj:IsA("UIGradient") and obj.Name == "CSRGBCircleGradient" then
			local parent = obj.Parent
			if not (parent and parent:IsA("UIStroke") and CS.RGB.IsAllowedOutlineStroke(parent)) then
				pcall(function()
					obj:Destroy()
				end)
			end
		end

		-- Remove any gradients directly on text/buttons/icons.
		if obj:IsA("TextLabel") or obj:IsA("TextButton") or obj:IsA("TextBox") or obj:IsA("ImageLabel") or obj:IsA("ImageButton") then
			for _, child in ipairs(obj:GetChildren()) do
				if child:IsA("UIGradient") then
					pcall(function()
						child:Destroy()
					end)
				end
			end
		end
	end
end

function CS.RGB.ForceNormalText()
	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	for _, obj in ipairs(gui:GetDescendants()) do
		if obj:IsA("TextLabel") or obj:IsA("TextButton") or obj:IsA("TextBox") then
			obj.TextStrokeTransparency = 1

			if obj.Name == "CSShutdownButton" then
				obj.TextColor3 = Color3.fromRGB(255, 255, 255)
			else
				obj.TextColor3 = CS.Theme.Text
			end
		end
	end
end

function CS.RGB.GetSlowCircleSpeed()
	local level = math.clamp(tonumber(CS.Flags.ColorCycleSpeedLevel) or 1, 1, 10)
	return 0.015 + ((level - 1) / 9) * 0.18
end

function CS.RGB.SetOutlineOnly(enabled)
	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	for _, stroke in ipairs(gui:GetDescendants()) do
		if stroke:IsA("UIStroke") then
			local gradient = stroke:FindFirstChild("CSRGBCircleGradient")

			if enabled and CS.RGB.IsAllowedOutlineStroke(stroke) then
				if not gradient then
					gradient = Instance.new("UIGradient")
					gradient.Name = "CSRGBCircleGradient"
					gradient.Parent = stroke
				end

				local colorA = CS.Settings.HexToColor(CS.Flags.ColorCycleA) or Color3.fromRGB(255, 0, 215)
				local colorB = CS.Settings.HexToColor(CS.Flags.ColorCycleB) or Color3.fromRGB(0, 226, 255)

				gradient.Color = ColorSequence.new({
					ColorSequenceKeypoint.new(0.00, colorA),
					ColorSequenceKeypoint.new(0.25, colorB),
					ColorSequenceKeypoint.new(0.50, colorA),
					ColorSequenceKeypoint.new(0.75, colorB),
					ColorSequenceKeypoint.new(1.00, colorA)
				})
				gradient.Rotation = CS.Runtime.RGBRotation or 0
				gradient.Enabled = true

				stroke.Color = Color3.fromRGB(255, 255, 255)
				stroke.Transparency = 0.18
				stroke.Thickness = math.max(stroke.Thickness, 1.2)
			else
				if gradient then
					gradient:Destroy()
				end

				if stroke.Parent and stroke.Parent:IsA("GuiObject") then
					local pn = tostring(stroke.Parent.Name or "")
					if pn == "CSShutdownButton" then
						stroke.Color = CS.Theme.Error
					elseif pn == "CSFullCloseButton" then
						stroke.Color = CS.Theme.Stroke
					else
						stroke.Color = CS.Theme.Stroke
					end
				end

				stroke.Transparency = 0.36
				stroke.Thickness = 1
			end
		end
	end

	CS.RGB.RemoveRGBFromNonOutlines()
	CS.RGB.ForceNormalText()
end

function CS.RGB.UpdateCircle()
	if CS.Runtime.Shutdown then return end

	if not CS.Flags.ColorCycle then
		CS.RGB.SetOutlineOnly(false)
		return
	end

	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	CS.Runtime.RGBRotation = ((CS.Runtime.RGBRotation or 0) + CS.RGB.GetSlowCircleSpeed()) % 360

	local colorA = CS.Settings.HexToColor(CS.Flags.ColorCycleA) or Color3.fromRGB(255, 0, 215)
	local colorB = CS.Settings.HexToColor(CS.Flags.ColorCycleB) or Color3.fromRGB(0, 226, 255)

	for _, stroke in ipairs(gui:GetDescendants()) do
		if stroke:IsA("UIStroke") then
			if CS.RGB.IsAllowedOutlineStroke(stroke) then
				local gradient = stroke:FindFirstChild("CSRGBCircleGradient")
				if not gradient then
					gradient = Instance.new("UIGradient")
					gradient.Name = "CSRGBCircleGradient"
					gradient.Parent = stroke
				end

				gradient.Color = ColorSequence.new({
					ColorSequenceKeypoint.new(0.00, colorA),
					ColorSequenceKeypoint.new(0.25, colorB),
					ColorSequenceKeypoint.new(0.50, colorA),
					ColorSequenceKeypoint.new(0.75, colorB),
					ColorSequenceKeypoint.new(1.00, colorA)
				})
				gradient.Rotation = CS.Runtime.RGBRotation
				gradient.Enabled = true

				stroke.Color = Color3.fromRGB(255, 255, 255)
				stroke.Transparency = 0.18
				stroke.Thickness = math.max(stroke.Thickness, 1.2)
			else
				local gradient = stroke:FindFirstChild("CSRGBCircleGradient")
				if gradient then
					gradient:Destroy()
				end
			end
		end
	end

	CS.RGB.RemoveRGBFromNonOutlines()
	CS.RGB.ForceNormalText()
end

-- Full replacement. The old function changed theme colors and caused text/button RGB.
function CS.Settings.UpdateColorCycle()
	if CS.Flags.ColorCycle then
		CS.RGB.UpdateCircle()
	else
		CS.RGB.SetOutlineOnly(false)
	end
end

-- Keep selected sidebar text normal; only tab background can show selection.
local CS_OriginalSwitchPage_393 = CS.UI.SwitchPage
function CS.UI.SwitchPage(name)
	CS_OriginalSwitchPage_393(name)

	for tabName, tab in pairs(CS.UI.Tabs or {}) do
		if tabName == name then
			tab.BackgroundColor3 = CS.Theme.Accent
			tab.BackgroundTransparency = 0.12
			tab.TextColor3 = CS.Theme.Text
		else
			tab.BackgroundColor3 = CS.Theme.Card
			tab.BackgroundTransparency = 0.18
			tab.TextColor3 = CS.Theme.Text
		end

		for _, child in ipairs(tab:GetChildren()) do
			if child:IsA("UIGradient") then
				child:Destroy()
			end
		end
	end

	task.defer(function()
		if CS.RGB and CS.RGB.UpdateCircle then
			CS.RGB.UpdateCircle()
		end
		CS.RGB.ForceNormalText()
	end)
end

local CS_OriginalBuild_393 = CS.Build
function CS.Build()
	CS_OriginalBuild_393()

	if CS.LayoutBig then CS.LayoutBig() end
	if CS.AddCloseAndShutdown then CS.AddCloseAndShutdown() end

	CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	CS.RGB.ForceNormalText()
end

local CS_OriginalConnect_393 = CS.Connect
function CS.Connect()
	CS_OriginalConnect_393()

	CS.Track(CS.Services.RunService.RenderStepped:Connect(function()
		if CS.Runtime.Shutdown then return end

		if CS.Flags.ColorCycle then
			CS.RGB.UpdateCircle()
		else
			CS.RGB.SetOutlineOnly(false)
		end

		if CS.UpdateLiveGraphs then
			CS.UpdateLiveGraphs()
		end

		CS.RGB.ForceNormalText()
	end))
end

--// =========================================================
--// END CS v3.9.3 PATCH
--// =========================================================





--// =========================================================
--// CS v3.9.4 RGB OUTLINE RESTORE + WORKING COLOR PICKER
--// - RGB is restored to outlines/panel borders.
--// - RGB is blocked only from letters/text/characters.
--// - Sidebar/main/card outlines can be RGB again.
--// - Color square + hex button open the picker.
--// - Removed the extra right-side ghost hex value.
--// =========================================================

CS.Version = "3.9.4"
CS.Config.Version = "3.9.4"

CS.RGB = CS.RGB or {}
CS.UI.ActiveColorPicker = nil
CS.Runtime.RGBRotation = CS.Runtime.RGBRotation or 0
CS.Flags.ColorCycleSpeedLevel = math.clamp(tonumber(CS.Flags.ColorCycleSpeedLevel) or 1, 1, 10)

function CS.RGB.ForceNormalText()
	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	for _, obj in ipairs(gui:GetDescendants()) do
		if obj:IsA("TextLabel") or obj:IsA("TextButton") or obj:IsA("TextBox") then
			obj.TextStrokeTransparency = 1

			if obj.Name == "CSShutdownButton" then
				obj.TextColor3 = Color3.fromRGB(255, 255, 255)
			else
				obj.TextColor3 = CS.Theme.Text
			end

			for _, child in ipairs(obj:GetChildren()) do
				if child:IsA("UIGradient") then
					child:Destroy()
				end
			end
		end
	end
end

function CS.RGB.IsAllowedOutlineStroke(stroke)
	if not stroke or not stroke:IsA("UIStroke") then
		return false
	end

	local parent = stroke.Parent
	if not parent or not parent:IsA("TextLabel") and not parent:IsA("TextButton") and not parent:IsA("TextBox") then
		return true
	end

	-- Do not RGB the stroke around text/button widgets, only real panels/frames.
	return false
end

function CS.RGB.SetOutlineOnly(enabled)
	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	local colorA = CS.Settings.HexToColor(CS.Flags.ColorCycleA) or Color3.fromRGB(255, 0, 215)
	local colorB = CS.Settings.HexToColor(CS.Flags.ColorCycleB) or Color3.fromRGB(0, 226, 255)

	for _, stroke in ipairs(gui:GetDescendants()) do
		if stroke:IsA("UIStroke") then
			local gradient = stroke:FindFirstChild("CSRGBCircleGradient")

			if enabled and CS.RGB.IsAllowedOutlineStroke(stroke) then
				if not gradient then
					gradient = Instance.new("UIGradient")
					gradient.Name = "CSRGBCircleGradient"
					gradient.Parent = stroke
				end

				gradient.Color = ColorSequence.new({
					ColorSequenceKeypoint.new(0.00, colorA),
					ColorSequenceKeypoint.new(0.25, colorB),
					ColorSequenceKeypoint.new(0.50, colorA),
					ColorSequenceKeypoint.new(0.75, colorB),
					ColorSequenceKeypoint.new(1.00, colorA)
				})
				gradient.Rotation = CS.Runtime.RGBRotation or 0
				gradient.Enabled = true

				stroke.Color = Color3.fromRGB(255, 255, 255)
				stroke.Transparency = 0.18
				stroke.Thickness = math.max(stroke.Thickness, 1.15)
			else
				if gradient then
					gradient:Destroy()
				end

				stroke.Color = CS.Theme.Stroke
				stroke.Transparency = 0.36
				stroke.Thickness = 1
			end
		end
	end

	CS.RGB.ForceNormalText()
end

function CS.RGB.GetSlowCircleSpeed()
	local level = math.clamp(tonumber(CS.Flags.ColorCycleSpeedLevel) or 1, 1, 10)
	return 0.015 + ((level - 1) / 9) * 0.18
end

function CS.RGB.UpdateCircle()
	if CS.Runtime.Shutdown then return end

	if not CS.Flags.ColorCycle then
		CS.RGB.SetOutlineOnly(false)
		return
	end

	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	CS.Runtime.RGBRotation = ((CS.Runtime.RGBRotation or 0) + CS.RGB.GetSlowCircleSpeed()) % 360

	local colorA = CS.Settings.HexToColor(CS.Flags.ColorCycleA) or Color3.fromRGB(255, 0, 215)
	local colorB = CS.Settings.HexToColor(CS.Flags.ColorCycleB) or Color3.fromRGB(0, 226, 255)

	for _, stroke in ipairs(gui:GetDescendants()) do
		if stroke:IsA("UIStroke") then
			local gradient = stroke:FindFirstChild("CSRGBCircleGradient")

			if CS.RGB.IsAllowedOutlineStroke(stroke) then
				if not gradient then
					gradient = Instance.new("UIGradient")
					gradient.Name = "CSRGBCircleGradient"
					gradient.Parent = stroke
				end

				gradient.Color = ColorSequence.new({
					ColorSequenceKeypoint.new(0.00, colorA),
					ColorSequenceKeypoint.new(0.25, colorB),
					ColorSequenceKeypoint.new(0.50, colorA),
					ColorSequenceKeypoint.new(0.75, colorB),
					ColorSequenceKeypoint.new(1.00, colorA)
				})
				gradient.Rotation = CS.Runtime.RGBRotation
				gradient.Enabled = true

				stroke.Color = Color3.fromRGB(255, 255, 255)
				stroke.Transparency = 0.18
				stroke.Thickness = math.max(stroke.Thickness, 1.15)
			else
				if gradient then
					gradient:Destroy()
				end
			end
		end
	end

	CS.RGB.ForceNormalText()
end

function CS.Settings.UpdateColorCycle()
	if CS.Flags.ColorCycle then
		CS.RGB.UpdateCircle()
	else
		CS.RGB.SetOutlineOnly(false)
	end
end

function CS.UI.CloseColorPicker()
	if CS.UI.ActiveColorPicker and CS.UI.ActiveColorPicker.Parent then
		CS.UI.ActiveColorPicker:Destroy()
	end
	CS.UI.ActiveColorPicker = nil
end

function CS.UI.OpenColorPicker(parent, title, currentHex, onSave)
	CS.UI.CloseColorPicker()

	local host = CS.UI.Objects.Content or parent
	local startColor = CS.Settings.HexToColor(currentHex or "#FFFFFF") or Color3.fromRGB(255, 255, 255)
	local hue, sat, val = startColor:ToHSV()

	local pickerCard = CS.Util.Create("Frame", {
		Parent = host,
		Name = "CSColorPickerPopup",
		Size = UDim2.new(0, 520, 0, 360),
		Position = UDim2.new(0.5, -260, 0.5, -180),
		BackgroundColor3 = CS.Theme.Card,
		BackgroundTransparency = 0.02,
		BorderSizePixel = 0,
		ZIndex = 250
	})

	CS.UI.ActiveColorPicker = pickerCard
	CS.Util.Corner(pickerCard, 16)
	CS.Util.Stroke(pickerCard, CS.Theme.Stroke, 0.12, 1)

	local titleLabel = CS.Util.Create("TextLabel", {
		Parent = pickerCard,
		Size = UDim2.new(1, -110, 0, 36),
		Position = UDim2.new(0, 16, 0, 10),
		BackgroundTransparency = 1,
		Text = "COLOR PICKER: " .. tostring(title or "Color"),
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 14,
		TextXAlignment = Enum.TextXAlignment.Left,
		ZIndex = 251
	})

	local close = CS.Util.Create("TextButton", {
		Parent = pickerCard,
		Size = UDim2.new(0, 76, 0, 30),
		Position = UDim2.new(1, -92, 0, 12),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = "Close",
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 11,
		ZIndex = 251
	})
	CS.Util.Corner(close, 8)
	CS.Util.Stroke(close, CS.Theme.Stroke, 0.45, 1)

	local preview = CS.Util.Create("Frame", {
		Parent = pickerCard,
		Size = UDim2.new(0, 76, 0, 76),
		Position = UDim2.new(0, 18, 0, 56),
		BackgroundColor3 = startColor,
		BorderSizePixel = 0,
		ZIndex = 251
	})
	CS.Util.Corner(preview, 12)
	CS.Util.Stroke(preview, CS.Theme.Stroke, 0.35, 1)

	local hexBox = CS.Util.Create("TextBox", {
		Parent = pickerCard,
		Size = UDim2.new(1, -124, 0, 38),
		Position = UDim2.new(0, 106, 0, 56),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = currentHex or "#FFFFFF",
		PlaceholderText = "#RRGGBB",
		TextColor3 = CS.Theme.Text,
		PlaceholderColor3 = CS.Theme.Muted,
		Font = Enum.Font.GothamBold,
		TextSize = 13,
		ClearTextOnFocus = false,
		ZIndex = 251
	})
	CS.Util.Corner(hexBox, 9)
	CS.Util.Stroke(hexBox, CS.Theme.Stroke, 0.45, 1)

	local palette = {
		"#FF005D", "#FF3B30", "#FF9500", "#FFD60A", "#32D74B", "#00E2FF",
		"#0BD7FD", "#007AFF", "#5759EC", "#9B5CFF", "#FF00D7", "#FFFFFF",
		"#C7C7CC", "#6B7280", "#1C1C28", "#000000"
	}

	local paletteHolder = CS.Util.Create("Frame", {
		Parent = pickerCard,
		Size = UDim2.new(1, -124, 0, 48),
		Position = UDim2.new(0, 106, 0, 104),
		BackgroundTransparency = 1,
		ZIndex = 251
	})

	local function setColor(color, hex)
		hex = hex or CS.Settings.ColorToHex(color)
		preview.BackgroundColor3 = color
		hexBox.Text = hex
		local h, s, v = color:ToHSV()
		hue, sat, val = h, s, v
	end

	for i, hex in ipairs(palette) do
		local color = CS.Settings.HexToColor(hex)
		local swatch = CS.Util.Create("TextButton", {
			Parent = paletteHolder,
			Size = UDim2.new(0, 24, 0, 24),
			Position = UDim2.new(0, ((i - 1) % 8) * 29, 0, math.floor((i - 1) / 8) * 25),
			BackgroundColor3 = color,
			BorderSizePixel = 0,
			Text = "",
			AutoButtonColor = true,
			ZIndex = 252
		})
		CS.Util.Corner(swatch, 999)
		CS.Util.Stroke(swatch, CS.Theme.Stroke, 0.35, 1)

		swatch.MouseButton1Click:Connect(function()
			setColor(color, hex)
		end)
	end

	local gradientBox = CS.Util.Create("Frame", {
		Parent = pickerCard,
		Size = UDim2.new(1, -36, 0, 126),
		Position = UDim2.new(0, 18, 0, 164),
		BackgroundColor3 = Color3.fromHSV(hue, 1, 1),
		BorderSizePixel = 0,
		ClipsDescendants = true,
		ZIndex = 251
	})
	CS.Util.Corner(gradientBox, 10)
	CS.Util.Stroke(gradientBox, CS.Theme.Stroke, 0.45, 1)

	local satGrad = Instance.new("UIGradient")
	satGrad.Color = ColorSequence.new(Color3.fromRGB(255, 255, 255), Color3.fromHSV(hue, 1, 1))
	satGrad.Rotation = 0
	satGrad.Parent = gradientBox

	local darkOverlay = CS.Util.Create("Frame", {
		Parent = gradientBox,
		Size = UDim2.new(1, 0, 1, 0),
		BackgroundColor3 = Color3.fromRGB(0, 0, 0),
		BorderSizePixel = 0,
		ZIndex = 252
	})

	local valueGrad = Instance.new("UIGradient")
	valueGrad.Transparency = NumberSequence.new({
		NumberSequenceKeypoint.new(0, 1),
		NumberSequenceKeypoint.new(1, 0)
	})
	valueGrad.Rotation = 90
	valueGrad.Parent = darkOverlay

	local cursor = CS.Util.Create("Frame", {
		Parent = gradientBox,
		Size = UDim2.new(0, 14, 0, 14),
		Position = UDim2.new(sat, -7, 1 - val, -7),
		BackgroundColor3 = Color3.fromRGB(255, 255, 255),
		BorderSizePixel = 0,
		ZIndex = 253
	})
	CS.Util.Corner(cursor, 999)
	CS.Util.Stroke(cursor, Color3.fromRGB(0, 0, 0), 0.15, 2)

	local hueBar = CS.Util.Create("Frame", {
		Parent = pickerCard,
		Size = UDim2.new(1, -156, 0, 18),
		Position = UDim2.new(0, 18, 0, 304),
		BackgroundColor3 = Color3.fromRGB(255, 255, 255),
		BorderSizePixel = 0,
		ZIndex = 251
	})
	CS.Util.Corner(hueBar, 999)
	CS.Util.Stroke(hueBar, CS.Theme.Stroke, 0.45, 1)

	local hueGrad = Instance.new("UIGradient")
	hueGrad.Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0.00, Color3.fromRGB(255, 0, 0)),
		ColorSequenceKeypoint.new(0.16, Color3.fromRGB(255, 255, 0)),
		ColorSequenceKeypoint.new(0.33, Color3.fromRGB(0, 255, 0)),
		ColorSequenceKeypoint.new(0.50, Color3.fromRGB(0, 255, 255)),
		ColorSequenceKeypoint.new(0.66, Color3.fromRGB(0, 0, 255)),
		ColorSequenceKeypoint.new(0.83, Color3.fromRGB(255, 0, 255)),
		ColorSequenceKeypoint.new(1.00, Color3.fromRGB(255, 0, 0))
	})
	hueGrad.Parent = hueBar

	local hueCursor = CS.Util.Create("Frame", {
		Parent = hueBar,
		Size = UDim2.new(0, 12, 0, 24),
		Position = UDim2.new(hue, -6, 0.5, -12),
		BackgroundColor3 = Color3.fromRGB(25, 25, 25),
		BorderSizePixel = 0,
		ZIndex = 253
	})
	CS.Util.Corner(hueCursor, 999)
	CS.Util.Stroke(hueCursor, CS.Theme.Text, 0.25, 2)

	local save = CS.Util.Create("TextButton", {
		Parent = pickerCard,
		Size = UDim2.new(0, 110, 0, 34),
		Position = UDim2.new(1, -128, 1, -48),
		BackgroundColor3 = CS.Theme.Success,
		BackgroundTransparency = 0.04,
		BorderSizePixel = 0,
		Text = "Save",
		TextColor3 = Color3.fromRGB(0, 0, 0),
		Font = Enum.Font.GothamBold,
		TextSize = 12,
		ZIndex = 251
	})
	CS.Util.Corner(save, 9)

	local draggingPicker = false
	local draggingHue = false

	local function refreshHSV()
		local color = Color3.fromHSV(hue, sat, val)
		local hex = CS.Settings.ColorToHex(color)
		preview.BackgroundColor3 = color
		hexBox.Text = hex
		gradientBox.BackgroundColor3 = Color3.fromHSV(hue, 1, 1)
		satGrad.Color = ColorSequence.new(Color3.fromRGB(255, 255, 255), Color3.fromHSV(hue, 1, 1))
	end

	local function updatePicker(input)
		local x = math.clamp((input.Position.X - gradientBox.AbsolutePosition.X) / math.max(gradientBox.AbsoluteSize.X, 1), 0, 1)
		local y = math.clamp((input.Position.Y - gradientBox.AbsolutePosition.Y) / math.max(gradientBox.AbsoluteSize.Y, 1), 0, 1)
		sat = x
		val = 1 - y
		cursor.Position = UDim2.new(x, -7, y, -7)
		refreshHSV()
	end

	local function updateHue(input)
		local x = math.clamp((input.Position.X - hueBar.AbsolutePosition.X) / math.max(hueBar.AbsoluteSize.X, 1), 0, 1)
		hue = x
		hueCursor.Position = UDim2.new(x, -6, 0.5, -12)
		refreshHSV()
	end

	gradientBox.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			draggingPicker = true
			updatePicker(input)
		end
	end)

	darkOverlay.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			draggingPicker = true
			updatePicker(input)
		end
	end)

	hueBar.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			draggingHue = true
			updateHue(input)
		end
	end)

	CS.Services.UserInputService.InputChanged:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseMovement then
			if draggingPicker then
				updatePicker(input)
			elseif draggingHue then
				updateHue(input)
			end
		end
	end)

	CS.Services.UserInputService.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 then
			draggingPicker = false
			draggingHue = false
		end
	end)

	hexBox.FocusLost:Connect(function()
		local color = CS.Settings.HexToColor(hexBox.Text)
		if color then
			setColor(color, CS.Settings.ColorToHex(color))
			cursor.Position = UDim2.new(sat, -7, 1 - val, -7)
			hueCursor.Position = UDim2.new(hue, -6, 0.5, -12)
			refreshHSV()
		else
			CS.Notify.Push("Color", "Invalid hex.", CS.Theme.Warning)
		end
	end)

	close.MouseButton1Click:Connect(function()
		CS.UI.CloseColorPicker()
	end)

	save.MouseButton1Click:Connect(function()
		local color = CS.Settings.HexToColor(hexBox.Text)
		if not color then
			CS.Notify.Push("Color", "Invalid hex.", CS.Theme.Warning)
			return
		end

		local hex = CS.Settings.ColorToHex(color)
		if onSave then
			onSave(color, hex)
		end

		CS.UI.CloseColorPicker()
	end)

	refreshHSV()
end

function CS.UI.WideHex(parent, y, title, desc, hexText, callback)
	-- Empty value prevents the duplicate ghost #HEX text on the far right.
	local valueLabel = CS.UI.OverlayValue(parent, y, "•", title, "", desc)

	local currentHex = hexText or "#FFFFFF"
	local currentColor = CS.Settings.HexToColor(currentHex) or Color3.fromRGB(255, 255, 255)

	local colorButton = CS.Util.Create("TextButton", {
		Parent = parent,
		Size = UDim2.new(0, 46, 0, 34),
		Position = UDim2.new(1, -250, 0, y + 7),
		BackgroundColor3 = currentColor,
		BackgroundTransparency = 0,
		BorderSizePixel = 0,
		Text = "",
		AutoButtonColor = true
	})
	CS.Util.Corner(colorButton, 10)
	CS.Util.Stroke(colorButton, CS.Theme.Stroke, 0.25, 1)

	local hexButton = CS.Util.Create("TextButton", {
		Parent = parent,
		Size = UDim2.new(0, 144, 0, 34),
		Position = UDim2.new(1, -194, 0, y + 7),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = currentHex,
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = 12,
		AutoButtonColor = true
	})
	CS.Util.Corner(hexButton, 9)
	CS.Util.Stroke(hexButton, CS.Theme.Stroke, 0.55, 1)

	local function open()
		CS.UI.OpenColorPicker(parent, title, currentHex, function(color, hex)
			currentHex = hex
			colorButton.BackgroundColor3 = color
			hexButton.Text = hex
			CS.Util.Set(valueLabel, "")

			if callback then
				callback(color, hex)
			end

			if CS.RGB and CS.RGB.SetOutlineOnly then
				CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
			end

			if CS.RGB and CS.RGB.ForceNormalText then
				CS.RGB.ForceNormalText()
			end
		end)
	end

	colorButton.MouseButton1Click:Connect(open)
	hexButton.MouseButton1Click:Connect(open)

	return colorButton, hexButton
end

-- Re-apply current settings page using fixed WideHex.
local CS_OriginalSettingsBuild_394 = CS.Settings.Build
function CS.Settings.Build()
	CS_OriginalSettingsBuild_394()

	if CS.RGB and CS.RGB.SetOutlineOnly then
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	end
end

local CS_OriginalBuild_394 = CS.Build
function CS.Build()
	CS_OriginalBuild_394()

	if CS.RGB and CS.RGB.SetOutlineOnly then
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	end
end

local CS_OriginalConnect_394 = CS.Connect
function CS.Connect()
	CS_OriginalConnect_394()

	CS.Track(CS.Services.RunService.RenderStepped:Connect(function()
		if CS.Runtime.Shutdown then return end

		if CS.RGB and CS.RGB.UpdateCircle then
			CS.RGB.UpdateCircle()
		end

		if CS.RGB and CS.RGB.ForceNormalText then
			CS.RGB.ForceNormalText()
		end
	end))
end

--// =========================================================
--// END CS v3.9.4 PATCH
--// =========================================================





--// =========================================================
--// CS v3.9.5 TOP RAIL RGB EXCLUSION PATCH
--// Keeps RGB off the thin top accent rail / long divider line.
--// RGB stays on panel outlines only, not text or top rail.
--// =========================================================

CS.Version = "3.9.5"
CS.Config.Version = "3.9.5"

CS.RGB = CS.RGB or {}

function CS.RGB.IsTopRailObject(obj)
	if not obj then return false end

	local current = obj
	while current do
		local name = tostring(current.Name or "")

		if name == "AccentRail"
			or name == "TopBar"
			or name == "PillHolder"
			or name == "VersionBadge"
			or name == "CSFullCloseButton"
			or name == "CSShutdownButton" then
			return true
		end

		current = current.Parent
	end

	return false
end

function CS.RGB.IsAllowedOutlineStroke(stroke)
	if not stroke or not stroke:IsA("UIStroke") then
		return false
	end

	local parent = stroke.Parent
	if not parent then
		return false
	end

	if CS.RGB.IsTopRailObject(parent) then
		return false
	end

	if parent:IsA("TextLabel") or parent:IsA("TextButton") or parent:IsA("TextBox") then
		return false
	end

	-- RGB only on real frames/panels/cards, not the thin accent rail.
	if parent:IsA("Frame") then
		if parent.Name == "AccentRail" then
			return false
		end

		local ok, size = pcall(function()
			return parent.AbsoluteSize
		end)

		if ok and size then
			-- avoid thin separators/rails
			if size.Y <= 8 or size.X <= 8 then
				return false
			end
		end

		return true
	end

	return false
end

function CS.RGB.FixTopRail()
	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	local accentRail = CS.UI.Objects.AccentRail
	if accentRail then
		accentRail.BackgroundColor3 = CS.Theme.Accent
		accentRail.BackgroundTransparency = 0.15

		for _, child in ipairs(accentRail:GetChildren()) do
			if child:IsA("UIGradient") and child.Name == "CSRGBCircleGradient" then
				child:Destroy()
			end
		end
	end

	for _, obj in ipairs(gui:GetDescendants()) do
		if CS.RGB.IsTopRailObject(obj) then
			if obj:IsA("UIStroke") then
				local gradient = obj:FindFirstChild("CSRGBCircleGradient")
				if gradient then gradient:Destroy() end
				obj.Color = CS.Theme.Stroke
				obj.Transparency = 0.36
				obj.Thickness = 1
			elseif obj:IsA("Frame") then
				local gradient = obj:FindFirstChild("CSRGBCircleGradient")
				if gradient then gradient:Destroy() end
			end
		end
	end
end

local CS_OriginalUpdateCircle_395 = CS.RGB.UpdateCircle
function CS.RGB.UpdateCircle()
	if CS_OriginalUpdateCircle_395 then
		CS_OriginalUpdateCircle_395()
	end

	CS.RGB.FixTopRail()
	if CS.RGB.ForceNormalText then
		CS.RGB.ForceNormalText()
	end
end

local CS_OriginalSetOutlineOnly_395 = CS.RGB.SetOutlineOnly
function CS.RGB.SetOutlineOnly(enabled)
	if CS_OriginalSetOutlineOnly_395 then
		CS_OriginalSetOutlineOnly_395(enabled)
	end

	CS.RGB.FixTopRail()
	if CS.RGB.ForceNormalText then
		CS.RGB.ForceNormalText()
	end
end

local CS_OriginalBuild_395 = CS.Build
function CS.Build()
	CS_OriginalBuild_395()

	if CS.RGB and CS.RGB.SetOutlineOnly then
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	end

	CS.RGB.FixTopRail()
end

local CS_OriginalConnect_395 = CS.Connect
function CS.Connect()
	CS_OriginalConnect_395()

	CS.Track(CS.Services.RunService.RenderStepped:Connect(function()
		if CS.Runtime.Shutdown then return end
		if CS.RGB and CS.RGB.FixTopRail then
			CS.RGB.FixTopRail()
		end
	end))
end

--// =========================================================
--// END CS v3.9.5 PATCH
--// =========================================================





--// =========================================================
--// CS v3.9.6 BACKGROUND COLOR OPTION PATCH
--// Adds a clearly separate Menu Background option and applies it
--// to the main shell, sidebar, and content panels.
--// =========================================================

CS.Version = "3.9.6"
CS.Config.Version = "3.9.6"

function CS.Settings.ApplyMenuBackground(color)
	if not color then return end

	CS.Theme.Background = color
	CS.Theme.Background2 = color
	CS.Theme.Panel = color
	CS.Theme.Panel2 = color

	if CS.UI and CS.UI.Objects then
		if CS.UI.Objects.Main then
			CS.UI.Objects.Main.BackgroundColor3 = color
		end

		if CS.UI.Objects.Sidebar then
			CS.UI.Objects.Sidebar.BackgroundColor3 = color
		end

		if CS.UI.Objects.Content then
			CS.UI.Objects.Content.BackgroundColor3 = color
		end
	end

	CS.Settings.ApplyVisuals()

	if CS.RGB and CS.RGB.SetOutlineOnly then
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	end

	if CS.RGB and CS.RGB.ForceNormalText then
		CS.RGB.ForceNormalText()
	end

	CS.Settings.Save(true)
end

-- Replace Settings page so Custom Hex/RGB has an obvious Menu Background row.
function CS.Settings.Build()
	local page = CS.UI.Pages["Settings"]
	if not page then return end

	CS.Util.Clear(page, true)

	local left = CS.Util.Scroll(page)
	left.Size = UDim2.new(0.5, -8, 1, 0)
	left.Position = UDim2.new(0, 0, 0, 0)

	local right = CS.Util.Scroll(page)
	right.Size = UDim2.new(0.5, -8, 1, 0)
	right.Position = UDim2.new(0.5, 8, 0, 0)

	local general = CS.UI.OverlayCard(left, "General", "▣", 290)
	CS.UI.WideToggle(general, 58, "Notifications", "Join, leave, and system notices.", CS.Flags.Notifications, function(v)
		CS.Flags.Notifications = v
		CS.Settings.Save(true)
	end)
	CS.UI.WideToggle(general, 112, "Player Notices", "Show non-friend player notices.", CS.Flags.ShowNonFriendNotices, function(v)
		CS.Flags.ShowNonFriendNotices = v
		CS.Settings.Save(true)
	end)
	CS.UI.WideToggle(general, 166, "Friend Sounds", "Play sounds for friend actions.", CS.Flags.FriendSounds, function(v)
		CS.Flags.FriendSounds = v
		CS.Settings.Save(true)
	end)
	CS.UI.WideToggle(general, 220, "Animations", "Smooth hover and page feedback.", CS.Flags.Animations, function(v)
		CS.Flags.Animations = v
		CS.Settings.Save(true)
	end)

	local rgb = CS.UI.OverlayCard(left, "RGB / Outline Circle", "◎", 290)
	CS.UI.WideToggle(rgb, 58, "Enable RGB", "Rotating outline only. Text/buttons/icons stay normal.", CS.Flags.ColorCycle, function(v)
		CS.Flags.ColorCycle = v
		if CS.RGB and CS.RGB.SetOutlineOnly then
			CS.RGB.SetOutlineOnly(v)
		end
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(rgb, 112, "Circle Color A", "First outline color.", CS.Flags.ColorCycleA or "#FF00D7", function(color, hex)
		CS.Flags.ColorCycleA = hex
		if CS.RGB and CS.RGB.SetOutlineOnly then
			CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		end
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(rgb, 166, "Circle Color B", "Second outline color.", CS.Flags.ColorCycleB or "#00E2FF", function(color, hex)
		CS.Flags.ColorCycleB = hex
		if CS.RGB and CS.RGB.SetOutlineOnly then
			CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		end
		CS.Settings.Save(true)
	end)
	CS.UI.WideAction(rgb, 220, "Circle Speed", "1 very slow, 10 faster but controlled.", tostring(CS.Flags.ColorCycleSpeedLevel or 1), function(btn)
		CS.Flags.ColorCycleSpeedLevel = ((CS.Flags.ColorCycleSpeedLevel or 1) % 10) + 1
		btn.Text = tostring(CS.Flags.ColorCycleSpeedLevel)
		CS.Settings.Save(true)
	end)

	local colors = CS.UI.OverlayCard(right, "Custom Hex / RGB", "#", 455)
	CS.UI.WideHex(colors, 58, "Accent", "Main active color.", CS.Settings.ColorToHex(CS.Theme.Accent), function(color, hex)
		CS.Theme.Accent = color
		CS.Settings.ApplyVisuals()
		if CS.RGB and CS.RGB.ForceNormalText then CS.RGB.ForceNormalText() end
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 112, "Menu Background", "Main shell, sidebar, and content panels.", CS.Settings.ColorToHex(CS.Theme.Background), function(color, hex)
		CS.Settings.ApplyMenuBackground(color)
	end)
	CS.UI.WideHex(colors, 166, "Card Background", "Individual card surface color.", CS.Settings.ColorToHex(CS.Theme.Card), function(color, hex)
		CS.Theme.Card = color
		CS.Theme.Card2 = color
		CS.Settings.ApplyVisuals()
		if CS.RGB and CS.RGB.ForceNormalText then CS.RGB.ForceNormalText() end
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 220, "Outlines", "Border color when RGB is off.", CS.Settings.ColorToHex(CS.Theme.Stroke), function(color, hex)
		CS.Theme.Stroke = color
		CS.Theme.StrokeSoft = color
		CS.Settings.ApplyVisuals()
		if CS.RGB and CS.RGB.SetOutlineOnly then
			CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		end
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 274, "Notifications", "Notice accent color.", CS.Settings.ColorToHex(CS.Theme.NotificationOutline), function(color, hex)
		CS.Theme.NotificationOutline = color
		CS.Theme.Info = color
		CS.Settings.ApplyVisuals()
		if CS.RGB and CS.RGB.ForceNormalText then CS.RGB.ForceNormalText() end
		CS.Settings.Save(true)
	end)
	CS.UI.WideHex(colors, 328, "Text Color", "Normal label/button text color.", CS.Settings.ColorToHex(CS.Theme.Text), function(color, hex)
		CS.Theme.Text = color
		if CS.RGB and CS.RGB.ForceNormalText then CS.RGB.ForceNormalText() end
		CS.Settings.Save(true)
	end)
	CS.UI.WideAction(colors, 382, "Reset Theme", "Restore default colors.", "Reset", function()
		CS.Settings.ResetThemeDefaults()
		CS.Settings.Build()
	end)

	local tools = CS.UI.OverlayCard(right, "Layout / Maintenance", "⚙", 345)
	tools.Position = UDim2.new(0, 0, 0, 470)

	CS.UI.WideAction(tools, 58, "Bigger Menu", "Apply the large clean layout.", "Apply", function()
		if CS.LayoutBig then CS.LayoutBig() end
	end)
	CS.UI.WideAction(tools, 112, "Refresh UI", "Rebuild all pages and labels.", "Refresh", function()
		CS.UI.LiveCharts = {}
		CS.Dashboard.Build()
		CS.PlayerDetails.Build()
		CS.ServerBrowser.Build()
		CS.GameInfo.Build()
		CS.Friends.Build()
		CS.Diagnostics.Build()
		CS.Settings.Build()
		CS.Utilities.Build()

		if CS.LayoutBig then CS.LayoutBig() end
		if CS.AddCloseAndShutdown then CS.AddCloseAndShutdown() end
		if CS.RGB and CS.RGB.SetOutlineOnly then
			CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		end
		if CS.RGB and CS.RGB.ForceNormalText then
			CS.RGB.ForceNormalText()
		end
	end)
	CS.UI.WideAction(tools, 166, "Save Config", "Save current settings.", "Save", function()
		CS.Settings.Save(false)
	end)
	CS.UI.WideAction(tools, 220, "Load Config", "Reload saved settings.", "Load", function()
		CS.Settings.Load()
		CS.Settings.ApplyVisuals()
		if CS.RGB and CS.RGB.SetOutlineOnly then
			CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
		end
		if CS.RGB and CS.RGB.ForceNormalText then
			CS.RGB.ForceNormalText()
		end
	end)
	CS.UI.WideAction(tools, 274, "Shutdown CS", "Fully destroy the menu.", "Shutdown", function()
		CS.Shutdown()
	end)

	if CS.LayoutBig then CS.LayoutBig() end
	if CS.AddCloseAndShutdown then CS.AddCloseAndShutdown() end
	if CS.RGB and CS.RGB.SetOutlineOnly then
		CS.RGB.SetOutlineOnly(CS.Flags.ColorCycle)
	end
	if CS.RGB and CS.RGB.ForceNormalText then
		CS.RGB.ForceNormalText()
	end
end

local CS_OriginalBuild_396 = CS.Build
function CS.Build()
	CS_OriginalBuild_396()
	CS.Settings.Build()
end

--// =========================================================
--// END CS v3.9.6 PATCH
--// =========================================================





--// =========================================================
--// CS v4.1.2 FULL FEATURES / NO ANIMATION
--// Keeps the feature-heavy UI base, but removes animation behavior.
--// Adds:
--// - Instant open/minimize
--// - "-" button next to FPS
--// - Rejoin button next to FPS
--// - No close button
--// - No animation loader / phase loader / tween menu open
--// =========================================================

CS.Version = "4.1.2"
CS.Config.Version = "4.1.2"

CS.Actions = CS.Actions or {}
CS.Runtime.MenuAnimating = false

function CS.UI.InstantOpen()
	CS.Flags.Open = true

	if CS.UI.Objects.Main then
		CS.UI.Objects.Main.Visible = true
		CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency or 0.54
	end

	if CS.UI.Objects.OpenButton then
		CS.UI.Objects.OpenButton.Text = "Close CS"
	end

	CS.UI.SwitchPage(CS.Runtime.CurrentPage or "Dashboard")
end

function CS.UI.InstantMinimize()
	CS.Flags.Open = false

	if CS.UI.Objects.Main then
		CS.UI.Objects.Main.Visible = false
	end

	if CS.UI.Objects.OpenButton then
		CS.UI.Objects.OpenButton.Text = "Open CS"
	end
end

function CS.UI.Toggle()
	if CS.Flags.Open then
		CS.UI.InstantMinimize()
	else
		CS.UI.InstantOpen()
	end
end

function CS.Actions.RejoinServer()
	local TeleportService = game:GetService("TeleportService")
	local Players = game:GetService("Players")
	local player = Players.LocalPlayer

	CS.Notify.Push("Rejoin", "Rejoining current server...", CS.Theme.Info)

	task.delay(0.15, function()
		pcall(function()
			TeleportService:TeleportToPlaceInstance(game.PlaceId, game.JobId, player)
		end)
	end)
end

function CS.UI.MakeTopThemeButton(parent, name, text, pos, size, callback)
	local existing = parent:FindFirstChild(name)
	if existing then
		existing:Destroy()
	end

	local button = CS.Util.Create("TextButton", {
		Parent = parent,
		Name = name,
		Size = size,
		Position = pos,
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = text,
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.GothamBold,
		TextSize = text == "-" and 22 or 12,
		AutoButtonColor = true,
		ZIndex = 240
	})

	CS.Util.Corner(button, 10)
	CS.Util.Stroke(button, CS.Theme.Stroke, 0.25, 1)

	button.MouseEnter:Connect(function()
		button.BackgroundColor3 = CS.Theme.Accent
		button.TextColor3 = CS.Theme.Background
	end)

	button.MouseLeave:Connect(function()
		button.BackgroundColor3 = CS.Theme.Card2
		button.TextColor3 = CS.Theme.Text
	end)

	button.MouseButton1Click:Connect(function()
		if callback then
			callback()
		end
	end)

	return button
end

function CS.UI.RebuildTopActions()
	local main = CS.UI and CS.UI.Objects and CS.UI.Objects.Main
	if not main then return end

	for _, name in ipairs({
		"CSFullCloseButton",
		"CSCloseButton",
		"CSMinimizeButton",
		"CSRejoinButton",
		"CSShutdownButton",
		"CSOpenCloseButton"
	}) do
		local obj = main:FindFirstChild(name)
		if obj then
			obj:Destroy()
		end
	end

	-- Next to the FPS pill; kept away from Ping/Players.
	CS.UI.MakeTopThemeButton(
		main,
		"CSMinimizeButton",
		"-",
		UDim2.new(0, 875, 0, 14),
		UDim2.new(0, 44, 0, 38),
		function()
			CS.UI.InstantMinimize()
		end
	)

	CS.UI.MakeTopThemeButton(
		main,
		"CSRejoinButton",
		"Rejoin",
		UDim2.new(0, 925, 0, 14),
		UDim2.new(0, 88, 0, 38),
		function()
			CS.Actions.RejoinServer()
		end
	)
end

function CS.AddCloseAndShutdown()
	CS.UI.RebuildTopActions()
end

-- Remove leftover animation scale objects if the user ran older versions in the same session.
function CS.UI.RemoveAnimationObjects()
	local main = CS.UI and CS.UI.Objects and CS.UI.Objects.Main
	if not main then return end

	for _, child in ipairs(main:GetChildren()) do
		if child:IsA("UIScale") and (
			child.Name == "CSMinimizeScale"
			or child.Name == "CSSimpleScale"
			or child.Name == "CSPhaseScale"
			or child.Name == "CSMenuOpenScale"
			or child.Name == "CS_OpenCloseScale"
			or child.Name == "CSFastScale"
			or child.Name == "CSMenuScale"
		) then
			child:Destroy()
		end

		if child.Name == "CSPhaseLoader"
			or child.Name == "CSAnimationCurtain" then
			child:Destroy()
		end
	end
end

local CS_OriginalBuild_412 = CS.Build
function CS.Build()
	CS_OriginalBuild_412()

	if CS.UI and CS.UI.Objects and CS.UI.Objects.Main then
		CS.UI.RemoveAnimationObjects()
		CS.UI.Objects.Main.Visible = false
		CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency or 0.54
	end

	CS.UI.RebuildTopActions()
end

local CS_OriginalSwitchPage_412 = CS.UI.SwitchPage
function CS.UI.SwitchPage(name)
	CS_OriginalSwitchPage_412(name)

	task.defer(function()
		if CS.UI and CS.UI.RebuildTopActions then
			CS.UI.RebuildTopActions()
		end

		if CS.UI and CS.UI.RemoveAnimationObjects then
			CS.UI.RemoveAnimationObjects()
		end
	end)
end

--// =========================================================
--// END CS v4.1.2 PATCH
--// =========================================================





--// =========================================================
--// CS v4.1.4 FULL FEATURE FPS OPTIMIZED
--// Keeps the fuller feature build, but reduces FPS drops.
--// Fixes:
--// - Removes top "-" and Rejoin buttons.
--// - Removes animation objects.
--// - Stops expensive per-frame full GUI scans.
--// - RGB outline update is throttled.
--// - Open / close is instant.
--// =========================================================

CS.Version = "4.1.4"
CS.Config.Version = "4.1.4"

CS.Runtime.Shutdown = false
CS.Runtime.LastRGBUpdate = 0
CS.Runtime.RGBRotation = CS.Runtime.RGBRotation or 0
CS.Runtime.LastLightCleanup = 0
CS.RGB = CS.RGB or {}

function CS.UI.Toggle()
	CS.Flags.Open = not CS.Flags.Open

	if CS.UI.Objects.Main then
		CS.UI.Objects.Main.Visible = CS.Flags.Open
		CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency or 0.54
	end

	if CS.UI.Objects.OpenButton then
		CS.UI.Objects.OpenButton.Text = CS.Flags.Open and "Close CS" or "Open CS"
	end

	if CS.Flags.Open then
		CS.UI.SwitchPage(CS.Runtime.CurrentPage or "Dashboard")
	end
end

function CS.UI.RemoveTopActionButtons()
	local main = CS.UI and CS.UI.Objects and CS.UI.Objects.Main
	if not main then return end

	for _, name in ipairs({
		"CSFullCloseButton",
		"CSCloseButton",
		"CSMinimizeButton",
		"CSRejoinButton",
		"CSShutdownButton",
		"CSOpenCloseButton",
		"CSPhaseLoader",
		"CSAnimationCurtain"
	}) do
		local obj = main:FindFirstChild(name)
		if obj then
			obj:Destroy()
		end
	end

	for _, child in ipairs(main:GetChildren()) do
		if child:IsA("UIScale") and (
			child.Name == "CSMinimizeScale"
			or child.Name == "CSSimpleScale"
			or child.Name == "CSPhaseScale"
			or child.Name == "CSMenuOpenScale"
			or child.Name == "CS_OpenCloseScale"
			or child.Name == "CSFastScale"
			or child.Name == "CSMenuScale"
		) then
			child:Destroy()
		end
	end
end

function CS.AddCloseAndShutdown()
	CS.UI.RemoveTopActionButtons()
end

function CS.RGB.StrokeAllowed(stroke)
	if not stroke or not stroke:IsA("UIStroke") then return false end

	local parent = stroke.Parent
	if not parent then return false end

	if parent:IsA("TextLabel") or parent:IsA("TextButton") or parent:IsA("TextBox") then
		return false
	end

	if parent.Name == "AccentRail"
		or parent.Name == "TopBar"
		or parent.Name == "PillHolder"
		or parent.Name == "CSFullCloseButton"
		or parent.Name == "CSMinimizeButton"
		or parent.Name == "CSRejoinButton"
		or parent.Name == "CSShutdownButton" then
		return false
	end

	return parent:IsA("Frame")
end

function CS.RGB.ApplyThrottled()
	if not CS.Flags.ColorCycle then
		return
	end

	local now = os.clock()

	-- About 6 updates per second instead of every frame.
	if now - (CS.Runtime.LastRGBUpdate or 0) < 0.16 then
		return
	end

	CS.Runtime.LastRGBUpdate = now
	CS.Runtime.RGBRotation = ((CS.Runtime.RGBRotation or 0) + 0.35) % 360

	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	local colorA = CS.Settings.HexToColor(CS.Flags.ColorCycleA) or Color3.fromRGB(255, 0, 215)
	local colorB = CS.Settings.HexToColor(CS.Flags.ColorCycleB) or Color3.fromRGB(0, 226, 255)

	for _, stroke in ipairs(gui:GetDescendants()) do
		if stroke:IsA("UIStroke") then
			local gradient = stroke:FindFirstChild("CSRGBOutline")

			if CS.RGB.StrokeAllowed(stroke) then
				if not gradient then
					gradient = Instance.new("UIGradient")
					gradient.Name = "CSRGBOutline"
					gradient.Parent = stroke
				end

				gradient.Color = ColorSequence.new({
					ColorSequenceKeypoint.new(0, colorA),
					ColorSequenceKeypoint.new(0.5, colorB),
					ColorSequenceKeypoint.new(1, colorA)
				})
				gradient.Rotation = CS.Runtime.RGBRotation
				stroke.Color = Color3.fromRGB(255, 255, 255)
			else
				if gradient then
					gradient:Destroy()
				end
			end
		end
	end
end

function CS.RGB.DisableOldRGBGradientsOnText()
	local now = os.clock()

	-- This is intentionally slow. It avoids the old every-frame cleanup lag.
	if now - (CS.Runtime.LastLightCleanup or 0) < 3 then
		return
	end

	CS.Runtime.LastLightCleanup = now

	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	for _, obj in ipairs(gui:GetDescendants()) do
		if obj:IsA("TextLabel") or obj:IsA("TextButton") or obj:IsA("TextBox") then
			obj.TextStrokeTransparency = 1

			if obj.Name ~= "CSShutdownButton" then
				obj.TextColor3 = CS.Theme.Text
			end

			for _, child in ipairs(obj:GetChildren()) do
				if child:IsA("UIGradient") then
					child.Enabled = false
				end
			end
		end
	end
end

function CS.Settings.UpdateColorCycle()
	CS.RGB.ApplyThrottled()
end

function CS.Settings.ApplyMenuBackground(color)
	if not color then return end

	CS.Theme.Background = color
	CS.Theme.Background2 = color
	CS.Theme.Panel = color
	CS.Theme.Panel2 = color

	if CS.UI and CS.UI.Objects then
		if CS.UI.Objects.Main then CS.UI.Objects.Main.BackgroundColor3 = color end
		if CS.UI.Objects.Sidebar then CS.UI.Objects.Sidebar.BackgroundColor3 = color end
		if CS.UI.Objects.Content then CS.UI.Objects.Content.BackgroundColor3 = color end
	end

	CS.Settings.ApplyVisuals()
	CS.Settings.Save(true)
end

local CS_OriginalBuild_414 = CS.Build
function CS.Build()
	CS_OriginalBuild_414()

	if CS.UI and CS.UI.Objects and CS.UI.Objects.Main then
		CS.UI.RemoveTopActionButtons()
		CS.UI.Objects.Main.Visible = false
		CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency or 0.54
	end
end

local CS_OriginalSwitchPage_414 = CS.UI.SwitchPage
function CS.UI.SwitchPage(name)
	CS_OriginalSwitchPage_414(name)

	task.defer(function()
		if CS.UI and CS.UI.RemoveTopActionButtons then
			CS.UI.RemoveTopActionButtons()
		end

		if CS.RGB and CS.RGB.DisableOldRGBGradientsOnText then
			CS.RGB.DisableOldRGBGradientsOnText()
		end
	end)
end

local CS_OriginalConnect_414 = CS.Connect
function CS.Connect()
	CS_OriginalConnect_414()

	-- Single low-frequency maintenance loop.
	task.spawn(function()
		while not CS.Runtime.Shutdown do
			task.wait(0.16)
			CS.RGB.ApplyThrottled()
			CS.RGB.DisableOldRGBGradientsOnText()
		end
	end)
end

--// =========================================================
--// END CS v4.1.4 PATCH
--// =========================================================





--// =========================================================
--// CS v4.1.5 FPS LAG FIX / SLOW REFRESH MODE
--// Changes:
--// - Slows heavy refresh/update loops.
--// - Disables RGB outline animation by default.
--// - RGB updates only every 1.25 seconds if enabled.
--// - Stops full-GUI cleanup scans from running often.
--// - Adds performance mode defaults.
--// =========================================================

CS.Version = "4.1.5"
CS.Config.Version = "4.1.5"

CS.RGB = CS.RGB or {}
CS.Runtime.Shutdown = CS.Runtime.Shutdown or false
CS.Runtime.LastRGBUpdate = 0
CS.Runtime.LastSlowUpdate = 0
CS.Runtime.LastDiagnosticsUpdate = 0
CS.Runtime.LastFriendsUpdate = 0
CS.Runtime.LastPlayerListUpdate = 0
CS.Runtime.LastTextCleanup = 0

-- Default to OFF because animated RGB gradients are the main FPS drain on big UI trees.
CS.Flags.ColorCycle = false
CS.Flags.PerformanceMode = true
CS.Flags.RefreshRate = 1.25
CS.Flags.DiagnosticsRefreshRate = 5
CS.Flags.FriendsRefreshRate = 4
CS.Flags.PlayerListRefreshRate = 3

function CS.UI.Toggle()
	CS.Flags.Open = not CS.Flags.Open

	if CS.UI.Objects.Main then
		CS.UI.Objects.Main.Visible = CS.Flags.Open
		CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency or 0.54
	end

	if CS.UI.Objects.OpenButton then
		CS.UI.Objects.OpenButton.Text = CS.Flags.Open and "Close CS" or "Open CS"
	end

	if CS.Flags.Open then
		CS.UI.SwitchPage(CS.Runtime.CurrentPage or "Dashboard")
	end
end

function CS.UI.RemoveTopActionButtons()
	local main = CS.UI and CS.UI.Objects and CS.UI.Objects.Main
	if not main then return end

	for _, name in ipairs({
		"CSFullCloseButton",
		"CSCloseButton",
		"CSMinimizeButton",
		"CSRejoinButton",
		"CSShutdownButton",
		"CSOpenCloseButton",
		"CSPhaseLoader",
		"CSAnimationCurtain"
	}) do
		local obj = main:FindFirstChild(name)
		if obj then
			obj:Destroy()
		end
	end
end

function CS.RGB.ClearAnimatedGradients()
	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	for _, obj in ipairs(gui:GetDescendants()) do
		if obj:IsA("UIGradient") and (
			obj.Name == "CSRGBOutline"
			or obj.Name == "CSRGBCircleGradient"
		) then
			obj:Destroy()
		end
	end
end

function CS.RGB.StrokeAllowed(stroke)
	if not stroke or not stroke:IsA("UIStroke") then return false end

	local parent = stroke.Parent
	if not parent then return false end

	if parent:IsA("TextLabel") or parent:IsA("TextButton") or parent:IsA("TextBox") then
		return false
	end

	if parent.Name == "AccentRail"
		or parent.Name == "TopBar"
		or parent.Name == "PillHolder"
		or parent.Name == "CSFullCloseButton"
		or parent.Name == "CSMinimizeButton"
		or parent.Name == "CSRejoinButton"
		or parent.Name == "CSShutdownButton" then
		return false
	end

	return parent:IsA("Frame")
end

function CS.RGB.ApplyVerySlow()
	if not CS.Flags.ColorCycle then
		return
	end

	local now = os.clock()
	local rate = tonumber(CS.Flags.RefreshRate) or 1.25

	if now - (CS.Runtime.LastRGBUpdate or 0) < rate then
		return
	end

	CS.Runtime.LastRGBUpdate = now
	CS.Runtime.RGBRotation = ((CS.Runtime.RGBRotation or 0) + 2) % 360

	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	local colorA = CS.Settings.HexToColor(CS.Flags.ColorCycleA) or Color3.fromRGB(255, 0, 215)
	local colorB = CS.Settings.HexToColor(CS.Flags.ColorCycleB) or Color3.fromRGB(0, 226, 255)

	for _, stroke in ipairs(gui:GetDescendants()) do
		if stroke:IsA("UIStroke") then
			local gradient = stroke:FindFirstChild("CSRGBOutline")

			if CS.RGB.StrokeAllowed(stroke) then
				if not gradient then
					gradient = Instance.new("UIGradient")
					gradient.Name = "CSRGBOutline"
					gradient.Parent = stroke
				end

				gradient.Color = ColorSequence.new({
					ColorSequenceKeypoint.new(0, colorA),
					ColorSequenceKeypoint.new(0.5, colorB),
					ColorSequenceKeypoint.new(1, colorA)
				})
				gradient.Rotation = CS.Runtime.RGBRotation
				stroke.Color = Color3.fromRGB(255, 255, 255)
			else
				if gradient then
					gradient:Destroy()
				end
			end
		end
	end
end

function CS.RGB.SlowTextCleanup()
	local now = os.clock()

	if now - (CS.Runtime.LastTextCleanup or 0) < 8 then
		return
	end

	CS.Runtime.LastTextCleanup = now

	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	for _, obj in ipairs(gui:GetDescendants()) do
		if obj:IsA("TextLabel") or obj:IsA("TextButton") or obj:IsA("TextBox") then
			obj.TextStrokeTransparency = 1

			if obj.Name ~= "CSShutdownButton" then
				obj.TextColor3 = CS.Theme.Text
			end

			for _, child in ipairs(obj:GetChildren()) do
				if child:IsA("UIGradient") then
					child.Enabled = false
				end
			end
		end
	end
end

function CS.Settings.UpdateColorCycle()
	if CS.Flags.ColorCycle then
		CS.RGB.ApplyVerySlow()
	else
		CS.RGB.ClearAnimatedGradients()
	end
end

-- Wrap expensive live updates with throttles.
local CS_OriginalDashboardUpdate_415 = CS.Dashboard.Update
function CS.Dashboard.Update()
	local now = os.clock()
	if now - (CS.Runtime.LastSlowUpdate or 0) < (tonumber(CS.Flags.RefreshRate) or 1.25) then
		return
	end
	CS.Runtime.LastSlowUpdate = now

	if CS_OriginalDashboardUpdate_415 then
		CS_OriginalDashboardUpdate_415()
	end
end

local CS_OriginalFriendsUpdate_415 = CS.Friends.Update
function CS.Friends.Update()
	local now = os.clock()
	if now - (CS.Runtime.LastFriendsUpdate or 0) < (tonumber(CS.Flags.FriendsRefreshRate) or 4) then
		return
	end
	CS.Runtime.LastFriendsUpdate = now

	if CS_OriginalFriendsUpdate_415 then
		CS_OriginalFriendsUpdate_415()
	end
end

local CS_OriginalDiagnosticsRun_415 = CS.Diagnostics.Run
function CS.Diagnostics.Run()
	local now = os.clock()
	if now - (CS.Runtime.LastDiagnosticsUpdate or 0) < (tonumber(CS.Flags.DiagnosticsRefreshRate) or 5) then
		return
	end
	CS.Runtime.LastDiagnosticsUpdate = now

	if CS_OriginalDiagnosticsRun_415 then
		CS_OriginalDiagnosticsRun_415()
	end
end

if CS.PlayerDetails and CS.PlayerDetails.RefreshList then
	local CS_OriginalPlayerListRefresh_415 = CS.PlayerDetails.RefreshList
	function CS.PlayerDetails.RefreshList(...)
		local now = os.clock()
		if now - (CS.Runtime.LastPlayerListUpdate or 0) < (tonumber(CS.Flags.PlayerListRefreshRate) or 3) then
			return
		end
		CS.Runtime.LastPlayerListUpdate = now

		return CS_OriginalPlayerListRefresh_415(...)
	end
end

function CS.Settings.ApplyMenuBackground(color)
	if not color then return end

	CS.Theme.Background = color
	CS.Theme.Background2 = color
	CS.Theme.Panel = color
	CS.Theme.Panel2 = color

	if CS.UI and CS.UI.Objects then
		if CS.UI.Objects.Main then CS.UI.Objects.Main.BackgroundColor3 = color end
		if CS.UI.Objects.Sidebar then CS.UI.Objects.Sidebar.BackgroundColor3 = color end
		if CS.UI.Objects.Content then CS.UI.Objects.Content.BackgroundColor3 = color end
	end

	CS.Settings.ApplyVisuals()
	CS.Settings.Save(true)
end

local CS_OriginalBuild_415 = CS.Build
function CS.Build()
	CS_OriginalBuild_415()

	if CS.UI and CS.UI.Objects and CS.UI.Objects.Main then
		CS.UI.RemoveTopActionButtons()
		CS.UI.Objects.Main.Visible = false
		CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency or 0.54
	end

	CS.RGB.ClearAnimatedGradients()
end

local CS_OriginalConnect_415 = CS.Connect
function CS.Connect()
	CS_OriginalConnect_415()

	-- Low-cost maintenance loop. No RenderStepped GUI scans.
	task.spawn(function()
		while not CS.Runtime.Shutdown do
			task.wait(1.25)

			if CS.Flags.ColorCycle then
				CS.RGB.ApplyVerySlow()
			end

			CS.RGB.SlowTextCleanup()
		end
	end)
end

--// =========================================================
--// END CS v4.1.5 PATCH
--// =========================================================





--// =========================================================
--// CS v4.1.6 DEBUG CONSOLE + HARD FPS SAFE MODE
--// Adds an in-menu console to see errors + lag reasons.
--// Also adds Safe Mode defaults:
--// - RGB off
--// - Diagnostics throttled
--// - Dashboard/Friends/PlayerList throttled
--// - Prints FPS/performance notes into console
--// =========================================================

CS.Version = "4.1.6"
CS.Config.Version = "4.1.6"

CS.Debug = CS.Debug or {}
CS.Debug.Logs = CS.Debug.Logs or {}
CS.Debug.MaxLogs = 90

CS.Flags.SafeMode = true
CS.Flags.ColorCycle = false
CS.Flags.RefreshRate = 2.5
CS.Flags.DiagnosticsRefreshRate = 8
CS.Flags.FriendsRefreshRate = 8
CS.Flags.PlayerListRefreshRate = 6
CS.Flags.ConsoleEnabled = true

CS.Runtime.LastConsoleFPS = 0
CS.Runtime.LastConsoleRefresh = 0
CS.Runtime.LastDashboardUpdate = 0
CS.Runtime.LastDiagnosticsUpdate = 0
CS.Runtime.LastFriendsUpdate = 0
CS.Runtime.LastPlayerListUpdate = 0
CS.Runtime.LastRGBUpdate = 0

function CS.Debug.Add(level, message)
	level = tostring(level or "INFO")
	message = tostring(message or "")

	local stamp = os.date("%H:%M:%S")
	table.insert(CS.Debug.Logs, 1, "[" .. stamp .. "] [" .. level .. "] " .. message)

	while #CS.Debug.Logs > CS.Debug.MaxLogs do
		table.remove(CS.Debug.Logs)
	end

	if CS.UI and CS.UI.Labels and CS.UI.Labels.ConsoleText then
		CS.UI.Labels.ConsoleText.Text = table.concat(CS.Debug.Logs, "\n")
	end
end

function CS.Debug.SafeCall(label, callback)
	local start = os.clock()
	local ok, err = pcall(callback)
	local elapsed = os.clock() - start

	if not ok then
		CS.Debug.Add("ERROR", label .. " failed: " .. tostring(err))
		return false, err
	end

	if elapsed > 0.05 then
		CS.Debug.Add("LAG", label .. " took " .. string.format("%.3f", elapsed) .. "s")
	end

	return true
end

function CS.Debug.BuildConsole()
	local page = CS.UI.Pages["Diagnostics"]
	if not page then return end

	local old = page:FindFirstChild("CSDebugConsoleCard", true)
	if old then old:Destroy() end

	local card = CS.UI.OverlayCard(page, "Debug Console", ">", 310)
	card.Name = "CSDebugConsoleCard"
	card.Position = UDim2.new(0, 14, 0, 395)

	local console = CS.Util.Create("TextLabel", {
		Parent = card,
		Name = "ConsoleText",
		Size = UDim2.new(1, -28, 1, -78),
		Position = UDim2.new(0, 14, 0, 58),
		BackgroundColor3 = Color3.fromRGB(5, 6, 12),
		BackgroundTransparency = 0.1,
		BorderSizePixel = 0,
		Text = table.concat(CS.Debug.Logs, "\n"),
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.Code,
		TextSize = 11,
		TextWrapped = false,
		TextXAlignment = Enum.TextXAlignment.Left,
		TextYAlignment = Enum.TextYAlignment.Top
	})
	CS.Util.Corner(console, 10)
	CS.Util.Stroke(console, CS.Theme.Stroke, 0.45, 1)

	CS.UI.Labels.ConsoleText = console

	CS.UI.ActionRow(card, 252, "Clear Console", "Clears debug output.", "Clear", function()
		CS.Debug.Logs = {}
		CS.UI.Labels.ConsoleText.Text = ""
		CS.Debug.Add("INFO", "Console cleared.")
	end)

	CS.Debug.Add("INFO", "Debug console loaded.")
end

-- Remove old expensive visuals.
function CS.PerformanceSafeMode()
	CS.Flags.ColorCycle = false

	if CS.RGB and CS.RGB.ClearAnimatedGradients then
		CS.RGB.ClearAnimatedGradients()
	end

	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if gui then
		for _, obj in ipairs(gui:GetDescendants()) do
			if obj:IsA("UIGradient") and (
				obj.Name == "CSRGBOutline"
				or obj.Name == "CSRGBCircleGradient"
				or obj.Name == "CS_RGB"
			) then
				obj:Destroy()
			end

			if obj:IsA("TextLabel") or obj:IsA("TextButton") or obj:IsA("TextBox") then
				obj.TextStrokeTransparency = 1
			end
		end
	end

	CS.Debug.Add("SAFE", "Safe Mode active: RGB off, refresh slowed, animations removed.")
end

-- Stop RGB animation from doing work unless user turns it back on.
function CS.Settings.UpdateColorCycle()
	if not CS.Flags.ColorCycle then return end

	local now = os.clock()
	if now - (CS.Runtime.LastRGBUpdate or 0) < 2.5 then
		return
	end

	CS.Runtime.LastRGBUpdate = now

	if CS.RGB and CS.RGB.ApplyVerySlow then
		CS.RGB.ApplyVerySlow()
	end
end

-- Throttle expensive updates harder.
if CS.Dashboard and CS.Dashboard.Update then
	local CS_OriginalDashboardUpdate_416 = CS.Dashboard.Update
	function CS.Dashboard.Update()
		local now = os.clock()
		if now - (CS.Runtime.LastDashboardUpdate or 0) < (CS.Flags.RefreshRate or 2.5) then
			return
		end

		CS.Runtime.LastDashboardUpdate = now
		return CS.Debug.SafeCall("Dashboard.Update", CS_OriginalDashboardUpdate_416)
	end
end

if CS.Diagnostics and CS.Diagnostics.Run then
	local CS_OriginalDiagnosticsRun_416 = CS.Diagnostics.Run
	function CS.Diagnostics.Run()
		local now = os.clock()
		if now - (CS.Runtime.LastDiagnosticsUpdate or 0) < (CS.Flags.DiagnosticsRefreshRate or 8) then
			return
		end

		CS.Runtime.LastDiagnosticsUpdate = now
		return CS.Debug.SafeCall("Diagnostics.Run", CS_OriginalDiagnosticsRun_416)
	end
end

if CS.Friends and CS.Friends.Update then
	local CS_OriginalFriendsUpdate_416 = CS.Friends.Update
	function CS.Friends.Update()
		local now = os.clock()
		if now - (CS.Runtime.LastFriendsUpdate or 0) < (CS.Flags.FriendsRefreshRate or 8) then
			return
		end

		CS.Runtime.LastFriendsUpdate = now
		return CS.Debug.SafeCall("Friends.Update", CS_OriginalFriendsUpdate_416)
	end
end

if CS.PlayerDetails and CS.PlayerDetails.RefreshList then
	local CS_OriginalPlayerRefresh_416 = CS.PlayerDetails.RefreshList
	function CS.PlayerDetails.RefreshList(...)
		local now = os.clock()
		if now - (CS.Runtime.LastPlayerListUpdate or 0) < (CS.Flags.PlayerListRefreshRate or 6) then
			return
		end

		CS.Runtime.LastPlayerListUpdate = now
		local args = {...}
		return CS.Debug.SafeCall("PlayerDetails.RefreshList", function()
			return CS_OriginalPlayerRefresh_416(unpack(args))
		end)
	end
end

-- Add console when Diagnostics page is built.
if CS.Diagnostics and CS.Diagnostics.Build then
	local CS_OriginalDiagnosticsBuild_416 = CS.Diagnostics.Build
	function CS.Diagnostics.Build()
		CS.Debug.SafeCall("Diagnostics.Build", CS_OriginalDiagnosticsBuild_416)
		CS.Debug.BuildConsole()
	end
end

-- FPS monitor: reports drops without scanning full GUI every frame.
function CS.Debug.FPSWatch()
	local now = os.clock()
	if now - (CS.Runtime.LastConsoleFPS or 0) < 4 then
		return
	end

	CS.Runtime.LastConsoleFPS = now

	local fps = tonumber(CS.Runtime.FPS) or 0
	local ping = tonumber(CS.Runtime.Ping) or 0

	if fps > 0 and fps < 45 then
		CS.Debug.Add("FPS", "Low FPS detected: " .. tostring(fps) .. ". Try disabling RGB, Diagnostics, and Friends live refresh.")
	elseif fps >= 45 then
		CS.Debug.Add("FPS", "FPS stable: " .. tostring(fps) .. " | Ping: " .. tostring(ping) .. "ms")
	end
end

local CS_OriginalBuild_416 = CS.Build
function CS.Build()
	CS.Debug.SafeCall("Build", CS_OriginalBuild_416)

	if CS.UI and CS.UI.Objects and CS.UI.Objects.Main then
		CS.UI.Objects.Main.Visible = false
		CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency or 0.54
	end

	CS.PerformanceSafeMode()
end

local CS_OriginalConnect_416 = CS.Connect
function CS.Connect()
	CS.Debug.SafeCall("Connect", CS_OriginalConnect_416)

	-- Low-frequency monitor only. No full UI scan here.
	task.spawn(function()
		while not CS.Runtime.Shutdown do
			task.wait(2.5)

			if CS.Flags.SafeMode then
				CS.Debug.FPSWatch()
			end

			if CS.Flags.ColorCycle then
				CS.Settings.UpdateColorCycle()
			end
		end
	end)
end

--// =========================================================
--// END CS v4.1.6 PATCH
--// =========================================================





--// =========================================================
--// CS v4.1.7 LAG KILL MODE
--// This is the strongest FPS fix without deleting the UI.
--// It disables the likely lag sources:
--// - live dashboard loop
--// - live diagnostics loop
--// - live friends loop
--// - RGB animation loop
--// - graph refresh loop
--// - repeated full-GUI scans
--// You can still manually refresh pages by switching tabs.
--// =========================================================

CS.Version = "4.1.7"
CS.Config.Version = "4.1.7"

CS.Flags.ColorCycle = false
CS.Flags.SafeMode = true
CS.Flags.LiveUpdates = false
CS.Flags.LiveGraphs = false
CS.Flags.LiveDiagnostics = false
CS.Flags.LiveFriends = false
CS.Flags.LivePlayerList = false
CS.Flags.LiveServerBrowser = false

CS.Runtime.Shutdown = CS.Runtime.Shutdown or false
CS.Runtime.LastManualUpdate = 0
CS.Runtime.LastDebugLog = 0

CS.Debug = CS.Debug or {}
CS.Debug.Logs = CS.Debug.Logs or {}

function CS.Debug.Add(level, message)
	level = tostring(level or "INFO")
	message = tostring(message or "")

	local line = "[" .. os.date("%H:%M:%S") .. "] [" .. level .. "] " .. message
	table.insert(CS.Debug.Logs, 1, line)

	while #CS.Debug.Logs > 80 do
		table.remove(CS.Debug.Logs)
	end

	if CS.UI and CS.UI.Labels and CS.UI.Labels.ConsoleText then
		CS.UI.Labels.ConsoleText.Text = table.concat(CS.Debug.Logs, "\n")
	end
end

function CS.KillLaggyVisuals()
	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	for _, obj in ipairs(gui:GetDescendants()) do
		if obj:IsA("UIGradient") and (
			obj.Name == "CSRGBOutline"
			or obj.Name == "CSRGBCircleGradient"
			or obj.Name == "CS_RGB"
		) then
			obj:Destroy()
		end

		if obj:IsA("Frame") and (
			obj.Name == "CSPhaseLoader"
			or obj.Name == "CSAnimationCurtain"
			or obj.Name == "CornerGlow"
			or obj.Name == "SoftCornerGlow"
		) then
			obj:Destroy()
		end
	end

	local main = CS.UI and CS.UI.Objects and CS.UI.Objects.Main
	if main then
		for _, child in ipairs(main:GetChildren()) do
			if child:IsA("UIScale") then
				child:Destroy()
			end
		end
	end
end

-- Instant open/close only.
function CS.UI.Toggle()
	CS.Flags.Open = not CS.Flags.Open

	if CS.UI.Objects.Main then
		CS.UI.Objects.Main.Visible = CS.Flags.Open
		CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency or 0.54
	end

	if CS.UI.Objects.OpenButton then
		CS.UI.Objects.OpenButton.Text = CS.Flags.Open and "Close CS" or "Open CS"
	end

	if CS.Flags.Open then
		CS.UI.SwitchPage(CS.Runtime.CurrentPage or "Dashboard")
	end
end

-- Disable RGB work entirely unless user manually re-enables later.
function CS.Settings.UpdateColorCycle()
	return
end

if CS.RGB then
	function CS.RGB.ApplyThrottled() return end
	function CS.RGB.ApplyVerySlow() return end
	function CS.RGB.Step() return end
	function CS.RGB.UpdateCircle() return end
end

-- Disable expensive auto refresh functions; allow page builds to still work.
if CS.Dashboard and CS.Dashboard.Update then
	local CS_ManualDashboardUpdate_417 = CS.Dashboard.Update
	function CS.Dashboard.Update(force)
		if force == true then
			return CS_ManualDashboardUpdate_417()
		end
		return
	end
end

if CS.Diagnostics and CS.Diagnostics.Run then
	local CS_ManualDiagnosticsRun_417 = CS.Diagnostics.Run
	function CS.Diagnostics.Run(force)
		if force == true then
			return CS_ManualDiagnosticsRun_417()
		end
		return
	end
end

if CS.Friends and CS.Friends.Update then
	local CS_ManualFriendsUpdate_417 = CS.Friends.Update
	function CS.Friends.Update(force)
		if force == true then
			return CS_ManualFriendsUpdate_417()
		end
		return
	end
end

if CS.PlayerDetails and CS.PlayerDetails.RefreshList then
	local CS_ManualPlayerRefresh_417 = CS.PlayerDetails.RefreshList
	function CS.PlayerDetails.RefreshList(force, ...)
		if force == true then
			return CS_ManualPlayerRefresh_417(...)
		end
		return
	end
end

if CS.ServerBrowser and CS.ServerBrowser.UpdateLive then
	local CS_ManualServerLive_417 = CS.ServerBrowser.UpdateLive
	function CS.ServerBrowser.UpdateLive(force)
		if force == true then
			return CS_ManualServerLive_417()
		end
		return
	end
end

-- Refresh current tab once when switched, not constantly.
local CS_OriginalSwitchPage_417 = CS.UI.SwitchPage
function CS.UI.SwitchPage(name)
	CS_OriginalSwitchPage_417(name)

	task.defer(function()
		CS.KillLaggyVisuals()

		local now = os.clock()
		if now - (CS.Runtime.LastManualUpdate or 0) < 0.75 then
			return
		end
		CS.Runtime.LastManualUpdate = now

		if name == "Dashboard" and CS.Dashboard and CS.Dashboard.Update then
			CS.Dashboard.Update(true)
		elseif name == "Diagnostics" and CS.Diagnostics and CS.Diagnostics.Run then
			CS.Diagnostics.Run(true)
		elseif name == "Friends" and CS.Friends and CS.Friends.Update then
			CS.Friends.Update(true)
		elseif name == "Player Details" and CS.PlayerDetails and CS.PlayerDetails.RefreshList then
			CS.PlayerDetails.RefreshList(true)
		elseif name == "Server Browser" and CS.ServerBrowser and CS.ServerBrowser.UpdateLive then
			CS.ServerBrowser.UpdateLive(true)
		end
	end)
end

-- Add a simple console card without live looping.
function CS.Debug.BuildConsole()
	local page = CS.UI.Pages["Diagnostics"]
	if not page then return end

	local old = page:FindFirstChild("CSDebugConsoleCard", true)
	if old then old:Destroy() end

	local card = CS.UI.OverlayCard(page, "Debug Console", ">", 300)
	card.Name = "CSDebugConsoleCard"
	card.Position = UDim2.new(0, 14, 0, 395)

	local console = CS.Util.Create("TextLabel", {
		Parent = card,
		Name = "ConsoleText",
		Size = UDim2.new(1, -28, 1, -76),
		Position = UDim2.new(0, 14, 0, 58),
		BackgroundColor3 = Color3.fromRGB(5, 6, 12),
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = table.concat(CS.Debug.Logs, "\n"),
		TextColor3 = CS.Theme.Text,
		Font = Enum.Font.Code,
		TextSize = 11,
		TextXAlignment = Enum.TextXAlignment.Left,
		TextYAlignment = Enum.TextYAlignment.Top
	})
	CS.Util.Corner(console, 10)
	CS.Util.Stroke(console, CS.Theme.Stroke, 0.45, 1)
	CS.UI.Labels.ConsoleText = console

	CS.UI.ActionRow(card, 252, "Manual Refresh", "Runs diagnostics once.", "Run", function()
		if CS.Diagnostics and CS.Diagnostics.Run then
			CS.Diagnostics.Run(true)
		end
		CS.Debug.Add("INFO", "Manual diagnostics refresh complete.")
	end)
end

if CS.Diagnostics and CS.Diagnostics.Build then
	local CS_OriginalDiagnosticsBuild_417 = CS.Diagnostics.Build
	function CS.Diagnostics.Build()
		CS_OriginalDiagnosticsBuild_417()
		CS.Debug.BuildConsole()
	end
end

local CS_OriginalBuild_417 = CS.Build
function CS.Build()
	CS_OriginalBuild_417()

	if CS.UI and CS.UI.Objects and CS.UI.Objects.Main then
		CS.UI.Objects.Main.Visible = false
		CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency or 0.54
	end

	CS.KillLaggyVisuals()
	CS.Debug.Add("SAFE", "Lag Kill Mode active: live loops, RGB animation, graphs, and repeated scans disabled.")
end

local CS_OriginalConnect_417 = CS.Connect
function CS.Connect()
	-- Keep original connections, but all heavy update functions above are no-ops unless forced.
	CS_OriginalConnect_417()

	task.spawn(function()
		while not CS.Runtime.Shutdown do
			task.wait(10)
			local fps = tonumber(CS.Runtime.FPS) or 0
			if fps > 0 then
				CS.Debug.Add("FPS", "Current FPS: " .. tostring(fps) .. " | Live updates disabled.")
			end
		end
	end)
end

--// =========================================================
--// END CS v4.1.7 PATCH
--// =========================================================





--// =========================================================
--// CS v4.1.8 ULTRA LOW JITTER PATCH
--// Goal: reduce leftover micro-jitter/FPS dips.
--// Changes:
--// - Do NOT call the original CS.Connect() live-loop bundle.
--// - Uses one slow 5s monitor loop only.
--// - No RGB animation work.
--// - No dashboard/friends/diagnostics auto loops.
--// - Manual refresh only when switching tabs.
--// =========================================================

CS.Version = "4.1.8"
CS.Config.Version = "4.1.8"

CS.Flags.ColorCycle = false
CS.Flags.LiveUpdates = false
CS.Flags.LiveGraphs = false
CS.Flags.LiveDiagnostics = false
CS.Flags.LiveFriends = false
CS.Flags.LivePlayerList = false
CS.Flags.LiveServerBrowser = false
CS.Flags.SafeMode = true

CS.Runtime.Shutdown = false
CS.Runtime.LastManualUpdate = 0
CS.Runtime.LastFPSLog = 0

function CS.UI.Toggle()
	CS.Flags.Open = not CS.Flags.Open

	if CS.UI.Objects.Main then
		CS.UI.Objects.Main.Visible = CS.Flags.Open
		CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency or 0.54
	end

	if CS.UI.Objects.OpenButton then
		CS.UI.Objects.OpenButton.Text = CS.Flags.Open and "Close CS" or "Open CS"
	end

	if CS.Flags.Open then
		CS.UI.SwitchPage(CS.Runtime.CurrentPage or "Dashboard")
	end
end

function CS.DisableHeavyRuntimeObjects()
	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	for _, obj in ipairs(gui:GetDescendants()) do
		if obj:IsA("UIGradient") and (
			obj.Name == "CSRGBOutline"
			or obj.Name == "CSRGBCircleGradient"
			or obj.Name == "CS_RGB"
		) then
			obj:Destroy()
		end
	end
end

function CS.Settings.UpdateColorCycle()
	return
end

if CS.RGB then
	function CS.RGB.ApplyThrottled() return end
	function CS.RGB.ApplyVerySlow() return end
	function CS.RGB.Step() return end
	function CS.RGB.UpdateCircle() return end
	function CS.RGB.Apply() return end
end

-- Manual-only wrappers.
if CS.Dashboard and CS.Dashboard.Update then
	local old = CS.Dashboard.Update
	function CS.Dashboard.Update(force)
		if force == true then
			return old()
		end
	end
end

if CS.Diagnostics and CS.Diagnostics.Run then
	local old = CS.Diagnostics.Run
	function CS.Diagnostics.Run(force)
		if force == true then
			return old()
		end
	end
end

if CS.Friends and CS.Friends.Update then
	local old = CS.Friends.Update
	function CS.Friends.Update(force)
		if force == true then
			return old()
		end
	end
end

if CS.PlayerDetails and CS.PlayerDetails.RefreshList then
	local old = CS.PlayerDetails.RefreshList
	function CS.PlayerDetails.RefreshList(force, ...)
		if force == true then
			return old(...)
		end
	end
end

if CS.ServerBrowser and CS.ServerBrowser.UpdateLive then
	local old = CS.ServerBrowser.UpdateLive
	function CS.ServerBrowser.UpdateLive(force)
		if force == true then
			return old()
		end
	end
end

local CS_OriginalSwitchPage_418 = CS.UI.SwitchPage
function CS.UI.SwitchPage(name)
	CS_OriginalSwitchPage_418(name)

	task.defer(function()
		CS.DisableHeavyRuntimeObjects()

		local now = os.clock()
		if now - (CS.Runtime.LastManualUpdate or 0) < 1.5 then
			return
		end
		CS.Runtime.LastManualUpdate = now

		if name == "Dashboard" and CS.Dashboard and CS.Dashboard.Update then
			CS.Dashboard.Update(true)
		elseif name == "Diagnostics" and CS.Diagnostics and CS.Diagnostics.Run then
			CS.Diagnostics.Run(true)
		elseif name == "Friends" and CS.Friends and CS.Friends.Update then
			CS.Friends.Update(true)
		elseif name == "Player Details" and CS.PlayerDetails and CS.PlayerDetails.RefreshList then
			CS.PlayerDetails.RefreshList(true)
		elseif name == "Server Browser" and CS.ServerBrowser and CS.ServerBrowser.UpdateLive then
			CS.ServerBrowser.UpdateLive(true)
		end
	end)
end

local CS_OriginalBuild_418 = CS.Build
function CS.Build()
	CS_OriginalBuild_418()

	if CS.UI and CS.UI.Objects and CS.UI.Objects.Main then
		CS.UI.Objects.Main.Visible = false
		CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency or 0.54
	end

	CS.DisableHeavyRuntimeObjects()

	if CS.Debug and CS.Debug.Add then
		CS.Debug.Add("SAFE", "Ultra Low Jitter active: original Connect loops skipped.")
	end
end

-- IMPORTANT: Do not call original CS.Connect().
-- The original script's Connect bundle is the remaining likely jitter source.
function CS.Connect()
	task.spawn(function()
		while not CS.Runtime.Shutdown do
			task.wait(5)

			if CS.Debug and CS.Debug.Add then
				local fps = tonumber(CS.Runtime.FPS) or 0
				local now = os.clock()

				if now - (CS.Runtime.LastFPSLog or 0) >= 10 then
					CS.Runtime.LastFPSLog = now
					CS.Debug.Add("FPS", "Ultra-low refresh active. FPS: " .. tostring(fps))
				end
			end
		end
	end)
end

--// =========================================================
--// END CS v4.1.8 PATCH
--// =========================================================





--// =========================================================
--// CS v4.1.9 OPEN BUTTON FIX
--// Fixes v4.1.8 not opening because original Connect() was skipped,
--// which also skipped the Open CS button connection.
--// Keeps ultra-low-jitter mode, but manually wires the open button.
--// =========================================================

CS.Version = "4.1.9"
CS.Config.Version = "4.1.9"

CS.Runtime.OpenButtonConnected = false

function CS.UI.Toggle()
	CS.Flags.Open = not CS.Flags.Open

	if CS.UI.Objects.Main then
		CS.UI.Objects.Main.Visible = CS.Flags.Open
		CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency or 0.54
	end

	if CS.UI.Objects.OpenButton then
		CS.UI.Objects.OpenButton.Text = CS.Flags.Open and "Close CS" or "Open CS"
	end

	if CS.Flags.Open then
		task.defer(function()
			if CS.UI and CS.UI.SwitchPage then
				CS.UI.SwitchPage(CS.Runtime.CurrentPage or "Dashboard")
			end
		end)
	end
end

function CS.UI.ConnectOpenButton()
	local button = CS.UI and CS.UI.Objects and CS.UI.Objects.OpenButton
	if not button or CS.Runtime.OpenButtonConnected then return end

	CS.Runtime.OpenButtonConnected = true

	button.MouseButton1Click:Connect(function()
		CS.UI.Toggle()
	end)
end

local CS_OriginalBuild_419 = CS.Build
function CS.Build()
	CS_OriginalBuild_419()

	if CS.UI and CS.UI.Objects then
		if CS.UI.Objects.Main then
			CS.UI.Objects.Main.Visible = false
			CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency or 0.54
		end

		CS.UI.ConnectOpenButton()
	end
end

-- Keep Connect lightweight, but ensure button is wired after UI exists.
function CS.Connect()
	task.defer(function()
		CS.UI.ConnectOpenButton()
	end)

	task.spawn(function()
		while not CS.Runtime.Shutdown do
			task.wait(5)

			if CS.UI and CS.UI.ConnectOpenButton then
				CS.UI.ConnectOpenButton()
			end
		end
	end)
end

--// =========================================================
--// END CS v4.1.9 PATCH
--// =========================================================





--// =========================================================
--// CS v4.2.0 LOW-LAG FUNCTION RESTORE
--// Fixes v4.1.9 issue where FPS/Ping/Players showed 0 and refresh buttons did nothing.
--// Keeps lag low by using slow lightweight loops instead of full live refresh spam.
--// =========================================================

CS.Version = "4.2.0"
CS.Config.Version = "4.2.0"

CS.Runtime.LastFrameTick = os.clock()
CS.Runtime.FrameCounter = 0
CS.Runtime.LastFpsCalc = os.clock()
CS.Runtime.LastLightMetrics = 0
CS.Runtime.LastForceRefresh = 0

-- Restore manual function calls. v4.1.9 made these require "true";
-- buttons call them without arguments, so this makes buttons work again.
if CS.Dashboard and CS.Dashboard.Update then
	local CS_PrevDashboardUpdate_420 = CS.Dashboard.Update
	function CS.Dashboard.Update(...)
		return CS_PrevDashboardUpdate_420(true, ...)
	end
end

if CS.Diagnostics and CS.Diagnostics.Run then
	local CS_PrevDiagnosticsRun_420 = CS.Diagnostics.Run
	function CS.Diagnostics.Run(...)
		return CS_PrevDiagnosticsRun_420(true, ...)
	end
end

if CS.Friends and CS.Friends.Update then
	local CS_PrevFriendsUpdate_420 = CS.Friends.Update
	function CS.Friends.Update(...)
		return CS_PrevFriendsUpdate_420(true, ...)
	end
end

if CS.PlayerDetails and CS.PlayerDetails.RefreshList then
	local CS_PrevPlayerRefresh_420 = CS.PlayerDetails.RefreshList
	function CS.PlayerDetails.RefreshList(...)
		return CS_PrevPlayerRefresh_420(true, ...)
	end
end

if CS.ServerBrowser and CS.ServerBrowser.UpdateLive then
	local CS_PrevServerLive_420 = CS.ServerBrowser.UpdateLive
	function CS.ServerBrowser.UpdateLive(...)
		return CS_PrevServerLive_420(true, ...)
	end
end

function CS.LightMetricsUpdate()
	local now = os.clock()
	if now - (CS.Runtime.LastLightMetrics or 0) < 0.75 then
		return
	end

	CS.Runtime.LastLightMetrics = now

	local players = CS.Services.Players:GetPlayers()
	local playerCount = #players
	local maxPlayers = CS.Services.Players.MaxPlayers or 0

	CS.Runtime.Players = playerCount
	CS.Runtime.MaxPlayers = maxPlayers

	-- Ping can be unavailable in some executors; keep last known if unavailable.
	local ping = CS.Runtime.Ping or 0
	pcall(function()
		local stats = game:GetService("Stats")
		local network = stats:FindFirstChild("Network")
		if network then
			local serverStats = network:FindFirstChild("ServerStatsItem")
			if serverStats and serverStats:FindFirstChild("Data Ping") then
				ping = math.floor(serverStats["Data Ping"]:GetValue())
			end
		end
	end)
	CS.Runtime.Ping = ping

	-- Update common labels safely.
	if CS.UI and CS.UI.Labels then
		for name, label in pairs(CS.UI.Labels) do
			if typeof(label) == "Instance" and label:IsA("TextLabel") then
				if name:lower():find("fps") then
					if label.Text:find("FPS") then
						label.Text = "FPS: " .. tostring(CS.Runtime.FPS or 0)
					end
				elseif name:lower():find("ping") then
					if label.Text:find("Ping") then
						label.Text = "Ping: " .. tostring(CS.Runtime.Ping or 0)
					end
				elseif name:lower():find("player") then
					if label.Text:find("Players") then
						label.Text = "Players: " .. tostring(playerCount) .. "/" .. tostring(maxPlayers)
					end
				end
			end
		end
	end

	-- Fallback update by visible text, but only every 0.75s to avoid lag.
	if CS.UI and CS.UI.Objects and CS.UI.Objects.Main then
		for _, obj in ipairs(CS.UI.Objects.Main:GetDescendants()) do
			if obj:IsA("TextLabel") or obj:IsA("TextButton") then
				local txt = tostring(obj.Text or "")
				if txt:match("^FPS:") then
					obj.Text = "FPS: " .. tostring(CS.Runtime.FPS or 0)
				elseif txt:match("^Ping:") then
					obj.Text = "Ping: " .. tostring(CS.Runtime.Ping or 0)
				elseif txt:match("^Players:") then
					obj.Text = "Players: " .. tostring(playerCount) .. "/" .. tostring(maxPlayers)
				end
			end
		end
	end
end

function CS.UI.ConnectOpenButton()
	local button = CS.UI and CS.UI.Objects and CS.UI.Objects.OpenButton
	if not button or CS.Runtime.OpenButtonConnected then return end

	CS.Runtime.OpenButtonConnected = true

	button.MouseButton1Click:Connect(function()
		CS.UI.Toggle()
	end)
end

local CS_OriginalBuild_420 = CS.Build
function CS.Build()
	CS_OriginalBuild_420()

	if CS.UI and CS.UI.Objects then
		if CS.UI.Objects.Main then
			CS.UI.Objects.Main.Visible = false
			CS.UI.Objects.Main.BackgroundTransparency = CS.Flags.Transparency or 0.54
		end

		CS.UI.ConnectOpenButton()
	end

	CS.LightMetricsUpdate()
end

-- Do not call old heavy Connect bundle. Use only lightweight loops.
function CS.Connect()
	task.defer(function()
		CS.UI.ConnectOpenButton()
	end)

	-- FPS counter. Cheap and necessary for visible FPS.
	CS.Services.RunService.RenderStepped:Connect(function()
		if CS.Runtime.Shutdown then return end

		CS.Runtime.FrameCounter = (CS.Runtime.FrameCounter or 0) + 1
		local now = os.clock()

		if now - (CS.Runtime.LastFpsCalc or 0) >= 1 then
			CS.Runtime.FPS = CS.Runtime.FrameCounter
			CS.Runtime.FrameCounter = 0
			CS.Runtime.LastFpsCalc = now
		end
	end)

	-- Slow metrics updater.
	task.spawn(function()
		while not CS.Runtime.Shutdown do
			task.wait(0.75)
			CS.LightMetricsUpdate()
		end
	end)

	-- Slow console/FPS notes only.
	task.spawn(function()
		while not CS.Runtime.Shutdown do
			task.wait(8)
			if CS.Debug and CS.Debug.Add then
				CS.Debug.Add("FPS", "Low-lag restore active. FPS: " .. tostring(CS.Runtime.FPS or 0))
			end
		end
	end)
end

--// =========================================================
--// END CS v4.2.0 PATCH
--// =========================================================





--// =========================================================
--// CS v4.2.1 RGB RESTORE + THEME IMPORT / EXPORT
--// - Restores low-cost RGB outline animation.
--// - RGB only updates slowly based on Circle Speed.
--// - Adds theme export code to clipboard.
--// - Adds theme import box for sharing themes.
--// =========================================================

CS.Version = "4.2.1"
CS.Config.Version = "4.2.1"

CS.RGB = CS.RGB or {}
CS.ThemeShare = CS.ThemeShare or {}
CS.Runtime.LastRGBUpdate = 0
CS.Runtime.RGBRotation = CS.Runtime.RGBRotation or 0

function CS.RGB.StrokeAllowed(stroke)
	if not stroke or not stroke:IsA("UIStroke") then return false end

	local parent = stroke.Parent
	if not parent then return false end

	if parent:IsA("TextLabel") or parent:IsA("TextButton") or parent:IsA("TextBox") then
		return false
	end

	if parent.Name == "AccentRail"
		or parent.Name == "TopBar"
		or parent.Name == "PillHolder"
		or parent.Name == "CSFullCloseButton"
		or parent.Name == "CSMinimizeButton"
		or parent.Name == "CSRejoinButton"
		or parent.Name == "CSShutdownButton" then
		return false
	end

	return parent:IsA("Frame")
end

function CS.RGB.SpeedDelay()
	local level = math.clamp(tonumber(CS.Flags.ColorCycleSpeedLevel) or 2, 1, 10)
	-- 1 = slowest, 10 = still safe. Lower delay means faster.
	return math.clamp(1.35 - (level * 0.10), 0.30, 1.25)
end

function CS.RGB.Update()
	if not CS.Flags.ColorCycle then return end

	local now = os.clock()
	if now - (CS.Runtime.LastRGBUpdate or 0) < CS.RGB.SpeedDelay() then
		return
	end

	CS.Runtime.LastRGBUpdate = now
	CS.Runtime.RGBRotation = ((CS.Runtime.RGBRotation or 0) + 14) % 360

	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	local colorA = CS.Settings.HexToColor(CS.Flags.ColorCycleA or "#FF00D7") or Color3.fromRGB(255, 0, 215)
	local colorB = CS.Settings.HexToColor(CS.Flags.ColorCycleB or "#00E2FF") or Color3.fromRGB(0, 226, 255)

	for _, stroke in ipairs(gui:GetDescendants()) do
		if stroke:IsA("UIStroke") then
			local gradient = stroke:FindFirstChild("CSRGBOutline")

			if CS.RGB.StrokeAllowed(stroke) then
				if not gradient then
					gradient = Instance.new("UIGradient")
					gradient.Name = "CSRGBOutline"
					gradient.Parent = stroke
				end

				gradient.Color = ColorSequence.new({
					ColorSequenceKeypoint.new(0.00, colorA),
					ColorSequenceKeypoint.new(0.50, colorB),
					ColorSequenceKeypoint.new(1.00, colorA)
				})

				gradient.Rotation = CS.Runtime.RGBRotation
				gradient.Enabled = true

				stroke.Color = Color3.fromRGB(255, 255, 255)
				stroke.Transparency = 0.18
			else
				if gradient then gradient:Destroy() end
			end
		end
	end
end

function CS.RGB.Clear()
	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	for _, obj in ipairs(gui:GetDescendants()) do
		if obj:IsA("UIGradient") and (obj.Name == "CSRGBOutline" or obj.Name == "CSRGBCircleGradient") then
			obj:Destroy()
		end
	end

	for _, stroke in ipairs(gui:GetDescendants()) do
		if stroke:IsA("UIStroke") then
			stroke.Color = CS.Theme.Stroke
			stroke.Transparency = 0.36
		end
	end
end

function CS.Settings.UpdateColorCycle()
	if CS.Flags.ColorCycle then
		CS.RGB.Update()
	else
		CS.RGB.Clear()
	end
end

function CS.ThemeShare.Export()
	local data = {
		"CS_THEME_V1",
		CS.Settings.ColorToHex(CS.Theme.Accent),
		CS.Settings.ColorToHex(CS.Theme.Background),
		CS.Settings.ColorToHex(CS.Theme.Card),
		CS.Settings.ColorToHex(CS.Theme.Stroke),
		CS.Settings.ColorToHex(CS.Theme.NotificationOutline),
		CS.Settings.ColorToHex(CS.Theme.Text),
		tostring(CS.Flags.ColorCycleA or "#FF00D7"),
		tostring(CS.Flags.ColorCycleB or "#00E2FF"),
		tostring(CS.Flags.ColorCycleSpeedLevel or 2)
	}

	return table.concat(data, "|")
end

function CS.ThemeShare.Apply(code)
	if type(code) ~= "string" then return false, "Theme code is not text." end

	local parts = string.split(code, "|")
	if parts[1] ~= "CS_THEME_V1" then
		return false, "Invalid theme code."
	end

	if #parts < 10 then
		return false, "Theme code is incomplete."
	end

	local accent = CS.Settings.HexToColor(parts[2])
	local background = CS.Settings.HexToColor(parts[3])
	local card = CS.Settings.HexToColor(parts[4])
	local stroke = CS.Settings.HexToColor(parts[5])
	local notice = CS.Settings.HexToColor(parts[6])
	local textColor = CS.Settings.HexToColor(parts[7])
	local cycleA = CS.Settings.HexToColor(parts[8])
	local cycleB = CS.Settings.HexToColor(parts[9])
	local speed = tonumber(parts[10]) or 2

	if not (accent and background and card and stroke and notice and textColor and cycleA and cycleB) then
		return false, "Theme code has invalid colors."
	end

	CS.Theme.Accent = accent
	CS.Theme.Background = background
	CS.Theme.Background2 = background
	CS.Theme.Panel = background
	CS.Theme.Panel2 = background
	CS.Theme.Card = card
	CS.Theme.Card2 = card
	CS.Theme.Stroke = stroke
	CS.Theme.StrokeSoft = stroke
	CS.Theme.NotificationOutline = notice
	CS.Theme.Info = notice
	CS.Theme.Text = textColor

	CS.Flags.ColorCycleA = CS.Settings.ColorToHex(cycleA)
	CS.Flags.ColorCycleB = CS.Settings.ColorToHex(cycleB)
	CS.Flags.ColorCycleSpeedLevel = math.clamp(speed, 1, 10)

	CS.Settings.ApplyVisuals()
	CS.Settings.Save(true)

	if CS.RGB and CS.RGB.Clear then
		CS.RGB.Clear()
	end

	if CS.Flags.ColorCycle and CS.RGB and CS.RGB.Update then
		CS.Runtime.LastRGBUpdate = 0
		CS.RGB.Update()
	end

	return true, "Theme imported."
end

function CS.ThemeShare.Copy()
	local code = CS.ThemeShare.Export()

	if setclipboard then
		setclipboard(code)
		CS.Notify.Push("Theme Export", "Theme code copied to clipboard.", CS.Theme.Success)
	else
		CS.Notify.Push("Theme Export", "Clipboard unavailable. Code shown in console.", CS.Theme.Warning)
		print(code)
	end

	return code
end

-- Add Import / Export card on Settings page without rebuilding the whole design.
local CS_OriginalSettingsBuild_421 = CS.Settings.Build
function CS.Settings.Build()
	CS_OriginalSettingsBuild_421()

	local page = CS.UI.Pages["Settings"]
	if not page then return end

	if page:FindFirstChild("CSThemeShareCard", true) then
		return
	end

	local card = CS.UI.OverlayCard(page, "Theme Share", "↗", 230)
	card.Name = "CSThemeShareCard"
	card.Position = UDim2.new(0, 14, 0, 735)

	local codeBox = CS.Util.Create("TextBox", {
		Parent = card,
		Name = "ThemeImportBox",
		Size = UDim2.new(1, -28, 0, 42),
		Position = UDim2.new(0, 14, 0, 58),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = "",
		PlaceholderText = "Paste CS_THEME_V1 code here...",
		TextColor3 = CS.Theme.Text,
		PlaceholderColor3 = CS.Theme.Muted,
		Font = Enum.Font.Gotham,
		TextSize = 12,
		ClearTextOnFocus = false
	})
	CS.Util.Corner(codeBox, 10)
	CS.Util.Stroke(codeBox, CS.Theme.Stroke, 0.45, 1)

	CS.UI.ActionRow(card, 112, "Export Theme", "Copy your current colors as a share code.", "Copy", function()
		CS.ThemeShare.Copy()
	end)

	CS.UI.ActionRow(card, 166, "Import Theme", "Paste a code above, then import it.", "Import", function()
		local ok, msg = CS.ThemeShare.Apply(codeBox.Text)
		CS.Notify.Push("Theme Import", msg, ok and CS.Theme.Success or CS.Theme.Warning)
		if ok then
			CS.Settings.Build()
		end
	end)
end

local CS_OriginalConnect_421 = CS.Connect
function CS.Connect()
	CS_OriginalConnect_421()

	task.spawn(function()
		while not CS.Runtime.Shutdown do
			task.wait(0.25)
			if CS.Flags.ColorCycle then
				CS.RGB.Update()
			end
		end
	end)
end

local CS_OriginalBuild_421 = CS.Build
function CS.Build()
	CS_OriginalBuild_421()

	if CS.Flags.ColorCycle and CS.RGB and CS.RGB.Update then
		CS.Runtime.LastRGBUpdate = 0
		CS.RGB.Update()
	end
end

--// =========================================================
--// END CS v4.2.1 PATCH
--// =========================================================





--// =========================================================
--// CS v4.2.2 FORCE RGB + FORCE THEME SHARE UI
--// This patch forces the new stuff to actually appear.
--// - RGB is no longer disabled by old SafeMode patches.
--// - RGB toggle immediately creates/clears outline gradients.
--// - Theme Share card is force-added to Settings after page loads.
--// - Refresh Settings rebuilds the card if missing.
--// =========================================================

CS.Version = "4.2.2"
CS.Config.Version = "4.2.2"

CS.RGB = CS.RGB or {}
CS.ThemeShare = CS.ThemeShare or {}
CS.Runtime.LastRGBUpdate = 0
CS.Runtime.RGBRotation = CS.Runtime.RGBRotation or 0

-- Important: older lag patches forced ColorCycle false every time.
-- Keep it user-controlled now.
if CS.Flags.ColorCycle == nil then
	CS.Flags.ColorCycle = false
end

function CS.RGB.StrokeAllowed(stroke)
	if not stroke or not stroke:IsA("UIStroke") then return false end
	local parent = stroke.Parent
	if not parent then return false end

	if parent:IsA("TextLabel") or parent:IsA("TextButton") or parent:IsA("TextBox") then
		return false
	end

	if parent.Name == "AccentRail"
		or parent.Name == "TopBar"
		or parent.Name == "PillHolder"
		or parent.Name == "CSFullCloseButton"
		or parent.Name == "CSMinimizeButton"
		or parent.Name == "CSRejoinButton"
		or parent.Name == "CSShutdownButton" then
		return false
	end

	return parent:IsA("Frame")
end

function CS.RGB.Clear()
	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	for _, obj in ipairs(gui:GetDescendants()) do
		if obj:IsA("UIGradient") and (
			obj.Name == "CSRGBOutline"
			or obj.Name == "CSRGBCircleGradient"
		) then
			obj:Destroy()
		end
	end

	for _, stroke in ipairs(gui:GetDescendants()) do
		if stroke:IsA("UIStroke") then
			stroke.Color = CS.Theme.Stroke
			stroke.Transparency = 0.36
		end
	end
end

function CS.RGB.ForceUpdate()
	local gui = CS.UI and CS.UI.Objects and CS.UI.Objects.GUI
	if not gui then return end

	local colorA = CS.Settings.HexToColor(CS.Flags.ColorCycleA or "#FF00D7") or Color3.fromRGB(255, 0, 215)
	local colorB = CS.Settings.HexToColor(CS.Flags.ColorCycleB or "#00E2FF") or Color3.fromRGB(0, 226, 255)

	CS.Runtime.RGBRotation = ((CS.Runtime.RGBRotation or 0) + 18) % 360

	for _, stroke in ipairs(gui:GetDescendants()) do
		if stroke:IsA("UIStroke") then
			local gradient = stroke:FindFirstChild("CSRGBOutline")

			if CS.RGB.StrokeAllowed(stroke) then
				if not gradient then
					gradient = Instance.new("UIGradient")
					gradient.Name = "CSRGBOutline"
					gradient.Parent = stroke
				end

				gradient.Color = ColorSequence.new({
					ColorSequenceKeypoint.new(0.00, colorA),
					ColorSequenceKeypoint.new(0.50, colorB),
					ColorSequenceKeypoint.new(1.00, colorA)
				})
				gradient.Rotation = CS.Runtime.RGBRotation
				gradient.Enabled = true
				stroke.Color = Color3.fromRGB(255, 255, 255)
				stroke.Transparency = 0.18
			else
				if gradient then gradient:Destroy() end
			end
		end
	end
end

function CS.RGB.Update()
	if not CS.Flags.ColorCycle then return end

	local now = os.clock()
	local level = math.clamp(tonumber(CS.Flags.ColorCycleSpeedLevel) or 2, 1, 10)
	local delay = math.clamp(1.35 - (level * 0.10), 0.30, 1.25)

	if now - (CS.Runtime.LastRGBUpdate or 0) < delay then
		return
	end

	CS.Runtime.LastRGBUpdate = now
	CS.RGB.ForceUpdate()
end

function CS.Settings.UpdateColorCycle()
	if CS.Flags.ColorCycle then
		CS.RGB.ForceUpdate()
	else
		CS.RGB.Clear()
	end
end

function CS.ThemeShare.Export()
	local data = {
		"CS_THEME_V1",
		CS.Settings.ColorToHex(CS.Theme.Accent),
		CS.Settings.ColorToHex(CS.Theme.Background),
		CS.Settings.ColorToHex(CS.Theme.Card),
		CS.Settings.ColorToHex(CS.Theme.Stroke),
		CS.Settings.ColorToHex(CS.Theme.NotificationOutline),
		CS.Settings.ColorToHex(CS.Theme.Text),
		tostring(CS.Flags.ColorCycleA or "#FF00D7"),
		tostring(CS.Flags.ColorCycleB or "#00E2FF"),
		tostring(CS.Flags.ColorCycleSpeedLevel or 2)
	}

	return table.concat(data, "|")
end

function CS.ThemeShare.Apply(code)
	if type(code) ~= "string" then
		return false, "Theme code is not text."
	end

	local parts = string.split(code, "|")
	if parts[1] ~= "CS_THEME_V1" then
		return false, "Invalid theme code."
	end

	if #parts < 10 then
		return false, "Theme code is incomplete."
	end

	local accent = CS.Settings.HexToColor(parts[2])
	local background = CS.Settings.HexToColor(parts[3])
	local card = CS.Settings.HexToColor(parts[4])
	local stroke = CS.Settings.HexToColor(parts[5])
	local notice = CS.Settings.HexToColor(parts[6])
	local textColor = CS.Settings.HexToColor(parts[7])
	local cycleA = CS.Settings.HexToColor(parts[8])
	local cycleB = CS.Settings.HexToColor(parts[9])
	local speed = tonumber(parts[10]) or 2

	if not (accent and background and card and stroke and notice and textColor and cycleA and cycleB) then
		return false, "Theme code has invalid colors."
	end

	CS.Theme.Accent = accent
	CS.Theme.Background = background
	CS.Theme.Background2 = background
	CS.Theme.Panel = background
	CS.Theme.Panel2 = background
	CS.Theme.Card = card
	CS.Theme.Card2 = card
	CS.Theme.Stroke = stroke
	CS.Theme.StrokeSoft = stroke
	CS.Theme.NotificationOutline = notice
	CS.Theme.Info = notice
	CS.Theme.Text = textColor

	CS.Flags.ColorCycleA = CS.Settings.ColorToHex(cycleA)
	CS.Flags.ColorCycleB = CS.Settings.ColorToHex(cycleB)
	CS.Flags.ColorCycleSpeedLevel = math.clamp(speed, 1, 10)

	CS.Settings.ApplyVisuals()
	CS.Settings.Save(true)

	if CS.Flags.ColorCycle then
		CS.Runtime.LastRGBUpdate = 0
		CS.RGB.ForceUpdate()
	else
		CS.RGB.Clear()
	end

	return true, "Theme imported."
end

function CS.ThemeShare.Copy()
	local code = CS.ThemeShare.Export()

	if setclipboard then
		setclipboard(code)
		CS.Notify.Push("Theme Export", "Theme code copied to clipboard.", CS.Theme.Success)
	else
		print("CS Theme Code:", code)
		CS.Notify.Push("Theme Export", "Clipboard unavailable. Code printed to console.", CS.Theme.Warning)
	end

	return code
end

function CS.ThemeShare.BuildCard()
	local page = CS.UI and CS.UI.Pages and CS.UI.Pages["Settings"]
	if not page then return end

	local old = page:FindFirstChild("CSThemeShareCard", true)
	if old then
		old:Destroy()
	end

	-- Use a parent that exists and is visible. If page has scroll columns, attach to the page root anyway.
	local card = CS.UI.OverlayCard(page, "Theme Share", "↗", 230)
	card.Name = "CSThemeShareCard"
	card.Position = UDim2.new(0, 14, 0, 735)

	local codeBox = CS.Util.Create("TextBox", {
		Parent = card,
		Name = "ThemeImportBox",
		Size = UDim2.new(1, -28, 0, 42),
		Position = UDim2.new(0, 14, 0, 58),
		BackgroundColor3 = CS.Theme.Card2,
		BackgroundTransparency = 0.08,
		BorderSizePixel = 0,
		Text = "",
		PlaceholderText = "Paste CS_THEME_V1 code here...",
		TextColor3 = CS.Theme.Text,
		PlaceholderColor3 = CS.Theme.Muted,
		Font = Enum.Font.Gotham,
		TextSize = 12,
		ClearTextOnFocus = false
	})
	CS.Util.Corner(codeBox, 10)
	CS.Util.Stroke(codeBox, CS.Theme.Stroke, 0.45, 1)

	CS.UI.ActionRow(card, 112, "Export Theme", "Copy current theme as a share code.", "Copy", function()
		CS.ThemeShare.Copy()
	end)

	CS.UI.ActionRow(card, 166, "Import Theme", "Paste a code above, then import it.", "Import", function()
		local ok, msg = CS.ThemeShare.Apply(codeBox.Text)
		CS.Notify.Push("Theme Import", msg, ok and CS.Theme.Success or CS.Theme.Warning)
		if ok then
			CS.Settings.Build()
			task.defer(CS.ThemeShare.BuildCard)
		end
	end)
end

-- Force Settings page additions every time Settings is opened.
local CS_OriginalSwitchPage_422 = CS.UI.SwitchPage
function CS.UI.SwitchPage(name)
	CS_OriginalSwitchPage_422(name)

	if name == "Settings" then
		task.defer(function()
			CS.ThemeShare.BuildCard()

			-- Force RGB button state to actually apply when entering settings.
			if CS.Flags.ColorCycle then
				CS.RGB.ForceUpdate()
			end
		end)
	end
end

local CS_OriginalSettingsBuild_422 = CS.Settings.Build
function CS.Settings.Build()
	CS_OriginalSettingsBuild_422()
	task.defer(CS.ThemeShare.BuildCard)
end

local CS_OriginalBuild_422 = CS.Build
function CS.Build()
	CS_OriginalBuild_422()

	task.defer(function()
		if CS.Flags.ColorCycle then
			CS.RGB.ForceUpdate()
		else
			CS.RGB.Clear()
		end
	end)
end

local CS_OriginalConnect_422 = CS.Connect
function CS.Connect()
	CS_OriginalConnect_422()

	task.spawn(function()
		while not CS.Runtime.Shutdown do
			task.wait(0.35)
			if CS.Flags.ColorCycle then
				CS.RGB.Update()
			end
		end
	end)
end

--// =========================================================
--// END CS v4.2.2 PATCH
--// =========================================================


CS.Start()

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: