ARCHBLOX
Key RequiredUniversal

ARCHBLOX

Universal Scriptchillingchilling 849 views 131 executesUpdated May 12, 2026
2.5/ 5(2 votes)
1150% Positive
Lua Script•2424 lines (100584 chars)
--[[
	WARNING: Heads up! This script has not been verified by ScriptBlox. Use at your own risk!
]]
--  █████╗ ██████╗  ██████╗██╗  ██╗ ██████╗ ███████╗
-- ██╔══██╗██╔══██╗██╔════╝██║  ██║██╔═══██╗██╔════╝
-- ███████║██████╔╝██║     ███████║██║   ██║███████╗
-- ██╔══██║██╔══██╗██║     ██╔══██║██║   ██║╚════██║
-- ██║  ██║██║  ██║╚██████╗██║  ██║╚██████╔╝███████║
-- ╚═╝  ╚═╝╚═╝  ╚═╝ ╚═════╝╚═╝  ╚═╝ ╚═════╝ ╚══════╝
--           v3.0 — Arch Linux Edition
-- "I use Arch btw" — Paste into executor

local Players        = game:GetService("Players")
local UIS            = game:GetService("UserInputService")
local TweenService   = game:GetService("TweenService")
local RunService     = game:GetService("RunService")

local player = Players.LocalPlayer

-- ── CONTAINER ──────────────────────────────────────────────────
local guiParent = (gethui and gethui()) or game:GetService("CoreGui")

-- Remove old copy
local old = guiParent:FindFirstChild("ArchOS_v3")
if old then old:Destroy() end
task.wait()

local gui = Instance.new("ScreenGui")
gui.Name            = "ArchOS_v3"
gui.ResetOnSpawn    = false
gui.ZIndexBehavior  = Enum.ZIndexBehavior.Global
gui.IgnoreGuiInset  = true
gui.Parent          = guiParent

-- ── THEMES ──────────────────────────────────────────────────────
local Themes = {
    ArchLinux = {
        name     = "ArchLinux",
        bg1      = Color3.fromRGB(12, 12, 12),       -- Pure dark
        bg2      = Color3.fromRGB(18, 18, 18),       -- Slightly lighter
        surface  = Color3.fromRGB(24, 24, 24),       -- Surface
        surface2 = Color3.fromRGB(32, 32, 32),       -- Elevated surface
        border   = Color3.fromRGB(23, 147, 209),     -- Arch blue
        accent   = Color3.fromRGB(23, 147, 209),     -- Arch blue #1793D1
        accent2  = Color3.fromRGB(8, 109, 156),      -- Dark Arch blue
        accentDk = Color3.fromRGB(8, 109, 156),      -- Dark blue
        text     = Color3.fromRGB(255, 255, 255),    -- Pure white
        textDim  = Color3.fromRGB(180, 180, 180),    -- Gray
        textMut  = Color3.fromRGB(100, 100, 100),    -- Muted gray
        green    = Color3.fromRGB(0, 255, 0),        -- Terminal green
        red      = Color3.fromRGB(255, 0, 0),        -- Terminal red
        yellow   = Color3.fromRGB(255, 255, 0),      -- Terminal yellow
        term     = Color3.fromRGB(0, 0, 0),          -- Pure black terminal
        termTxt  = Color3.fromRGB(255, 255, 255),    -- White terminal text
        close    = Color3.fromRGB(255, 0, 0),        -- Red
        minimize = Color3.fromRGB(255, 255, 0),      -- Yellow
        maximize = Color3.fromRGB(0, 255, 0),        -- Green
        winTitle = Color3.fromRGB(18, 18, 18),       -- Dark title bar
        gradA    = Color3.fromRGB(0,0,0),
        gradB    = Color3.fromRGB(12,12,12),
        dotCol   = Color3.fromRGB(23,147,209),       -- Arch blue dots
    },
    ArchClassic = {
        name     = "ArchClassic",
        bg1      = Color3.fromRGB(8, 8, 8),          -- Even darker
        bg2      = Color3.fromRGB(15, 15, 15),       
        surface  = Color3.fromRGB(20, 20, 20),       
        surface2 = Color3.fromRGB(28, 28, 28),       
        border   = Color3.fromRGB(23, 147, 209),     -- Arch blue
        accent   = Color3.fromRGB(23, 147, 209),     -- Arch blue
        accent2  = Color3.fromRGB(51, 181, 229),     -- Light blue
        accentDk = Color3.fromRGB(8, 109, 156),      
        text     = Color3.fromRGB(220, 220, 220),    
        textDim  = Color3.fromRGB(150, 150, 150),    
        textMut  = Color3.fromRGB(80, 80, 80),       
        green    = Color3.fromRGB(138, 226, 52),     -- Arch wiki green
        red      = Color3.fromRGB(204, 0, 0),        
        yellow   = Color3.fromRGB(252, 233, 79),     
        term     = Color3.fromRGB(0, 0, 0),          
        termTxt  = Color3.fromRGB(220, 220, 220),    
        close    = Color3.fromRGB(204, 0, 0),        
        minimize = Color3.fromRGB(252, 233, 79),     
        maximize = Color3.fromRGB(138, 226, 52),     
        winTitle = Color3.fromRGB(15, 15, 15),       
        gradA    = Color3.fromRGB(0,0,0),
        gradB    = Color3.fromRGB(8,8,8),
        dotCol   = Color3.fromRGB(23,147,209),
    },
    ArchMonokai = {
        name     = "ArchMonokai",
        bg1      = Color3.fromRGB(39, 40, 34),       -- Monokai background
        bg2      = Color3.fromRGB(46, 47, 41),       
        surface  = Color3.fromRGB(54, 55, 49),       
        surface2 = Color3.fromRGB(62, 63, 57),       
        border   = Color3.fromRGB(102, 217, 239),    -- Monokai cyan
        accent   = Color3.fromRGB(102, 217, 239),    -- Cyan
        accent2  = Color3.fromRGB(166, 226, 46),     -- Green
        accentDk = Color3.fromRGB(73, 156, 171),     
        text     = Color3.fromRGB(248, 248, 242),    -- Monokai white
        textDim  = Color3.fromRGB(117, 113, 94),     -- Comment
        textMut  = Color3.fromRGB(117, 113, 94),     
        green    = Color3.fromRGB(166, 226, 46),     -- Monokai green
        red      = Color3.fromRGB(249, 38, 114),     -- Monokai pink/red
        yellow   = Color3.fromRGB(230, 219, 116),    -- Monokai yellow
        term     = Color3.fromRGB(30, 31, 25),       
        termTxt  = Color3.fromRGB(248, 248, 242),    
        close    = Color3.fromRGB(249, 38, 114),     
        minimize = Color3.fromRGB(230, 219, 116),    
        maximize = Color3.fromRGB(166, 226, 46),     
        winTitle = Color3.fromRGB(46, 47, 41),       
        gradA    = Color3.fromRGB(30,31,25),
        gradB    = Color3.fromRGB(39,40,34),
        dotCol   = Color3.fromRGB(102,217,239),
    },
}

local T = Themes.ArchLinux -- current theme
local ActiveTheme = "ArchLinux"

-- ── HELPERS ────────────────────────────────────────────────────
local function tw(obj, props, t, style)
    TweenService:Create(obj,
        TweenInfo.new(t or .18, style or Enum.EasingStyle.Quad, Enum.EasingDirection.Out),
        props):Play()
end

local function c(cls, props, parent)
    local o = Instance.new(cls)
    for k,v in pairs(props) do
        pcall(function() o[k] = v end)
    end
    if parent then o.Parent = parent end
    return o
end

local function corner(p, r)
    return c("UICorner", {CornerRadius = UDim.new(0, r or 8)}, p)
end

local function stroke(p, col, thick, trans)
    return c("UIStroke", {Color = col or T.border, Thickness = thick or 1, Transparency = trans or .4}, p)
end

local function pad(p, px)
    local u = Instance.new("UIPadding")
    u.PaddingLeft   = UDim.new(0, px)
    u.PaddingRight  = UDim.new(0, px)
    u.PaddingTop    = UDim.new(0, px)
    u.PaddingBottom = UDim.new(0, px)
    u.Parent = p
end

local function gradient(p, a, b, rot)
    local g = Instance.new("UIGradient")
    g.Color = ColorSequence.new(a, b)
    g.Rotation = rot or 0
    g.Parent = p
    return g
end

local function hover(btn, norm, hov, prop)
    prop = prop or "BackgroundColor3"
    btn.MouseEnter:Connect(function() tw(btn, {[prop]=hov})  end)
    btn.MouseLeave:Connect(function() tw(btn, {[prop]=norm}) end)
end

local function shadow(parent, zIdx)
    local s = c("Frame", {
        Size = UDim2.new(1, 20, 1, 20),
        Position = UDim2.new(0, -10, 0, -10),
        BackgroundColor3 = Color3.new(0,0,0),
        BackgroundTransparency = .65,
        ZIndex = zIdx - 1,
        BorderSizePixel = 0,
    }, parent)
    corner(s, 14)
    return s
end

-- ── NOTIFICATION SYSTEM ───────────────────────────────────────
local notifContainer = c("Frame", {
    Size = UDim2.new(0, 340, 1, 0),
    Position = UDim2.new(1, -350, 0, 10),
    BackgroundTransparency = 1,
    ZIndex = 8000,
}, gui)
c("UIListLayout", {
    Padding = UDim.new(0, 8),
    VerticalAlignment = Enum.VerticalAlignment.Top,
    SortOrder = Enum.SortOrder.LayoutOrder,
}, notifContainer)

local function notify(title, text, duration, icon)
    local nf = c("Frame", {
        Size = UDim2.new(1, 0, 0, 70),
        BackgroundColor3 = T.bg2,
        BorderSizePixel = 0,
        ZIndex = 8001,
        BackgroundTransparency = 1,
    }, notifContainer)
    corner(nf, 10)
    stroke(nf, T.accent, 1, .3)

    -- Accent bar on left
    local bar = c("Frame", {
        Size = UDim2.new(0, 4, 1, -8),
        Position = UDim2.new(0, 4, 0, 4),
        BackgroundColor3 = T.accent,
        BorderSizePixel = 0,
        ZIndex = 8002,
    }, nf)
    corner(bar, 2)

    c("TextLabel", {
        Size = UDim2.new(0, 30, 0, 30),
        Position = UDim2.new(0, 14, 0, 8),
        BackgroundTransparency = 1,
        Text = icon or "🔔",
        TextSize = 20,
        ZIndex = 8002,
    }, nf)

    c("TextLabel", {
        Size = UDim2.new(1, -60, 0, 22),
        Position = UDim2.new(0, 48, 0, 6),
        BackgroundTransparency = 1,
        Text = title,
        Font = Enum.Font.GothamBold,
        TextSize = 14,
        TextColor3 = T.text,
        TextXAlignment = Enum.TextXAlignment.Left,
        ZIndex = 8002,
    }, nf)

    c("TextLabel", {
        Size = UDim2.new(1, -60, 0, 30),
        Position = UDim2.new(0, 48, 0, 28),
        BackgroundTransparency = 1,
        Text = text,
        Font = Enum.Font.Gotham,
        TextSize = 12,
        TextColor3 = T.textDim,
        TextXAlignment = Enum.TextXAlignment.Left,
        TextWrapped = true,
        ZIndex = 8002,
    }, nf)

    -- Appear animation
    tw(nf, {BackgroundTransparency = 0}, .3)

    task.delay(duration or 4, function()
        tw(nf, {BackgroundTransparency = 1, Size = UDim2.new(1, 0, 0, 0)}, .3)
        task.delay(.35, function() nf:Destroy() end)
    end)
end

-- ── FILE SYSTEM ───────────────────────────────────────────────
local FS = {}
local CWD = "/home/"..player.Name:lower()

local function fsNew(t, content)
    return {t=t, content=content or "", children={}, time=os.time()}
end

FS["/"]              = fsNew("dir")
FS["/bin"]           = fsNew("dir")
FS["/boot"]          = fsNew("dir")
FS["/etc"]           = fsNew("dir")
FS["/home"]          = fsNew("dir")
FS["/home/"..player.Name:lower()]   = fsNew("dir")
FS["/home/"..player.Name:lower().."/Documents"] = fsNew("dir")
FS["/home/"..player.Name:lower().."/Downloads"] = fsNew("dir")
FS["/opt"]           = fsNew("dir")
FS["/tmp"]           = fsNew("dir")
FS["/usr"]           = fsNew("dir")
FS["/usr/bin"]       = fsNew("dir")
FS["/var"]           = fsNew("dir")
FS["/var/log"]       = fsNew("dir")

local function regChild(parent, child)
    if FS[parent] then
        table.insert(FS[parent].children, child)
    end
end

regChild("/",           "/bin")
regChild("/",           "/boot")
regChild("/",           "/etc")
regChild("/",           "/home")
regChild("/",           "/opt")
regChild("/",           "/tmp")
regChild("/",           "/usr")
regChild("/",           "/var")
regChild("/home",       "/home/"..player.Name:lower())
regChild("/home/"..player.Name:lower(),"/home/"..player.Name:lower().."/Documents")
regChild("/home/"..player.Name:lower(),"/home/"..player.Name:lower().."/Downloads")
regChild("/usr",        "/usr/bin")
regChild("/var",        "/var/log")

local function mkf(path, content, parent)
    FS[path] = fsNew("file", content)
    if parent then regChild(parent, path) end
end

mkf("/etc/hostname",              "archos-roblox",                          "/etc")
mkf("/etc/motd",                  "Welcome to Arch Linux!\nType 'help' for available commands.\n'man archlinux' for system info.\nBTW, you're using Arch.\n", "/etc")
mkf("/etc/os-release",            "NAME=\"Arch Linux\"\nID=arch\nVERSION_ID=\"rolling\"\nBUILD_ID=rolling\nPRETTY_NAME=\"Arch Linux\"\nHOME_URL=\"https://archlinux.org/\"\n", "/etc")
mkf("/etc/passwd",                "root:x:0:0::/root:/bin/bash\n"..player.Name:lower()..":x:1000:1000::"..CWD..":/bin/bash\n", "/etc")
mkf("/etc/pacman.conf",           "[options]\nArchitecture = auto\nColor\nILoveCandy\nParallelDownloads = 5\n\n[core]\nInclude = /etc/pacman.d/mirrorlist\n\n[extra]\nInclude = /etc/pacman.d/mirrorlist\n", "/etc")
mkf("/home/"..player.Name:lower().."/README.md",    "# Welcome to ArchOS v3.0\n\n**I use Arch btw**\n\n## Features:\n- Pacman package manager\n- Rolling release system\n- 3 Arch themes\n- Full terminal with Arch commands\n- System monitor & task manager\n\n## Quick Start:\n```bash\nneofetch          # System info\npacman -Syu       # System update\npacman -S firefox # Install package\nhtop              # Process monitor\n```\n\nType 'help' in terminal for all commands!\n", "/home/"..player.Name:lower())
mkf("/home/"..player.Name:lower().."/TODO.md",      "# TODO List\n\n- [x] Install Arch Linux\n- [ ] Configure i3wm\n- [ ] Set up AUR helper\n- [ ] Rice the desktop\n- [ ] Tell everyone you use Arch\n", "/home/"..player.Name:lower())
mkf("/home/"..player.Name:lower().."/Documents/notes.txt", "# Arch Linux Notes\n\n## Why Arch?\n- Rolling release = always up to date\n- Minimalist base installation\n- AUR = Arch User Repository\n- Pacman is blazingly fast\n- You can tell people you use Arch\n\n## Essential Commands:\n- sudo pacman -Syu (update system)\n- pacman -Ss <pkg> (search package)\n- pacman -S <pkg> (install package)\n- pacman -R <pkg> (remove package)\n", "/home/"..player.Name:lower().."/Documents")
mkf("/tmp/session.log",           "Session started: "..os.date("%H:%M:%S").."\nArch Linux rolling release\n", "/tmp")
mkf("/var/log/pacman.log",        "["..(os.date("%Y-%m-%d %H:%M")).."] [PACMAN] Running 'pacman -Syu'\n["..(os.date("%Y-%m-%d %H:%M")).."] [PACMAN] synchronizing package lists\n["..(os.date("%Y-%m-%d %H:%M")).."] [PACMAN] starting full system upgrade\n["..(os.date("%Y-%m-%d %H:%M")).."] [ALPM] upgraded linux (6.6.1-arch1-1 -> 6.6.2-arch1-1)\n", "/var/log")
mkf("/var/log/kernel.log",        "[    0.000000] Linux version 6.6.2-arch1-1 (linux@archlinux)\n[    0.001234] Command line: BOOT_IMAGE=/vmlinuz-linux root=UUID=XXXX rw loglevel=3\n[    0.002456] Kernel command line: BOOT_IMAGE=/vmlinuz-linux root=UUID=XXXX rw\n[    0.045678] Arch Linux initialized\n[    0.067890] systemd initialized\n", "/var/log")

local function fsResolve(path)
    if path == "~" then return CWD end
    if path:sub(1,2) == "~/" then
        path = CWD .. "/" .. path:sub(3)
    end
    if path:sub(1,1) ~= "/" then
        path = (CWD == "/" and "/"..path) or (CWD.."/"..path)
    end
    local parts = {}
    for seg in path:gmatch("[^/]+") do
        if seg == ".." then table.remove(parts)
        elseif seg ~= "." then table.insert(parts, seg) end
    end
    return (#parts == 0 and "/") or ("/"..table.concat(parts,"/"))
end

local function fsRead(path)
    local nd = FS[fsResolve(path)]
    return nd and nd.t == "file" and nd.content or nil
end

local function fsWrite(path, content)
    local abs = fsResolve(path)
    if FS[abs] then
        FS[abs].content = content
        FS[abs].time = os.time()
    else
        FS[abs] = fsNew("file", content)
        local parentPath = abs:match("(.+)/[^/]+$") or "/"
        if FS[parentPath] and FS[parentPath].t == "dir" then
            table.insert(FS[parentPath].children, abs)
        end
    end
end

local function fsList(path)
    local node = FS[fsResolve(path)]
    return node and node.t == "dir" and node.children or nil
end

local function fsMkdir(path)
    local abs = fsResolve(path)
    if FS[abs] then return false, "already exists" end
    FS[abs] = fsNew("dir")
    local parentPath = abs:match("(.+)/[^/]+$") or "/"
    if FS[parentPath] and FS[parentPath].t == "dir" then
        table.insert(FS[parentPath].children, abs)
    end
    return true
end

-- ── KERNEL ───────────────────────────────────────────────────────
local Kernel = { procs={}, pid=1, boot=os.clock() }

local function kspawn(name, mem, sys)
    local id = Kernel.pid; Kernel.pid+=1
    Kernel.procs[id] = {
        pid=id, name=name, state="running",
        mem=mem or math.random(2,18), cpu=0,
        start=os.clock(), sys=sys or false
    }
    return id
end

local function kkill(pid)
    if not Kernel.procs[pid] then return false, "no process" end
    if Kernel.procs[pid].sys  then return false, "system process" end
    Kernel.procs[pid] = nil
    return true
end

kspawn("systemd",      2, true)
kspawn("systemd-journald", 3, true)
kspawn("dbus-daemon",  2, true)
kspawn("arch-wm",      6, true)
kspawn("pacman",       4, true)

RunService.Heartbeat:Connect(function(dt)
    for _, p in pairs(Kernel.procs) do
        p.cpu += dt * math.random(1,12)/100
    end
end)

-- ── DESKTOP ───────────────────────────────────────────────────
local desktop = c("Frame", {
    Size=UDim2.new(1,0,1,0),
    BackgroundColor3=T.bg1,
    BorderSizePixel=0,
    ZIndex=1,
}, gui)
local desktopGrad = gradient(desktop, T.gradA, T.gradB, 135)

-- Dot grid
local dots = c("Frame", {
    Size=UDim2.new(1,0,1,0),
    BackgroundTransparency=1,
    ZIndex=1,
}, desktop)

do
    local rows, cols = 20, 35
    for r=0, rows do
        for cc=0, cols do
            c("Frame", {
                Size=UDim2.new(0,2,0,2),
                Position=UDim2.new(cc/cols, 0, r/rows, 0),
                BackgroundColor3=T.dotCol,
                BackgroundTransparency=0.6,
                BorderSizePixel=0,
                ZIndex=1,
            }, dots)
        end
    end
end

-- ── WINDOWS SYSTEM ─────────────────────────────────────────────
local Z = 10
local WINS = {}
local OpenWinNames = {} -- for taskbar

local function makeDrag(handle, win)
    local drag, dstart, dpos = false, nil, nil
    handle.InputBegan:Connect(function(i)
        if i.UserInputType == Enum.UserInputType.MouseButton1 then
            drag=true; dstart=i.Position; dpos=win.Position
            i.Changed:Connect(function()
                if i.UserInputState==Enum.UserInputState.End then drag=false end
            end)
        end
    end)
    UIS.InputChanged:Connect(function(i)
        if drag and i.UserInputType==Enum.UserInputType.MouseMovement then
            local d=i.Position-dstart
            win.Position=UDim2.new(dpos.X.Scale, dpos.X.Offset+d.X,
                                   dpos.Y.Scale, dpos.Y.Offset+d.Y)
        end
    end)
end

local refreshTaskbar -- forward declare

local function newWindow(title, w, h, x, y)
    Z+=1
    local z = Z

    local win = c("Frame", {
        Size=UDim2.new(0,w,0,h),
        Position=UDim2.new(0,x or 200,0,y or 100),
        BackgroundColor3=T.surface,
        BorderSizePixel=0, ZIndex=z,
        ClipsDescendants=true,
    }, gui)
    corner(win, 10)
    stroke(win, T.accent, 1, .5)
    shadow(win, z)

    win.InputBegan:Connect(function(i)
        if i.UserInputType==Enum.UserInputType.MouseButton1 then
            Z+=1; win.ZIndex=Z
        end
    end)

    -- Title bar
    local bar = c("Frame", {
        Size=UDim2.new(1,0,0,38),
        BackgroundColor3=T.winTitle,
        BorderSizePixel=0, ZIndex=z+1,
    }, win)

    c("Frame", {
        Size=UDim2.new(1,0,0,1),
        Position=UDim2.new(0,0,1,-1),
        BackgroundColor3=T.accent,
        BackgroundTransparency=0.7,
        BorderSizePixel=0, ZIndex=z+2,
    }, bar)

    corner(bar, 10)
    c("Frame", {
        Size=UDim2.new(1,0,0.5,0),
        Position=UDim2.new(0,0,0.5,0),
        BackgroundColor3=T.winTitle,
        BorderSizePixel=0, ZIndex=z+1,
    }, bar)

    -- Control buttons (●●●)
    local function wbtn(col, xoff, sym, cb)
        local b = c("TextButton", {
            Size=UDim2.new(0,14,0,14),
            Position=UDim2.new(1,xoff,0.5,-7),
            BackgroundColor3=col,
            Text="", ZIndex=z+3, BorderSizePixel=0,
        }, bar)
        corner(b,7)
        local lbl=c("TextLabel", {
            Size=UDim2.new(1,0,1,0),
            BackgroundTransparency=1,
            Text=sym, TextColor3=Color3.new(0,0,0),
            Font=Enum.Font.GothamBold, TextSize=9,
            Visible=false, ZIndex=z+4,
        },b)
        b.MouseEnter:Connect(function() lbl.Visible=true  end)
        b.MouseLeave:Connect(function() lbl.Visible=false end)
        b.MouseButton1Click:Connect(cb)
        return b
    end

    local mini=false
    local maxi=false
    local orig=UDim2.new(0,w,0,h)
    local origPos=UDim2.new(0,x or 200,0,y or 100)
    local body

    -- Close
    wbtn(T.close, -22, "✕", function()
        tw(win,{Size=UDim2.new(0,w,0,0),BackgroundTransparency=1},.2)
        task.delay(.25, function()
            win:Destroy()
            WINS[title]=nil
            OpenWinNames[title]=nil
            if refreshTaskbar then refreshTaskbar() end
        end)
    end)

    -- Minimize
    wbtn(T.minimize, -40, "─", function()
        if mini then
            tw(win,{Size=orig},.2)
            if body then body.Visible=true end
            mini=false
        else
            tw(win,{Size=UDim2.new(0,w,0,38)},.2)
            task.delay(.15,function()
                if body then body.Visible=false end
            end)
            mini=true
        end
    end)

    -- Maximize
    wbtn(T.maximize, -58, "□", function()
        if maxi then
            tw(win,{Size=orig, Position=origPos},.25)
            maxi=false
        else
            origPos=win.Position
            orig=win.Size
            tw(win,{Size=UDim2.new(1,0,1,-44), Position=UDim2.new(0,0,0,0)},.25)
            maxi=true
        end
        if mini then
            mini=false
            if body then body.Visible=true end
        end
    end)

    -- Title text
    c("TextLabel", {
        Size=UDim2.new(1,-120,1,0),
        Position=UDim2.new(0,14,0,0),
        BackgroundTransparency=1,
        Text=title, Font=Enum.Font.GothamBold,
        TextSize=13, TextColor3=T.text,
        TextXAlignment=Enum.TextXAlignment.Left,
        ZIndex=z+2,
    }, bar)

    body = c("Frame", {
        Size=UDim2.new(1,0,1,-38),
        Position=UDim2.new(0,0,0,38),
        BackgroundTransparency=1,
        ZIndex=z+1, ClipsDescendants=true,
    }, win)

    makeDrag(bar, win)

    -- Appear animation
    win.Size=UDim2.new(0,w,0,0)
    win.BackgroundTransparency=1
    tw(win,{Size=UDim2.new(0,w,0,h), BackgroundTransparency=0},.25,Enum.EasingStyle.Back)

    WINS[title]=win
    OpenWinNames[title]=true
    if refreshTaskbar then refreshTaskbar() end

    return win, body, z
end

-- ── TERMINAL COMMANDS ────────────────────────────────────────
local cmdHistory = {}

local Fortunes = {
    "I use Arch btw.",
    "Pacman says: Wakka wakka wakka!",
    "There are no bugs in Arch, only features you haven't configured yet.",
    "sudo rm -rf / --no-preserve-root (Don't actually run this.)",
    "The AUR is a pathway to many packages some consider to be... unstable.",
    "Gentoo users still compiling while you're gaming.",
    "RTFM — Read The Friendly Manual (it's on the wiki).",
    "ArchWiki > Stack Overflow",
    "systemd is not the enemy, embrace it.",
    "Your system is bleeding edge... and sometimes it bleeds.",
    "Rolling release = always fresh, always broken.",
    "Kernel panic? Time for a kernel parameter!",
    "If it compiles, ship it. If it doesn't, check the AUR.",
    "The best time to switch to Arch was yesterday. The second best time is now.",
    "sudo pacman -Syu # The most dangerous command.",
}

local function runCmd(cmd, out)
    local args={}
    for a in cmd:gmatch("%S+") do table.insert(args,a) end
    local cc=args[1]
    if not cc or cc=="" then return end

    table.insert(cmdHistory, cmd)

    if cc=="help" then
        out("╔══════════════════════════════════════════════╗", T.accent)
        out("║     Arch Linux Shell — Command Reference     ║", T.accent)
        out("╠══════════════════════════════════════════════╣", T.accent)
        out("║  File System:                                ║", T.accent2)
        out("║  ls [path]      — list directory             ║", T.text)
        out("║  cd [path]      — change directory           ║", T.text)
        out("║  cat [file]     — display file               ║", T.text)
        out("║  head [file]    — first lines                ║", T.text)
        out("║  tail [file]    — last lines                 ║", T.text)
        out("║  mkdir [dir]    — create directory           ║", T.text)
        out("║  touch [file]   — create file                ║", T.text)
        out("║  rm [file]      — remove file                ║", T.text)
        out("║  mv [src] [dst] — move/rename                ║", T.text)
        out("║  cp [src] [dst] — copy file                  ║", T.text)
        out("║  grep [pat] [f] — search in file            ║", T.text)
        out("║  tree [path]    — directory tree            ║", T.text)
        out("║  pwd            — print working directory    ║", T.text)
        out("╠══════════════════════════════════════════════╣", T.accent2)
        out("║  Package Management (Pacman):                ║", T.accent2)
        out("║  pacman -Syu    — update system              ║", T.text)
        out("║  pacman -S pkg  — install package            ║", T.text)
        out("║  pacman -R pkg  — remove package             ║", T.text)
        out("║  pacman -Ss pat — search packages            ║", T.text)
        out("║  pacman -Q      — list installed             ║", T.text)
        out("╠══════════════════════════════════════════════╣", T.accent2)
        out("║  System Information:                         ║", T.accent2)
        out("║  uname          — system info                ║", T.text)
        out("║  neofetch       — system info (fancy)        ║", T.text)
        out("║  screenfetch    — system info (alt)          ║", T.text)
        out("║  htop           — process viewer             ║", T.text)
        out("║  ps             — list processes             ║", T.text)
        out("║  kill [pid]     — terminate process          ║", T.text)
        out("║  free           — memory usage               ║", T.text)
        out("║  df             — disk space                 ║", T.text)
        out("║  uptime         — system uptime              ║", T.text)
        out("║  whoami         — current user               ║", T.text)
        out("║  man [cmd]      — manual pages               ║", T.text)
        out("║  fortune        — random wisdom              ║", T.text)
        out("║  history        — command history            ║", T.text)
        out("║  clear          — clear screen               ║", T.text)
        out("║  exit           — close terminal             ║", T.text)
        out("╚══════════════════════════════════════════════╝", T.accent)

    elseif cc=="neofetch" or cc=="screenfetch" then
        local up=os.clock()-Kernel.boot
        local h=math.floor(up/3600)
        local m=math.floor(up%3600/60)
        local cnt=0; local mem=0
        for _,p in pairs(Kernel.procs) do cnt+=1; mem+=p.mem end

        out("", T.text)
        out("                   -`                    "..player.Name.."@archos", T.accent)
        out("                  .o+`                   ──────────────────", T.accent)
        out("                 `ooo/                   OS:       Arch Linux x86_64", T.text)
        out("                `+oooo:                  Host:     Roblox Runtime", T.text)
        out("               `+oooooo:                 Kernel:   6.6.2-arch1-1", T.text)
        out("               -+oooooo+:                Uptime:   "..string.format("%dh %dm", h, m), T.text)
        out("             `/:-:++oooo+:               Packages: "..math.random(800,1200).." (pacman)", T.text)
        out("            `/++++/+++++++:              Shell:    bash 5.2.21", T.text)
        out("           `/++++++++++++++:             Theme:    "..ActiveTheme, T.text)
        out("          `/+++ooooooooooooo/`           WM:       arch-wm", T.text)
        out("         ./ooosssso++osssssso+`          Terminal: alacritty", T.text)
        out("        .oossssso-````/ossssss+`         CPU:      Luau JIT", T.text)
        out("       -osssssso.      :ssssssso.        Memory:   "..mem.."MB / 2048MB", T.text)
        out("      :osssssss/        osssso+++.       Procs:    "..cnt, T.text)
        out("     /ossssssss/        +ssssooo/-       Player:   "..player.DisplayName, T.text)
        out("   `/ossssso+/:-        -:/+osssso+-     Uptime:   Since "..os.date("%H:%M"), T.text)
        out("  `+sso+:-`                 `.-/+oso:    ", T.text)
        out(" `++:.                           `-/+/   ", T.text)
        out(" .`                                 `/   ", T.text)
        out("", T.text)

    elseif cc=="man" then
        if not args[2] then 
            out("What manual page do you want?", T.yellow)
            out("Example: man pacman", T.textDim)
        elseif args[2]=="pacman" then
            out("", T.text)
            out("PACMAN(8)              Arch Linux             PACMAN(8)", T.accent)
            out("", T.text)
            out("NAME", T.accent2)
            out("       pacman - package manager utility", T.text)
            out("", T.text)
            out("SYNOPSIS", T.accent2)
            out("       pacman <operation> [options] [targets]", T.text)
            out("", T.text)
            out("DESCRIPTION", T.accent2)
            out("       Pacman is a package management utility that tracks", T.text)
            out("       installed packages. It uses simple compressed", T.text)
            out("       files as a package format.", T.text)
            out("", T.text)
            out("OPERATIONS", T.accent2)
            out("       -S, --sync       Synchronize packages", T.text)
            out("       -R, --remove     Remove packages", T.text)
            out("       -Q, --query      Query installed packages", T.text)
            out("       -Syu             Update system", T.text)
            out("", T.text)
            out("EXAMPLES", T.accent2)
            out("       pacman -Syu              Update system", T.text)
            out("       pacman -S firefox        Install Firefox", T.text)
            out("       pacman -R firefox        Remove Firefox", T.text)
            out("       pacman -Ss browser       Search for browser", T.text)
            out("", T.text)
        elseif args[2]=="archlinux" then
            out("", T.text)
            out("ARCH LINUX", T.accent)
            out("", T.text)
            out("Arch Linux is an independently developed, x86-64 general-", T.text)
            out("purpose GNU/Linux distribution that strives to provide the", T.text)
            out("latest stable versions of most software by following a", T.text)
            out("rolling-release model.", T.text)
            out("", T.text)
            out("PHILOSOPHY", T.accent2)
            out("  • Simplicity      Design without unnecessary additions", T.text)
            out("  • Modernity       Cutting-edge software", T.text)
            out("  • Pragmatism      Principles over ideology", T.text)
            out("  • User centrality You make the decisions", T.text)
            out("  • Versatility     Handle any task", T.text)
            out("", T.text)
            out("KEY FEATURES", T.accent2)
            out("  • Rolling release model (always up-to-date)", T.text)
            out("  • Pacman package manager", T.text)
            out("  • AUR (Arch User Repository)", T.text)
            out("  • systemd init system", T.text)
            out("  • Excellent documentation (ArchWiki)", T.text)
            out("", T.text)
            out("Learn more at: https://archlinux.org/", T.accent2)
            out("", T.text)
        else
            out("No manual entry for "..args[2], T.red)
        end

    elseif cc=="fortune" then
        out("🔮  "..Fortunes[math.random(#Fortunes)], T.yellow)

    elseif cc=="pacman" then
        if args[2]=="-Syu" then
            out(":: Synchronizing package databases...", T.accent2)
            task.wait(0.2)
            out(" core is up to date", T.textDim)
            out(" extra is up to date", T.textDim)
            out(" multilib is up to date", T.textDim)
            out(":: Starting full system upgrade...", T.accent2)
            task.wait(0.3)
            out(" there is nothing to do", T.green)
        elseif args[2]=="-S" then
            if not args[3] then
                out("error: no targets specified (use -h for help)", T.red)
            else
                local pkg=args[3]
                out("resolving dependencies...", T.textDim)
                out("looking for conflicting packages...", T.textDim)
                out("", T.text)
                out("Packages (1) "..pkg.."-1.0.0", T.text)
                out("", T.text)
                out("Total Download Size:   "..math.random(5,50)..".00 MiB", T.text)
                out("Total Installed Size:  "..math.random(10,100)..".00 MiB", T.text)
                out("", T.text)
                out(":: Proceed with installation? [Y/n] ", T.accent2)
                out(":: Retrieving packages...", T.accent2)
                out(" "..pkg.."-1.0.0-x86_64    "..math.random(5,50)..".0 MiB    "..math.random(500,9999).." KiB/s 00:0"..math.random(1,9), T.textDim)
                out("(1/1) checking keys in keyring", T.textDim)
                out("(1/1) checking package integrity", T.textDim)
                out("(1/1) loading package files", T.textDim)
                out("(1/1) checking for file conflicts", T.textDim)
                out("(1/1) installing "..pkg.."...", T.textDim)
                out(":: Transaction successfully finished ✓", T.green)
            end
        elseif args[2]=="-R" then
            if not args[3] then
                out("error: no targets specified (use -h for help)", T.red)
            else
                out("checking dependencies...", T.textDim)
                out("", T.text)
                out("Packages (1) "..args[3].."-1.0.0", T.text)
                out("", T.text)
                out("Total Removed Size:  "..math.random(10,100)..".00 MiB", T.text)
                out("", T.text)
                out(":: Do you want to remove these packages? [Y/n]", T.accent2)
                out("(1/1) removing "..args[3].."...", T.textDim)
                out(":: Transaction successfully finished ✓", T.green)
            end
        elseif args[2]=="-Ss" then
            if not args[3] then
                out("error: no targets specified", T.red)
            else
                local fake={"firefox","chromium","brave","vivaldi","qutebrowser"}
                out("Searching repositories for '"..args[3].."'...", T.accent2)
                out("", T.text)
                for _,pk in ipairs(fake) do
                    if pk:lower():find(args[3]:lower()) then
                        out("extra/"..pk.." 120.0-1", T.accent)
                        out("    "..pk.." web browser", T.textDim)
                    end
                end
            end
        elseif args[2]=="-Q" then
            local pkgs={"base","linux","pacman","systemd","bash","gcc","git","vim","neofetch"}
            out("Installed packages:", T.accent2)
            for _,pk in ipairs(pkgs) do
                out("  "..pk.." 1.0.0-"..math.random(1,5), T.text)
            end
        else
            out("usage:  pacman <operation> [...]", T.yellow)
            out("operations:", T.text)
            out("    -Syu         update system", T.text)
            out("    -S <pkg>     install package", T.text)
            out("    -R <pkg>     remove package", T.text)
            out("    -Ss <query>  search packages", T.text)
            out("    -Q           list installed packages", T.text)
        end

    elseif cc=="htop" then
        out("Opening htop (process monitor)...", T.accent2)
        task.wait(0.3)
        openTaskManager()

    elseif cc=="free" then
        local total=2048; local used=0
        for _,p in pairs(Kernel.procs) do used+=p.mem end
        local free=total-used
        local pct=math.floor(used/total*100)
        out("               total        used        free", T.accent)
        out(string.format("Mem:        %4dMB      %4dMB      %4dMB", total, used, free), T.text)
        out("", T.text)
        out("Memory usage: "..pct.."%", pct>80 and T.red or T.green)

    elseif cc=="df" then
        out("Filesystem      Size  Used Avail Use% Mounted on", T.accent)
        out("/dev/sda1        50G   12G   36G  26% /", T.text)
        out("/dev/sda2       200G   48G  142G  26% /home", T.text)
        out("tmpfs           1.0G  120K  1.0G   1% /tmp", T.text)

    elseif cc=="history" then
        out("  Command history:", T.accent)
        for i, cmd2 in ipairs(cmdHistory) do
            out(string.format("  %4d  %s", i, cmd2), T.text)
        end

    elseif cc=="tree" then
        local path = args[2] and fsResolve(args[2]) or CWD
        local function printTree(p, prefix)
            local nd = FS[p]
            if not nd or nd.t ~= "dir" then return end
            local ch = nd.children
            for i, cp in ipairs(ch) do
                local child = FS[cp]
                if not child then continue end
                local segs = cp:split("/")
                local nm = segs[#segs]
                local isLast = (i == #ch)
                local connector = isLast and "└── " or "├── "
                local icon = child.t == "dir" and "📁 " or "📄 "
                out(prefix .. connector .. icon .. nm, child.t == "dir" and T.accent2 or T.text)
                if child.t == "dir" then
                    local newPrefix = prefix .. (isLast and "    " or "│   ")
                    printTree(cp, newPrefix)
                end
            end
        end
        local segs = path:split("/")
        out("📂 " .. (segs[#segs] ~= "" and segs[#segs] or "/"), T.accent)
        printTree(path, "")

    elseif cc=="mkdir" then
        if not args[2] then out("mkdir: missing operand", T.yellow); return end
        local ok, err = fsMkdir(args[2])
        if ok then
            out("Created directory: "..fsResolve(args[2]), T.textDim)
        else
            out("mkdir: "..tostring(err), T.red)
        end

    elseif cc=="mv" then
        if not args[2] or not args[3] then out("mv: missing file operand", T.yellow); return end
        local src = fsResolve(args[2])
        local dst = fsResolve(args[3])
        if not FS[src] then out("mv: cannot stat '"..args[2].."': No such file", T.red); return end
        FS[dst] = FS[src]
        FS[dst].time = os.time()
        FS[src] = nil
        for _, nd in pairs(FS) do
            if nd.t == "dir" then
                for i, ch in ipairs(nd.children) do
                    if ch == src then nd.children[i] = dst; break end
                end
            end
        end
        out("'"..src.."' -> '"..dst.."'", T.textDim)

    elseif cc=="cp" then
        if not args[2] or not args[3] then out("cp: missing file operand", T.yellow); return end
        local src = fsResolve(args[2])
        local dst = fsResolve(args[3])
        if not FS[src] or FS[src].t ~= "file" then out("cp: cannot stat '"..args[2].."'", T.red); return end
        fsWrite(dst, FS[src].content)
        out("'"..src.."' -> '"..dst.."'", T.textDim)

    elseif cc=="grep" then
        if not args[2] or not args[3] then out("grep: usage: grep PATTERN FILE", T.yellow); return end
        local pattern = args[2]
        local content = fsRead(fsResolve(args[3]))
        if not content then out("grep: "..args[3]..": No such file", T.red); return end
        local found = 0
        for _, ln in ipairs(content:split("\n")) do
            if ln:lower():find(pattern:lower()) then
                out(ln, T.green)
                found += 1
            end
        end
        if found == 0 then out("(no matches)", T.textDim) end

    elseif cc=="head" then
        if not args[2] then out("head: missing operand", T.yellow); return end
        local content = fsRead(fsResolve(args[2]))
        if not content then out("head: cannot open '"..args[2].."'", T.red); return end
        local lines = content:split("\n")
        local count = tonumber(args[3]) or 10
        for i = 1, math.min(count, #lines) do
            out(lines[i], T.text)
        end

    elseif cc=="tail" then
        if not args[2] then out("tail: missing operand", T.yellow); return end
        local content = fsRead(fsResolve(args[2]))
        if not content then out("tail: cannot open '"..args[2].."'", T.red); return end
        local lines = content:split("\n")
        local count = tonumber(args[3]) or 10
        for i = math.max(1, #lines - count + 1), #lines do
            out(lines[i], T.text)
        end

    elseif cc=="ls" then
        local path = args[2] and fsResolve(args[2]) or CWD
        local ch = fsList(path)
        if not ch then out("ls: cannot access '"..path.."': No such directory", T.red); return end
        if #ch==0 then out("(empty)", T.textDim); return end
        for _, cp in ipairs(ch) do
            local nd=FS[cp]
            if nd then
                local segs=cp:split("/")
                local nm=segs[#segs]
                if nd.t=="dir" then
                    out("  📁  "..nm.."/", T.accent2)
                else
                    out(string.format("  📄  %-26s %5dB", nm, #nd.content), T.text)
                end
            end
        end

    elseif cc=="cd" then
        local p = args[2] and fsResolve(args[2]) or ("/home/"..player.Name:lower())
        if FS[p] and FS[p].t=="dir" then
            CWD=p; out("→ "..CWD, T.textDim)
        else
            out("cd: "..tostring(args[2])..": No such directory", T.red)
        end

    elseif cc=="pwd" then
        out(CWD, T.text)

    elseif cc=="cat" then
        if not args[2] then out("cat: missing operand", T.yellow); return end
        local content=fsRead(fsResolve(args[2]))
        if content then
            for _,ln in ipairs(content:split("\n")) do out(ln, T.text) end
        else
            out("cat: "..args[2]..": No such file", T.red)
        end

    elseif cc=="echo" then
        local full=table.concat(args," ",2)
        local lpart, rpart=full:match("^(.-)%s*>%s*(.+)$")
        if lpart and rpart then
            fsWrite(fsResolve(rpart), lpart.."\n")
            out("→ "..rpart, T.textDim)
        else
            out(full, T.text)
        end

    elseif cc=="touch" then
        if not args[2] then out("touch: missing file operand", T.yellow); return end
        local abs=fsResolve(args[2])
        if not FS[abs] then
            fsWrite(abs,""); out("Created: "..abs, T.textDim)
        else
            FS[abs].time=os.time(); out("Updated timestamp", T.textDim)
        end

    elseif cc=="rm" then
        if not args[2] then out("rm: missing operand", T.yellow); return end
        local abs=fsResolve(args[2])
        if not FS[abs] then out("rm: cannot remove '"..args[2].."': No such file", T.red); return end
        if FS[abs].t=="dir" then out("rm: cannot remove '"..args[2].."': Is a directory", T.red); return end
        FS[abs]=nil
        for _, nd in pairs(FS) do
            if nd.t=="dir" then
                for i,ch in ipairs(nd.children) do
                    if ch==abs then table.remove(nd.children,i); break end
                end
            end
        end
        out("removed '"..abs.."'", T.textDim)

    elseif cc=="ps" then
        out(string.format("  %-6s %-24s %-10s %s","PID","CMD","STAT","RSS"), T.accent)
        out("  "..("─"):rep(56), T.textMut)
        local sorted={}
        for _,p in pairs(Kernel.procs) do table.insert(sorted,p) end
        table.sort(sorted,function(a,b) return a.pid<b.pid end)
        for _,p in ipairs(sorted) do
            out(string.format("  %-6s %-24s %-10s %dM",
                p.pid, p.name, p.state=="running" and "R" or "S", p.mem), 
                p.state=="running" and T.green or T.textDim)
        end

    elseif cc=="kill" then
        local pid=tonumber(args[2])
        if not pid then out("kill: missing PID", T.yellow); return end
        local ok, err=kkill(pid)
        if ok then out("killed process "..pid, T.green)
        else out("kill: "..tostring(err), T.red) end

    elseif cc=="uptime" then
        local up=os.clock()-Kernel.boot
        local d=math.floor(up/86400)
        local h=math.floor((up%86400)/3600)
        local m=math.floor((up%3600)/60)
        out(string.format("up %d days, %d hours, %d minutes", d, h, m), T.text)

    elseif cc=="date" then
        out(os.date("%a %b %d %H:%M:%S %Y"), T.text)

    elseif cc=="whoami" then out(player.Name:lower(), T.text)
    elseif cc=="hostname" then out(fsRead("/etc/hostname") or "archos", T.text)
    elseif cc=="uname" then 
        if args[2]=="-a" then
            out("Linux archos 6.6.2-arch1-1 #1 SMP PREEMPT_DYNAMIC x86_64 GNU/Linux", T.text)
        else
            out("Linux", T.text)
        end
    elseif cc=="clear" then return "clear"
    elseif cc=="exit" then return "exit"
    else
        out("bash: "..cc..": command not found", T.red)
        out("Type 'help' for available commands", T.textDim)
    end
end

-- ── FORWARD DECLARATIONS ──────────────────────────────────────
local openTerminal, openNotepad, openTaskManager, openBrowser, openFiles
local openCalc, openSettings, openSysMonitor

-- ── TERMINAL ───────────────────────────────────────────────────
openTerminal = function()
    if WINS["Terminal"] and WINS["Terminal"].Parent then
        WINS["Terminal"].Visible=true; return
    end

    local win,body,z = newWindow("  ⌨  Terminal", 680, 480, 100, 60)

    local tbg = c("Frame", {
        Size=UDim2.new(1,0,1,0),
        BackgroundColor3=T.term,
        BorderSizePixel=0, ZIndex=z+1,
    }, body)

    local outScroll = c("ScrollingFrame", {
        Size=UDim2.new(1,0,1,-44),
        BackgroundTransparency=1, BorderSizePixel=0,
        ScrollBarThickness=3, ScrollBarImageColor3=T.accent,
        AutomaticCanvasSize=Enum.AutomaticSize.Y,
        CanvasSize=UDim2.new(0,0,0,0), ZIndex=z+2,
    }, tbg)
    c("UIListLayout", {Padding=UDim.new(0,1)}, outScroll)
    pad(outScroll, 10)

    local function addOut(txt, col)
        local lbl = c("TextLabel", {
            Size=UDim2.new(1,0,0,0),
            AutomaticSize=Enum.AutomaticSize.Y,
            BackgroundTransparency=1, Text=txt,
            Font=Enum.Font.Code, TextSize=13,
            TextColor3=col or T.termTxt,
            TextXAlignment=Enum.TextXAlignment.Left,
            TextWrapped=true, ZIndex=z+3,
        }, outScroll)
        task.defer(function()
            outScroll.CanvasPosition=Vector2.new(0,outScroll.AbsoluteCanvasSize.Y)
        end)
        return lbl
    end

    local inputRow = c("Frame", {
        Size=UDim2.new(1,0,0,40), Position=UDim2.new(0,0,1,-40),
        BackgroundColor3=Color3.fromRGB(8,10,16),
        BorderSizePixel=0, ZIndex=z+2,
    }, tbg)

    c("Frame", {
        Size=UDim2.new(1,0,0,1),
        BackgroundColor3=T.accent, BackgroundTransparency=0.7,
        BorderSizePixel=0, ZIndex=z+3,
    }, inputRow)

    local promptLbl = c("TextLabel", {
        Size=UDim2.new(0,0,1,0), AutomaticSize=Enum.AutomaticSize.X,
        Position=UDim2.new(0,10,0,0), BackgroundTransparency=1,
        Text="["..player.Name:lower().."@archos "..CWD:gsub("/home/"..player.Name:lower(), "~").."]$ ",
        Font=Enum.Font.Code, TextSize=13, TextColor3=T.accent, ZIndex=z+3,
    }, inputRow)

    local inputBox = c("TextBox", {
        Size=UDim2.new(1,-220,1,-8), Position=UDim2.new(0,200,0,4),
        BackgroundTransparency=1, Text="", PlaceholderText="enter command...",
        PlaceholderColor3=T.textMut, Font=Enum.Font.Code, TextSize=13,
        TextColor3=T.termTxt, TextXAlignment=Enum.TextXAlignment.Left,
        ClearTextOnFocus=false, ZIndex=z+3,
    }, inputRow)

    addOut("╔═══════════════════════════════════════════════════╗", T.accent)
    addOut("║          Welcome to Arch Linux Terminal          ║", T.accent)
    addOut("║   Kernel: 6.6.2-arch1-1   Shell: bash 5.2.21    ║", T.textDim)
    addOut("║   Type 'help' for commands | 'neofetch' for info ║", T.textDim)
    addOut("╚═══════════════════════════════════════════════════╝", T.accent)
    addOut("", T.text)
    addOut(fsRead("/etc/motd") or "", T.text)

    local hist={}; local hidx=0

    inputBox.FocusLost:Connect(function(enter)
        if not enter then return end
        local cmd2=inputBox.Text; inputBox.Text=""
        if cmd2=="" then return end
        table.insert(hist,cmd2); hidx=#hist+1
        local displayPath = CWD:gsub("/home/"..player.Name:lower(), "~")
        addOut("["..player.Name:lower().."@archos "..displayPath.."]$ "..cmd2, T.textDim)
        local r=runCmd(cmd2, addOut)
        if r=="clear" then
            for _,ch in ipairs(outScroll:GetChildren()) do
                if ch:IsA("TextLabel") then ch:Destroy() end
            end
        elseif r=="exit" then
            win:Destroy(); WINS["Terminal"]=nil; OpenWinNames["Terminal"]=nil
            if refreshTaskbar then refreshTaskbar() end
        end
        displayPath = CWD:gsub("/home/"..player.Name:lower(), "~")
        promptLbl.Text="["..player.Name:lower().."@archos "..displayPath.."]$ "
        task.defer(function() inputBox:CaptureFocus() end)
    end)

    UIS.InputBegan:Connect(function(i,gp)
        if gp or not inputBox:IsFocused() then return end
        if i.KeyCode==Enum.KeyCode.Up then
            hidx=math.max(1,hidx-1); inputBox.Text=hist[hidx] or ""
        elseif i.KeyCode==Enum.KeyCode.Down then
            hidx=math.min(#hist+1,hidx+1); inputBox.Text=hist[hidx] or ""
        end
    end)

    task.defer(function() inputBox:CaptureFocus() end)
    kspawn("bash", 3)
end

-- ── NOTEPAD ────────────────────────────────────────────────────
openNotepad = function()
    if WINS["Notepad"] and WINS["Notepad"].Parent then WINS["Notepad"].Visible=true; return end

    local win,body,z = newWindow("  📝  Text Editor", 540, 420, 160, 90)
    local curFile = "/home/"..player.Name:lower().."/README.md"

    local bg=c("Frame",{Size=UDim2.new(1,0,1,0),BackgroundColor3=T.surface,
        BorderSizePixel=0,ZIndex=z+1},body)

    local tb=c("Frame",{Size=UDim2.new(1,0,0,36),
        BackgroundColor3=T.surface2,BorderSizePixel=0,ZIndex=z+2},bg)

    local fileLbl=c("TextLabel",{
        Size=UDim2.new(1,-200,1,0),Position=UDim2.new(0,8,0,0),
        BackgroundTransparency=1,Text="📄 "..curFile,
        Font=Enum.Font.Gotham,TextSize=11,TextColor3=T.textDim,
        TextXAlignment=Enum.TextXAlignment.Left,ZIndex=z+3},tb)

    local saveBtn=c("TextButton",{
        Size=UDim2.new(0,90,0,26), Position=UDim2.new(1,-100,0.5,-13),
        BackgroundColor3=T.surface, Text="💾 Save",TextColor3=T.text,
        Font=Enum.Font.Gotham,TextSize=12, ZIndex=z+3,BorderSizePixel=0},tb)
    corner(saveBtn,5); stroke(saveBtn,T.border,1,.5)
    hover(saveBtn,T.surface,T.surface2)

    local ta=c("TextBox",{
        Size=UDim2.new(1,-16,1,-52), Position=UDim2.new(0,8,0,44),
        BackgroundColor3=T.bg1, Text=fsRead(curFile) or "",
        TextColor3=T.text, Font=Enum.Font.Code,TextSize=13,
        TextXAlignment=Enum.TextXAlignment.Left,
        TextYAlignment=Enum.TextYAlignment.Top,
        MultiLine=true,ClearTextOnFocus=false,
        TextWrapped=true,ZIndex=z+2,BorderSizePixel=0},bg)
    corner(ta,6); pad(ta,8); stroke(ta,T.border,1,.5)

    saveBtn.MouseButton1Click:Connect(function()
        fsWrite(curFile, ta.Text)
        fileLbl.Text="📄 "..curFile.."  ✓ Saved"
        notify("Text Editor", "File saved: "..curFile, 3, "💾")
        task.delay(2,function() fileLbl.Text="📄 "..curFile end)
    end)
    
    kspawn("vim", 2)
end

-- ── TASK MANAGER ─────────────────────────────────────────────
openTaskManager = function()
    if WINS["htop"] and WINS["htop"].Parent then
        WINS["htop"].Visible=true; return
    end

    local win,body,z = newWindow("  📊  htop", 550, 420, 200, 110)

    local bg=c("Frame",{Size=UDim2.new(1,0,1,0),BackgroundColor3=T.surface,
        BorderSizePixel=0,ZIndex=z+1},body)

    local hdr=c("Frame",{Size=UDim2.new(1,0,0,30),
        BackgroundColor3=T.winTitle,BorderSizePixel=0,ZIndex=z+2},bg)
    stroke(hdr, T.border, 1, .5)

    local cols={
        {t="PID", w=.10, x=0},
        {t="Command",w=.38,x=.10},
        {t="State",w=.20, x=.48},
        {t="Memory", w=.17, x=.68},
        {t="",   w=.15, x=.85},
    }
    for _,col in ipairs(cols) do
        c("TextLabel",{
            Size=UDim2.new(col.w,0,1,0), Position=UDim2.new(col.x,8,0,0),
            BackgroundTransparency=1, Text=col.t,Font=Enum.Font.GothamBold,TextSize=12,
            TextColor3=T.accent2,TextXAlignment=Enum.TextXAlignment.Left,
            ZIndex=z+3},hdr)
    end

    local list=c("ScrollingFrame",{
        Size=UDim2.new(1,0,1,-80), Position=UDim2.new(0,0,0,30),
        BackgroundTransparency=1,BorderSizePixel=0,
        ScrollBarThickness=3,ScrollBarImageColor3=T.accent,
        AutomaticCanvasSize=Enum.AutomaticSize.Y,
        CanvasSize=UDim2.new(0,0,0,0),ZIndex=z+2},bg)
    c("UIListLayout",{Padding=UDim.new(0,2)},list)
    pad(list,4)

    local rows={}

    local function refresh()
        for _,r in ipairs(rows) do r:Destroy() end; rows={}
        local sorted={}
        for _,p in pairs(Kernel.procs) do table.insert(sorted,p) end
        table.sort(sorted,function(a,b) return a.pid<b.pid end)

        for i,p in ipairs(sorted) do
            local row=c("Frame",{
                Size=UDim2.new(1,0,0,30),
                BackgroundColor3=i%2==0 and T.surface2 or T.surface,
                BorderSizePixel=0,ZIndex=z+3},list)
            corner(row,5)

            local datas={tostring(p.pid), p.name, p.state=="running" and "R" or "S", p.mem.."M"}
            for ci,col in ipairs(cols) do
                if ci <= 4 then
                    c("TextLabel",{
                        Size=UDim2.new(col.w,0,1,0), Position=UDim2.new(col.x,8,0,0),
                        BackgroundTransparency=1, Text=datas[ci],
                        Font=Enum.Font.Code,TextSize=12,
                        TextColor3=ci==3 and (p.state=="running" and T.green or T.textDim) or T.text,
                        TextXAlignment=Enum.TextXAlignment.Left, ZIndex=z+4},row)
                end
            end

            if not p.sys then
                local kb=c("TextButton",{
                    Size=UDim2.new(0,50,0,20), Position=UDim2.new(.85,4,0.5,-10),
                    BackgroundColor3=T.red, Text="Kill",
                    TextColor3=Color3.new(1,1,1), Font=Enum.Font.GothamBold,
                    TextSize=10, ZIndex=z+4, BorderSizePixel=0},row)
                corner(kb,4)
                kb.MouseButton1Click:Connect(function()
                    kkill(p.pid)
                    notify("htop", "Killed process "..p.name, 3, "📊")
                end)
            end

            table.insert(rows,row)
        end
    end

    local statBar=c("Frame",{
        Size=UDim2.new(1,0,0,46), Position=UDim2.new(0,0,1,-46),
        BackgroundColor3=T.winTitle, BorderSizePixel=0,ZIndex=z+2},bg)

    local statLbl=c("TextLabel",{
        Size=UDim2.new(1,-16,1,0),Position=UDim2.new(0,8,0,0),
        BackgroundTransparency=1,Text="",
        Font=Enum.Font.Code,TextSize=11,TextColor3=T.textDim,
        TextXAlignment=Enum.TextXAlignment.Left, RichText=true,ZIndex=z+3},statBar)

    local ramBg=c("Frame",{
        Size=UDim2.new(1,-16,0,4),Position=UDim2.new(0,8,0,38),
        BackgroundColor3=T.surface,BorderSizePixel=0,ZIndex=z+2},statBar)
    corner(ramBg,2)
    local ramBar=c("Frame",{
        Size=UDim2.new(0,0,0,4),Position=UDim2.new(0,8,0,38),
        BackgroundColor3=T.accent,BorderSizePixel=0,ZIndex=z+3},statBar)
    corner(ramBar,2)

    local conn=RunService.Heartbeat:Connect(function()
        local total=2048; local used=0; local cnt=0
        for _,p in pairs(Kernel.procs) do used+=p.mem; cnt+=1 end
        local pct=math.floor(used/total*100)
        statLbl.Text=string.format("Tasks: %d  │  Mem: %dM/%dM (%d%%)  │  Uptime: %ds",
            cnt, used, total, pct, math.floor(os.clock()-Kernel.boot))
        tw(ramBar,{Size=UDim2.new(used/total,0,0,4)},.3)
        ramBar.BackgroundColor3=pct>80 and T.red or pct>50 and T.yellow or T.accent
    end)

    task.spawn(function()
        while win and win.Parent do refresh(); task.wait(0.5) end
        conn:Disconnect()
    end)
    refresh()
end

-- ── BROWSER ────────────────────────────────────────────────────
openBrowser = function()
    if WINS["Browser"] and WINS["Browser"].Parent then WINS["Browser"].Visible=true; return end

    local win,body,z = newWindow("  🌐  Firefox", 620, 460, 180, 80)

    local bg=c("Frame",{Size=UDim2.new(1,0,1,0),
        BackgroundColor3=Color3.fromRGB(240,242,245),
        BorderSizePixel=0,ZIndex=z+1},body)

    local addrRow=c("Frame",{
        Size=UDim2.new(1,-16,0,36), Position=UDim2.new(0,8,0,6),
        BackgroundColor3=Color3.new(1,1,1),
        BorderSizePixel=0,ZIndex=z+2},bg)
    corner(addrRow,18); stroke(addrRow,T.accent,1,.3)

    local addrBox=c("TextBox",{
        Size=UDim2.new(1,-24,1,0),Position=UDim2.new(0,12,0,0),
        BackgroundTransparency=1, Text="arch://home",
        Font=Enum.Font.Gotham,TextSize=13,
        TextColor3=Color3.fromRGB(30,40,80),
        ClearTextOnFocus=false,ZIndex=z+3},addrRow)

    local page=c("ScrollingFrame",{
        Size=UDim2.new(1,-16,1,-54), Position=UDim2.new(0,8,0,48),
        BackgroundColor3=Color3.new(1,1,1), BorderSizePixel=0,
        ScrollBarThickness=4, AutomaticCanvasSize=Enum.AutomaticSize.Y,
        CanvasSize=UDim2.new(0,0,0,0),ZIndex=z+2},bg)
    corner(page,8); stroke(page,T.border,1,.5)
    c("UIListLayout",{Padding=UDim.new(0,6)},page)
    pad(page,14)

    local pages={
        ["arch://home"]={
            {h=1, t="🏠 Arch Linux Browser"},
            {h=0, t="Welcome to your Arch Linux system!"},
            {h=2, t="Quick Links:"},
            {lnk="arch://about"}, {lnk="arch://wiki"},
            {lnk="arch://packages"}, {lnk="arch://community"},
        },
        ["arch://about"]={
            {h=1, t="ℹ️ About Arch Linux"},
            {h=0, t="Distribution: Arch Linux"},
            {h=0, t="Architecture: x86_64"},
            {h=0, t="Kernel:       6.6.2-arch1-1"},
            {h=0, t="Init System:  systemd"},
            {h=0, t="Package Mgr:  pacman"},
            {h=0, t="Release:      Rolling"},
            {h=0, t="User:         "..player.Name:lower()},
            {h=0, t="Hostname:     archos-roblox"},
            {lnk="arch://home"},
        },
        ["arch://wiki"]={
            {h=1, t="📚 ArchWiki"},
            {h=0, t="The Arch Linux Wiki is the most comprehensive"},
            {h=0, t="distribution wiki online. Documentation is"},
            {h=0, t="written by users, for users."},
            {h=2, t="Popular Articles:"},
            {h=0, t="• Installation Guide"},
            {h=0, t="• General Recommendations"},
            {h=0, t="• List of Applications"},
            {h=0, t="• Pacman Tips & Tricks"},
            {h=0, t="• systemd Configuration"},
            {h=2, t="Remember:"},
            {h=0, t="RTFM — The wiki has your answer!"},
            {lnk="arch://home"},
        },
        ["arch://packages"]={
            {h=1, t="📦 Package Management"},
            {h=2, t="Official Repositories:"},
            {h=0, t="• core     — Essential packages"},
            {h=0, t="• extra    — Additional packages"},
            {h=0, t="• multilib — 32-bit packages"},
            {h=2, t="Pacman Commands:"},
            {h=0, t="  pacman -Syu        Update system"},
            {h=0, t="  pacman -S pkg      Install package"},
            {h=0, t="  pacman -R pkg      Remove package"},
            {h=0, t="  pacman -Ss query   Search packages"},
            {h=0, t="  pacman -Q          List installed"},
            {h=2, t="AUR — Arch User Repository:"},
            {h=0, t="Community-maintained package repository"},
            {h=0, t="Use AUR helpers like yay or paru"},
            {lnk="arch://home"},
        },
        ["arch://community"]={
            {h=1, t="👥 Arch Community"},
            {h=0, t="Arch Linux is built by its community."},
            {h=2, t="Get Involved:"},
            {h=0, t="• Forums      — https://bbs.archlinux.org"},
            {h=0, t="• Reddit      — r/archlinux"},
            {h=0, t="• IRC         — #archlinux on Libera.Chat"},
            {h=0, t="• Bug Tracker — bugs.archlinux.org"},
            {h=0, t="• Contribute  — Submit packages to AUR"},
            {h=2, t="Remember:"},
            {h=0, t="Be helpful, follow the Code of Conduct,"},
            {h=0, t="and always search before asking!"},
            {lnk="arch://home"},
        },
    }

    local function render(url)
        for _,ch in ipairs(page:GetChildren()) do
            if ch:IsA("GuiObject") then ch:Destroy() end
        end
        local pg=pages[url]
        if not pg then
            c("TextLabel",{Size=UDim2.new(1,0,0,40),BackgroundTransparency=1,
                Text="404 — Page not found",
                Font=Enum.Font.GothamBold,TextSize=16,
                TextColor3=Color3.fromRGB(200,40,40),
                TextXAlignment=Enum.TextXAlignment.Left,ZIndex=z+3},page)
            return
        end
        for _,item in ipairs(pg) do
            if item.lnk then
                local b=c("TextButton",{
                    Size=UDim2.new(1,0,0,28),
                    BackgroundColor3=Color3.fromRGB(230,240,255),
                    Text="🔗  "..item.lnk,
                    Font=Enum.Font.Gotham,TextSize=13,
                    TextColor3=T.accent,
                    TextXAlignment=Enum.TextXAlignment.Left,
                    BorderSizePixel=0,ZIndex=z+3},page)
                corner(b,5); pad(b,6)
                b.MouseButton1Click:Connect(function() addrBox.Text=item.lnk; render(item.lnk) end)
            elseif item.h==1 then
                c("TextLabel",{Size=UDim2.new(1,0,0,0),AutomaticSize=Enum.AutomaticSize.Y,
                    BackgroundTransparency=1,Text=item.t,
                    Font=Enum.Font.GothamBold,TextSize=22,
                    TextColor3=Color3.fromRGB(20,60,180),
                    TextXAlignment=Enum.TextXAlignment.Left,TextWrapped=true,ZIndex=z+3},page)
            elseif item.h==2 then
                c("TextLabel",{Size=UDim2.new(1,0,0,0),AutomaticSize=Enum.AutomaticSize.Y,
                    BackgroundTransparency=1,Text=item.t,
                    Font=Enum.Font.GothamBold,TextSize=15,
                    TextColor3=T.accent,
                    TextXAlignment=Enum.TextXAlignment.Left,ZIndex=z+3},page)
            else
                c("TextLabel",{Size=UDim2.new(1,0,0,0),AutomaticSize=Enum.AutomaticSize.Y,
                    BackgroundTransparency=1,Text=item.t,
                    Font=Enum.Font.Code,TextSize=13,
                    TextColor3=Color3.fromRGB(30,40,70),
                    TextXAlignment=Enum.TextXAlignment.Left,TextWrapped=true,ZIndex=z+3},page)
            end
        end
    end
    render("arch://home")
    addrBox.FocusLost:Connect(function(e) if e then render(addrBox.Text) end end)
    
    kspawn("firefox", 48)
end

-- ── FILE MANAGER ──────────────────────────────────────────────
openFiles = function()
    if WINS["Files"] and WINS["Files"].Parent then WINS["Files"].Visible=true; return end

    local win,body,z = newWindow("  📁  Thunar", 520, 440, 220, 100)
    local viewPath="/"

    local bg=c("Frame",{Size=UDim2.new(1,0,1,0),BackgroundColor3=T.surface,
        BorderSizePixel=0,ZIndex=z+1},body)

    local bread=c("Frame",{Size=UDim2.new(1,0,0,34),
        BackgroundColor3=T.surface2,BorderSizePixel=0,ZIndex=z+2},bg)

    local pathLbl=c("TextLabel",{
        Size=UDim2.new(1,-8,1,0),Position=UDim2.new(0,8,0,0),
        BackgroundTransparency=1, Text="📂 /",
        Font=Enum.Font.Gotham,TextSize=12,TextColor3=T.text,
        TextXAlignment=Enum.TextXAlignment.Left,ZIndex=z+3},bread)

    local flist=c("ScrollingFrame",{
        Size=UDim2.new(1,-16,1,-50), Position=UDim2.new(0,8,0,40),
        BackgroundTransparency=1,BorderSizePixel=0,
        ScrollBarThickness=3,ScrollBarImageColor3=T.accent,
        AutomaticCanvasSize=Enum.AutomaticSize.Y,
        CanvasSize=UDim2.new(0,0,0,0),ZIndex=z+2},bg)
    c("UIListLayout",{Padding=UDim.new(0,3)},flist)

    local function renderDir(path)
        viewPath=path; pathLbl.Text="📂 "..path
        for _,ch in ipairs(flist:GetChildren()) do
            if ch:IsA("GuiObject") then ch:Destroy() end
        end

        if path~="/" then
            local segs=path:split("/"); table.remove(segs)
            local par=table.concat(segs,"/"); if par=="" then par="/" end
            local upb=c("TextButton",{Size=UDim2.new(1,0,0,34),
                BackgroundColor3=T.surface2, Text="",BorderSizePixel=0,ZIndex=z+3},flist)
            corner(upb,6)
            c("TextLabel",{Size=UDim2.new(1,-10,1,0),Position=UDim2.new(0,10,0,0),
                BackgroundTransparency=1, Text="⬆   ..",
                Font=Enum.Font.Gotham,TextSize=13,TextColor3=T.accent2,
                TextXAlignment=Enum.TextXAlignment.Left,ZIndex=z+4},upb)
            hover(upb,T.surface2,T.surface)
            upb.MouseButton1Click:Connect(function() renderDir(par) end)
        end

        local nd=FS[path]
        if not nd then return end
        for _,cp in ipairs(nd.children) do
            local child=FS[cp]
            if not child then continue end
            local segs=cp:split("/"); local nm=segs[#segs]
            local isDir=child.t=="dir"

            local row=c("TextButton",{Size=UDim2.new(1,0,0,34),
                BackgroundColor3=T.surface, Text="",BorderSizePixel=0,ZIndex=z+3},flist)
            corner(row,6); stroke(row,T.border,1,.6)
            hover(row,T.surface,T.surface2)

            c("TextLabel",{Size=UDim2.new(1,-10,1,0),Position=UDim2.new(0,10,0,0),
                BackgroundTransparency=1,
                Text=(isDir and "📁  " or "📄  ")..nm,
                Font=Enum.Font.Gotham,TextSize=13,
                TextColor3=isDir and T.accent2 or T.text,
                TextXAlignment=Enum.TextXAlignment.Left,ZIndex=z+4},row)

            if not isDir then
                c("TextLabel",{Size=UDim2.new(0,70,1,0),Position=UDim2.new(1,-75,0,0),
                    BackgroundTransparency=1, Text=#child.content.."B",
                    Font=Enum.Font.Code,TextSize=11,TextColor3=T.textMut, ZIndex=z+4},row)
            end

            row.MouseButton1Click:Connect(function()
                if isDir then renderDir(cp) end
            end)
        end
    end
    renderDir("/")
    
    kspawn("thunar", 12)
end

-- ── CALCULATOR ───────────────────────────────────────────────
openCalc = function()
    if WINS["Calculator"] and WINS["Calculator"].Parent then
        WINS["Calculator"].Visible=true; return
    end

    local win,body,z = newWindow("  🧮  Calculator", 280, 400, 300, 100)

    local bg=c("Frame",{Size=UDim2.new(1,0,1,0),BackgroundColor3=T.bg1,
        BorderSizePixel=0,ZIndex=z+1},body)

    local display=c("TextLabel",{
        Size=UDim2.new(1,-16,0,70), Position=UDim2.new(0,8,0,8),
        BackgroundColor3=T.surface, Text="0",
        Font=Enum.Font.Code, TextSize=32, TextColor3=T.text,
        TextXAlignment=Enum.TextXAlignment.Right,
        ZIndex=z+2, BorderSizePixel=0},bg)
    corner(display,8); pad(display,12)

    local expr = ""
    local lastResult = ""

    local function updateDisplay()
        display.Text = (expr == "" and "0") or expr
    end

    local buttons = {
        {"C", "⌫", "%", "÷"},
        {"7", "8", "9", "×"},
        {"4", "5", "6", "-"},
        {"1", "2", "3", "+"},
        {"±", "0", ".", "="},
    }

    local grid = c("Frame",{
        Size=UDim2.new(1,-16,1,-96), Position=UDim2.new(0,8,0,86),
        BackgroundTransparency=1, ZIndex=z+1},bg)

    for ri, row in ipairs(buttons) do
        for ci, label in ipairs(row) do
            local isOp = (label == "÷" or label == "×" or label == "-" or label == "+" or label == "=")
            local isSpecial = (label == "C" or label == "⌫" or label == "%" or label == "±")

            local btnColor = isOp and T.accent or isSpecial and T.surface2 or T.surface
            local txtColor = isOp and Color3.new(1,1,1) or T.text

            local btn = c("TextButton",{
                Size = UDim2.new(0.25, -6, 0.2, -6),
                Position = UDim2.new((ci-1)*0.25, 3, (ri-1)*0.2, 3),
                BackgroundColor3 = btnColor,
                Text = label,
                Font = Enum.Font.GothamBold,
                TextSize = 20,
                TextColor3 = txtColor,
                ZIndex = z+2,
                BorderSizePixel = 0,
            }, grid)
            corner(btn, 8)

            btn.MouseButton1Click:Connect(function()
                if label == "C" then
                    expr = ""; updateDisplay()
                elseif label == "⌫" then
                    expr = expr:sub(1, -2); updateDisplay()
                elseif label == "±" then
                    if expr:sub(1,1) == "-" then
                        expr = expr:sub(2)
                    else
                        expr = "-" .. expr
                    end
                    updateDisplay()
                elseif label == "=" then
                    local eval = expr:gsub("×","*"):gsub("÷","/")
                    local fn = loadstring("return " .. eval)
                    if fn then
                        local ok, result = pcall(fn)
                        if ok then
                            lastResult = tostring(result)
                            display.Text = lastResult
                            expr = lastResult
                        else
                            display.Text = "Error"
                            expr = ""
                        end
                    else
                        display.Text = "Error"
                        expr = ""
                    end
                else
                    expr = expr .. label
                    updateDisplay()
                end
            end)
        end
    end
    kspawn("gnome-calculator", 8)
end

-- ── SETTINGS ─────────────────────────────────────────────────
openSettings = function()
    if WINS["Settings"] and WINS["Settings"].Parent then
        WINS["Settings"].Visible=true; return
    end

    local win,body,z = newWindow("  ⚙  Settings", 420, 380, 250, 100)

    local bg=c("Frame",{Size=UDim2.new(1,0,1,0),BackgroundColor3=T.surface,
        BorderSizePixel=0,ZIndex=z+1},body)

    c("TextLabel",{
        Size=UDim2.new(1,-16,0,30), Position=UDim2.new(0,8,0,10),
        BackgroundTransparency=1, Text="🎨 Theme Selection",
        Font=Enum.Font.GothamBold, TextSize=16, TextColor3=T.text,
        TextXAlignment=Enum.TextXAlignment.Left, ZIndex=z+2},bg)

    local themeList = c("Frame",{
        Size=UDim2.new(1,-16,0,280), Position=UDim2.new(0,8,0,48),
        BackgroundTransparency=1, ZIndex=z+1},bg)
    c("UIListLayout",{Padding=UDim.new(0,8)},themeList)

    local themeData = {
        {name="ArchLinux", desc="Pure Arch blue on black", icon="🏛️", preview={Color3.fromRGB(12,12,12), Color3.fromRGB(23,147,209)}},
        {name="ArchClassic", desc="Classic terminal dark", icon="💻", preview={Color3.fromRGB(8,8,8), Color3.fromRGB(23,147,209)}},
        {name="ArchMonokai", desc="Monokai Pro theme", icon="🎨", preview={Color3.fromRGB(39,40,34), Color3.fromRGB(102,217,239)}},
    }

    for _, td in ipairs(themeData) do
        local row = c("Frame",{
            Size=UDim2.new(1,0,0,75),
            BackgroundColor3=T.surface2,
            BorderSizePixel=0, ZIndex=z+2},themeList)
        corner(row,10); stroke(row, T.border, 1, .4)

        local preview = c("Frame",{
            Size=UDim2.new(0,50,0,50), Position=UDim2.new(0,12,0.5,-25),
            BackgroundColor3=td.preview[1], BorderSizePixel=0, ZIndex=z+3},row)
        corner(preview,8); stroke(preview, td.preview[2], 2, 0)

        c("TextLabel",{
            Size=UDim2.new(0,30,0,30), Position=UDim2.new(0,10,0,10),
            BackgroundTransparency=1, Text=td.icon,
            TextSize=24, ZIndex=z+4},preview)

        c("TextLabel",{
            Size=UDim2.new(1,-160,0,22), Position=UDim2.new(0,74,0,12),
            BackgroundTransparency=1, Text=td.name,
            Font=Enum.Font.GothamBold, TextSize=16, TextColor3=T.text,
            TextXAlignment=Enum.TextXAlignment.Left, ZIndex=z+3},row)

        c("TextLabel",{
            Size=UDim2.new(1,-160,0,18), Position=UDim2.new(0,74,0,36),
            BackgroundTransparency=1, Text=td.desc,
            Font=Enum.Font.Gotham, TextSize=12, TextColor3=T.textDim,
            TextXAlignment=Enum.TextXAlignment.Left, ZIndex=z+3},row)

        local active = (ActiveTheme == td.name)
        local applyBtn = c("TextButton",{
            Size=UDim2.new(0,80,0,30), Position=UDim2.new(1,-92,0.5,-15),
            BackgroundColor3=active and T.green or T.accentDk,
            Text=active and "✓ Active" or "Apply",
            TextColor3=Color3.new(1,1,1),
            Font=Enum.Font.GothamBold, TextSize=12,
            ZIndex=z+3, BorderSizePixel=0},row)
        corner(applyBtn,6)

        applyBtn.MouseButton1Click:Connect(function()
            if Themes[td.name] then
                ActiveTheme = td.name
                T = Themes[td.name]
                notify("Settings", "Theme '"..td.name.."' applied!\nRestart for full effect.", 5, "🎨")
            end
        end)
    end
end

-- ── SYSTEM MONITOR ─────────────────────────────────────────────
openSysMonitor = function()
    if WINS["Monitor"] and WINS["Monitor"].Parent then
        WINS["Monitor"].Visible=true; return
    end

    local win,body,z = newWindow("  📈  System Monitor", 400, 360, 280, 120)

    local bg=c("Frame",{Size=UDim2.new(1,0,1,0),BackgroundColor3=T.surface,
        BorderSizePixel=0,ZIndex=z+1},body)

    local labels = {}
    local info = {
        {lbl="OS:", key="os"},
        {lbl="Kernel:", key="kern"},
        {lbl="Architecture:", key="arch"},
        {lbl="Uptime:", key="up"},
        {lbl="Processes:", key="procs"},
        {lbl="Memory:", key="ram"},
        {lbl="User:", key="user"},
        {lbl="Hostname:", key="host"},
        {lbl="Shell:", key="shell"},
        {lbl="Display:", key="display"},
    }

    for i, item in ipairs(info) do
        c("TextLabel",{
            Size=UDim2.new(0,120,0,26), Position=UDim2.new(0,12,0,10+(i-1)*30),
            BackgroundTransparency=1, Text=item.lbl,
            Font=Enum.Font.GothamBold, TextSize=13, TextColor3=T.accent2,
            TextXAlignment=Enum.TextXAlignment.Left, ZIndex=z+2},bg)

        labels[item.key] = c("TextLabel",{
            Size=UDim2.new(1,-140,0,26), Position=UDim2.new(0,135,0,10+(i-1)*30),
            BackgroundTransparency=1, Text="...",
            Font=Enum.Font.Code, TextSize=12, TextColor3=T.text,
            TextXAlignment=Enum.TextXAlignment.Left, ZIndex=z+2},bg)
    end

    task.spawn(function()
        while win and win.Parent do
            local up = os.clock()-Kernel.boot
            local cnt=0; local mem=0
            for _,p in pairs(Kernel.procs) do cnt+=1; mem+=p.mem end

            labels.os.Text = "Arch Linux"
            labels.kern.Text = "6.6.2-arch1-1"
            labels.arch.Text = "x86_64"
            labels.up.Text = string.format("%dd %dh %dm", 
                math.floor(up/86400), math.floor((up%86400)/3600), math.floor((up%3600)/60))
            labels.procs.Text = tostring(cnt)
            labels.ram.Text = string.format("%dM / 2048M (%d%%)", mem, math.floor(mem/2048*100))
            labels.user.Text = player.Name:lower()
            labels.host.Text = "archos-roblox"
            labels.shell.Text = "bash 5.2.21"
            labels.display.Text = player.DisplayName

            task.wait(0.5)
        end
    end)
    
    kspawn("gnome-system-monitor", 14)
end

-- ── DESKTOP ICONS ──────────────────────────────────────────────
local ICONS={
    {lbl="Terminal",  ico="⌨",  fn=openTerminal,    pos=UDim2.new(0,18,0,18)},
    {lbl="Editor",    ico="📝", fn=openNotepad,     pos=UDim2.new(0,18,0,112)},
    {lbl="htop",      ico="📊", fn=openTaskManager,  pos=UDim2.new(0,18,0,206)},
    {lbl="Firefox",   ico="🌐", fn=openBrowser,      pos=UDim2.new(0,18,0,300)},
    {lbl="Thunar",    ico="📁", fn=openFiles,        pos=UDim2.new(0,18,0,394)},
    {lbl="Calc",      ico="🧮",fn=openCalc,         pos=UDim2.new(0,110,0,18)},
    {lbl="Settings",  ico="⚙",  fn=openSettings,     pos=UDim2.new(0,110,0,112)},
    {lbl="Monitor",   ico="📈", fn=openSysMonitor,   pos=UDim2.new(0,110,0,206)},
}

for _,ic in ipairs(ICONS) do
    local fr=c("Frame",{
        Size=UDim2.new(0,76,0,82), Position=ic.pos,
        BackgroundColor3=T.surface, BackgroundTransparency=0.3,
        BorderSizePixel=0,ZIndex=2},desktop)
    corner(fr,10); stroke(fr,T.border,1,.4)

    c("TextLabel",{Size=UDim2.new(1,0,0,48),Position=UDim2.new(0,0,0,4),
        BackgroundTransparency=1,Text=ic.ico,
        Font=Enum.Font.GothamBold,TextSize=30,ZIndex=3},fr)

    c("TextLabel",{Size=UDim2.new(1,-4,0,26),Position=UDim2.new(0,2,0,50),
        BackgroundTransparency=1,Text=ic.lbl,
        Font=Enum.Font.Gotham,TextSize=10,TextColor3=T.text,
        TextWrapped=true,ZIndex=3},fr)

    local btn=c("TextButton",{Size=UDim2.new(1,0,1,0),BackgroundTransparency=1,
        Text="",ZIndex=4},fr)

    btn.MouseEnter:Connect(function()
        tw(fr,{BackgroundTransparency=0.1, BackgroundColor3=T.surface2})
    end)
    btn.MouseLeave:Connect(function()
        tw(fr,{BackgroundTransparency=0.3, BackgroundColor3=T.surface})
    end)
    btn.MouseButton1Click:Connect(ic.fn)
end

-- ── TASKBAR ───────────────────────────────────────────────────
local taskbar=c("Frame",{
    Size=UDim2.new(1,0,0,44), Position=UDim2.new(0,0,1,-44),
    BackgroundColor3=T.bg1, BorderSizePixel=0,ZIndex=50},gui)

c("Frame",{Size=UDim2.new(1,0,0,1),
    BackgroundColor3=T.accent,BackgroundTransparency=0.6,
    BorderSizePixel=0,ZIndex=51},taskbar)

local startBtn=c("TextButton",{
    Size=UDim2.new(0,100,0,32), Position=UDim2.new(0,6,0.5,-16),
    BackgroundColor3=T.accentDk, Text="🏛  Arch",
    TextColor3=Color3.new(1,1,1), Font=Enum.Font.GothamBold,TextSize=14,
    ZIndex=51,BorderSizePixel=0},taskbar)
corner(startBtn,6)

local taskWinArea = c("Frame",{
    Size=UDim2.new(0,520,0,32), Position=UDim2.new(0,116,0.5,-16),
    BackgroundTransparency=1, ZIndex=51},taskbar)
c("UIListLayout",{
    FillDirection=Enum.FillDirection.Horizontal,
    Padding=UDim.new(0,4),
},taskWinArea)

refreshTaskbar = function()
    for _,ch in ipairs(taskWinArea:GetChildren()) do
        if ch:IsA("TextButton") then ch:Destroy() end
    end
    for title, _ in pairs(OpenWinNames) do
        if WINS[title] and WINS[title].Parent then
            local short = title:gsub("^%s+",""):sub(1,14)
            local tb = c("TextButton",{
                Size=UDim2.new(0,100,1,0),
                BackgroundColor3=T.surface2,
                Text=short, TextColor3=T.text,
                Font=Enum.Font.Gotham, TextSize=11,
                ZIndex=52, BorderSizePixel=0,
            },taskWinArea)
            corner(tb,5)
            hover(tb, T.surface2, T.surface)
            tb.MouseButton1Click:Connect(function()
                local w = WINS[title]
                if w then w.Visible=true; Z+=1; w.ZIndex=Z end
            end)
        end
    end
end

-- Clock
local clockFrame=c("Frame",{
    Size=UDim2.new(0,90,1,0), Position=UDim2.new(1,-96,0,0),
    BackgroundTransparency=1,ZIndex=51},taskbar)

local clockMain=c("TextLabel",{
    Size=UDim2.new(1,0,0,22),Position=UDim2.new(0,0,0,4),
    BackgroundTransparency=1, Text=os.date("%H:%M"),
    Font=Enum.Font.GothamBold,TextSize=16,TextColor3=T.text,
    ZIndex=52},clockFrame)

local clockDate=c("TextLabel",{
    Size=UDim2.new(1,0,0,14),Position=UDim2.new(0,0,0,24),
    BackgroundTransparency=1, Text=os.date("%m/%d/%Y"),
    Font=Enum.Font.Gotham,TextSize=11,TextColor3=T.textDim,
    ZIndex=52},clockFrame)

task.spawn(function()
    while gui and gui.Parent do
        task.wait(1)
        clockMain.Text=os.date("%H:%M")
        clockDate.Text=os.date("%m/%d/%Y")
    end
end)

-- Logo
c("TextLabel",{
    Size=UDim2.new(0,80,1,0), Position=UDim2.new(0.5,-40,0,0),
    BackgroundTransparency=1, Text="Arch Linux",
    Font=Enum.Font.GothamBold,TextSize=12,TextColor3=T.textMut,
    ZIndex=51},taskbar)

-- ── START MENU ─────────────────────────────────────────────────
local smOpen=false
local sm=c("Frame",{
    Size=UDim2.new(0,300,0,480),
    Position=UDim2.new(0,-310,1,-44),
    BackgroundColor3=T.bg2,
    BorderSizePixel=0,ZIndex=60, Visible=false},gui)
corner(sm,12); stroke(sm,T.accent,1,.4)

local smHead=c("Frame",{
    Size=UDim2.new(1,0,0,80),
    BackgroundColor3=T.accentDk,
    BorderSizePixel=0,ZIndex=61},sm)
corner(smHead,12)
c("Frame",{Size=UDim2.new(1,0,0.5,0),Position=UDim2.new(0,0,0.5,0),
    BackgroundColor3=T.accentDk,BorderSizePixel=0,ZIndex=61},smHead)

c("TextLabel",{
    Size=UDim2.new(1,-12,0,32),Position=UDim2.new(0,12,0,12),
    BackgroundTransparency=1, Text="🏛  Arch Linux",
    Font=Enum.Font.GothamBold,TextSize=18,TextColor3=T.text,
    TextXAlignment=Enum.TextXAlignment.Left,ZIndex=62},smHead)

c("TextLabel",{
    Size=UDim2.new(1,-12,0,18),Position=UDim2.new(0,12,0,46),
    BackgroundTransparency=1, Text=player.Name:lower().."@archos",
    Font=Enum.Font.Code,TextSize=13,TextColor3=Color3.fromRGB(180,210,255),
    TextXAlignment=Enum.TextXAlignment.Left,ZIndex=62},smHead)

local smApps={
    {ico="⌨",  lbl="Terminal",          fn=openTerminal},
    {ico="📝", lbl="Text Editor",       fn=openNotepad},
    {ico="📊", lbl="htop",               fn=openTaskManager},
    {ico="🌐", lbl="Firefox",            fn=openBrowser},
    {ico="📁", lbl="Thunar",             fn=openFiles},
    {ico="🧮", lbl="Calculator",         fn=openCalc},
    {ico="⚙",  lbl="Settings",           fn=openSettings},
    {ico="📈", lbl="System Monitor",     fn=openSysMonitor},
}

local smList=c("Frame",{
    Size=UDim2.new(1,-12,0,310),
    Position=UDim2.new(0,6,0,86),
    BackgroundTransparency=1,ZIndex=61},sm)
c("UIListLayout",{Padding=UDim.new(0,3)},smList)

for _,app in ipairs(smApps) do
    local row=c("TextButton",{
        Size=UDim2.new(1,0,0,34),
        BackgroundColor3=T.bg2,
        Text="",BorderSizePixel=0,ZIndex=62},smList)
    corner(row,7); hover(row,T.bg2,T.surface)

    c("TextLabel",{Size=UDim2.new(0,36,1,0),Position=UDim2.new(0,8,0,0),
        BackgroundTransparency=1,Text=app.ico,
        Font=Enum.Font.GothamBold,TextSize=18,ZIndex=63},row)

    c("TextLabel",{Size=UDim2.new(1,-50,1,0),Position=UDim2.new(0,46,0,0),
        BackgroundTransparency=1,Text=app.lbl,
        Font=Enum.Font.Gotham,TextSize=13,TextColor3=T.text,
        TextXAlignment=Enum.TextXAlignment.Left,ZIndex=63},row)

    row.MouseButton1Click:Connect(function()
        smOpen=false
        tw(sm,{Position=UDim2.new(0,-310,1,-44)},.2)
        task.delay(.21,function() sm.Visible=false end)
        app.fn()
    end)
end

-- Separator
c("Frame",{Size=UDim2.new(1,-12,0,1),Position=UDim2.new(0,6,0,405),
    BackgroundColor3=T.border,BackgroundTransparency=.4,
    BorderSizePixel=0,ZIndex=61},sm)

-- Power button
local shutBtn=c("TextButton",{
    Size=UDim2.new(1,-12,0,45), Position=UDim2.new(0,6,0,414),
    BackgroundColor3=Color3.fromRGB(180,40,40),
    Text="⏻   Shutdown",
    TextColor3=Color3.new(1,1,1),
    Font=Enum.Font.GothamBold,TextSize=14,
    ZIndex=62,BorderSizePixel=0},sm)
corner(shutBtn,7)
hover(shutBtn,Color3.fromRGB(180,40,40),Color3.fromRGB(220,50,50))

shutBtn.MouseButton1Click:Connect(function()
    smOpen=false; sm.Visible=false
    local ov=c("Frame",{
        Size=UDim2.new(1,0,1,0),
        BackgroundColor3=Color3.new(0,0,0),
        BackgroundTransparency=1, ZIndex=9999},gui)
    tw(ov,{BackgroundTransparency=0},1)
    task.delay(1,function()
        c("TextLabel",{
            Size=UDim2.new(1,0,0,60),Position=UDim2.new(0,0,0.40,0),
            BackgroundTransparency=1, Text="Arch Linux",
            Font=Enum.Font.GothamBold,TextSize=28,
            TextColor3=T.accent,ZIndex=10000},ov)
        c("TextLabel",{
            Size=UDim2.new(1,0,0,40),Position=UDim2.new(0,0,0.48,0),
            BackgroundTransparency=1, Text="System Shutdown",
            Font=Enum.Font.Gotham,TextSize=18,
            TextColor3=T.text,ZIndex=10000},ov)
        c("TextLabel",{
            Size=UDim2.new(1,0,0,30),Position=UDim2.new(0,0,0.56,0),
            BackgroundTransparency=1, Text="I use Arch btw.",
            Font=Enum.Font.Gotham,TextSize=14,
            TextColor3=T.textDim,ZIndex=10000},ov)
    end)
    task.delay(4,function() gui:Destroy() end)
end)

-- Start menu logic
local function toggleSM()
    smOpen=not smOpen
    if smOpen then
        sm.Visible=true
        sm.Position=UDim2.new(0,-310,1,-44)
        tw(sm,{Position=UDim2.new(0,6,1,-sm.Size.Y.Offset-44)},.22,Enum.EasingStyle.Back)
    else
        tw(sm,{Position=UDim2.new(0,-310,1,-44)},.18)
        task.delay(.2,function() sm.Visible=false end)
    end
end

startBtn.MouseButton1Click:Connect(toggleSM)
hover(startBtn, T.accentDk, T.accent)

desktop.InputBegan:Connect(function(i)
    if smOpen and i.UserInputType==Enum.UserInputType.MouseButton1 then
        smOpen=false
        tw(sm,{Position=UDim2.new(0,-310,1,-44)},.18)
        task.delay(.2,function() sm.Visible=false end)
    end
end)

-- ── ARCH INSTALLER (archinstall) ──────────────────────────────
local INSTALL_CONFIG = {
    keyboard = "us",
    locale = "en_US.UTF-8",
    timezone = "UTC",
    hostname = "archos",
    username = player.Name:lower(),
    profile = "desktop",
    theme = "ArchLinux",
}

local function runInstaller()
    local installer = c("Frame", {
        Size = UDim2.new(1, 0, 1, 0),
        BackgroundColor3 = Color3.fromRGB(0, 0, 0),
        ZIndex = 10000,
    }, gui)

    -- Terminal-style installer
    local installScroll = c("ScrollingFrame", {
        Size = UDim2.new(1, -40, 1, -40),
        Position = UDim2.new(0, 20, 0, 20),
        BackgroundColor3 = Color3.fromRGB(10, 10, 15),
        BorderSizePixel = 0,
        ScrollBarThickness = 4,
        ScrollBarImageColor3 = Color3.fromRGB(137, 180, 250),
        AutomaticCanvasSize = Enum.AutomaticSize.Y,
        CanvasSize = UDim2.new(0, 0, 0, 0),
        ZIndex = 10001,
    }, installer)
    
    c("UIListLayout", {Padding = UDim.new(0, 2)}, installScroll)
    pad(installScroll, 12)

    local function iout(txt, col)
        local lbl = c("TextLabel", {
            Size = UDim2.new(1, 0, 0, 0),
            AutomaticSize = Enum.AutomaticSize.Y,
            BackgroundTransparency = 1,
            Text = txt,
            Font = Enum.Font.Code,
            TextSize = 13,
            TextColor3 = col or Color3.fromRGB(205, 214, 244),
            TextXAlignment = Enum.TextXAlignment.Left,
            TextWrapped = true,
            ZIndex = 10002,
        }, installScroll)
        task.defer(function()
            installScroll.CanvasPosition = Vector2.new(0, installScroll.AbsoluteCanvasSize.Y)
        end)
        return lbl
    end

    -- Installation menu
    local currentStep = 1
    local steps = {
        {name = "Keyboard layout", key = "keyboard", options = {"us", "uk", "de", "fr", "es"}},
        {name = "Locale", key = "locale", options = {"en_US.UTF-8", "en_GB.UTF-8", "de_DE.UTF-8"}},
        {name = "Timezone", key = "timezone", options = {"UTC", "America/New_York", "Europe/London", "Asia/Tokyo"}},
        {name = "Hostname", key = "hostname", custom = true},
        {name = "Desktop profile", key = "profile", options = {"minimal", "desktop", "xfce", "kde"}},
        {name = "Theme", key = "theme", options = {"ArchLinux", "ArchClassic", "ArchMonokai"}},
    }

    local menuActive = true
    local selectedOption = 1

    local function drawMenu()
        for _, ch in ipairs(installScroll:GetChildren()) do
            if ch:IsA("TextLabel") then ch:Destroy() end
        end

        iout("", Color3.fromRGB(23, 147, 209))
        iout("                   -`                    ", Color3.fromRGB(23, 147, 209))
        iout("                  .o+`                   ", Color3.fromRGB(23, 147, 209))
        iout("                 `ooo/                   ", Color3.fromRGB(23, 147, 209))
        iout("                `+oooo:                  ", Color3.fromRGB(23, 147, 209))
        iout("               `+oooooo:                 ", Color3.fromRGB(23, 147, 209))
        iout("               -+oooooo+:                ", Color3.fromRGB(23, 147, 209))
        iout("             `/:-:++oooo+:               ", Color3.fromRGB(23, 147, 209))
        iout("            `/++++/+++++++:              ", Color3.fromRGB(23, 147, 209))
        iout("           `/++++++++++++++:             ", Color3.fromRGB(23, 147, 209))
        iout("          `/+++ooooooooooooo/`           ", Color3.fromRGB(23, 147, 209))
        iout("         ./ooosssso++osssssso+`          ", Color3.fromRGB(23, 147, 209))
        iout("        .oossssso-````/ossssss+`         ", Color3.fromRGB(23, 147, 209))
        iout("       -osssssso.      :ssssssso.        ", Color3.fromRGB(23, 147, 209))
        iout("      :osssssss/        osssso+++.       ", Color3.fromRGB(23, 147, 209))
        iout("     /ossssssss/        +ssssooo/-       ", Color3.fromRGB(23, 147, 209))
        iout("   `/ossssso+/:-        -:/+osssso+-     ", Color3.fromRGB(23, 147, 209))
        iout("  `+sso+:-`                 `.-/+oso:    ", Color3.fromRGB(23, 147, 209))
        iout(" `++:.                           `-/+/   ", Color3.fromRGB(23, 147, 209))
        iout(" .`                                 `/   ", Color3.fromRGB(23, 147, 209))
        iout("", Color3.fromRGB(23, 147, 209))
        iout("╔═══════════════════════════════════════════════════════╗", Color3.fromRGB(23, 147, 209))
        iout("║                                                       ║", Color3.fromRGB(23, 147, 209))
        iout("║              ARCH LINUX INSTALLER                     ║", Color3.fromRGB(255, 255, 255))
        iout("║                  (archinstall)                        ║", Color3.fromRGB(255, 255, 255))
        iout("║                                                       ║", Color3.fromRGB(23, 147, 209))
        iout("╚═══════════════════════════════════════════════════════╝", Color3.fromRGB(23, 147, 209))
        iout("", Color3.fromRGB(255, 255, 255))
        iout("Use ↑/↓ arrows to navigate, ENTER to select, ESC to skip", Color3.fromRGB(180, 180, 180))
        iout("", Color3.fromRGB(255, 255, 255))

        if currentStep <= #steps then
            local step = steps[currentStep]
            iout(">>> " .. step.name, Color3.fromRGB(23, 147, 209))
            iout("", Color3.fromRGB(255, 255, 255))

            if step.custom then
                iout("Current: " .. INSTALL_CONFIG[step.key], Color3.fromRGB(0, 255, 0))
                iout("[Press ENTER to keep current value]", Color3.fromRGB(100, 100, 100))
            else
                for i, opt in ipairs(step.options) do
                    local prefix = (i == selectedOption) and "  → " or "    "
                    local color = (i == selectedOption) and Color3.fromRGB(23, 147, 209) or Color3.fromRGB(180, 180, 180)
                    iout(prefix .. opt, color)
                end
            end
        else
            iout("╔═══════════════════════════════════════════════════════╗", Color3.fromRGB(23, 147, 209))
            iout("║              INSTALLATION SUMMARY                     ║", Color3.fromRGB(255, 255, 255))
            iout("╚═══════════════════════════════════════════════════════╝", Color3.fromRGB(23, 147, 209))
            iout("", Color3.fromRGB(255, 255, 255))
            iout("Keyboard:  " .. INSTALL_CONFIG.keyboard, Color3.fromRGB(0, 255, 0))
            iout("Locale:    " .. INSTALL_CONFIG.locale, Color3.fromRGB(0, 255, 0))
            iout("Timezone:  " .. INSTALL_CONFIG.timezone, Color3.fromRGB(0, 255, 0))
            iout("Hostname:  " .. INSTALL_CONFIG.hostname, Color3.fromRGB(0, 255, 0))
            iout("Profile:   " .. INSTALL_CONFIG.profile, Color3.fromRGB(0, 255, 0))
            iout("Theme:     " .. INSTALL_CONFIG.theme, Color3.fromRGB(0, 255, 0))
            iout("", Color3.fromRGB(255, 255, 255))
            iout("  → Press ENTER to begin installation", Color3.fromRGB(23, 147, 209))
        end
    end

    drawMenu()

    local inputConn
    inputConn = UIS.InputBegan:Connect(function(input, gpe)
        if gpe or not menuActive then return end

        if currentStep <= #steps then
            local step = steps[currentStep]
            
            if input.KeyCode == Enum.KeyCode.Up then
                if not step.custom then
                    selectedOption = math.max(1, selectedOption - 1)
                    drawMenu()
                end
            elseif input.KeyCode == Enum.KeyCode.Down then
                if not step.custom then
                    selectedOption = math.min(#step.options, selectedOption + 1)
                    drawMenu()
                end
            elseif input.KeyCode == Enum.KeyCode.Return then
                if not step.custom then
                    INSTALL_CONFIG[step.key] = step.options[selectedOption]
                end
                currentStep += 1
                selectedOption = 1
                drawMenu()
            elseif input.KeyCode == Enum.KeyCode.Escape then
                currentStep += 1
                selectedOption = 1
                drawMenu()
            end
        else
            if input.KeyCode == Enum.KeyCode.Return then
                menuActive = false
                inputConn:Disconnect()
                
                -- Apply selected theme
                if Themes[INSTALL_CONFIG.theme] then
                    T = Themes[INSTALL_CONFIG.theme]
                    ActiveTheme = INSTALL_CONFIG.theme
                end
                
                -- Run installation
                for _, ch in ipairs(installScroll:GetChildren()) do
                    if ch:IsA("TextLabel") then ch:Destroy() end
                end
                
                iout("", Color3.fromRGB(23, 147, 209))
                iout("╔═══════════════════════════════════════════════════════╗", Color3.fromRGB(23, 147, 209))
                iout("║           STARTING INSTALLATION...                    ║", Color3.fromRGB(255, 255, 255))
                iout("╚═══════════════════════════════════════════════════════╝", Color3.fromRGB(23, 147, 209))
                iout("", Color3.fromRGB(255, 255, 255))
                
                local installSteps = {
                    "[1/12] Partitioning disk...",
                    "[2/12] Formatting partitions...",
                    "[3/12] Mounting file systems...",
                    "[4/12] Installing base system...",
                    "[5/12] Installing kernel...",
                    "[6/12] Configuring locale (" .. INSTALL_CONFIG.locale .. ")...",
                    "[7/12] Setting timezone (" .. INSTALL_CONFIG.timezone .. ")...",
                    "[8/12] Setting hostname (" .. INSTALL_CONFIG.hostname .. ")...",
                    "[9/12] Installing " .. INSTALL_CONFIG.profile .. " profile...",
                    "[10/12] Configuring bootloader...",
                    "[11/12] Applying " .. INSTALL_CONFIG.theme .. " theme...",
                    "[12/12] Finalizing installation...",
                }
                
                task.spawn(function()
                    for i, step in ipairs(installSteps) do
                        iout(step, Color3.fromRGB(0, 255, 0))
                        
                        -- Progress bar
                        local pct = math.floor((i / #installSteps) * 100)
                        local barFilled = math.floor(pct / 2)
                        local bar = "["..string.rep("█", barFilled)..string.rep("░", 50 - barFilled).."] "..pct.."%"
                        iout(bar, Color3.fromRGB(23, 147, 209))
                        iout("", Color3.fromRGB(255, 255, 255))
                        
                        task.wait(math.random(30, 80) / 100)
                    end
                    
                    task.wait(0.5)
                    iout("╔═══════════════════════════════════════════════════════╗", Color3.fromRGB(0, 255, 0))
                    iout("║         INSTALLATION COMPLETE!                        ║", Color3.fromRGB(0, 255, 0))
                    iout("╚═══════════════════════════════════════════════════════╝", Color3.fromRGB(0, 255, 0))
                    iout("", Color3.fromRGB(255, 255, 255))
                    iout("Arch Linux has been successfully installed.", Color3.fromRGB(23, 147, 209))
                    iout("Your system will now boot...", Color3.fromRGB(23, 147, 209))
                    iout("", Color3.fromRGB(255, 255, 255))
                    iout("Welcome to Arch Linux. I use Arch btw.", Color3.fromRGB(255, 255, 0))
                    
                    task.wait(2)
                    
                    -- Fade out installer
                    local function fadeOut(obj)
                        if obj:IsA("TextLabel") or obj:IsA("Frame") then
                            tw(obj, {BackgroundTransparency = 1}, 0.5)
                        end
                        if obj:IsA("TextLabel") then
                            tw(obj, {TextTransparency = 1}, 0.5)
                        end
                        for _, ch in ipairs(obj:GetChildren()) do fadeOut(ch) end
                    end
                    
                    fadeOut(installer)
                    task.wait(0.6)
                    installer:Destroy()
                    
                    -- Start boot sequence
                    runBootSequence()
                end)
            end
        end
    end)
end

-- ── BOOT SCREEN ─────────────────────────────────────────────
function runBootSequence()
    local boot=c("Frame",{
        Size=UDim2.new(1,0,1,0),
        BackgroundColor3=Color3.fromRGB(0,0,0),
        ZIndex=9000},gui)

local bootLogo=c("TextLabel",{
    Size=UDim2.new(1,0,0,100), Position=UDim2.new(0,0,0.32,0),
    BackgroundTransparency=1, Text="Arch Linux",
    Font=Enum.Font.GothamBold,TextSize=64,
    TextColor3=T.accent,ZIndex=9001},boot)

local bootSub=c("TextLabel",{
    Size=UDim2.new(1,0,0,28), Position=UDim2.new(0,0,0.32,100),
    BackgroundTransparency=1, Text="v3.0  —  I use Arch btw",
    Font=Enum.Font.Gotham,TextSize=18,
    TextColor3=T.textDim,ZIndex=9001},boot)

local pbBg=c("Frame",{
    Size=UDim2.new(0,400,0,4), Position=UDim2.new(0.5,-200,0.70,0),
    BackgroundColor3=T.surface2, BorderSizePixel=0,ZIndex=9001},boot)
corner(pbBg,2)

local pbFill=c("Frame",{
    Size=UDim2.new(0,0,1,0),
    BackgroundColor3=T.accent,
    BorderSizePixel=0,ZIndex=9002},pbBg)
corner(pbFill,2)

local pbStatus=c("TextLabel",{
    Size=UDim2.new(0,400,0,22), Position=UDim2.new(0.5,-200,0.70,12),
    BackgroundTransparency=1, Text="Loading...",
    Font=Enum.Font.Code,TextSize=13,
    TextColor3=T.textDim,ZIndex=9001},boot)

local steps={
    {t="[    0.000000] Booting Linux 6.6.2-arch1-1...",     p=0.10},
    {t="[    0.123456] Initializing kernel modules...",     p=0.22},
    {t="[    0.245678] Mounting file systems...",           p=0.34},
    {t="[    0.367890] Starting systemd...",                p=0.46},
    {t="[    0.489012] Loading user profile...",            p=0.58},
    {t="[    0.610234] Applying theme: "..ActiveTheme.."...", p=0.70},
    {t="[    0.732456] Starting window manager...",         p=0.82},
    {t="[    0.854678] System ready. Welcome to Arch!",     p=1.00},
}

task.spawn(function()
    for _,s in ipairs(steps) do
        pbStatus.Text=s.t
        tw(pbFill,{Size=UDim2.new(s.p,0,1,0)},.35)
        task.wait(.32)
    end
    task.wait(.4)

    local function fadeOut(obj)
        if obj:IsA("TextLabel") then tw(obj,{TextTransparency=1},.5) end
        if obj:IsA("Frame") or obj:IsA("TextLabel") then
            tw(obj,{BackgroundTransparency=1},.5)
        end
        for _,ch in ipairs(obj:GetChildren()) do fadeOut(ch) end
    end

    fadeOut(bootLogo); fadeOut(bootSub)
    fadeOut(pbBg); fadeOut(pbStatus)
    task.wait(.3)
    tw(boot,{BackgroundTransparency=1},.5)
    task.wait(.55)
    boot:Destroy()

    task.delay(0.5, function()
        notify("Welcome!", "Arch Linux loaded successfully.\n"..player.DisplayName..", I use Arch btw.", 6, "🏛️")
    end)
end)
end

-- ── START INSTALLATION ─────────────────────────────────────────
-- Run the installer first, which will then boot the OS
runInstaller()

Features & Information

THIS IS A REPLICA FOR ARCH LINUX BUT IN ROBLOX

Community Comments (5)

chillingchillingMay 12, 2026

leave ideas here

voltexvoltexMay 12, 2026

good idea

chillingchillingMay 12, 2026

thank you!

voltexvoltexMay 12, 2026

Im pretty sure you bumbed the script but I dont recommend doing that so early

chillingchillingMay 12, 2026

ok sorry i am new

More Scripts for Universal Scripts