local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local HttpService = game:GetService("HttpService")
local Players = game:GetService("Players")
local StarterGui = game:GetService("StarterGui")
local JustHub = {}

JustHub.Themes = {
	Darker = {
		["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(25,25,25)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(32,32,32)), ColorSequenceKeypoint.new(1, Color3.fromRGB(25,25,25))}),
		["Color Hub 2"] = Color3.fromRGB(30,30,30),
		["Color Stroke"] = Color3.fromRGB(40,40,40),
		["Color Theme"] = Color3.fromRGB(88,101,242),
		["Color Text"] = Color3.fromRGB(243,243,243),
		["Color Dark Text"] = Color3.fromRGB(180,180,180)
	},
	Dark = {
		["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(40,40,40)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(47,47,47)), ColorSequenceKeypoint.new(1, Color3.fromRGB(40,40,40))}),
		["Color Hub 2"] = Color3.fromRGB(45,45,45),
		["Color Stroke"] = Color3.fromRGB(65,65,65),
		["Color Theme"] = Color3.fromRGB(65,150,255),
		["Color Text"] = Color3.fromRGB(245,245,245),
		["Color Dark Text"] = Color3.fromRGB(190,190,190)
	},
	Purple = {
		["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(28,25,30)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(32,32,32)), ColorSequenceKeypoint.new(1, Color3.fromRGB(28,25,30))}),
		["Color Hub 2"] = Color3.fromRGB(30,30,30),
		["Color Stroke"] = Color3.fromRGB(40,40,40),
		["Color Theme"] = Color3.fromRGB(150,0,255),
		["Color Text"] = Color3.fromRGB(240,240,240),
		["Color Dark Text"] = Color3.fromRGB(180,180,180)
	},
	Light = {
		["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(230,230,230)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(245,245,245)), ColorSequenceKeypoint.new(1, Color3.fromRGB(230,230,230))}),
		["Color Hub 2"] = Color3.fromRGB(240,240,240),
		["Color Stroke"] = Color3.fromRGB(200,200,200),
		["Color Theme"] = Color3.fromRGB(0,120,255),
		["Color Text"] = Color3.fromRGB(30,30,30),
		["Color Dark Text"] = Color3.fromRGB(80,80,80)
	},
	Neon = {
		["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(10,10,10)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(0,200,200)), ColorSequenceKeypoint.new(1, Color3.fromRGB(10,10,10))}),
		["Color Hub 2"] = Color3.fromRGB(15,15,15),
		["Color Stroke"] = Color3.fromRGB(0,255,255),
		["Color Theme"] = Color3.fromRGB(0,255,0),
		["Color Text"] = Color3.fromRGB(255,255,255),
		["Color Dark Text"] = Color3.fromRGB(200,200,200)
	},
	Forest = {
		["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(0,50,0)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(0,80,0)), ColorSequenceKeypoint.new(1, Color3.fromRGB(0,50,0))}),
		["Color Hub 2"] = Color3.fromRGB(0,60,0),
		["Color Stroke"] = Color3.fromRGB(0,80,0),
		["Color Theme"] = Color3.fromRGB(0,120,0),
		["Color Text"] = Color3.fromRGB(220,220,220),
		["Color Dark Text"] = Color3.fromRGB(160,160,160)
	},
	Aqua = {
		["Color Hub 1"] = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.fromRGB(0,100,100)), ColorSequenceKeypoint.new(0.5, Color3.fromRGB(0,150,150)), ColorSequenceKeypoint.new(1, Color3.fromRGB(0,100,100))}),
		["Color Hub 2"] = Color3.fromRGB(0,110,110),
		["Color Stroke"] = Color3.fromRGB(0,180,180),
		["Color Theme"] = Color3.fromRGB(0,220,220),
		["Color Text"] = Color3.fromRGB(255,255,255),
		["Color Dark Text"] = Color3.fromRGB(200,200,200)
	}
}

JustHub.Info = {Version = "1.1.0"}
JustHub.Save = {UISize = {550,380}, TabSize = 160, Theme = "Darker"}
JustHub.ConfigData = {}
JustHub.ControlRegistry = {}

local function createInstance(className, properties, parent)
	local inst = Instance.new(className)
	if properties then
		for k, v in pairs(properties) do
			inst[k] = v
		end
	end
	if parent then
		inst.Parent = parent
	end
	return inst
end

local function tweenProperty(object, propertyTable, duration)
	local ti = TweenInfo.new(duration, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
	local tw = TweenService:Create(object, ti, propertyTable)
	tw:Play()
	return tw
end

local function getCurrentTheme(themeChoice)
	if type(themeChoice) == "table" then
		return themeChoice
	else
		return JustHub.Themes[themeChoice or JustHub.Save.Theme]
	end
end

local function clampPosition(pos, screenSize)
	local x = math.clamp(pos.X.Offset, 0, screenSize.X)
	local y = math.clamp(pos.Y.Offset, 0, screenSize.Y)
	return UDim2.new(pos.X.Scale, x, pos.Y.Scale, y)
end

local function addBorder(obj, color, thickness)
	return createInstance("UIStroke", {Color = color, Thickness = thickness}, obj)
end

function JustHub:RegisterControl(key, updateFunction)
	JustHub.ControlRegistry[key] = updateFunction
end

function JustHub:ApplyConfig(config)
	for key, savedValue in pairs(config) do
		if JustHub.ControlRegistry[key] then
			JustHub.ControlRegistry[key](savedValue)
		end
	end
end

local SectionMethods = {}

function SectionMethods:addMenu(menuName)
	menuName = menuName or "Menu"
	local menuFrame = createInstance("Frame", {Name = menuName, Size = UDim2.new(1,0,0,40), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], BackgroundTransparency = 0.3}, self.Content)
	createInstance("UICorner", {CornerRadius = UDim.new(0,6)}, menuFrame)
	createInstance("TextLabel", {Name = "MenuLabel", Text = menuName, Size = UDim2.new(1,0,1,0), BackgroundTransparency = 1, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.GothamBold, TextSize = 16}, menuFrame)
	return menuFrame
end

function SectionMethods:addToggle(options)
	options = options or {}
	local toggleTitle = options.Name or "Toggle"
	local default = options.Default or false
	local callback = options.Callback or function(state) end
	local toggleFrame = createInstance("Frame", {Name = toggleTitle.."Toggle", Size = UDim2.new(1,0,0,20), BackgroundColor3 = Color3.fromRGB(40,40,40)}, self.Content)
	createInstance("UICorner", {CornerRadius = UDim.new(0,20)}, toggleFrame)
	addBorder(toggleFrame, getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], 1)
	local label = createInstance("TextLabel", {Size = UDim2.new(0.7,0,1,0), Position = UDim2.new(0,0,0,0), BackgroundTransparency = 1, Text = toggleTitle, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.Gotham, TextSize = 12, TextXAlignment = Enum.TextXAlignment.Left}, toggleFrame)
	local separator = createInstance("Frame", {Size = UDim2.new(0,2,1,0), Position = UDim2.new(0.7,0,0,0), BackgroundColor3 = Color3.fromRGB(255,255,255)}, toggleFrame)
	createInstance("UICorner", {CornerRadius = UDim.new(0,1)}, separator)
	local toggleContainer = createInstance("Frame", {Size = UDim2.new(0.3,0,1,0), Position = UDim2.new(0.7,0,0,0), BackgroundTransparency = 1}, toggleFrame)
	local toggleSwitch = createInstance("Frame", {Size = UDim2.new(0,35,0,15), Position = UDim2.new(1,-35,0.5,-7.5), BackgroundColor3 = default and Color3.fromRGB(0,200,0) or Color3.fromRGB(100,100,100), BorderSizePixel = 0}, toggleContainer)
	toggleSwitch.Active = true
	toggleSwitch.Selectable = true
	createInstance("UICorner", {CornerRadius = UDim.new(0,15)}, toggleSwitch)
	local toggleCircle = createInstance("Frame", {Size = UDim2.new(0,13,0,13), Position = default and UDim2.new(0,20,0.5,-6.5) or UDim2.new(0,2,0.5,-6.5), BackgroundColor3 = Color3.new(1,1,1), BorderSizePixel = 0}, toggleSwitch)
	createInstance("UICorner", {CornerRadius = UDim.new(1,0)}, toggleCircle)
	local state = default
	if default then callback(true) else callback(false) end
	JustHub.ConfigData[toggleTitle] = state
	JustHub:RegisterControl(toggleTitle, function(savedValue)
		state = savedValue
		if state then
			toggleCircle.Position = UDim2.new(0,20,0.5,-6.5)
			toggleSwitch.BackgroundColor3 = Color3.fromRGB(0,200,0)
			label.TextColor3 = Color3.fromRGB(0,255,0)
		else
			toggleCircle.Position = UDim2.new(0,2,0.5,-6.5)
			toggleSwitch.BackgroundColor3 = Color3.fromRGB(100,100,100)
			label.TextColor3 = Color3.fromRGB(255,255,255)
		end
	end)
	toggleSwitch.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
			if not state then
				tweenProperty(toggleCircle, {Position = UDim2.new(0,20,0.5,-6.5)}, 0.3)
				tweenProperty(toggleSwitch, {BackgroundColor3 = Color3.fromRGB(0,200,0)}, 0.3)
				tweenProperty(label, {TextColor3 = Color3.fromRGB(0,255,0)}, 0.3)
			else
				tweenProperty(toggleCircle, {Position = UDim2.new(0,2,0.5,-6.5)}, 0.3)
				tweenProperty(toggleSwitch, {BackgroundColor3 = Color3.fromRGB(100,100,100)}, 0.3)
				tweenProperty(label, {TextColor3 = Color3.fromRGB(255,255,255)}, 0.3)
			end
			state = not state
			JustHub.ConfigData[toggleTitle] = state
			callback(state)
		end
	end)
	return toggleFrame
end

function SectionMethods:addSlider(options)
	options = options or {}
	local sliderName = options.Name or "Slider"
	local min = options.Min or 0
	local max = options.Max or 100
	local default = options.Default or min
	local callback = options.Callback or function(value) end
	local sliderFrame = createInstance("Frame", {Name = sliderName.."Slider", Size = UDim2.new(1,0,0,25), BackgroundTransparency = 1}, self.Content)
	addBorder(sliderFrame, getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], 1)
	local label = createInstance("TextLabel", {Name = "Label", Text = sliderName, Size = UDim2.new(0.7,0,1,0), Position = UDim2.new(0,0,0,0), BackgroundTransparency = 1, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.Gotham, TextSize = 10}, sliderFrame)
	local separator = createInstance("Frame", {Size = UDim2.new(0,2,1,0), Position = UDim2.new(0.7,0,0,0), BackgroundColor3 = Color3.fromRGB(255,255,255)}, sliderFrame)
	createInstance("UICorner", {CornerRadius = UDim.new(0,1)}, separator)
	local sliderContainer = createInstance("Frame", {Name = "SliderContainer", Size = UDim2.new(0.3,0,1,0), Position = UDim2.new(0.7,0,0,0), BackgroundTransparency = 1}, sliderFrame)
	local sliderBar = createInstance("Frame", {Name = "SliderBar", Size = UDim2.new(1,-20,0,4), Position = UDim2.new(0,10,0.5,-2), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Stroke"]}, sliderContainer)
	createInstance("UICorner", {CornerRadius = UDim.new(0,4)}, sliderBar)
	local sliderHandle = createInstance("Frame", {Name = "SliderHandle", Size = UDim2.new(0,12,0,12), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Theme"], Position = UDim2.new((default - min)/(max - min), -6, 0.5,-6)}, sliderBar)
	createInstance("UICorner", {CornerRadius = UDim.new(0,4)}, sliderHandle)
	local dragging = false
	sliderHandle.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = true end
	end)
	sliderHandle.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = false end
	end)
	UserInputService.InputChanged:Connect(function(input)
		if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
			local barAbsPos = sliderBar.AbsolutePosition.X
			local barWidth = sliderBar.AbsoluteSize.X
			local relativePos = math.clamp((input.Position.X - barAbsPos) / barWidth, 0, 1)
			sliderHandle.Position = UDim2.new(relativePos, -6, sliderHandle.Position.Y.Scale, sliderHandle.Position.Y.Offset)
			local value = min + relativePos*(max - min)
			JustHub.ConfigData[sliderName] = value
			callback(value)
		end
	end)
	JustHub:RegisterControl(sliderName, function(savedValue)
		local newRel = (savedValue - min)/(max - min)
		sliderHandle.Position = UDim2.new(newRel, -6, 0.5, -6)
	end)
	return sliderFrame
end

function SectionMethods:addTextBox(options)
	options = options or {}
	local textBoxName = options.Name or "TextBox"
	local defaultText = options.Default or ""
	local callback = options.Callback or function(text) end
	local textBoxFrame = createInstance("Frame", {Name = textBoxName.."TextBox", Size = UDim2.new(1,0,0,20), BackgroundTransparency = 1}, self.Content)
	addBorder(textBoxFrame, getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], 1)
	local label = createInstance("TextLabel", {Name = "Label", Text = textBoxName, Size = UDim2.new(0.7,0,1,0), Position = UDim2.new(0,0,0,0), BackgroundTransparency = 1, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.Gotham, TextSize = 10}, textBoxFrame)
	local textbox = createInstance("TextBox", {Name = "Input", Text = defaultText, Size = UDim2.new(0.3,0,1,0), Position = UDim2.new(0.7,0,0,0), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.Gotham, TextSize = 10}, textBoxFrame)
	textbox.FocusLost:Connect(function(enterPressed)
		JustHub.ConfigData[textBoxName] = textbox.Text
		callback(textbox.Text)
	end)
	JustHub:RegisterControl(textBoxName, function(savedText)
		textbox.Text = savedText
	end)
	return textBoxFrame
end

function SectionMethods:addDropdown(options)
	options = options or {}
	local dropdownTitle = options.Name or "Dropdown"
	local default = options.Default or ""
	local items = options.Items or {}
	local callback = options.Callback or function(value) end
	local dropdownFrame = createInstance("Frame", {Name = dropdownTitle.."Dropdown", BackgroundTransparency = 1}, self.Content)
	dropdownFrame.Size = UDim2.new(1,0,0,20)
	addBorder(dropdownFrame, getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], 1)
	local label = createInstance("TextLabel", {Name = "Label", Text = dropdownTitle, Size = UDim2.new(0.7,0,1,0), Position = UDim2.new(0,0,0,0), BackgroundTransparency = 1, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.Gotham, TextSize = 10}, dropdownFrame)
	local dropdownButton = createInstance("TextButton", {Name = "DropdownButton", Text = (default ~= "" and (default .. " ▼") or "Select ▼"), Size = UDim2.new(0.3,0,1,0), Position = UDim2.new(0.7,0,0,0), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], Font = Enum.Font.GothamBold, TextSize = 10}, dropdownFrame)
	local listFrame = createInstance("Frame", {Name = "DropdownList", BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Hub 2"], Visible = false, Position = UDim2.new(0,0,1,0)}, dropdownFrame)
	listFrame.Size = UDim2.new(1,0,0,#items*20 + ((#items-1)*2))
	createInstance("UIListLayout", {Padding = UDim.new(0,2), SortOrder = Enum.SortOrder.LayoutOrder}, listFrame)
	local dropdownToggle = false
	dropdownButton.MouseButton1Click:Connect(function()
		if dropdownToggle then
			tweenProperty(listFrame, {Size = UDim2.new(1,0,0,0)}, 0.15)
			tweenProperty(dropdownButton, {TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"]}, 0.15)
			wait(0.15)
			listFrame.Visible = false
		else
			listFrame.Visible = true
			tweenProperty(listFrame, {Size = UDim2.new(1,0,0,#items*20 + ((#items-1)*2))}, 0.15)
			tweenProperty(dropdownButton, {TextColor3 = Color3.fromRGB(0,255,0)}, 0.15)
		end
		dropdownToggle = not dropdownToggle
	end)
	for _, option in ipairs(items) do
		local btn = createInstance("TextButton", {Size = UDim2.new(1,0,0,20), Text = option, TextColor3 = Color3.fromRGB(255,255,255), BackgroundTransparency = 1, Font = Enum.Font.Gotham, TextSize = 10}, listFrame)
		btn.MouseButton1Click:Connect(function()
			label.Text = dropdownTitle .. " - " .. option
			JustHub.ConfigData[dropdownTitle] = option
			pcall(callback, option)
			tweenProperty(listFrame, {Size = UDim2.new(1,0,0,0)}, 0.15)
			dropdownToggle = false
			wait(0.15)
			listFrame.Visible = false
		end)
	end
	JustHub.ConfigData[dropdownTitle] = default
	JustHub:RegisterControl(dropdownTitle, function(savedValue)
		label.Text = dropdownTitle .. " - " .. savedValue
	end)
	local updatedropfunc = {}
	function updatedropfunc:Clear()
		for i, v in pairs(listFrame:GetChildren()) do
			if v:IsA("TextButton") then
				v:Destroy()
				dropdownToggle = false
				label.Text = dropdownTitle
				tweenProperty(listFrame, {Size = UDim2.new(1,0,0,0)}, 0.15)
			end
		end
	end
	function updatedropfunc:Refresh(newlist)
		newlist = newlist or {}
		for i, v in pairs(newlist) do
			local btn = createInstance("TextButton", {Size = UDim2.new(1,0,0,25), Text = v, TextColor3 = Color3.fromRGB(255,255,255), BackgroundTransparency = 1, Font = Enum.Font.SourceSansSemibold, TextSize = 12}, listFrame)
			btn.MouseButton1Click:Connect(function()
				dropdownToggle = false
				label.Text = dropdownTitle .. " - " .. v
				pcall(callback, v)
				tweenProperty(listFrame, {Size = UDim2.new(1,0,0,0)}, 0.15)
			end)
		end
	end
	return updatedropfunc
end

function SectionMethods:addButton(options)
	options = options or {}
	local labelText = options.Name or "Button"
	local buttonText = options.ButtonText or "Click"
	local callback = options.Callback or function() end
	local container = createInstance("Frame", {Name = labelText.."ButtonControl", Size = UDim2.new(1,0,0,30), BackgroundTransparency = 1}, self.Content)
	addBorder(container, getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], 1)
	local label = createInstance("TextLabel", {Name = "Label", Text = labelText, Size = UDim2.new(0.7,0,1,0), Position = UDim2.new(0,0,0,0), BackgroundTransparency = 1, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.Gotham, TextSize = 10, TextXAlignment = Enum.TextXAlignment.Left}, container)
	local button = createInstance("TextButton", {Name = "ActionButton", Text = buttonText, Size = UDim2.new(0.3,0,0.8,0), Position = UDim2.new(0.7,0,0.1,0), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Theme"], TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.GothamBold, TextSize = 10}, container)
	createInstance("UICorner", {CornerRadius = UDim.new(0,6)}, button)
	button.MouseButton1Click:Connect(function() pcall(callback) end)
	return container
end

function JustHub:addSection(sectionName, sectionHeight)
	sectionName = sectionName or "Section"
	sectionHeight = sectionHeight or 100
	local sectionFrame = createInstance("Frame", {Name = sectionName, Size = UDim2.new(1,0,0,sectionHeight), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Hub 2"], BackgroundTransparency = 0.2}, nil)
	createInstance("UICorner", {CornerRadius = UDim.new(0,8)}, sectionFrame)
	local sectionTitle = createInstance("TextLabel", {Name = "SectionTitle", Text = sectionName, Size = UDim2.new(1,0,0,30), BackgroundTransparency = 1, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], Font = Enum.Font.GothamBold, TextSize = 16, TextXAlignment = Enum.TextXAlignment.Left}, sectionFrame)
	local sectionContent = createInstance("Frame", {Name = "SectionContent", Size = UDim2.new(1,0,1,-30), Position = UDim2.new(0,0,0,30), BackgroundTransparency = 1}, sectionFrame)
	createInstance("UIListLayout", {FillDirection = Enum.FillDirection.Vertical, Padding = UDim.new(0,5), SortOrder = Enum.SortOrder.LayoutOrder}, sectionContent)
	local sectionObj = {Frame = sectionFrame, Title = sectionTitle, Content = sectionContent}
	setmetatable(sectionObj, {__index = SectionMethods})
	return sectionObj
end

function JustHub:CreateWindow(options)
	options = options or {}
	local windowName = options.Name or "JustHub Window"
	local currentTheme = getCurrentTheme(options.Theme)
	local windowGUID = HttpService:GenerateGUID(false)
	local finalTitle = windowName .. " [" .. windowGUID .. "]"
	local player = Players.LocalPlayer
	local playerGui = player:WaitForChild("PlayerGui")
	local screenGui = createInstance("ScreenGui", {Name = "JustHub", ResetOnSpawn = false}, playerGui)
	self.ScreenGui = screenGui
	local uiWidth = JustHub.Save.UISize[1]
	local uiHeight = JustHub.Save.UISize[2]
	local mainFrame = createInstance("Frame", {Name = "MainFrame", AnchorPoint = Vector2.new(0.5,0.5), Position = UDim2.new(0.5,0,-0.5,0), Size = UDim2.new(0,uiWidth,0,uiHeight), BackgroundColor3 = currentTheme["Color Hub 2"]}, screenGui)
	createInstance("UICorner", {CornerRadius = UDim.new(0,12)}, mainFrame)
	addBorder(mainFrame, currentTheme["Color Stroke"], 2)
	createInstance("UIGradient", {Color = currentTheme["Color Hub 1"]}, mainFrame)
	local topBar = createInstance("Frame", {Name = "TopBar", Size = UDim2.new(1,0,0,60), BackgroundColor3 = currentTheme["Color Hub 2"]}, mainFrame)
	createInstance("UICorner", {CornerRadius = UDim.new(0,12)}, topBar)
	local titleLabel = createInstance("TextLabel", {Name = "TitleLabel", Size = UDim2.new(1,-180,1,0), Position = UDim2.new(0,10,0,0), BackgroundTransparency = 1, Text = finalTitle, TextColor3 = currentTheme["Color Text"], Font = Enum.Font.GothamBold, TextSize = 18, TextXAlignment = Enum.TextXAlignment.Left}, topBar)
	local welcomeLabel = createInstance("TextLabel", {Name = "WelcomeLabel", Size = UDim2.new(0,150,0,20), AnchorPoint = Vector2.new(0,1), Position = UDim2.new(0,10,1,-30), BackgroundTransparency = 1, Text = "Welcome, " .. player.Name, TextColor3 = currentTheme["Color Text"], Font = Enum.Font.GothamBold, TextSize = 16, TextXAlignment = Enum.TextXAlignment.Left}, mainFrame)
	local function createControlButton(name, image, pos)
		return createInstance("ImageButton", {Name = name, Size = UDim2.new(0,40,0,40), Position = pos, BackgroundTransparency = 1, Image = image, ImageColor3 = currentTheme["Color Theme"]}, topBar)
	end
	local hideButton = createControlButton("HideButton", "rbxassetid://1307617803", UDim2.new(1,-110,0,10))
	local maxButton = createControlButton("MaxButton", "rbxassetid://1307617941", UDim2.new(1,-70,0,10))
	local closeButton = createControlButton("CloseButton", "rbxassetid://3926305904", UDim2.new(1,-30,0,10))
	local sidebarWidth = JustHub.Save.TabSize
	local sidebar = createInstance("Frame", {Name = "Sidebar", Size = UDim2.new(0,sidebarWidth,1,-60), Position = UDim2.new(0,0,0,60), BackgroundColor3 = currentTheme["Color Hub 2"]}, mainFrame)
	createInstance("UICorner", {CornerRadius = UDim.new(0,10)}, sidebar)
	createInstance("UIListLayout", {FillDirection = Enum.FillDirection.Vertical, Padding = UDim.new(0,10), HorizontalAlignment = Enum.HorizontalAlignment.Center, VerticalAlignment = Enum.VerticalAlignment.Top}, sidebar)
	local contentContainer = createInstance("Frame", {Name = "ContentContainer", Size = UDim2.new(1,-sidebarWidth,1,-60), Position = UDim2.new(0,sidebarWidth,0,60), BackgroundColor3 = currentTheme["Color Hub 2"]}, mainFrame)
	createInstance("UICorner", {CornerRadius = UDim.new(0,10)}, contentContainer)
	local scrollingFrame = createInstance("ScrollingFrame", {Size = UDim2.new(1,0,1,0), BackgroundTransparency = 1, ScrollBarThickness = 8, BorderSizePixel = 0}, contentContainer)
	createInstance("UIListLayout", {SortOrder = Enum.SortOrder.LayoutOrder, Padding = UDim.new(0,10)}, scrollingFrame)
	local fpsLabel = createInstance("TextLabel", {Name = "FPSLabel", Size = UDim2.new(0,100,0,20), AnchorPoint = Vector2.new(1,1), Position = UDim2.new(1,-10,1,-10), BackgroundTransparency = 1, TextColor3 = currentTheme["Color Text"], Font = Enum.Font.Gotham, TextSize = 14, Text = "FPS: Calculating..."}, mainFrame)
	RunService.Heartbeat:Connect(function(delta)
		local fps = math.floor(1/delta)
		fpsLabel.Text = "FPS: " .. fps
	end)
	local tweenInfoIn = TweenInfo.new(0.5, Enum.EasingStyle.Back, Enum.EasingDirection.Out)
	local tweenIn = TweenService:Create(mainFrame, tweenInfoIn, {Position = UDim2.new(0.5,0,0.5,0)})
	tweenIn:Play()
	closeButton.MouseButton1Click:Connect(function()
		local tweenInfoOut = TweenInfo.new(0.5, Enum.EasingStyle.Back, Enum.EasingDirection.In)
		local tweenOut = TweenService:Create(mainFrame, tweenInfoOut, {Position = UDim2.new(0.5,0,-0.5,0)})
		tweenOut:Play()
		tweenOut.Completed:Connect(function() screenGui:Destroy() end)
	end)
	local dragging = false
	local dragStart, startPos
	topBar.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
			dragging = true
			dragStart = input.Position
			startPos = mainFrame.Position
		end
	end)
	topBar.InputChanged:Connect(function(input)
		if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
			local delta = input.Position - dragStart
			local newPos = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y)
			newPos = clampPosition(newPos, Vector2.new(screenGui.AbsoluteSize.X, screenGui.AbsoluteSize.Y))
			mainFrame.Position = newPos
		end
	end)
	UserInputService.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragging = false end
	end)
	print("JustHub Window dibuat.")
	local windowObject = {ScreenGui = screenGui, MainFrame = mainFrame, TopBar = topBar, Sidebar = sidebar, ContentContainer = contentContainer, Tabs = {}}
	function windowObject:addTab(tabName)
		tabName = tabName or "Tab"
		local tabButton = createInstance("TextButton", {Name = tabName.."Button", Text = tabName, Size = UDim2.new(1,0,0,30), BackgroundColor3 = currentTheme["Color Stroke"], TextColor3 = currentTheme["Color Text"], Font = Enum.Font.GothamBold, TextSize = 16}, self.Sidebar)
		local tabContent = createInstance("Frame", {Name = tabName.."Content", Size = UDim2.new(1,0,1,0), BackgroundTransparency = 1, Visible = false}, scrollingFrame)
		local tabObject = {Name = tabName, Button = tabButton, Content = tabContent, Sections = {}}
		table.insert(self.Tabs, tabObject)
		tabButton.MouseButton1Click:Connect(function()
			for _, t in ipairs(self.Tabs) do t.Content.Visible = false end
			tabObject.Content.Visible = true
		end)
		if #self.Tabs == 1 then tabObject.Content.Visible = true end
		function tabObject:addSection(sectionName, sectionHeight)
			sectionName = sectionName or "Section"
			sectionHeight = sectionHeight or 100
			local sectionFrame = createInstance("Frame", {Name = sectionName, Size = UDim2.new(1,0,0,sectionHeight), BackgroundColor3 = currentTheme["Color Hub 2"], BackgroundTransparency = 0.2}, self.Content)
			createInstance("UICorner", {CornerRadius = UDim.new(0,8)}, sectionFrame)
			local sectionTitle = createInstance("TextLabel", {Name = "SectionTitle", Text = sectionName, Size = UDim2.new(1,0,0,30), BackgroundTransparency = 1, TextColor3 = currentTheme["Color Text"], Font = Enum.Font.GothamBold, TextSize = 16, TextXAlignment = Enum.TextXAlignment.Left}, sectionFrame)
			local sectionContent = createInstance("Frame", {Name = "SectionContent", Size = UDim2.new(1,0,1,-30), Position = UDim2.new(0,0,0,30), BackgroundTransparency = 1}, sectionFrame)
			createInstance("UIListLayout", {FillDirection = Enum.FillDirection.Vertical, Padding = UDim.new(0,5), SortOrder = Enum.SortOrder.LayoutOrder}, sectionContent)
			local sectionObj = {Frame = sectionFrame, Title = sectionTitle, Content = sectionContent}
			table.insert(self.Sections, sectionObj)
			setmetatable(sectionObj, {__index = SectionMethods})
			return sectionObj
		end
		return tabObject
	end
	return windowObject
end

function JustHub:ShowLoadingScreen(duration, callback)
	duration = duration or 5
	callback = callback or function() end
	local player = Players.LocalPlayer
	local playerGui = player:WaitForChild("PlayerGui")
	local loadingGui = createInstance("ScreenGui", {Name = "LoadingScreen", ResetOnSpawn = false, IgnoreGuiInset = true}, playerGui)
	local background = createInstance("Frame", {Size = UDim2.new(1,0,1,0), Position = UDim2.new(0,0,0,0), BackgroundColor3 = Color3.new(0,0,0), BackgroundTransparency = 0.5, BorderSizePixel = 0}, loadingGui)
	local titleLabel = createInstance("TextLabel", {Text = "JustHub Library", Font = Enum.Font.SourceSansSemibold, TextSize = 20, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], BackgroundTransparency = 1, Size = UDim2.new(0,200,0,50), AnchorPoint = Vector2.new(0.5,0.5), Position = UDim2.new(0.5,0,0.5,-50)}, loadingGui)
	local welcomeLabel = createInstance("TextLabel", {Text = "Welcome, " .. player.Name, Font = Enum.Font.SourceSansSemibold, TextSize = 16, TextColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Text"], BackgroundTransparency = 1, Size = UDim2.new(0,200,0,30), AnchorPoint = Vector2.new(0.5,0), Position = UDim2.new(0.5,0,0.5,10)}, loadingGui)
	local progressBarContainer = createInstance("Frame", {Size = UDim2.new(0.5,0,0,20), Position = UDim2.new(0.5,0,0.5,50), AnchorPoint = Vector2.new(0.5,0.5), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Stroke"], BackgroundTransparency = 0.5, BorderSizePixel = 0}, loadingGui)
	createInstance("UICorner", {CornerRadius = UDim.new(0,4)}, progressBarContainer)
	local progressBarFill = createInstance("Frame", {Size = UDim2.new(0,0,1,0), BackgroundColor3 = getCurrentTheme(JustHub.Save.Theme)["Color Theme"], BorderSizePixel = 0}, progressBarContainer)
	createInstance("UICorner", {CornerRadius = UDim.new(0,4)}, progressBarFill)
	local tweenInfo = TweenInfo.new(duration, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
	local progressTween = TweenService:Create(progressBarFill, tweenInfo, {Size = UDim2.new(1,0,1,0)})
	progressTween:Play()
	spawn(function()
		while progressTween.PlaybackState == Enum.PlaybackState.Playing do
			tweenProperty(titleLabel, {TextTransparency = 0.5}, 0.5)
			wait(0.5)
			tweenProperty(titleLabel, {TextTransparency = 0}, 0.5)
			wait(0.5)
		end
	end)
	progressTween.Completed:Connect(function()
		wait(0.5)
		loadingGui:Destroy()
		callback()
	end)
end

function JustHub:InitializeUI(options)
	self:ShowLoadingScreen(5, function()
		local window = self:CreateWindow(options)
		self.Window = window
		print("Window dibuat setelah loading screen.")
	end)
end

function JustHub:SaveConfig(fileName)
	fileName = fileName or "JustHub_Config.json"
	if writefile then
		local json = HttpService:JSONEncode(JustHub.ConfigData)
		writefile(fileName, json)
		StarterGui:SetCore("SendNotification", {Title = "Save Config", Text = "Config berhasil disimpan ke " .. fileName, Duration = 5})
	else
		warn("Saving config is not supported in this environment.")
	end
end

function JustHub:LoadConfig(fileName)
	fileName = fileName or "JustHub_Config.json"
	if readfile then
		local data = readfile(fileName)
		local config = HttpService:JSONDecode(data)
		JustHub.ConfigData = config
		JustHub:ApplyConfig(config)
		StarterGui:SetCore("SendNotification", {Title = "Load Config", Text = "Config berhasil dimuat dari " .. fileName, Duration = 5})
		return config
	else
		warn("Loading config is not supported in this environment.")
		return {}
	end
end

function JustHub:ToggleUIVisibility()
	if self.ScreenGui and self.ScreenGui.Parent then
		self.ScreenGui.Enabled = not self.ScreenGui.Enabled
	end
end

UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if not gameProcessed and input.KeyCode and input.KeyCode == Enum.KeyCode.RightShift then
		JustHub:ToggleUIVisibility()
	end
end)

function JustHub:Notify(options)
	options = options or {}
	local title = options.Title or ""
	local text = options.Message or ""
	local duration = options.Duration or 5
	local success, errorMessage = pcall(function()
		StarterGui:SetCore("SendNotification", {Title = title, Text = text, Duration = duration})
	end)
	if not success then
		warn("Gagal mengirim notifikasi: " .. errorMessage)
	end
end

return JustHub