include("shared.lua")

-- === НАСТРОЙКА ИКОНОК, НАЗВАНИЙ И ОПИСАНИЙ (ARMA STYLE) ===
local CUSTOM_ICONS_BG = {
    ["shirt_and_jaket"] = {
        default = Material("wardrobe_ui/body.png", "noclamp smooth"),
    },
    ["helm"] = {
        -- default = Material("wardrobe_ui/helm_icon.png", "noclamp smooth"),
    }
}

local CUSTOM_ICONS_SKIN = {
    -- default = Material("wardrobe_ui/skin_bg.png", "noclamp smooth"),
}

local CUSTOM_NAMES_BG = {
    ["shirt_and_jaket"] = {
        [0] = "Стандартная форма",
        [1] = "Закатанные рукава",
    },
    ["helm"] = {
        [0] = "Без шлема",
    }
}

local CUSTOM_DESC_BG = {
    ["shirt_and_jaket"] = {
        [0] = "Полевая форма из плотного материала.\nОбеспечивает базовую маскировку.\n\n1.2kg",
        [1] = "Облегченный вариант формы для жаркого климата.\nСнижает перегрев бойца.\n\n1.0kg",
    },
    ["helm"] = {
        [0] = "Отсутствие головного убора.\nНе предоставляет баллистической защиты.\n\n0.0kg",
    }
}

local CUSTOM_NAMES_SKIN = {
    [0] = "Лесной камуфляж (Woodland)",
    [1] = "Пустынный камуфляж (Desert)",
}

local CUSTOM_DESC_SKIN = {
    [0] = "Стандартный лесной паттерн для умеренного климата.\n\nКамуфляж",
    [1] = "Песочный паттерн для засушливых регионов.\n\nКамуфляж",
}
-- ========================

local C_BG_D = Color(3, 5, 4)
local C_BG_M = Color(8, 12, 10)
local C_BG_L = Color(12, 18, 14)
local C_PRI = Color(27, 94, 32)
local C_PRI_H = Color(33, 110, 38)
local C_ACC = Color(56, 102, 35)
local C_ACC_H = Color(66, 120, 45)
local C_BDR = Color(46, 125, 50, 80)
local C_TXT_P = Color(165, 214, 167)
local C_GRAD = Color(27, 94, 32, 15)
local C_WARN = Color(150, 40, 40)
local C_WARN_H = Color(180, 50, 50)
local C_WHITE = Color(255, 255, 255, 200)

local C_ARMA_TOOLTIP_BG = Color(35, 35, 35, 240)
local C_ARMA_SLOT = Color(40, 40, 40, 255)
local C_ARMA_SLOT_HOVER = Color(60, 60, 60, 255)
local C_ARMA_SLOT_EMPTY = Color(20, 20, 20, 150)
local C_ARMA_SEL = Color(194, 138, 74, 255) 
local C_ARMA_TEXT = Color(180, 180, 180, 255)

local bgMat = Material("materials/wardrobe_ui/fon.jpg", "noclamp smooth")

-- =====================================================================
-- ПАНЕЛЬ ОБЫЧНОГО ИГРОКА
-- =====================================================================
net.Receive("SandboxWardrobeOpen", function()
    local model = net.ReadString()
    local bodygroups = net.ReadTable()
    local availableSkins = net.ReadTable()
    local currentBodygroups = net.ReadTable()
    local currentSkin = net.ReadUInt(8)
    local unlockedBodygroups = net.ReadTable()
    local serverPresets = net.ReadTable()

    local scrW, scrH = ScrW(), ScrH()
    local fW = math.Clamp(scrW * 0.62, 950, 1600)
    local fH = math.Clamp(scrH * 0.62, 600, 1000)

    local leftW = 230
    local rightW = math.Clamp(fW * 0.38, 350, 550)
    local midW = fW - leftW - rightW - 80
    local midX = 40 + leftW
    local rightX = midX + midW + 20

    local frame = vgui.Create("DFrame")
    frame:SetSize(fW, fH)
    frame:Center()
    frame:SetTitle("")
    frame:ShowCloseButton(false)
    frame:MakePopup()
    frame:SetBackgroundBlur(true)
    frame.Paint = function(s, w, h)
        draw.RoundedBox(8, 0, 0, w, h, C_BG_D)
        surface.SetDrawColor(C_GRAD)
        surface.DrawRect(0, 0, w, 3)
        draw.RoundedBoxEx(8, 0, 0, w, 50, C_BG_M, true, true, false, false)
        surface.SetDrawColor(C_BDR)
        surface.DrawLine(0, 50, w, 50)
        draw.SimpleText("ГАРДЕРОБ", "DermaLarge", w/2, 25, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
        surface.SetDrawColor(C_ACC)
        surface.DrawRect(20, 48, 30, 2)
        surface.DrawRect(w-50, 48, 30, 2)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
    end
    
    local closeBtn = vgui.Create("DButton", frame)
    closeBtn:SetPos(frame:GetWide() - 40, 10)
    closeBtn:SetSize(30, 30)
    closeBtn:SetText("")
    closeBtn.Paint = function(s, w, h)
        local col = s:IsHovered() and C_ACC_H or C_ACC
        draw.RoundedBox(4, 0, 0, w, h, col)
        draw.SimpleText("X", "DermaLarge", w/2, h/2-2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    end
    closeBtn.DoClick = function() frame:Close() end

    local btnOffset = 45

    local hintsPanel = vgui.Create("DPanel", frame)
    hintsPanel:SetPos(20, 60)
    hintsPanel.Expanded = true
    hintsPanel.CurHeight = 305
    hintsPanel:SetSize(230, hintsPanel.CurHeight)
    hintsPanel.Paint = function(s, w, h) draw.RoundedBox(6, 0, 0, w, h, C_BG_M); surface.SetDrawColor(C_BDR); surface.DrawOutlinedRect(0, 0, w, h, 1) end
    hintsPanel.Think = function(s)
        local targetHeight = s.Expanded and 305 or 35
        if s.CurHeight ~= targetHeight then s.CurHeight = Lerp(FrameTime() * 15, s.CurHeight, targetHeight); if math.abs(s.CurHeight - targetHeight) < 0.5 then s.CurHeight = targetHeight end; s:SetTall(math.Round(s.CurHeight)) end
    end

    local hintsHeader = vgui.Create("DButton", hintsPanel)
    hintsHeader:SetPos(0, 0); hintsHeader:SetSize(230, 35); hintsHeader:SetText("")
    hintsHeader.Paint = function(s, w, h)
        local col = s:IsHovered() and C_BG_L or C_BG_D
        draw.RoundedBoxEx(6, 0, 0, w, h, col, true, true, not hintsPanel.Expanded, not hintsPanel.Expanded)
        surface.SetDrawColor(C_ACC); surface.DrawRect(0, 0, 3, h)
        draw.SimpleText("УПРАВЛЕНИЕ", "DermaLarge", 10, h/2, C_TXT_P, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
        draw.SimpleText(hintsPanel.Expanded and "▼" or "◀", "DermaDefault", w - 15, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    end
    hintsHeader.DoClick = function(s) hintsPanel.Expanded = not hintsPanel.Expanded end

    local hintsContent = vgui.Create("DPanel", hintsPanel)
    hintsContent:SetPos(0, 35); hintsContent:SetSize(230, 270); hintsContent.Paint = function() end
    local binds = { {"ЛКМ / Перетаскивание", "Примерить одежду"}, {"ALT + ЛКМ", "Вращение камеры"}, {"SHIFT + ЛКМ", "Перемещение камеры"}, {"Колёсико мыши", "Приблизить / Отдалить"} }
    local hy = 10
    for _, bind in ipairs(binds) do
        local bindItem = vgui.Create("DPanel", hintsContent)
        bindItem:SetPos(10, hy); bindItem:SetSize(210, 55)
        bindItem.Paint = function(s, w, h) draw.RoundedBox(4, 0, 0, w, h, C_BG_D); surface.SetDrawColor(C_BDR); surface.DrawOutlinedRect(0, 0, w, h, 1); draw.SimpleText(bind[1], "DermaDefaultBold", w/2, 16, C_WHITE, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER); draw.SimpleText(bind[2], "DermaDefault", w/2, 36, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) end
        hy = hy + 60
    end
    
    local presetsPanel = vgui.Create("DPanel", frame)
    presetsPanel.Expanded = false
    presetsPanel.CurHeight = 35
    presetsPanel:SetSize(230, presetsPanel.CurHeight)
    
    local presetsContent = vgui.Create("DScrollPanel", presetsPanel)
    presetsContent:SetPos(0, 35)
    
    presetsPanel.Paint = function(s, w, h)
        draw.RoundedBox(6, 0, 0, w, h, C_BG_M)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
    end
    
    presetsPanel.Think = function(s)
        local maxH = fH - hintsPanel.CurHeight - 80
        local targetHeight = s.Expanded and maxH or 35
        if s.CurHeight ~= targetHeight then
            s.CurHeight = Lerp(FrameTime() * 15, s.CurHeight, targetHeight)
            if math.abs(s.CurHeight - targetHeight) < 0.5 then s.CurHeight = targetHeight end
            s:SetTall(math.Round(s.CurHeight))
        end
        local targetY = hintsPanel:GetY() + hintsPanel:GetTall() + 10
        if s:GetY() ~= targetY then s:SetPos(20, targetY) end
        
        presetsContent:SetSize(230, s:GetTall() - 35)
    end

    local presetsHeader = vgui.Create("DButton", presetsPanel)
    presetsHeader:SetPos(0, 0); presetsHeader:SetSize(230, 35); presetsHeader:SetText("")
    presetsHeader.Paint = function(s, w, h)
        local col = s:IsHovered() and C_BG_L or C_BG_D
        draw.RoundedBoxEx(6, 0, 0, w, h, col, true, true, not presetsPanel.Expanded, not presetsPanel.Expanded)
        surface.SetDrawColor(C_ACC); surface.DrawRect(0, 0, 3, h); draw.SimpleText("СБОРКИ", "DermaLarge", 10, h/2, C_TXT_P, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
        draw.SimpleText(presetsPanel.Expanded and "▼" or "◀", "DermaDefault", w - 15, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    end
    presetsHeader.DoClick = function(s) presetsPanel.Expanded = not presetsPanel.Expanded end

    local allPresets = serverPresets or {}
    if not allPresets[model] then allPresets[model] = {} end

    local function SavePresetsToServer()
        net.Start("SandboxWardrobeSavePreset")
        net.WriteTable(allPresets)
        net.SendToServer()
    end

    -- НОРМАЛИЗАЦИЯ ключей (util.JSONToTable превращает строковые числа обратно в number type)
    local norm = {}
    for k, v in pairs(allPresets[model]) do norm[tostring(k)] = v end
    allPresets[model] = norm

    local py = 10
    for i = 1, 10 do
        local slotPanel = vgui.Create("DPanel", presetsContent)
        slotPanel:SetPos(10, py)
        slotPanel:SetSize(200, 85)
        slotPanel.Paint = function(s, w, h)
            draw.RoundedBox(4, 0, 0, w, h, C_BG_D)
            surface.SetDrawColor(C_BDR)
            surface.DrawOutlinedRect(0, 0, w, h, 1)
        end

        local pData = allPresets[model][i] or allPresets[model][tostring(i)]
        local hasData = pData ~= nil
        local defaultName = "Сборка " .. i

        local iconCell = vgui.Create("DPanel", slotPanel)
        iconCell:SetPos(130, 12)
        iconCell:SetSize(60, 60)
        iconCell.Paint = function(s, w, h)
            local curData = allPresets[model][tostring(i)]
            local isFilled = curData ~= nil
            
            draw.RoundedBox(4, 0, 0, w, h, isFilled and C_ARMA_SLOT or C_ARMA_SLOT_EMPTY)
            
            if isFilled then
                local mat = Material("wardrobe_ui/body.png", "noclamp smooth")
                if mat and not mat:IsError() then
                    surface.SetDrawColor(255, 255, 255, 200)
                    surface.SetMaterial(mat)
                    surface.DrawTexturedRect(5, 5, w-10, h-10)
                end
                surface.SetDrawColor(C_PRI)
                surface.DrawOutlinedRect(0, 0, w, h, 1)
            else
                draw.SimpleText("ПУСТО", "DermaDefault", w/2, h/2, Color(100, 100, 100), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                surface.SetDrawColor(Color(0,0,0,100))
                surface.DrawOutlinedRect(0, 0, w, h, 1)
            end
        end

        local nameEntry = vgui.Create("DTextEntry", slotPanel)
        nameEntry:SetPos(10, 12)
        nameEntry:SetSize(110, 25)
        nameEntry:SetText(hasData and (pData.name or defaultName) or defaultName)
        nameEntry.Paint = function(s, w, h)
            draw.RoundedBox(4, 0, 0, w, h, C_BG_M)
            surface.SetDrawColor(s:IsEditing() and C_PRI or C_BDR)
            surface.DrawOutlinedRect(0, 0, w, h, 1)
            s:DrawTextEntryText(C_WHITE, C_PRI, C_WHITE)
        end
        nameEntry.OnChange = function(s)
            local curData = allPresets[model][tostring(i)]
            if curData then
                curData.name = s:GetText()
                timer.Create("WardrobePresetSave_"..i, 0.5, 1, function()
                    if IsValid(frame) then SavePresetsToServer() end
                end)
            end
        end

        local btnW = 33
        local btnY = 47

        local loadBtn = vgui.Create("DButton", slotPanel)
        loadBtn:SetPos(10, btnY)
        loadBtn:SetSize(btnW, 25)
        loadBtn:SetText("")
        loadBtn.Paint = function(s, w, h)
            if not allPresets[model][tostring(i)] then
                draw.RoundedBox(4, 0, 0, w, h, Color(30, 30, 30, 150))
                draw.SimpleText("ЗАГР", "DermaDefault", w/2, h/2, Color(100, 100, 100), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                return
            end
            local col = s:IsHovered() and C_ACC_H or C_ACC
            draw.RoundedBox(4, 0, 0, w, h, col)
            draw.SimpleText("ЗАГР", "DermaDefault", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
        end
        loadBtn.DoClick = function()
            local curData = allPresets[model][tostring(i)]
            if not curData then return end
            for idx, val in pairs(curData.bgs) do currentBodygroups[tonumber(idx) or idx] = val end
            if curData.skin then currentSkin = curData.skin end
            surface.PlaySound("buttons/button15.wav")
        end

        local saveBtn = vgui.Create("DButton", slotPanel)
        saveBtn:SetPos(48, btnY)
        saveBtn:SetSize(btnW, 25)
        saveBtn:SetText("")
        saveBtn.Paint = function(s, w, h)
            local col = s:IsHovered() and C_PRI_H or C_PRI
            draw.RoundedBox(4, 0, 0, w, h, col)
            draw.SimpleText("СОХР", "DermaDefault", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
        end
        saveBtn.DoClick = function()
            local finalName = nameEntry:GetText()
            if finalName == "" then finalName = defaultName end
            local safeBGs = {}
            for k, v in pairs(currentBodygroups) do safeBGs[tostring(k)] = v end
            allPresets[model][tostring(i)] = {
                name = finalName,
                bgs = safeBGs,
                skin = currentSkin
            }
            SavePresetsToServer()
            surface.PlaySound("buttons/button15.wav")
        end

        local delBtn = vgui.Create("DButton", slotPanel)
        delBtn:SetPos(87, btnY)
        delBtn:SetSize(btnW, 25)
        delBtn:SetText("")
        delBtn.Paint = function(s, w, h)
            if not allPresets[model][tostring(i)] then
                draw.RoundedBox(4, 0, 0, w, h, Color(30, 30, 30, 150))
                draw.SimpleText("УДАЛ", "DermaDefault", w/2, h/2, Color(100, 100, 100), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                return
            end
            local col = s:IsHovered() and C_WARN_H or C_WARN
            draw.RoundedBox(4, 0, 0, w, h, col)
            draw.SimpleText("УДАЛ", "DermaDefault", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
        end
        delBtn.DoClick = function()
            if allPresets[model][tostring(i)] or allPresets[model][i] then
                allPresets[model][tostring(i)] = nil
                allPresets[model][i] = nil
                SavePresetsToServer()
                nameEntry:SetText(defaultName)
                surface.PlaySound("buttons/button15.wav")
            end
        end

        py = py + 95
    end

    local modelPanel = vgui.Create("DModelPanel", frame)
    modelPanel:SetPos(midX, 60); modelPanel:SetSize(midW, fH - 140); modelPanel:SetModel(model)
    modelPanel:Receiver("wardrobe_item", function(pnl, tbl, bDoDrop, command, x, y)
        if bDoDrop then local droppedCell = tbl[1]; if IsValid(droppedCell) then if droppedCell.isBodygroup then currentBodygroups[droppedCell.bgIdx] = droppedCell.bgVal elseif droppedCell.isSkin then currentSkin = droppedCell.skinVal end; surface.PlaySound("UI/buttonclick.wav") end end
    end)
    
    local oldPaint = modelPanel.Paint
    modelPanel.Paint = function(s, w, h)
        if bgMat and not bgMat:IsError() then surface.SetDrawColor(255, 255, 255, 255); surface.SetMaterial(bgMat); surface.DrawTexturedRect(0, 0, w, h) end
        local mx, my = gui.MousePos(); local px, py = s:LocalToScreen(0, 0)
        local isHoveredDrag = dragndrop.IsDragging() and (mx >= px and mx <= px + w and my >= py and my <= py + h)
        if isHoveredDrag then surface.SetDrawColor(C_PRI); surface.DrawOutlinedRect(0, 0, w, h, 3); surface.SetDrawColor(C_GRAD); surface.DrawRect(0, 0, w, h) else surface.SetDrawColor(C_BDR); surface.DrawOutlinedRect(0, 0, w, h, 1) end
        oldPaint(s, w, h)
    end
    modelPanel.camAnims = { zoom = 60, rot = Angle(0, 180, 0), offset = Vector(0, 0, 0) }; modelPanel.curZoom = 60; modelPanel.curRot = Angle(0, 180, 0); modelPanel.curOffset = Vector(0, 0, 0)
    modelPanel.LayoutEntity = function(s, ent)
        if not s.bAnimSet then local seq = ent:LookupSequence("idle_subtle"); if seq <= 0 then seq = ent:LookupSequence("idle_all_01") end; if seq > 0 then ent:SetSequence(seq) end; s.bAnimSet = true end
        if (s.bDragging) then
            local x, y = gui.MousePos(); local dx = x - s.lastX; local dy = y - s.lastY
            if input.IsKeyDown(KEY_LSHIFT) or input.IsKeyDown(KEY_RSHIFT) then local right = s.curRot:Right(); local up = s.curRot:Up(); s.camAnims.offset = s.camAnims.offset - right * (dx * 0.15) + up * (dy * 0.15) elseif input.IsKeyDown(KEY_LALT) or input.IsKeyDown(KEY_RALT) then s.camAnims.rot.yaw = s.camAnims.rot.yaw - dx * 0.8; s.camAnims.rot.pitch = math.Clamp(s.camAnims.rot.pitch - dy * 0.8, -45, 45) end
            s.lastX, s.lastY = x, y
        end
        local speed = FrameTime() * 10; s.curZoom = Lerp(speed, s.curZoom, s.camAnims.zoom); s.curRot = LerpAngle(speed, s.curRot, s.camAnims.rot); s.curOffset = LerpVector(speed, s.curOffset, s.camAnims.offset)
        local targetPos = ent:GetPos() + Vector(0, 0, 40) + s.curOffset; s:SetCamPos(targetPos - s.curRot:Forward() * s.curZoom); s:SetLookAng(s.curRot)
        ent:FrameAdvance((RealTime() - (s.lastTick or RealTime())) * 1); s.lastTick = RealTime()
    end
    
    local function SetCameraAngle(angle)
        if angle == "front" then modelPanel.camAnims.rot = Angle(0, 180, 0) elseif angle == "side" then modelPanel.camAnims.rot = Angle(0, 90, 0) elseif angle == "back" then modelPanel.camAnims.rot = Angle(0, 0, 0) end
        modelPanel.camAnims.offset = Vector(0, 0, 0)
    end
    
    modelPanel.OnMousePressed = function(s, code) if code == MOUSE_LEFT then local clickTime = SysTime(); if s.lastClickTime and (clickTime - s.lastClickTime) < 0.3 then s.camAnims.zoom = 60; s.camAnims.rot = Angle(0, 180, 0); s.camAnims.offset = Vector(0, 0, 0); s.lastClickTime = 0; return end; s.lastClickTime = clickTime; s.bDragging = true; s.lastX, s.lastY = gui.MousePos() end end
    modelPanel.OnMouseReleased = function(s, code) if code == MOUSE_LEFT then s.bDragging = false end end
    modelPanel.OnCursorExited = function(s) s.bDragging = false end
    modelPanel.OnMouseWheeled = function(s, delta) s.camAnims.zoom = math.Clamp(s.camAnims.zoom - delta * 15, 10, 120) end
    timer.Simple(0.05, function() if IsValid(modelPanel) then SetCameraAngle("front") end end)
    modelPanel.Think = function(s) local entity = s:GetEntity(); if IsValid(entity) then for idx, value in pairs(currentBodygroups) do if entity:GetBodygroup(idx) ~= value then entity:SetBodygroup(idx, value) end end; if entity:GetSkin() ~= currentSkin then entity:SetSkin(currentSkin) end end end

    local viewButtons = vgui.Create("DPanel", frame)
    viewButtons:SetPos(midX, fH - 70); viewButtons:SetSize(midW, 50)
    viewButtons.Paint = function(s, w, h) draw.RoundedBox(6, 0, 0, w, h, C_BG_M); surface.SetDrawColor(C_BDR); surface.DrawOutlinedRect(0, 0, w, h, 1) end
    
    local angles = {{"СПЕРЕДИ", "front"}, {"СБОКУ", "side"}, {"СЗАДИ", "back"}}
    for k, v in ipairs(angles) do
        local btn = vgui.Create("DButton", viewButtons)
        btn.Paint = function(s, w, h) local col = s:IsHovered() and C_PRI_H or C_PRI; draw.RoundedBox(4, 0, 0, w, h, col); surface.SetDrawColor(C_BDR); surface.DrawOutlinedRect(0, 0, w, h, 1); draw.SimpleText(v[1], "DermaDefault", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) end
        btn.DoClick = function() SetCameraAngle(v[2]) end
        btn.PerformLayout = function(s, w, h)
            local bs = (k == 2) and 20 or 10
            local bw = (viewButtons:GetWide() - 40) / 3
            btn:SetSize(bw, 30)
            btn:SetPos(10 + (k-1)*(bw+10), 10)
        end
        btn:SetText("")
    end

    local HoveredItemName = nil
    local HoveredItemDesc = nil

    local tooltipPanel = vgui.Create("DPanel", frame)
    tooltipPanel:SetSize(280, 100)
    tooltipPanel:SetDrawOnTop(true)
    tooltipPanel:SetMouseInputEnabled(false)
    tooltipPanel:SetAlpha(0)
    tooltipPanel.Paint = function(s, w, h)
        draw.RoundedBox(0, 0, 0, w, h, C_ARMA_TOOLTIP_BG)
        surface.SetDrawColor(C_ARMA_SEL)
        surface.DrawRect(0, 0, w, 3)
        if HoveredItemName then draw.SimpleText(HoveredItemName, "DermaDefaultBold", 10, 12, C_ARMA_SEL, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP) end
        if HoveredItemDesc then draw.DrawText(HoveredItemDesc, "DermaDefault", 10, 35, C_ARMA_TEXT, TEXT_ALIGN_LEFT) end
    end
    tooltipPanel.Think = function(s)
        if HoveredItemName then
            s:SetAlpha(math.Clamp(s:GetAlpha() + FrameTime() * 1500, 0, 255))
            local mx, my = gui.MousePos()
            local fx, fy = frame:GetPos()
            s:SetPos(mx - fx + 15, my - fy + 15)
            local _, lineCount = string.gsub(HoveredItemDesc or "", "\n", "")
            s:SetTall(50 + (lineCount * 16))
        else
            s:SetAlpha(math.Clamp(s:GetAlpha() - FrameTime() * 1500, 0, 255))
        end
    end

    local settingsPanel = vgui.Create("DPanel", frame)
    settingsPanel:SetPos(rightX, 60)
    settingsPanel:SetSize(rightW, fH - 80)
    settingsPanel.Paint = function(s, w, h)
        draw.RoundedBox(6, 0, 0, w, h, C_BG_M)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
    end

    local settingsScroll = vgui.Create("DScrollPanel", settingsPanel)
    settingsScroll:Dock(FILL)
    settingsScroll:DockMargin(10, 10, 10, 55) 
    
    local sbar = settingsScroll:GetVBar()
    sbar:SetWide(4)
    sbar.Paint = function() end
    sbar.btnGrip.Paint = function(s, w, h) draw.RoundedBox(0, 0, 0, w, h, Color(100, 100, 100, 100)) end
    sbar.btnUp.Paint = function() end
    sbar.btnDown.Paint = function() end

    local baseCellSize = 108 

    local bgMainHeaderLabel = vgui.Create("DLabel", settingsScroll)
    bgMainHeaderLabel:Dock(TOP)
    bgMainHeaderLabel:DockMargin(22, 0, 30, 15)
    bgMainHeaderLabel:SetTall(20)
    bgMainHeaderLabel:SetText("РЕДАКТИРОВАНИЕ БОДИГРУПП")
    bgMainHeaderLabel:SetFont("DermaDefaultBold")
    bgMainHeaderLabel:SetTextColor(C_ARMA_SEL)

    if table.Count(bodygroups) > 0 then
        local bgArray = {}
        for idx, data in pairs(bodygroups) do table.insert(bgArray, data) end
        table.sort(bgArray, function(a, b) return a.index < b.index end)

        for _, data in ipairs(bgArray) do
            local idx = data.index
            local bgName = string.lower(data.name)
            
            local allowedValues = {}
            local blockedForModel = WARDROBE_BLOCKED_BGS[string.lower(model)] or {}
            for i = 0, data.count - 1 do
                local isBlocked = false
                
                if not (unlockedBodygroups[tostring(idx)] and unlockedBodygroups[tostring(idx)][tostring(i)]) then
                    for _, blockData in ipairs(blockedForModel) do
                        if blockData[1] == idx and blockData[2] == i then
                            if isfunction(blockData[3]) then
                                if not blockData[3](LocalPlayer()) then
                                    isBlocked = true
                                end
                            else
                                isBlocked = true
                            end
                            break
                        end
                    end
                end
                
                if not isBlocked then
                    table.insert(allowedValues, i)
                end
            end
            
            if #allowedValues == 0 then continue end
            
            local bgPanel = vgui.Create("DPanel", settingsScroll)
            bgPanel:Dock(TOP)
            bgPanel:DockMargin(10, 5, 30, 10) 
            bgPanel.Expanded = true
            local panelExpandedHeight = 25 + baseCellSize
            bgPanel.CurHeight = panelExpandedHeight
            bgPanel:SetTall(panelExpandedHeight)
            bgPanel.Paint = function(s, w, h) end
            bgPanel.Think = function(s)
                local targetHeight = s.Expanded and panelExpandedHeight or 25
                if s.CurHeight ~= targetHeight then
                    s.CurHeight = Lerp(FrameTime() * 15, s.CurHeight, targetHeight)
                    if math.abs(s.CurHeight - targetHeight) < 0.5 then s.CurHeight = targetHeight end
                    s:SetTall(math.Round(s.CurHeight))
                end
            end

            local headerBtn = vgui.Create("DButton", bgPanel)
            headerBtn:SetPos(22, 0)
            headerBtn:SetSize(336, 25)
            headerBtn:SetText("")
            headerBtn.Paint = function(s, w, h)
                local col = s:IsHovered() and Color(255, 255, 255) or Color(200, 200, 200)
                draw.SimpleText(string.upper(data.name), "DermaDefaultBold", 0, h/2, col, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
                draw.SimpleText(bgPanel.Expanded and "▼" or "◀", "DermaDefault", w, h/2, col, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER)
            end
            headerBtn.DoClick = function(s)
                bgPanel.Expanded = not bgPanel.Expanded
                surface.PlaySound("UI/buttonclick.wav")
            end

            local carouselPanel = vgui.Create("DPanel", bgPanel)
            carouselPanel:SetPos(22, 25)
            carouselPanel:SetSize(336, baseCellSize)
            carouselPanel.Paint = function() end
            
            local startScrollIdx = 0
            for k, v in ipairs(allowedValues) do
                if v == (currentBodygroups[idx] or 0) then
                    startScrollIdx = k - 1
                    break
                end
            end
            
            carouselPanel.TargetScroll = startScrollIdx
            carouselPanel.CurScroll = carouselPanel.TargetScroll

            local leftBtn = vgui.Create("DButton", bgPanel)
            leftBtn:SetPos(0, 25)
            leftBtn:SetSize(16, baseCellSize)
            leftBtn:SetText("")
            leftBtn.Paint = function(s, w, h)
                local col = s:IsHovered() and C_ARMA_SLOT_HOVER or C_ARMA_SLOT_EMPTY
                draw.RoundedBox(0, 0, 0, w, h, col)
                draw.SimpleText("<", "DermaDefaultBold", w/2, h/2, s:IsHovered() and C_ARMA_SEL or Color(150, 150, 150), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                surface.SetDrawColor(Color(0, 0, 0, 120))
                surface.DrawOutlinedRect(0, 0, w, h, 1)
            end

            local rightBtn = vgui.Create("DButton", bgPanel)
            rightBtn:SetPos(364, 25)
            rightBtn:SetSize(16, baseCellSize)
            rightBtn:SetText("")
            rightBtn.Paint = function(s, w, h)
                local col = s:IsHovered() and C_ARMA_SLOT_HOVER or C_ARMA_SLOT_EMPTY
                draw.RoundedBox(0, 0, 0, w, h, col)
                draw.SimpleText(">", "DermaDefaultBold", w/2, h/2, s:IsHovered() and C_ARMA_SEL or Color(150, 150, 150), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                surface.SetDrawColor(Color(0, 0, 0, 120))
                surface.DrawOutlinedRect(0, 0, w, h, 1)
            end

            local maxScroll = math.max(0, #allowedValues - 1)

            leftBtn.DoClick = function()
                carouselPanel.TargetScroll = math.max(0, carouselPanel.TargetScroll - 1)
                surface.PlaySound("UI/buttonclick.wav")
            end

            rightBtn.DoClick = function()
                carouselPanel.TargetScroll = math.min(maxScroll, carouselPanel.TargetScroll + 1)
                surface.PlaySound("UI/buttonclick.wav")
            end

            local cells = {}
            for scrollIdx, val in ipairs(allowedValues) do
                local i = val 
                local cell = vgui.Create("DButton", carouselPanel)
                cell:SetText("")
                
                cell.isBodygroup = true
                cell.bgIdx = idx
                cell.bgVal = i
                cell:Droppable("wardrobe_item")
                
                cell.OnCursorEntered = function(s)
                    HoveredItemName = CUSTOM_NAMES_BG[bgName] and CUSTOM_NAMES_BG[bgName][i] or (string.upper(bgName) .. " #" .. i)
                    HoveredItemDesc = CUSTOM_DESC_BG[bgName] and CUSTOM_DESC_BG[bgName][i] or "Дополнительная экипировка.\n\n0.5kg"
                end
                cell.OnCursorExited = function(s) HoveredItemName = nil; HoveredItemDesc = nil end
                
                cell.DoClick = function(s)
                    currentBodygroups[idx] = i
                    carouselPanel.TargetScroll = scrollIdx - 1
                    surface.PlaySound("UI/buttonclick.wav")
                end
                
                cell.Paint = function(s, w, h)
                    local isSelected = (currentBodygroups[idx] or 0) == i
                    local bgColor = C_ARMA_SLOT
                    
                    if isSelected then bgColor = C_ARMA_SEL
                    elseif s:IsHovered() then bgColor = C_ARMA_SLOT_HOVER end
                    
                    local alphaMult = math.Clamp(1 - (s.AbsOffset or 0) * 0.35, 0.2, 1)
                    if s:IsDragging() then surface.SetDrawColor(255, 255, 255, 20); surface.DrawRect(0, 0, w, h); return end
                    
                    surface.SetDrawColor(bgColor.r, bgColor.g, bgColor.b, bgColor.a * alphaMult)
                    surface.DrawRect(0, 0, w, h)
                    
                    local iconData = CUSTOM_ICONS_BG[bgName]
                    local customIcon = iconData and (iconData[i] or iconData.default)
                    
                    if customIcon and not customIcon:IsError() then
                        surface.SetDrawColor(255, 255, 255, 255 * alphaMult)
                        surface.SetMaterial(customIcon)
                        surface.DrawTexturedRect(4, 4, w - 8, h - 8)
                    else
                        local txtColor = isSelected and Color(40, 40, 40, 255 * alphaMult) or Color(150, 150, 150, 255 * alphaMult)
                        draw.SimpleText(tostring(i), "DermaLarge", w/2, h/2, txtColor, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                    end
                    
                    surface.SetDrawColor(0, 0, 0, 120 * alphaMult)
                    surface.DrawOutlinedRect(0, 0, w, h, 1)
                end
                
                table.insert(cells, cell)
            end

            carouselPanel.Think = function(s)
                s.CurScroll = Lerp(FrameTime() * 12, s.CurScroll, s.TargetScroll)
                for i, cell in ipairs(cells) do
                    local index = i - 1
                    local offset = index - s.CurScroll
                    local absOffset = math.abs(offset)
                    
                    cell.AbsOffset = absOffset
                    local scale = math.Clamp(1 - absOffset * 0.25, 0.5, 1)
                    local size = baseCellSize * scale
                    local spacing = 65 
                    local x = (s:GetWide() / 2) - (size / 2) + (offset * spacing)
                    local y = (s:GetTall() / 2) - (size / 2)
                    
                    cell:SetSize(size, size)
                    cell:SetPos(x, y)
                    cell:SetZPos(100 - math.floor(absOffset * 10))
                end
            end
        end
    end

    if #availableSkins > 1 then
        local skinPanel = vgui.Create("DPanel", settingsScroll)
        skinPanel:Dock(TOP)
        skinPanel:DockMargin(10, 5, 30, 10)
        skinPanel.Expanded = true
        local panelExpandedHeight = 25 + baseCellSize
        skinPanel.CurHeight = panelExpandedHeight
        skinPanel:SetTall(panelExpandedHeight)
        skinPanel.Paint = function(s, w, h) end
        skinPanel.Think = function(s)
            local targetHeight = s.Expanded and panelExpandedHeight or 25
            if s.CurHeight ~= targetHeight then
                s.CurHeight = Lerp(FrameTime() * 15, s.CurHeight, targetHeight)
                if math.abs(s.CurHeight - targetHeight) < 0.5 then s.CurHeight = targetHeight end
                s:SetTall(math.Round(s.CurHeight))
            end
        end

        local headerBtn = vgui.Create("DButton", skinPanel)
        headerBtn:SetPos(22, 0)
        headerBtn:SetSize(336, 25)
        headerBtn:SetText("")
        headerBtn.Paint = function(s, w, h)
            local col = s:IsHovered() and Color(255, 255, 255) or Color(200, 200, 200)
            draw.SimpleText("ВАРИАНТ КАМУФЛЯЖА", "DermaDefaultBold", 0, h/2, col, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
            draw.SimpleText(skinPanel.Expanded and "▼" or "◀", "DermaDefault", w, h/2, col, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER)
        end
        headerBtn.DoClick = function(s)
            skinPanel.Expanded = not skinPanel.Expanded
            surface.PlaySound("UI/buttonclick.wav")
        end

        local carouselPanel = vgui.Create("DPanel", skinPanel)
        carouselPanel:SetPos(22, 25)
        carouselPanel:SetSize(336, baseCellSize)
        carouselPanel.Paint = function() end
        carouselPanel.TargetScroll = currentSkin or 0
        carouselPanel.CurScroll = carouselPanel.TargetScroll

        local leftBtn = vgui.Create("DButton", skinPanel)
        leftBtn:SetPos(0, 25); leftBtn:SetSize(16, baseCellSize); leftBtn:SetText("")
        leftBtn.Paint = function(s, w, h)
            local col = s:IsHovered() and C_ARMA_SLOT_HOVER or C_ARMA_SLOT_EMPTY
            draw.RoundedBox(0, 0, 0, w, h, col)
            draw.SimpleText("<", "DermaDefaultBold", w/2, h/2, s:IsHovered() and C_ARMA_SEL or Color(150, 150, 150), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
            surface.SetDrawColor(Color(0, 0, 0, 120)); surface.DrawOutlinedRect(0, 0, w, h, 1)
        end

        local rightBtn = vgui.Create("DButton", skinPanel)
        rightBtn:SetPos(364, 25); rightBtn:SetSize(16, baseCellSize); rightBtn:SetText("")
        rightBtn.Paint = function(s, w, h)
            local col = s:IsHovered() and C_ARMA_SLOT_HOVER or C_ARMA_SLOT_EMPTY
            draw.RoundedBox(0, 0, 0, w, h, col)
            draw.SimpleText(">", "DermaDefaultBold", w/2, h/2, s:IsHovered() and C_ARMA_SEL or Color(150, 150, 150), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
            surface.SetDrawColor(Color(0, 0, 0, 120)); surface.DrawOutlinedRect(0, 0, w, h, 1)
        end

        local maxScroll = math.max(0, #availableSkins - 1)

        leftBtn.DoClick = function()
            carouselPanel.TargetScroll = math.max(0, carouselPanel.TargetScroll - 1)
            surface.PlaySound("UI/buttonclick.wav")
        end

        rightBtn.DoClick = function()
            carouselPanel.TargetScroll = math.min(maxScroll, carouselPanel.TargetScroll + 1)
            surface.PlaySound("UI/buttonclick.wav")
        end

        local cells = {}
        for i = 0, #availableSkins - 1 do
            local cell = vgui.Create("DButton", carouselPanel)
            cell:SetText("")
            
            cell.isSkin = true
            cell.skinVal = i
            cell:Droppable("wardrobe_item")
            
            cell.OnCursorEntered = function(s) HoveredItemName = CUSTOM_NAMES_SKIN[i] or ("Текстура #" .. i); HoveredItemDesc = CUSTOM_DESC_SKIN[i] or "Альтернативный паттерн экипировки." end
            cell.OnCursorExited = function(s) HoveredItemName = nil; HoveredItemDesc = nil end
            
            cell.DoClick = function(s)
                currentSkin = i
                carouselPanel.TargetScroll = i
                surface.PlaySound("UI/buttonclick.wav")
            end
            
            cell.Paint = function(s, w, h)
                local isSelected = currentSkin == i
                local bgColor = C_ARMA_SLOT
                
                if isSelected then bgColor = C_ARMA_SEL elseif s:IsHovered() then bgColor = C_ARMA_SLOT_HOVER end
                
                local alphaMult = math.Clamp(1 - (s.AbsOffset or 0) * 0.35, 0.2, 1)
                if s:IsDragging() then surface.SetDrawColor(255, 255, 255, 20); surface.DrawRect(0, 0, w, h); return end
                
                surface.SetDrawColor(bgColor.r, bgColor.g, bgColor.b, bgColor.a * alphaMult)
                surface.DrawRect(0, 0, w, h)
                
                local customIcon = CUSTOM_ICONS_SKIN[i] or CUSTOM_ICONS_SKIN.default
                if customIcon and not customIcon:IsError() then 
                    surface.SetDrawColor(255, 255, 255, 255 * alphaMult)
                    surface.SetMaterial(customIcon)
                    surface.DrawTexturedRect(4, 4, w - 8, h - 8) 
                else 
                    local txtColor = isSelected and Color(40, 40, 40, 255 * alphaMult) or Color(150, 150, 150, 255 * alphaMult)
                    draw.SimpleText(tostring(i), "DermaLarge", w/2, h/2, txtColor, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) 
                end
                
                surface.SetDrawColor(0, 0, 0, 120 * alphaMult)
                surface.DrawOutlinedRect(0, 0, w, h, 1)
            end
            
            table.insert(cells, cell)
        end

        carouselPanel.Think = function(s)
            s.CurScroll = Lerp(FrameTime() * 12, s.CurScroll, s.TargetScroll)
            for i, cell in ipairs(cells) do
                local index = i - 1
                local offset = index - s.CurScroll
                local absOffset = math.abs(offset)
                
                cell.AbsOffset = absOffset
                local scale = math.Clamp(1 - absOffset * 0.25, 0.5, 1)
                local size = baseCellSize * scale
                local spacing = 65 
                local x = (s:GetWide() / 2) - (size / 2) + (offset * spacing)
                local y = (s:GetTall() / 2) - (size / 2)
                
                cell:SetSize(size, size)
                cell:SetPos(x, y)
                cell:SetZPos(100 - math.floor(absOffset * 10))
            end
        end
    end

    local applyBtn = vgui.Create("DButton", settingsPanel)
    local wipeBtn = vgui.Create("DButton", settingsPanel)
    
    wipeBtn:SetSize(135, 35); wipeBtn:SetText("")
    wipeBtn.Paint = function(s, w, h)
        local col = s:IsHovered() and C_WARN_H or C_WARN
        draw.RoundedBox(8, 0, 0, w, h, C_BDR); draw.RoundedBox(8, 2, 2, w-4, h-4, col)
        draw.SimpleText("СБРОСИТЬ", "DermaDefaultBold", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    end
    wipeBtn.DoClick = function() net.Start("SandboxWardrobeApply"); net.WriteBool(true); net.SendToServer(); frame:Close() end

    applyBtn:SetSize(135, 35); applyBtn:SetText("")
    applyBtn.Paint = function(s, w, h)
        local col = s:IsHovered() and C_PRI_H or C_PRI
        draw.RoundedBox(8, 0, 0, w, h, C_BDR); draw.RoundedBox(8, 2, 2, w-4, h-4, col); draw.RoundedBoxEx(8, 2, 2, w-4, h/2-2, C_GRAD, true, true, false, false)
        draw.SimpleText("ПРИМЕНИТЬ", "DermaDefaultBold", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    end
    applyBtn.DoClick = function() net.Start("SandboxWardrobeApply"); net.WriteBool(false); net.WriteTable(currentBodygroups); net.WriteUInt(currentSkin, 8); net.SendToServer(); frame:Close() end

    settingsPanel.PerformLayout = function(s, w, h)
        applyBtn:SetPos(w - 135 - 10, h - 35 - 10)
        wipeBtn:SetPos(w - 135*2 - 20, h - 35 - 10)
    end
end)

-- =====================================================================
-- АДМИН ПАНЕЛЬ
-- =====================================================================
net.Receive("SandboxWardrobeAdminOpen", function()
    local unlockedData = net.ReadTable()
    
    local fW, fH = 800, 600
    local frame = vgui.Create("DFrame")
    frame:SetSize(fW, fH)
    frame:Center()
    frame:SetTitle("")
    frame:ShowCloseButton(false)
    frame:MakePopup()
    frame:SetBackgroundBlur(true)
    frame.Paint = function(s, w, h)
        draw.RoundedBox(8, 0, 0, w, h, C_BG_D)
        surface.SetDrawColor(C_GRAD)
        surface.DrawRect(0, 0, w, 3)
        draw.RoundedBoxEx(8, 0, 0, w, 50, C_BG_M, true, true, false, false)
        surface.SetDrawColor(C_BDR)
        surface.DrawLine(0, 50, w, 50)
        draw.SimpleText("АДМИН ПАНЕЛЬ (ДОСТУП)", "DermaLarge", w/2, 25, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
        surface.SetDrawColor(C_ACC)
        surface.DrawRect(20, 48, 30, 2)
        surface.DrawRect(w-50, 48, 30, 2)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
    end
    
    local closeBtn = vgui.Create("DButton", frame)
    closeBtn:SetPos(frame:GetWide() - 40, 10)
    closeBtn:SetSize(30, 30)
    closeBtn:SetText("")
    closeBtn.Paint = function(s, w, h)
        local col = s:IsHovered() and C_ACC_H or C_ACC
        draw.RoundedBox(4, 0, 0, w, h, col)
        draw.SimpleText("X", "DermaLarge", w/2, h/2-2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    end
    closeBtn.DoClick = function() frame:Close() end
    
    local leftPanel = vgui.Create("DPanel", frame)
    leftPanel:SetPos(20, 60)
    leftPanel:SetSize(230, fH - 80)
    leftPanel.Paint = function(s, w, h)
        draw.RoundedBox(6, 0, 0, w, h, C_BG_M)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
    end
    
    local plyList = vgui.Create("DListView", leftPanel)
    plyList:Dock(FILL)
    plyList:DockMargin(10, 10, 10, 10)
    plyList:AddColumn("Игрок")
    plyList.Paint = function(s, w, h)
        draw.RoundedBox(4, 0, 0, w, h, C_BG_D)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
    end
    
    local function FormatLine(line)
        for _, col in pairs(line.Columns) do 
            col:SetTextColor(C_WHITE)
            col:SetFont("DermaDefaultBold")
        end
        line.Paint = function(s, w, h)
            local col = C_BG_M
            if s:IsSelected() then col = C_PRI
            elseif s:IsHovered() then col = C_BG_L end
            draw.RoundedBox(0, 0, 0, w, h, col)
            surface.SetDrawColor(C_BDR)
            surface.DrawOutlinedRect(0, 0, w, h, 1)
        end
    end
    
    local manualBtn = vgui.Create("DButton", leftPanel)
    manualBtn:Dock(BOTTOM)
    manualBtn:DockMargin(10, 0, 10, 10)
    manualBtn:SetTall(30)
    manualBtn:SetText("")
    manualBtn.Paint = function(s, w, h)
        local col = s:IsHovered() and C_PRI_H or C_PRI
        draw.RoundedBox(4, 0, 0, w, h, col)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
        draw.SimpleText("ДОБАВИТЬ ID", "DermaDefault", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    end
    manualBtn.DoClick = function()
        Derma_StringRequest("Оффлайн игрок", "SteamID64:", "", function(text)
            if string.len(text) == 17 then
                local line = plyList:AddLine("Оффлайн ("..text..")")
                FormatLine(line)
                line.sid = text
                line.mdl = "models/cwz/characters/mason_pm.mdl"
            end
        end)
    end

    local selectedSid = nil
    
    local rightPanel = vgui.Create("DPanel", frame)
    rightPanel:SetPos(260, 60)
    rightPanel:SetSize(fW - 280, fH - 80)
    rightPanel.Paint = function(s, w, h)
        draw.RoundedBox(6, 0, 0, w, h, C_BG_M)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
    end
    
    local topRow = vgui.Create("DPanel", rightPanel)
    topRow:Dock(TOP)
    topRow:SetTall(45)
    topRow:DockMargin(10, 10, 10, 0)
    topRow.Paint = function() end
    
    local modelEntry = vgui.Create("DTextEntry", topRow)
    modelEntry:Dock(FILL)
    modelEntry:DockMargin(0, 0, 10, 15)
    modelEntry:SetPlaceholderText(" Путь к модели (напр. models/cwz/characters/mason_pm.mdl)")
    modelEntry.Paint = function(s, w, h)
        draw.RoundedBox(4, 0, 0, w, h, C_BG_D)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
        s:DrawTextEntryText(C_WHITE, C_ACC, C_WHITE)
    end
    
    local loadBtn = vgui.Create("DButton", topRow)
    loadBtn:Dock(RIGHT)
    loadBtn:SetWide(100)
    loadBtn:DockMargin(0, 0, 0, 15)
    loadBtn:SetText("")
    loadBtn.Paint = function(s, w, h)
        local col = s:IsHovered() and C_PRI_H or C_PRI
        draw.RoundedBox(4, 0, 0, w, h, col)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
        draw.SimpleText("ОБНОВИТЬ", "DermaDefault", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    end
    
    local bgScroll = vgui.Create("DScrollPanel", rightPanel)
    bgScroll:Dock(FILL)
    bgScroll:DockMargin(10, 0, 10, 10)
    
    local sbar = bgScroll:GetVBar()
    sbar:SetWide(4)
    sbar.Paint = function() end
    sbar.btnGrip.Paint = function(s, w, h) draw.RoundedBox(0, 0, 0, w, h, Color(100, 100, 100, 100)) end
    sbar.btnUp.Paint = function() end
    sbar.btnDown.Paint = function() end

    local function LoadModelBGs(modelSearch)
        bgScroll:Clear()
        if not modelSearch or modelSearch == "" then return end
        
        local sidData = unlockedData[selectedSid] or {}
        local modelData = sidData[string.lower(modelSearch)] or {}
        
        local blockedForModel = WARDROBE_BLOCKED_BGS[string.lower(modelSearch)]
        if not blockedForModel or table.IsEmpty(blockedForModel) then
            local err = bgScroll:Add("DLabel")
            err:SetText(" Для этой модели нет заблокированных бодигрупп в настройках.")
            err:SetTextColor(C_WARN)
            err:SetFont("DermaDefaultBold")
            err:SizeToContents()
            err:Dock(TOP)
            return
        end
        
        for _, blockData in ipairs(blockedForModel) do
            local bg_id = blockData[1]
            local bg_val = blockData[2]
            local str_bg_id = tostring(bg_id)
            local str_bg_val = tostring(bg_val)
            local bg_name = blockData[4] or ("Бодигруппа " .. bg_id .. " Вариант " .. bg_val)
            
            local linePnl = vgui.Create("DPanel", bgScroll)
            linePnl:Dock(TOP)
            linePnl:SetTall(35)
            linePnl:DockMargin(0, 5, 10, 5)
            linePnl.Paint = function(s, w, h)
                draw.RoundedBox(4, 0, 0, w, h, C_BG_D)
                surface.SetDrawColor(C_BDR)
                surface.DrawOutlinedRect(0, 0, w, h, 1)
            end
            
            local lbl = vgui.Create("DLabel", linePnl)
            lbl:Dock(LEFT)
            lbl:DockMargin(10, 0, 0, 0)
            lbl:SetWide(300)
            lbl:SetText(bg_name)
            lbl:SetFont("DermaDefaultBold")
            lbl:SetTextColor(C_WHITE)
            
            local lockBtn = vgui.Create("DButton", linePnl)
            lockBtn:Dock(RIGHT)
            lockBtn:SetWide(100)
            lockBtn:DockMargin(0, 5, 5, 5)
            lockBtn:SetText("")
            
            local isUnlocked = (modelData[str_bg_id] and modelData[str_bg_id][str_bg_val]) and true or false
            lockBtn.IsUnlocked = isUnlocked
            
            lockBtn.Paint = function(s, w, h)
                local col = s.IsUnlocked and C_PRI or C_WARN
                if s:IsHovered() then
                    col = s.IsUnlocked and C_PRI_H or C_WARN_H
                end
                draw.RoundedBox(4, 0, 0, w, h, col)
                draw.SimpleText(s.IsUnlocked and "ОТКРЫТ" or "ЗАКРЫТ", "DermaDefaultBold", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
            end
            lockBtn.DoClick = function(s)
                s.IsUnlocked = not s.IsUnlocked
                
                unlockedData[selectedSid] = unlockedData[selectedSid] or {}
                unlockedData[selectedSid][string.lower(modelSearch)] = unlockedData[selectedSid][string.lower(modelSearch)] or {}
                unlockedData[selectedSid][string.lower(modelSearch)][str_bg_id] = unlockedData[selectedSid][string.lower(modelSearch)][str_bg_id] or {}
                unlockedData[selectedSid][string.lower(modelSearch)][str_bg_id][str_bg_val] = s.IsUnlocked and true or nil
                
                net.Start("SandboxWardrobeAdminUpdate")
                net.WriteString(selectedSid)
                net.WriteString(modelSearch)
                net.WriteUInt(bg_id, 8)
                net.WriteUInt(bg_val, 8)
                net.WriteBool(s.IsUnlocked)
                net.SendToServer()
                
                surface.PlaySound("UI/buttonclick.wav")
            end
        end
    end
    
    for _, ply in ipairs(player.GetAll()) do
        local line = plyList:AddLine(ply:Nick())
        FormatLine(line)
        line.sid = ply:SteamID64()
        line.mdl = ply:GetModel()
    end
    
    plyList.OnRowSelected = function(lst, index, pnl)
        selectedSid = pnl.sid
        modelEntry:SetText(pnl.mdl or "")
        LoadModelBGs(pnl.mdl)
    end
    
    loadBtn.DoClick = function()
        if not selectedSid then return end
        LoadModelBGs(modelEntry:GetText())
    end
end)

-- =====================================================================
-- ПАНЕЛЬ КОМАНДИРА
-- =====================================================================

local C_CMD = Color(40, 75, 120)
local C_CMD_H = Color(50, 90, 140)
local C_CMD_SEL = Color(70, 130, 180)

net.Receive("SandboxWardrobeCommanderOpen", function()
    local membersData = net.ReadTable()
    
    local scrW, scrH = ScrW(), ScrH()
    local fW = math.Clamp(scrW * 0.65, 1000, 1600)
    local fH = math.Clamp(scrH * 0.65, 650, 1000)
    
    local frame = vgui.Create("DFrame")
    frame:SetSize(fW, fH)
    frame:Center()
    frame:SetTitle("")
    frame:ShowCloseButton(false)
    frame:MakePopup()
    frame:SetBackgroundBlur(true)
    frame.Paint = function(s, w, h)
        draw.RoundedBox(8, 0, 0, w, h, C_BG_D)
        surface.SetDrawColor(C_GRAD)
        surface.DrawRect(0, 0, w, 3)
        draw.RoundedBoxEx(8, 0, 0, w, 50, C_BG_M, true, true, false, false)
        surface.SetDrawColor(C_BDR)
        surface.DrawLine(0, 50, w, 50)
        draw.SimpleText("ПАНЕЛЬ КОМАНДИРА", "DermaLarge", w/2, 25, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
        surface.SetDrawColor(C_CMD)
        surface.DrawRect(20, 48, 30, 2)
        surface.DrawRect(w - 50, 48, 30, 2)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
    end
    
    local closeBtn = vgui.Create("DButton", frame)
    closeBtn:SetPos(frame:GetWide() - 40, 10)
    closeBtn:SetSize(30, 30)
    closeBtn:SetText("")
    closeBtn.Paint = function(s, w, h)
        local col = s:IsHovered() and C_ACC_H or C_ACC
        draw.RoundedBox(4, 0, 0, w, h, col)
        draw.SimpleText("X", "DermaLarge", w/2, h/2 - 2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    end
    closeBtn.DoClick = function() frame:Close() end

    -- Предварительное объявление локальных функций для перестроения интерфейса
    local selectedMember = nil
    local cmdCurrentBodygroups = {}
    local cmdCurrentSkin = 0
    local cmdModel = ""
    local cmdBodygroups = {}
    local cmdAvailableSkins = {}
    
    local RebuildSettings
    local RebuildCommanderPresets
    
    -- === ЛЕВАЯ ПАНЕЛЬ: СПИСОК ПОДРАЗДЕЛЕНИЯ И СБОРКИ ===
    local leftW = 230
    local leftContainer = vgui.Create("DPanel", frame)
    leftContainer:SetPos(20, 60)
    leftContainer:SetSize(leftW, fH - 80)
    leftContainer.Paint = function() end
    
    local squadPanel = vgui.Create("DPanel", leftContainer)
    squadPanel:Dock(FILL)
    squadPanel.Paint = function(s, w, h)
        draw.RoundedBox(6, 0, 0, w, h, C_BG_M)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
    end
    
    local squadLabel = vgui.Create("DLabel", squadPanel)
    squadLabel:Dock(TOP)
    squadLabel:DockMargin(10, 10, 10, 5)
    squadLabel:SetTall(20)
    squadLabel:SetText("ПОДРАЗДЕЛЕНИЕ")
    squadLabel:SetFont("DermaDefaultBold")
    squadLabel:SetTextColor(C_CMD_SEL)
    
    local memberList = vgui.Create("DListView", squadPanel)
    memberList:Dock(FILL)
    memberList:DockMargin(10, 5, 10, 10)
    memberList:AddColumn("Боец")
    memberList.Paint = function(s, w, h)
        draw.RoundedBox(4, 0, 0, w, h, C_BG_D)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
    end
    
    local function FormatMemberLine(line)
        for _, col in pairs(line.Columns) do
            col:SetTextColor(C_WHITE)
            col:SetFont("DermaDefaultBold")
        end
        line.Paint = function(s, w, h)
            local col = C_BG_M
            if s:IsSelected() then col = C_CMD
            elseif s:IsHovered() then col = C_BG_L end
            draw.RoundedBox(0, 0, 0, w, h, col)
            surface.SetDrawColor(C_BDR)
            surface.DrawOutlinedRect(0, 0, w, h, 1)
        end
    end
    
    if #membersData == 0 then
        local emptyLbl = vgui.Create("DLabel", squadPanel)
        emptyLbl:Dock(TOP)
        emptyLbl:DockMargin(10, 10, 10, 0)
        emptyLbl:SetTall(40)
        emptyLbl:SetText("Нет бойцов\nв подразделении")
        emptyLbl:SetFont("DermaDefault")
        emptyLbl:SetTextColor(Color(120, 120, 120))
        emptyLbl:SetWrap(true)
    end
    
    for _, data in ipairs(membersData) do
        local line = memberList:AddLine(data.nick)
        FormatMemberLine(line)
        line.memberData = data
    end

    -- === ПАНЕЛЬ СБОРОК КОМАНДИРА ===
    local presetsPanel = vgui.Create("DPanel", leftContainer)
    presetsPanel:Dock(BOTTOM)
    presetsPanel:DockMargin(0, 10, 0, 0)
    presetsPanel.Expanded = false
    presetsPanel.CurHeight = 35
    presetsPanel:SetTall(35)
    presetsPanel.Paint = function(s, w, h)
        draw.RoundedBox(6, 0, 0, w, h, C_BG_M)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
    end
    presetsPanel.Think = function(s)
        local maxH = fH - 80 - 150 -- Резервируем хотя бы 150px для списка бойцов
        local targetHeight = s.Expanded and maxH or 35
        if s.CurHeight ~= targetHeight then
            s.CurHeight = Lerp(FrameTime() * 15, s.CurHeight, targetHeight)
            if math.abs(s.CurHeight - targetHeight) < 0.5 then s.CurHeight = targetHeight end
            s:SetTall(math.Round(s.CurHeight))
        end
    end

    local presetsHeader = vgui.Create("DButton", presetsPanel)
    presetsHeader:Dock(TOP)
    presetsHeader:SetTall(35)
    presetsHeader:SetText("")
    presetsHeader.Paint = function(s, w, h)
        local col = s:IsHovered() and C_BG_L or C_BG_D
        draw.RoundedBoxEx(6, 0, 0, w, h, col, true, true, not presetsPanel.Expanded, not presetsPanel.Expanded)
        surface.SetDrawColor(C_CMD)
        surface.DrawRect(0, 0, 3, h)
        draw.SimpleText("СБОРКИ", "DermaLarge", 10, h/2, C_TXT_P, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
        draw.SimpleText(presetsPanel.Expanded and "▼" or "◀", "DermaDefault", w - 15, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    end
    presetsHeader.DoClick = function(s) presetsPanel.Expanded = not presetsPanel.Expanded; surface.PlaySound("UI/buttonclick.wav") end

    local presetsContent = vgui.Create("DScrollPanel", presetsPanel)
    presetsContent:Dock(FILL)

    RebuildCommanderPresets = function()
        presetsContent:Clear()
        if not selectedMember or cmdModel == "" then return end
        
        local allPresets = {}
        if file.Exists("wardrobe_presets.txt", "DATA") then allPresets = util.JSONToTable(file.Read("wardrobe_presets.txt", "DATA")) or {} end
        if not allPresets[cmdModel] then allPresets[cmdModel] = {} end

        local py = 10
        for i = 1, 10 do
            local slotPanel = vgui.Create("DPanel", presetsContent)
            slotPanel:SetPos(10, py)
            slotPanel:SetSize(200, 85)
            slotPanel.Paint = function(s, w, h)
                draw.RoundedBox(4, 0, 0, w, h, C_BG_D)
                surface.SetDrawColor(C_BDR)
                surface.DrawOutlinedRect(0, 0, w, h, 1)
            end

            local pData = allPresets[cmdModel][i] or allPresets[cmdModel][tostring(i)]
            local hasData = pData ~= nil
            local defaultName = "Сборка " .. i

            local iconCell = vgui.Create("DPanel", slotPanel)
            iconCell:SetPos(130, 12)
            iconCell:SetSize(60, 60)
            iconCell.Paint = function(s, w, h)
                local curData = allPresets[cmdModel][tostring(i)]
                local isFilled = curData ~= nil
                
                draw.RoundedBox(4, 0, 0, w, h, isFilled and C_ARMA_SLOT or C_ARMA_SLOT_EMPTY)
                
                if isFilled then
                    local mat = Material("wardrobe_ui/body.png", "noclamp smooth")
                    if mat and not mat:IsError() then
                        surface.SetDrawColor(255, 255, 255, 200)
                        surface.SetMaterial(mat)
                        surface.DrawTexturedRect(5, 5, w-10, h-10)
                    end
                    surface.SetDrawColor(C_CMD)
                    surface.DrawOutlinedRect(0, 0, w, h, 1)
                else
                    draw.SimpleText("ПУСТО", "DermaDefault", w/2, h/2, Color(100, 100, 100), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                    surface.SetDrawColor(Color(0,0,0,100))
                    surface.DrawOutlinedRect(0, 0, w, h, 1)
                end
            end

            local nameEntry = vgui.Create("DTextEntry", slotPanel)
            nameEntry:SetPos(10, 12)
            nameEntry:SetSize(110, 25)
            nameEntry:SetText(hasData and (pData.name or defaultName) or defaultName)
            nameEntry.Paint = function(s, w, h)
                draw.RoundedBox(4, 0, 0, w, h, C_BG_M)
                surface.SetDrawColor(s:IsEditing() and C_CMD or C_BDR)
                surface.DrawOutlinedRect(0, 0, w, h, 1)
                s:DrawTextEntryText(C_WHITE, C_CMD, C_WHITE)
            end
            nameEntry.OnChange = function(s)
                local curData = allPresets[cmdModel][tostring(i)]
                if curData then
                    curData.name = s:GetText()
                    file.Write("wardrobe_presets.txt", util.TableToJSON(allPresets))
                end
            end

            local btnW = 33
            local btnY = 47

            local loadBtn = vgui.Create("DButton", slotPanel)
            loadBtn:SetPos(10, btnY)
            loadBtn:SetSize(btnW, 25)
            loadBtn:SetText("")
            loadBtn.Paint = function(s, w, h)
                if not allPresets[cmdModel][tostring(i)] then
                    draw.RoundedBox(4, 0, 0, w, h, Color(30, 30, 30, 150))
                    draw.SimpleText("ЗАГР", "DermaDefault", w/2, h/2, Color(100, 100, 100), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                    return
                end
                local col = s:IsHovered() and C_CMD_H or C_CMD
                draw.RoundedBox(4, 0, 0, w, h, col)
                draw.SimpleText("ЗАГР", "DermaDefault", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
            end
            loadBtn.DoClick = function()
                local curData = allPresets[cmdModel][tostring(i)]
                if not curData then return end
                for idx, val in pairs(curData.bgs) do cmdCurrentBodygroups[tonumber(idx) or idx] = val end
                if curData.skin then cmdCurrentSkin = curData.skin end
                surface.PlaySound("buttons/button15.wav")
                -- Обновляем правую панель чтобы отразить загруженный пресет
                RebuildSettings()
            end

            local saveBtn = vgui.Create("DButton", slotPanel)
            saveBtn:SetPos(48, btnY)
            saveBtn:SetSize(btnW, 25)
            saveBtn:SetText("")
            saveBtn.Paint = function(s, w, h)
                local col = s:IsHovered() and C_CMD_H or C_CMD
                draw.RoundedBox(4, 0, 0, w, h, col)
                draw.SimpleText("СОХР", "DermaDefault", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
            end
            saveBtn.DoClick = function()
                local finalName = nameEntry:GetText()
                if finalName == "" then finalName = defaultName end
                local safeBGs = {}
                for k, v in pairs(cmdCurrentBodygroups) do safeBGs[tostring(k)] = v end
                allPresets[cmdModel][tostring(i)] = {
                    name = finalName,
                    bgs = safeBGs,
                    skin = cmdCurrentSkin
                }
                file.Write("wardrobe_presets.txt", util.TableToJSON(allPresets))
                surface.PlaySound("buttons/button15.wav")
            end

            local delBtn = vgui.Create("DButton", slotPanel)
            delBtn:SetPos(87, btnY)
            delBtn:SetSize(btnW, 25)
            delBtn:SetText("")
            delBtn.Paint = function(s, w, h)
                if not allPresets[cmdModel][tostring(i)] then
                    draw.RoundedBox(4, 0, 0, w, h, Color(30, 30, 30, 150))
                    draw.SimpleText("УДАЛ", "DermaDefault", w/2, h/2, Color(100, 100, 100), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                    return
                end
                local col = s:IsHovered() and C_WARN_H or C_WARN
                draw.RoundedBox(4, 0, 0, w, h, col)
                draw.SimpleText("УДАЛ", "DermaDefault", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
            end
            delBtn.DoClick = function()
                if allPresets[cmdModel][tostring(i)] then
                    allPresets[cmdModel][tostring(i)] = nil
                    file.Write("wardrobe_presets.txt", util.TableToJSON(allPresets))
                    nameEntry:SetText(defaultName)
                    surface.PlaySound("buttons/button15.wav")
                end
            end

            py = py + 95
        end
    end
    
    -- === ЦЕНТРАЛЬНАЯ ПАНЕЛЬ: МОДЕЛЬ ===
    local rightW = math.Clamp(fW * 0.38, 350, 550)
    local midW = fW - leftW - rightW - 80
    local midX = 40 + leftW
    local rightX = midX + midW + 20
    
    local modelPanel = vgui.Create("DModelPanel", frame)
    modelPanel:SetPos(midX, 60)
    modelPanel:SetSize(midW, fH - 140)
    modelPanel.bModelReady = false
    
    local oldCmdPaint = modelPanel.Paint
    modelPanel.Paint = function(s, w, h)
        if bgMat and not bgMat:IsError() then
            surface.SetDrawColor(255, 255, 255, 255)
            surface.SetMaterial(bgMat)
            surface.DrawTexturedRect(0, 0, w, h)
        end
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
        
        if not selectedMember then
            draw.SimpleText("Выберите бойца", "DermaLarge", w/2, h/2, Color(100, 100, 100), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
        elseif s.bModelReady then
            oldCmdPaint(s, w, h)
        end
    end
    
    modelPanel.camAnims = { zoom = 60, rot = Angle(0, 180, 0), offset = Vector(0, 0, 0) }
    modelPanel.curZoom = 60
    modelPanel.curRot = Angle(0, 180, 0)
    modelPanel.curOffset = Vector(0, 0, 0)
    
    modelPanel.LayoutEntity = function(s, ent)
        if not s.bAnimSet then
            local seq = ent:LookupSequence("idle_subtle")
            if seq <= 0 then seq = ent:LookupSequence("idle_all_01") end
            if seq > 0 then ent:SetSequence(seq) end
            s.bAnimSet = true
        end
        if s.bDragging then
            local x, y = gui.MousePos()
            local dx = x - s.lastX
            local dy = y - s.lastY
            if input.IsKeyDown(KEY_LSHIFT) or input.IsKeyDown(KEY_RSHIFT) then
                local right = s.curRot:Right()
                local up = s.curRot:Up()
                s.camAnims.offset = s.camAnims.offset - right * (dx * 0.15) + up * (dy * 0.15)
            elseif input.IsKeyDown(KEY_LALT) or input.IsKeyDown(KEY_RALT) then
                s.camAnims.rot.yaw = s.camAnims.rot.yaw - dx * 0.8
                s.camAnims.rot.pitch = math.Clamp(s.camAnims.rot.pitch - dy * 0.8, -45, 45)
            end
            s.lastX, s.lastY = x, y
        end
        local speed = FrameTime() * 10
        s.curZoom = Lerp(speed, s.curZoom, s.camAnims.zoom)
        s.curRot = LerpAngle(speed, s.curRot, s.camAnims.rot)
        s.curOffset = LerpVector(speed, s.curOffset, s.camAnims.offset)
        local targetPos = ent:GetPos() + Vector(0, 0, 40) + s.curOffset
        s:SetCamPos(targetPos - s.curRot:Forward() * s.curZoom)
        s:SetLookAng(s.curRot)
        ent:FrameAdvance((RealTime() - (s.lastTick or RealTime())) * 1)
        s.lastTick = RealTime()
    end
    
    modelPanel.OnMousePressed = function(s, code)
        if code == MOUSE_LEFT then
            local clickTime = SysTime()
            if s.lastClickTime and (clickTime - s.lastClickTime) < 0.3 then
                s.camAnims.zoom = 60
                s.camAnims.rot = Angle(0, 180, 0)
                s.camAnims.offset = Vector(0, 0, 0)
                s.lastClickTime = 0
                return
            end
            s.lastClickTime = clickTime
            s.bDragging = true
            s.lastX, s.lastY = gui.MousePos()
        end
    end
    modelPanel.OnMouseReleased = function(s, code) if code == MOUSE_LEFT then s.bDragging = false end end
    modelPanel.OnCursorExited = function(s) s.bDragging = false end
    modelPanel.OnMouseWheeled = function(s, delta) s.camAnims.zoom = math.Clamp(s.camAnims.zoom - delta * 15, 10, 120) end
    
    modelPanel.Think = function(s)
        local entity = s:GetEntity()
        if IsValid(entity) then
            for idx, value in pairs(cmdCurrentBodygroups) do
                if entity:GetBodygroup(idx) ~= value then entity:SetBodygroup(idx, value) end
            end
            if entity:GetSkin() ~= cmdCurrentSkin then entity:SetSkin(cmdCurrentSkin) end
        end
    end
    
    -- === КНОПКИ РАКУРСОВ ===
    local viewButtons = vgui.Create("DPanel", frame)
    viewButtons:SetPos(midX, fH - 70)
    viewButtons:SetSize(midW, 50)
    viewButtons.Paint = function(s, w, h)
        draw.RoundedBox(6, 0, 0, w, h, C_BG_M)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
    end
    
    local angles = {{"СПЕРЕДИ", "front"}, {"СБОКУ", "side"}, {"СЗАДИ", "back"}}
    for k, v in ipairs(angles) do
        local btn = vgui.Create("DButton", viewButtons)
        btn:SetText("")
        btn.Paint = function(s, w, h)
            local col = s:IsHovered() and C_CMD_H or C_CMD
            draw.RoundedBox(4, 0, 0, w, h, col)
            surface.SetDrawColor(C_BDR)
            surface.DrawOutlinedRect(0, 0, w, h, 1)
            draw.SimpleText(v[1], "DermaDefault", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
        end
        btn.DoClick = function()
            if v[2] == "front" then modelPanel.camAnims.rot = Angle(0, 180, 0)
            elseif v[2] == "side" then modelPanel.camAnims.rot = Angle(0, 90, 0)
            elseif v[2] == "back" then modelPanel.camAnims.rot = Angle(0, 0, 0) end
            modelPanel.camAnims.offset = Vector(0, 0, 0)
        end
        btn.PerformLayout = function(s, w, h)
            local bw = (viewButtons:GetWide() - 40) / 3
            btn:SetSize(bw, 30)
            btn:SetPos(10 + (k - 1) * (bw + 10), 10)
        end
    end
    
    -- === ПРАВАЯ ПАНЕЛЬ: НАСТРОЙКИ БОДИГРУПП И СКИНОВ ===
    local settingsPanel = vgui.Create("DPanel", frame)
    settingsPanel:SetPos(rightX, 60)
    settingsPanel:SetSize(rightW, fH - 80)
    settingsPanel.Paint = function(s, w, h)
        draw.RoundedBox(6, 0, 0, w, h, C_BG_M)
        surface.SetDrawColor(C_BDR)
        surface.DrawOutlinedRect(0, 0, w, h, 1)
    end
    
    local settingsScroll = vgui.Create("DScrollPanel", settingsPanel)
    settingsScroll:Dock(FILL)
    settingsScroll:DockMargin(10, 10, 10, 55)
    
    local sbar = settingsScroll:GetVBar()
    sbar:SetWide(4)
    sbar.Paint = function() end
    sbar.btnGrip.Paint = function(s, w, h) draw.RoundedBox(0, 0, 0, w, h, Color(100, 100, 100, 100)) end
    sbar.btnUp.Paint = function() end
    sbar.btnDown.Paint = function() end
    
    local baseCellSize = 108
    
    RebuildSettings = function()
        settingsScroll:Clear()
        
        if not selectedMember then
            local lbl = vgui.Create("DLabel", settingsScroll)
            lbl:Dock(TOP)
            lbl:DockMargin(10, 20, 10, 0)
            lbl:SetTall(30)
            lbl:SetText("Выберите бойца из списка слева")
            lbl:SetFont("DermaDefaultBold")
            lbl:SetTextColor(Color(120, 120, 120))
            return
        end
        
        local headerLabel = vgui.Create("DLabel", settingsScroll)
        headerLabel:Dock(TOP)
        headerLabel:DockMargin(22, 0, 30, 15)
        headerLabel:SetTall(20)
        headerLabel:SetText("ЭКИПИРОВКА: " .. string.upper(selectedMember.nick))
        headerLabel:SetFont("DermaDefaultBold")
        headerLabel:SetTextColor(C_CMD_SEL)
        
        -- === БОДИГРУППЫ ===
        if table.Count(cmdBodygroups) > 0 then
            local bgArray = {}
            for idx, data in pairs(cmdBodygroups) do table.insert(bgArray, data) end
            table.sort(bgArray, function(a, b) return a.index < b.index end)
            
            for _, data in ipairs(bgArray) do
                local idx = data.index
                local bgName = string.lower(data.name)
                
                local bgPanel = vgui.Create("DPanel", settingsScroll)
                bgPanel:Dock(TOP)
                bgPanel:DockMargin(10, 5, 30, 10)
                bgPanel.Expanded = true
                local panelExpandedHeight = 25 + baseCellSize
                bgPanel.CurHeight = panelExpandedHeight
                bgPanel:SetTall(panelExpandedHeight)
                bgPanel.Paint = function() end
                bgPanel.Think = function(s)
                    local targetHeight = s.Expanded and panelExpandedHeight or 25
                    if s.CurHeight ~= targetHeight then
                        s.CurHeight = Lerp(FrameTime() * 15, s.CurHeight, targetHeight)
                        if math.abs(s.CurHeight - targetHeight) < 0.5 then s.CurHeight = targetHeight end
                        s:SetTall(math.Round(s.CurHeight))
                    end
                end
                
                local headerBtn = vgui.Create("DButton", bgPanel)
                headerBtn:SetPos(22, 0)
                headerBtn:SetSize(336, 25)
                headerBtn:SetText("")
                headerBtn.Paint = function(s, w, h)
                    local col = s:IsHovered() and Color(255, 255, 255) or Color(200, 200, 200)
                    draw.SimpleText(string.upper(data.name), "DermaDefaultBold", 0, h/2, col, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
                    draw.SimpleText(bgPanel.Expanded and "▼" or "◀", "DermaDefault", w, h/2, col, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER)
                end
                headerBtn.DoClick = function() bgPanel.Expanded = not bgPanel.Expanded; surface.PlaySound("UI/buttonclick.wav") end
                
                local carouselPanel = vgui.Create("DPanel", bgPanel)
                carouselPanel:SetPos(22, 25)
                carouselPanel:SetSize(336, baseCellSize)
                carouselPanel.Paint = function() end
                
                local startIdx = 0
                for k2 = 0, data.count - 1 do
                    if k2 == (cmdCurrentBodygroups[idx] or 0) then startIdx = k2; break end
                end
                carouselPanel.TargetScroll = startIdx
                carouselPanel.CurScroll = startIdx
                
                local leftArrow = vgui.Create("DButton", bgPanel)
                leftArrow:SetPos(0, 25); leftArrow:SetSize(16, baseCellSize); leftArrow:SetText("")
                leftArrow.Paint = function(s, w, h)
                    local col = s:IsHovered() and C_ARMA_SLOT_HOVER or C_ARMA_SLOT_EMPTY
                    draw.RoundedBox(0, 0, 0, w, h, col)
                    draw.SimpleText("<", "DermaDefaultBold", w/2, h/2, s:IsHovered() and C_CMD_SEL or Color(150, 150, 150), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                    surface.SetDrawColor(Color(0, 0, 0, 120)); surface.DrawOutlinedRect(0, 0, w, h, 1)
                end
                
                local rightArrow = vgui.Create("DButton", bgPanel)
                rightArrow:SetPos(364, 25); rightArrow:SetSize(16, baseCellSize); rightArrow:SetText("")
                rightArrow.Paint = function(s, w, h)
                    local col = s:IsHovered() and C_ARMA_SLOT_HOVER or C_ARMA_SLOT_EMPTY
                    draw.RoundedBox(0, 0, 0, w, h, col)
                    draw.SimpleText(">", "DermaDefaultBold", w/2, h/2, s:IsHovered() and C_CMD_SEL or Color(150, 150, 150), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                    surface.SetDrawColor(Color(0, 0, 0, 120)); surface.DrawOutlinedRect(0, 0, w, h, 1)
                end
                
                local maxScroll = math.max(0, data.count - 1)
                leftArrow.DoClick = function() carouselPanel.TargetScroll = math.max(0, carouselPanel.TargetScroll - 1); surface.PlaySound("UI/buttonclick.wav") end
                rightArrow.DoClick = function() carouselPanel.TargetScroll = math.min(maxScroll, carouselPanel.TargetScroll + 1); surface.PlaySound("UI/buttonclick.wav") end
                
                local cells = {}
                for i = 0, data.count - 1 do
                    local cell = vgui.Create("DButton", carouselPanel)
                    cell:SetText("")
                    cell.DoClick = function()
                        cmdCurrentBodygroups[idx] = i
                        carouselPanel.TargetScroll = i
                        surface.PlaySound("UI/buttonclick.wav")
                    end
                    cell.Paint = function(s, w, h)
                        local isSelected = (cmdCurrentBodygroups[idx] or 0) == i
                        local bgColor = C_ARMA_SLOT
                        if isSelected then bgColor = C_CMD_SEL
                        elseif s:IsHovered() then bgColor = C_ARMA_SLOT_HOVER end
                        local alphaMult = math.Clamp(1 - (s.AbsOffset or 0) * 0.35, 0.2, 1)
                        surface.SetDrawColor(bgColor.r, bgColor.g, bgColor.b, bgColor.a * alphaMult)
                        surface.DrawRect(0, 0, w, h)
                        
                        local iconData = CUSTOM_ICONS_BG[bgName]
                        local customIcon = iconData and (iconData[i] or iconData.default)
                        if customIcon and not customIcon:IsError() then
                            surface.SetDrawColor(255, 255, 255, 255 * alphaMult)
                            surface.SetMaterial(customIcon)
                            surface.DrawTexturedRect(4, 4, w - 8, h - 8)
                        else
                            local txtColor = isSelected and Color(40, 40, 40, 255 * alphaMult) or Color(150, 150, 150, 255 * alphaMult)
                            draw.SimpleText(tostring(i), "DermaLarge", w/2, h/2, txtColor, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                        end
                        surface.SetDrawColor(0, 0, 0, 120 * alphaMult)
                        surface.DrawOutlinedRect(0, 0, w, h, 1)
                    end
                    table.insert(cells, cell)
                end
                
                carouselPanel.Think = function(s)
                    s.CurScroll = Lerp(FrameTime() * 12, s.CurScroll, s.TargetScroll)
                    for ci, cell in ipairs(cells) do
                        local index = ci - 1
                        local offset = index - s.CurScroll
                        local absOffset = math.abs(offset)
                        cell.AbsOffset = absOffset
                        local scale = math.Clamp(1 - absOffset * 0.25, 0.5, 1)
                        local size = baseCellSize * scale
                        local spacing = 65
                        local x = (s:GetWide() / 2) - (size / 2) + (offset * spacing)
                        local y = (s:GetTall() / 2) - (size / 2)
                        cell:SetSize(size, size)
                        cell:SetPos(x, y)
                        cell:SetZPos(100 - math.floor(absOffset * 10))
                    end
                end
            end
        end
        
        -- === СКИНЫ ===
        if #cmdAvailableSkins > 1 then
            local skinPanel = vgui.Create("DPanel", settingsScroll)
            skinPanel:Dock(TOP)
            skinPanel:DockMargin(10, 5, 30, 10)
            skinPanel.Expanded = true
            local panelExpandedHeight = 25 + baseCellSize
            skinPanel.CurHeight = panelExpandedHeight
            skinPanel:SetTall(panelExpandedHeight)
            skinPanel.Paint = function() end
            skinPanel.Think = function(s)
                local targetHeight = s.Expanded and panelExpandedHeight or 25
                if s.CurHeight ~= targetHeight then
                    s.CurHeight = Lerp(FrameTime() * 15, s.CurHeight, targetHeight)
                    if math.abs(s.CurHeight - targetHeight) < 0.5 then s.CurHeight = targetHeight end
                    s:SetTall(math.Round(s.CurHeight))
                end
            end
            
            local skinHeader = vgui.Create("DButton", skinPanel)
            skinHeader:SetPos(22, 0); skinHeader:SetSize(336, 25); skinHeader:SetText("")
            skinHeader.Paint = function(s, w, h)
                local col = s:IsHovered() and Color(255, 255, 255) or Color(200, 200, 200)
                draw.SimpleText("ВАРИАНТ КАМУФЛЯЖА", "DermaDefaultBold", 0, h/2, col, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
                draw.SimpleText(skinPanel.Expanded and "▼" or "◀", "DermaDefault", w, h/2, col, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER)
            end
            skinHeader.DoClick = function() skinPanel.Expanded = not skinPanel.Expanded; surface.PlaySound("UI/buttonclick.wav") end
            
            local skinCarousel = vgui.Create("DPanel", skinPanel)
            skinCarousel:SetPos(22, 25); skinCarousel:SetSize(336, baseCellSize)
            skinCarousel.Paint = function() end
            skinCarousel.TargetScroll = cmdCurrentSkin or 0
            skinCarousel.CurScroll = skinCarousel.TargetScroll
            
            -- ИСПРАВЛЕНА ОПЕЧАТКА ТУТ:
            local skinLeft = vgui.Create("DButton", skinPanel)
            skinLeft:SetPos(0, 25); skinLeft:SetSize(16, baseCellSize); skinLeft:SetText("")
            skinLeft.Paint = function(s, w, h)
                local col = s:IsHovered() and C_ARMA_SLOT_HOVER or C_ARMA_SLOT_EMPTY
                draw.RoundedBox(0, 0, 0, w, h, col)
                draw.SimpleText("<", "DermaDefaultBold", w/2, h/2, s:IsHovered() and C_CMD_SEL or Color(150, 150, 150), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                surface.SetDrawColor(Color(0, 0, 0, 120)); surface.DrawOutlinedRect(0, 0, w, h, 1)
            end
            
            local skinRight = vgui.Create("DButton", skinPanel)
            skinRight:SetPos(364, 25); skinRight:SetSize(16, baseCellSize); skinRight:SetText("")
            skinRight.Paint = function(s, w, h)
                local col = s:IsHovered() and C_ARMA_SLOT_HOVER or C_ARMA_SLOT_EMPTY
                draw.RoundedBox(0, 0, 0, w, h, col)
                draw.SimpleText(">", "DermaDefaultBold", w/2, h/2, s:IsHovered() and C_CMD_SEL or Color(150, 150, 150), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                surface.SetDrawColor(Color(0, 0, 0, 120)); surface.DrawOutlinedRect(0, 0, w, h, 1)
            end
            
            local skinMaxScroll = math.max(0, #cmdAvailableSkins - 1)
            skinLeft.DoClick = function() skinCarousel.TargetScroll = math.max(0, skinCarousel.TargetScroll - 1); surface.PlaySound("UI/buttonclick.wav") end
            skinRight.DoClick = function() skinCarousel.TargetScroll = math.min(skinMaxScroll, skinCarousel.TargetScroll + 1); surface.PlaySound("UI/buttonclick.wav") end
            
            local skinCells = {}
            for i = 0, #cmdAvailableSkins - 1 do
                local cell = vgui.Create("DButton", skinCarousel)
                cell:SetText("")
                cell.DoClick = function()
                    cmdCurrentSkin = i
                    skinCarousel.TargetScroll = i
                    surface.PlaySound("UI/buttonclick.wav")
                end
                cell.Paint = function(s, w, h)
                    local isSelected = cmdCurrentSkin == i
                    local bgColor = C_ARMA_SLOT
                    if isSelected then bgColor = C_CMD_SEL
                    elseif s:IsHovered() then bgColor = C_ARMA_SLOT_HOVER end
                    local alphaMult = math.Clamp(1 - (s.AbsOffset or 0) * 0.35, 0.2, 1)
                    surface.SetDrawColor(bgColor.r, bgColor.g, bgColor.b, bgColor.a * alphaMult)
                    surface.DrawRect(0, 0, w, h)
                    local txtColor = isSelected and Color(40, 40, 40, 255 * alphaMult) or Color(150, 150, 150, 255 * alphaMult)
                    draw.SimpleText(tostring(i), "DermaLarge", w/2, h/2, txtColor, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
                    surface.SetDrawColor(0, 0, 0, 120 * alphaMult)
                    surface.DrawOutlinedRect(0, 0, w, h, 1)
                end
                table.insert(skinCells, cell)
            end
            
            skinCarousel.Think = function(s)
                s.CurScroll = Lerp(FrameTime() * 12, s.CurScroll, s.TargetScroll)
                for ci, cell in ipairs(skinCells) do
                    local index = ci - 1
                    local offset = index - s.CurScroll
                    local absOffset = math.abs(offset)
                    cell.AbsOffset = absOffset
                    local scale = math.Clamp(1 - absOffset * 0.25, 0.5, 1)
                    local size = baseCellSize * scale
                    local spacing = 65
                    local x = (s:GetWide() / 2) - (size / 2) + (offset * spacing)
                    local y = (s:GetTall() / 2) - (size / 2)
                    cell:SetSize(size, size)
                    cell:SetPos(x, y)
                    cell:SetZPos(100 - math.floor(absOffset * 10))
                end
            end
        end
    end
    
    -- === КНОПКИ ПРИМЕНИТЬ / СБРОС ===
    local applyBtn = vgui.Create("DButton", settingsPanel)
    local wipeBtn = vgui.Create("DButton", settingsPanel)
    
    wipeBtn:SetSize(135, 35); wipeBtn:SetText("")
    wipeBtn.Paint = function(s, w, h)
        local col = s:IsHovered() and C_WARN_H or C_WARN
        draw.RoundedBox(8, 0, 0, w, h, C_BDR)
        draw.RoundedBox(8, 2, 2, w - 4, h - 4, col)
        draw.SimpleText("СБРОСИТЬ", "DermaDefaultBold", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    end
    wipeBtn.DoClick = function()
        if not selectedMember then return end
        net.Start("SandboxWardrobeCommanderApply")
        net.WriteUInt(selectedMember.entIndex, 16)
        net.WriteBool(true)
        net.SendToServer()
        surface.PlaySound("UI/buttonclick.wav")
    end
    
    applyBtn:SetSize(135, 35); applyBtn:SetText("")
    applyBtn.Paint = function(s, w, h)
        local col = s:IsHovered() and C_CMD_H or C_CMD
        draw.RoundedBox(8, 0, 0, w, h, C_BDR)
        draw.RoundedBox(8, 2, 2, w - 4, h - 4, col)
        draw.RoundedBoxEx(8, 2, 2, w - 4, h/2 - 2, C_GRAD, true, true, false, false)
        draw.SimpleText("ПРИМЕНИТЬ", "DermaDefaultBold", w/2, h/2, C_TXT_P, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    end
    applyBtn.DoClick = function()
        if not selectedMember then return end
        net.Start("SandboxWardrobeCommanderApply")
        net.WriteUInt(selectedMember.entIndex, 16)
        net.WriteBool(false)
        net.WriteTable(cmdCurrentBodygroups)
        net.WriteUInt(cmdCurrentSkin, 8)
        net.SendToServer()
        surface.PlaySound("UI/buttonclick.wav")
    end
    
    settingsPanel.PerformLayout = function(s, w, h)
        applyBtn:SetPos(w - 135 - 10, h - 35 - 10)
        wipeBtn:SetPos(w - 135 * 2 - 20, h - 35 - 10)
    end
    
    -- Инициальный rebuild
    RebuildSettings()
    RebuildCommanderPresets()
    
    -- === Выбор бойца ===
    memberList.OnRowSelected = function(lst, index, pnl)
        selectedMember = pnl.memberData
        if not selectedMember then return end
        
        cmdModel = selectedMember.model
        cmdCurrentBodygroups = {}
        cmdCurrentSkin = 0
        cmdBodygroups = {}
        cmdAvailableSkins = {}
        
        -- Обновляем модель
        modelPanel:SetModel(cmdModel)
        modelPanel.bAnimSet = false
        modelPanel.bModelReady = false
        modelPanel.camAnims.zoom = 60
        modelPanel.camAnims.rot = Angle(0, 180, 0)
        modelPanel.camAnims.offset = Vector(0, 0, 0)
        
        -- Задержка нужна чтобы DModelPanel успел обновить Entity после SetModel
        timer.Simple(0.1, function()
            if not IsValid(modelPanel) then return end
            modelPanel.bModelReady = true
            
            local ent = modelPanel:GetEntity()
            if IsValid(ent) then
                for i = 0, ent:GetNumBodyGroups() - 1 do
                    local name = ent:GetBodygroupName(i)
                    local count = ent:GetBodygroupCount(i)
                    if count > 1 then
                        cmdBodygroups[i] = { name = name, count = count, index = i }
                        cmdCurrentBodygroups[i] = 0
                    end
                end
                
                local skinCount = ent:SkinCount() or 0
                for i = 0, skinCount - 1 do
                    table.insert(cmdAvailableSkins, i)
                end
            end
            
            -- Пробуем получить текущие бодигруппы от серверного игрока
            local target = Entity(selectedMember.entIndex)
            if IsValid(target) then
                for idx in pairs(cmdBodygroups) do
                    cmdCurrentBodygroups[idx] = target:GetBodygroup(idx)
                end
                cmdCurrentSkin = target:GetSkin()
            end
            
            RebuildSettings()
            RebuildCommanderPresets()
        end)
    end
end)
