local addonName, addonTable = ...
local db = addonTable.db
local L = addonTable.L
local spellDB = addonTable.spellDB
local mapaClases = addonTable.mapaClases or {}

local uiElements = { sliders = {}, checks = {}, valStrs = {} }
local filterCBs = {}
local lblPerfilActual, dropdownPerfiles
local customSelectors = {}
local themedSections = {}

local FORCED_MENU_BACKGROUND = "brushedmetal"
local FORCED_MENU_BORDER = "roth"

local tabButtonStates = {}

local _, playerClassTag = UnitClass("player")
local classColors = CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS
local playerClassColor = (classColors and playerClassTag and classColors[playerClassTag]) or NORMAL_FONT_COLOR
local BUTTON_TEXTURE_PATH = "Interface\\AddOns\\" .. addonName .. "\\Media\\Textures\\statusbar\\Button.tga"
local FRAME_OPACITY = 0.90
local POPUP_FRAME_OPACITY = 1.00

local function GetClassTint(mult, alpha)
    local m = mult or 1
    return math.min(1, (playerClassColor.r or 1) * m), math.min(1, (playerClassColor.g or 1) * m), math.min(1, (playerClassColor.b or 1) * m), alpha or 1
end

local function GetMediaEntry(getterName, selectedName)
    local media = addonTable.Media
    if not media or not media[getterName] then return nil end
    local list = media[getterName](media) or {}
    if selectedName then
        for _, entry in ipairs(list) do
            if entry.name == selectedName then return entry end
        end
    end
    return nil
end

local function GetNamedTexturePath(name, getterName)
    local entry = GetMediaEntry(getterName or "GetAvailableTextures", name)
    return entry and entry.path or nil
end

local SLIDER_TEXTURE_PATH = GetNamedTexturePath("Minimalist") or GetNamedTexturePath("Smooth") or BUTTON_TEXTURE_PATH

local function EnsureBackdropBorder(frame, inset)
    if frame._pcdThemeBorder then return frame._pcdThemeBorder end
    local bf = CreateFrame("Frame", nil, frame, "BackdropTemplate")
    bf:SetFrameLevel(frame:GetFrameLevel() + 3)
    local off = inset or 0
    bf:SetPoint("TOPLEFT", frame, "TOPLEFT", off, -off)
    bf:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -off, off)
    frame._pcdThemeBorder = bf
    return bf
end

local function ApplyMenuTheme()
    local bgEntry = GetMediaEntry("GetAvailableBackgrounds", FORCED_MENU_BACKGROUND)
    local borderEntry = GetMediaEntry("GetAvailableBorders", FORCED_MENU_BORDER)
    local bgPath = bgEntry and bgEntry.path or nil
    local borderPath = borderEntry and borderEntry.path or nil

    local function ApplyFrameTheme(frame)
        if not frame then return end
        local bgOverlayAlpha = frame._pcdIsPopup and 1.00 or 0.22
        local insetOverlayAlpha = frame._pcdIsPopup and 1.00 or 0.18
        if frame._pcdIsPopup then
            if frame.Bg then
                frame.Bg:SetTexture("Interface\\Buttons\\WHITE8X8")
                frame.Bg:SetHorizTile(false)
                frame.Bg:SetVertTile(false)
                frame.Bg:SetVertexColor(0, 0, 0, 1)
            end
            if frame.InsetBg then
                frame.InsetBg:SetTexture("Interface\\Buttons\\WHITE8X8")
                frame.InsetBg:SetHorizTile(false)
                frame.InsetBg:SetVertTile(false)
                frame.InsetBg:SetVertexColor(0, 0, 0, 1)
            end
            if frame.TitleBg then
                frame.TitleBg:SetTexture("Interface\\Buttons\\WHITE8X8")
                frame.TitleBg:SetVertexColor(0, 0, 0, 1)
            end
            if frame._pcdPopupSolidBg then frame._pcdPopupSolidBg:SetColorTexture(0, 0, 0, 1); frame._pcdPopupSolidBg:Show() end
            if frame._pcdPopupSolidInset then frame._pcdPopupSolidInset:SetColorTexture(0, 0, 0, 1); frame._pcdPopupSolidInset:Show() end
            if frame._pcdPopupTitleFill then frame._pcdPopupTitleFill:SetColorTexture(0, 0, 0, 1); frame._pcdPopupTitleFill:Show() end
        elseif bgPath then
            if frame.Bg then
                frame.Bg:SetTexture(bgPath)
                frame.Bg:SetHorizTile(true)
                frame.Bg:SetVertTile(true)
                frame.Bg:SetVertexColor(1, 1, 1, bgOverlayAlpha)
            end
            if frame.InsetBg then
                frame.InsetBg:SetTexture(bgPath)
                frame.InsetBg:SetHorizTile(true)
                frame.InsetBg:SetVertTile(true)
                frame.InsetBg:SetVertexColor(1, 1, 1, insetOverlayAlpha)
            end
            if frame.TitleBg then
                frame.TitleBg:SetTexture("Interface\\Buttons\\WHITE8X8")
                frame.TitleBg:SetVertexColor(0.12, 0.12, 0.14, math.min(1, frame._pcdBaseOpacity * 0.98))
            end
        end
        if borderPath then
            local bf = EnsureBackdropBorder(frame, 2)
            bf:SetBackdrop({
                bgFile = "Interface\\Buttons\\WHITE8X8",
                edgeFile = borderPath,
                tile = true,
                tileSize = 8,
                edgeSize = 10,
                insets = { left = 2, right = 2, top = 2, bottom = 2 },
            })
            bf:SetBackdropColor(0, 0, 0, 0)
            bf:SetBackdropBorderColor(1, 1, 1, frame._pcdIsPopup and 0.80 or 0.62)
            bf:Show()
        end
    end

    ApplyFrameTheme(menuMain)
    ApplyFrameTheme(menuFiltros)
    ApplyFrameTheme(selectorPopup)

    for _, section in ipairs(themedSections) do
        if section and section.bg and bgPath then
            section.bg:SetTexture(bgPath)
            section.bg:SetHorizTile(true)
            section.bg:SetVertTile(true)
            section.bg:SetVertexColor(1, 1, 1, 0.14)
        end
        if section and borderPath then
            if section.borderTop then section.borderTop:SetAlpha(0) end
            if section.borderBottom then section.borderBottom:SetAlpha(0) end
            if section.borderLeft then section.borderLeft:SetAlpha(0) end
            if section.borderRight then section.borderRight:SetAlpha(0) end
            local bf = EnsureBackdropBorder(section, 0)
            bf:SetBackdrop({
                bgFile = "Interface\\Buttons\\WHITE8X8",
                edgeFile = borderPath,
                tile = true,
                tileSize = 8,
                edgeSize = 8,
                insets = { left = 2, right = 2, top = 2, bottom = 2 },
            })
            bf:SetBackdropColor(0, 0, 0, 0)
            bf:SetBackdropBorderColor(1, 1, 1, 0.42)
            bf:Show()
        end
    end
end

local function ApplyFrameChrome(frame)
    if frame._pcdStyled then return end
    frame._pcdStyled = true

    local baseAlpha = frame._pcdBaseOpacity or FRAME_OPACITY
    if frame._pcdIsPopup then
        if frame.Bg then
            frame.Bg:SetTexture("Interface\\Buttons\\WHITE8X8")
            frame.Bg:SetVertexColor(0, 0, 0, 1)
        end
        if frame.InsetBg then
            frame.InsetBg:SetTexture("Interface\\Buttons\\WHITE8X8")
            frame.InsetBg:SetVertexColor(0, 0, 0, 1)
        end
        if frame.TitleBg then
            frame.TitleBg:SetTexture("Interface\\Buttons\\WHITE8X8")
            frame.TitleBg:SetVertexColor(0, 0, 0, 1)
        end
        if frame._pcdPopupSolidBg then frame._pcdPopupSolidBg:SetColorTexture(0, 0, 0, 1); frame._pcdPopupSolidBg:Show() end
        if frame._pcdPopupSolidInset then frame._pcdPopupSolidInset:SetColorTexture(0, 0, 0, 1); frame._pcdPopupSolidInset:Show() end
        if frame._pcdPopupTitleFill then frame._pcdPopupTitleFill:SetColorTexture(0, 0, 0, 1); frame._pcdPopupTitleFill:Show() end
    else
        if frame.Bg then frame.Bg:SetVertexColor(0.08, 0.08, 0.10, baseAlpha) end
        if frame.InsetBg then frame.InsetBg:SetVertexColor(0.03, 0.03, 0.04, math.min(1, baseAlpha * 0.96)) end
        if frame.TitleBg then frame.TitleBg:SetVertexColor(0.12, 0.12, 0.14, math.min(1, baseAlpha * 0.98)) end
    end

    frame.accent = frame:CreateTexture(nil, "ARTWORK")
    frame.accent:SetColorTexture(1, 0.82, 0, 0.14)
    frame.accent:SetHeight(1)
    frame.accent:SetPoint("TOPLEFT", frame, "TOPLEFT", 12, -31)
    frame.accent:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -28, -31)
end

local function CreateTabHeading(parent, text)
    local heading = parent:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    heading:SetPoint("TOP", parent, "TOP", 0, -10)
    heading:SetWidth(620)
    heading:SetJustifyH("CENTER")
    heading:SetText("|cffffd100" .. text .. "|r")
    return heading
end

local function CreateSection(parent, title, x, y, w, h)
    local section = CreateFrame("Frame", nil, parent)
    section:SetSize(w, h)
    section:SetPoint("TOPLEFT", x, y)

    section.bg = section:CreateTexture(nil, "BACKGROUND")
    section.bg:SetAllPoints()
    section.bg:SetColorTexture(0.07, 0.07, 0.09, FRAME_OPACITY * 0.52)

    section.borderTop = section:CreateTexture(nil, "BORDER")
    section.borderTop:SetColorTexture(1, 1, 1, 0.08)
    section.borderTop:SetHeight(1)
    section.borderTop:SetPoint("TOPLEFT", 0, 0)
    section.borderTop:SetPoint("TOPRIGHT", 0, 0)

    section.borderBottom = section:CreateTexture(nil, "BORDER")
    section.borderBottom:SetColorTexture(1, 1, 1, 0.06)
    section.borderBottom:SetHeight(1)
    section.borderBottom:SetPoint("BOTTOMLEFT", 0, 0)
    section.borderBottom:SetPoint("BOTTOMRIGHT", 0, 0)

    section.borderLeft = section:CreateTexture(nil, "BORDER")
    section.borderLeft:SetColorTexture(1, 1, 1, 0.05)
    section.borderLeft:SetWidth(1)
    section.borderLeft:SetPoint("TOPLEFT", 0, 0)
    section.borderLeft:SetPoint("BOTTOMLEFT", 0, 0)

    section.borderRight = section:CreateTexture(nil, "BORDER")
    section.borderRight:SetColorTexture(1, 1, 1, 0.05)
    section.borderRight:SetWidth(1)
    section.borderRight:SetPoint("TOPRIGHT", 0, 0)
    section.borderRight:SetPoint("BOTTOMRIGHT", 0, 0)

    section.title = section:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    section.title:SetPoint("TOPLEFT", 12, -10)
    section.title:SetText("|cffffd100" .. title .. "|r")

    section.line = section:CreateTexture(nil, "ARTWORK")
    section.line:SetColorTexture(1, 0.82, 0, 0.18)
    section.line:SetHeight(1)
    section.line:SetPoint("TOPLEFT", 12, -28)
    section.line:SetPoint("TOPRIGHT", -12, -28)

    table.insert(themedSections, section)
    return section
end

local function StripButtonTextures(btn)
    if btn._pcdStripped then return end
    btn._pcdStripped = true

    local normal = btn.GetNormalTexture and btn:GetNormalTexture()
    local pushed = btn.GetPushedTexture and btn:GetPushedTexture()
    local highlight = btn.GetHighlightTexture and btn:GetHighlightTexture()
    local disabled = btn.GetDisabledTexture and btn:GetDisabledTexture()
    if normal then normal:SetAlpha(0); normal:SetTexture(nil) end
    if pushed then pushed:SetAlpha(0); pushed:SetTexture(nil) end
    if highlight then highlight:SetAlpha(0); highlight:SetTexture(nil) end
    if disabled then disabled:SetAlpha(0); disabled:SetTexture(nil) end

    local regions = { btn:GetRegions() }
    for _, region in ipairs(regions) do
        if region and region.IsObjectType and region:IsObjectType("Texture") then
            region:SetAlpha(0)
            region:SetTexture(nil)
        end
    end
end

local function EnsureButtonSkin(btn)
    if btn._pcdBg then return end
    btn._pcdBg = btn:CreateTexture(nil, "BACKGROUND")
    btn._pcdBg:SetAllPoints()
    btn._pcdBg:SetTexture(BUTTON_TEXTURE_PATH)
    btn._pcdBg:SetHorizTile(false)
    btn._pcdBg:SetVertTile(false)
    btn._pcdBg:SetDesaturated(true)

    btn._pcdShade = btn:CreateTexture(nil, "BORDER")
    btn._pcdShade:SetAllPoints()
    btn._pcdShade:SetColorTexture(0, 0, 0, 0.14)

    btn._pcdBorderTop = btn:CreateTexture(nil, "ARTWORK")
    btn._pcdBorderTop:SetHeight(1)
    btn._pcdBorderTop:SetPoint("TOPLEFT", 1, -1)
    btn._pcdBorderTop:SetPoint("TOPRIGHT", -1, -1)

    btn._pcdBorderBottom = btn:CreateTexture(nil, "ARTWORK")
    btn._pcdBorderBottom:SetHeight(1)
    btn._pcdBorderBottom:SetPoint("BOTTOMLEFT", 1, 1)
    btn._pcdBorderBottom:SetPoint("BOTTOMRIGHT", -1, 1)

    btn._pcdBorderLeft = btn:CreateTexture(nil, "ARTWORK")
    btn._pcdBorderLeft:SetWidth(1)
    btn._pcdBorderLeft:SetPoint("TOPLEFT", 1, -1)
    btn._pcdBorderLeft:SetPoint("BOTTOMLEFT", 1, 1)

    btn._pcdBorderRight = btn:CreateTexture(nil, "ARTWORK")
    btn._pcdBorderRight:SetWidth(1)
    btn._pcdBorderRight:SetPoint("TOPRIGHT", -1, -1)
    btn._pcdBorderRight:SetPoint("BOTTOMRIGHT", -1, 1)
end

local function ApplyButtonVisualState(btn, state)
    if not btn or not btn._pcdBg then return end

    local mult, alpha, borderAlpha, textR, textG, textB
    if state == "pressed" then
        mult, alpha, borderAlpha = 0.78, 0.98, 0.70
        textR, textG, textB = 1, 1, 1
    elseif state == "hover" then
        mult, alpha, borderAlpha = 1.18, 0.98, 0.82
        textR, textG, textB = 1, 1, 1
    elseif state == "active" then
        mult, alpha, borderAlpha = 1.00, 0.98, 0.76
        textR, textG, textB = 1, 1, 1
    else
        mult, alpha, borderAlpha = 0.92, 0.94, 0.58
        textR, textG, textB = 0.98, 0.98, 0.98
    end

    local r, g, b, a = GetClassTint(mult, alpha)
    btn._pcdBg:SetTexture(BUTTON_TEXTURE_PATH)
    btn._pcdBg:SetDesaturated(true)
    btn._pcdBg:SetVertexColor(r, g, b, a)
    btn._pcdShade:SetColorTexture(0, 0, 0, state == "pressed" and 0.24 or 0.12)

    local br, bg, bb = GetClassTint(1.25, 1)
    btn._pcdBorderTop:SetColorTexture(br, bg, bb, borderAlpha)
    btn._pcdBorderBottom:SetColorTexture(br, bg, bb, borderAlpha)
    btn._pcdBorderLeft:SetColorTexture(br, bg, bb, borderAlpha)
    btn._pcdBorderRight:SetColorTexture(br, bg, bb, borderAlpha)

    if btn.Text then btn.Text:SetTextColor(textR, textG, textB) end
    local fs = btn.GetFontString and btn:GetFontString()
    if fs and fs ~= btn.Text then fs:SetTextColor(textR, textG, textB) end
end

local function StyleActionButton(btn, variant)
    StripButtonTextures(btn)
    btn:SetNormalFontObject(GameFontHighlightSmall)
    btn:SetHighlightFontObject(GameFontHighlightSmall)
    btn:SetPushedTextOffset(0, -1)

    EnsureButtonSkin(btn)
    ApplyButtonVisualState(btn, "normal")

    if not btn._pcdButtonHooks then
        btn._pcdButtonHooks = true
        btn:HookScript("OnEnter", function(self) ApplyButtonVisualState(self, "hover") end)
        btn:HookScript("OnLeave", function(self) ApplyButtonVisualState(self, "normal") end)
        btn:HookScript("OnMouseDown", function(self) ApplyButtonVisualState(self, "pressed") end)
        btn:HookScript("OnMouseUp", function(self)
            if self:IsMouseOver() then ApplyButtonVisualState(self, "hover") else ApplyButtonVisualState(self, "normal") end
        end)
        btn:HookScript("OnDisable", function(self)
            if self._pcdBg then
                local r, g, b = GetClassTint(0.60, 1)
                self._pcdBg:SetVertexColor(r, g, b, 0.45)
                self._pcdShade:SetColorTexture(0, 0, 0, 0.22)
                self._pcdBorderTop:SetColorTexture(r, g, b, 0.30)
                self._pcdBorderBottom:SetColorTexture(r, g, b, 0.30)
                self._pcdBorderLeft:SetColorTexture(r, g, b, 0.30)
                self._pcdBorderRight:SetColorTexture(r, g, b, 0.30)
            end
        end)
        btn:HookScript("OnEnable", function(self) ApplyButtonVisualState(self, "normal") end)
    end
end

local function SetTabButtonState(btn, active)
    if not btn or not btn._pcdBg then return end
    ApplyButtonVisualState(btn, active and "active" or "normal")
    tabButtonStates[btn] = active and true or false
end

local function StyleTabButton(btn)
    StripButtonTextures(btn)
    btn:SetNormalFontObject(GameFontHighlightSmall)
    btn:SetHighlightFontObject(GameFontHighlightSmall)
    btn:SetPushedTextOffset(0, -1)

    EnsureButtonSkin(btn)
    SetTabButtonState(btn, false)

    if not btn._pcdTabHooks then
        btn._pcdTabHooks = true
        btn:HookScript("OnEnter", function(self)
            if not tabButtonStates[self] then
                ApplyButtonVisualState(self, "hover")
            end
        end)
        btn:HookScript("OnLeave", function(self)
            if not tabButtonStates[self] then
                SetTabButtonState(self, false)
            end
        end)
        btn:HookScript("OnMouseDown", function(self)
            if not tabButtonStates[self] then ApplyButtonVisualState(self, "pressed") end
        end)
        btn:HookScript("OnMouseUp", function(self)
            if not tabButtonStates[self] then
                if self:IsMouseOver() then ApplyButtonVisualState(self, "hover") else SetTabButtonState(self, false) end
            end
        end)
    end
end

local function DeepCopy(src, dest)
    for k, v in pairs(src) do
        if type(v) == "table" then dest[k] = {}; DeepCopy(v, dest[k]) else dest[k] = v end
    end
end

local function InicializarPerfil(perfil)
    perfil.anchors = perfil.anchors or {}
    perfil.width = perfil.width or 180; perfil.height = perfil.height or 30
    perfil.fontSizeName = perfil.fontSizeName or 12; perfil.nameFontSize = perfil.nameFontSize or 12 
    perfil.iconSize = perfil.iconSize or 30; perfil.iconSpacing = perfil.iconSpacing or 2 
    perfil.offsetX = perfil.offsetX or 0; perfil.offsetY = perfil.offsetY or 0
    perfil.growDirection = perfil.growDirection or "AUTO"
    if perfil.defensivosFirst == nil then perfil.defensivosFirst = true end
    perfil.ccSize = perfil.ccSize or 40; perfil.ccPerRow = perfil.ccPerRow or 5
    perfil.ccSpacing = perfil.ccSpacing or 2; perfil.ccGrowDirection = perfil.ccGrowDirection or "RIGHT_DOWN"
    perfil.iconsPerRow = perfil.iconsPerRow or 4
    perfil.disabledSpells = perfil.disabledSpells or {}
    perfil.sortMode = perfil.sortMode or "CD_ASC" 
    perfil.anchorMode = perfil.anchorMode or "Auto"
    perfil.anchorSide = perfil.anchorSide or "LEFT"
    if perfil.showListo == nil then perfil.showListo = true end 
    if perfil.ttsEnabled == nil then perfil.ttsEnabled = true end
    if perfil.activeDungeon == nil then perfil.activeDungeon = true end
    if perfil.activeRaid == nil then perfil.activeRaid = true end
    if perfil.activeWorld == nil then perfil.activeWorld = true end
    if perfil.activePvp == nil then perfil.activePvp = true end
    if perfil.showCortes == nil then perfil.showCortes = true end
    if perfil.showDefensivos == nil then perfil.showDefensivos = true end
    if perfil.showOfensivos == nil then perfil.showOfensivos = true end
    if perfil.showCCs == nil then perfil.showCCs = true end
    if perfil.pixelPerfect == nil then perfil.pixelPerfect = true end 
    if perfil.language == nil then perfil.language = "Auto" end
    perfil.menuBackgroundName = FORCED_MENU_BACKGROUND
    perfil.menuBorderName = FORCED_MENU_BORDER
end

local function ActualizarValoresUI()
    for key, s in pairs(uiElements.sliders) do
        local minV, maxV = s:GetMinMaxValues()
        s:SetValue(math.max(minV, math.min(maxV, db[key] or minV)))
        local val = math.floor(s:GetValue() + 0.5)
        if uiElements.valStrs[key] then uiElements.valStrs[key]:SetText(val) end
    end
    for key, cb in pairs(uiElements.checks) do cb:SetChecked(db[key] == true); if cb.RefreshVisual then cb:RefreshVisual() end end
    for id, cb in pairs(filterCBs) do cb:SetChecked(not db.disabledSpells[id]); if cb.RefreshVisual then cb:RefreshVisual() end end
    if lblPerfilActual then lblPerfilActual:SetText((L.SEC_PROFILES or "Profiles") .. ": |cff44ff44" .. tostring(db.profileName or "Default") .. "|r") end
    if dropdownPerfiles then dropdownPerfiles:SetText(db.profileName or "Default") end
    for key, cfg in pairs(customSelectors) do
        if cfg and cfg.button and cfg.options then
            local selectedLabel = db[key] or L.SELECT or "Select..."
            for _, op in ipairs(cfg.options) do
                if op.name == db[key] then
                    selectedLabel = op.label or op.name
                    break
                end
            end
            cfg.button:SetText(selectedLabel)
        end
    end
end

addonTable.AplicarPerfil = function(nombrePerfil)
    if not PremadeCDsDB.profiles[nombrePerfil] then return end
    PremadeCDsDB.charToProfile[UnitName("player")] = nombrePerfil
    
    for k in pairs(db) do db[k] = nil end
    DeepCopy(PremadeCDsDB.profiles[nombrePerfil], db)
    
    db.profileName = nombrePerfil
    InicializarPerfil(db)
    ActualizarValoresUI()
    if addonTable.RestaurarAnclas then addonTable.RestaurarAnclas() end
    if addonTable.ActualizarTodoEnVivo then addonTable.ActualizarTodoEnVivo() end
end

local function BringWindowToFront(frame)
    if not frame then return end
    local desiredStrata = frame._pcdDesiredStrata or (frame._pcdIsPopup and "FULLSCREEN_DIALOG" or "DIALOG")
    local desiredLevel = frame._pcdDesiredLevel or (frame._pcdIsPopup and 180 or 120)
    frame:SetFrameStrata(desiredStrata)
    frame:SetFrameLevel(math.max(frame:GetFrameLevel() or 0, desiredLevel))
    frame:SetToplevel(true)
    frame:Raise()
end

local function CreateThemedWindow(name, parent, width, height, point, relativeTo, relativePoint, x, y, frameStrata)
    local frame = CreateFrame("Frame", name, UIParent, "BackdropTemplate")
    frame._pcdIsPopup = name and string.find(name, "SelectorPopup") and true or false
    frame._pcdBaseOpacity = frame._pcdIsPopup and POPUP_FRAME_OPACITY or FRAME_OPACITY
    frame._pcdDesiredStrata = frameStrata or (frame._pcdIsPopup and "FULLSCREEN_DIALOG" or "DIALOG")
    frame._pcdDesiredLevel = frame._pcdIsPopup and 180 or 120
    frame:SetSize(width, height)
    frame:SetPoint(point, relativeTo, relativePoint, x or 0, y or 0)
    frame:SetMovable(true)
    frame:EnableMouse(true)
    frame:RegisterForDrag("LeftButton")
    frame:SetClampedToScreen(true)
    frame:SetFrameStrata(frame._pcdDesiredStrata)
    frame:SetFrameLevel(frame._pcdDesiredLevel)
    frame:SetToplevel(true)
    frame:SetScript("OnDragStart", function(self)
        BringWindowToFront(self)
        self:StartMoving()
    end)
    frame:SetScript("OnDragStop", frame.StopMovingOrSizing)
    frame:HookScript("OnShow", BringWindowToFront)
    frame:HookScript("OnMouseDown", BringWindowToFront)

    frame.Bg = frame:CreateTexture(nil, "BACKGROUND")
    frame.Bg:SetAllPoints()
    frame.Bg:SetColorTexture(0.08, 0.08, 0.10, frame._pcdBaseOpacity)

    frame.InsetBg = frame:CreateTexture(nil, "BORDER")
    frame.InsetBg:SetPoint("TOPLEFT", frame, "TOPLEFT", 10, -36)
    frame.InsetBg:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -10, 10)
    frame.InsetBg:SetColorTexture(0.03, 0.03, 0.04, math.min(1, frame._pcdBaseOpacity * 0.96))

    frame.TitleBg = frame:CreateTexture(nil, "ARTWORK")
    frame.TitleBg:SetPoint("TOPLEFT", frame, "TOPLEFT", 10, -8)
    frame.TitleBg:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -36, -8)
    frame.TitleBg:SetHeight(22)
    frame.TitleBg:SetColorTexture(0.12, 0.12, 0.14, math.min(1, frame._pcdBaseOpacity * 0.98))

    if frame._pcdIsPopup then
        frame._pcdPopupSolidBg = frame:CreateTexture(nil, "BACKGROUND", nil, 1)
        frame._pcdPopupSolidBg:SetAllPoints(frame)
        frame._pcdPopupSolidBg:SetTexture("Interface\\Buttons\\WHITE8X8")
        frame._pcdPopupSolidBg:SetVertexColor(0, 0, 0, 1)

        frame._pcdPopupSolidInset = frame:CreateTexture(nil, "BORDER", nil, 1)
        frame._pcdPopupSolidInset:SetPoint("TOPLEFT", frame, "TOPLEFT", 10, -36)
        frame._pcdPopupSolidInset:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -10, 10)
        frame._pcdPopupSolidInset:SetTexture("Interface\\Buttons\\WHITE8X8")
        frame._pcdPopupSolidInset:SetVertexColor(0, 0, 0, 1)

        frame._pcdPopupTitleFill = frame:CreateTexture(nil, "ARTWORK", nil, 1)
        frame._pcdPopupTitleFill:SetPoint("TOPLEFT", frame, "TOPLEFT", 10, -8)
        frame._pcdPopupTitleFill:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -36, -8)
        frame._pcdPopupTitleFill:SetHeight(22)
        frame._pcdPopupTitleFill:SetTexture("Interface\\Buttons\\WHITE8X8")
        frame._pcdPopupTitleFill:SetVertexColor(0, 0, 0, 1)
    end

    if not frame._pcdIsPopup then
        frame.CloseButton = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
        frame.CloseButton:SetSize(20, 20)
        frame.CloseButton:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -10, -9)
        frame.CloseButton:SetText("×")
        StyleActionButton(frame.CloseButton, "secondary")
        local fs = frame.CloseButton:GetFontString()
        if fs then fs:SetFont("Fonts\\FRIZQT__.TTF", 14, "OUTLINE") end
        frame.CloseButton:SetScript("OnClick", function() frame:Hide() end)
    end

    return frame
end

local menuMain = CreateThemedWindow("PremadeCDsMenu", UIParent, 720, 724, "CENTER", UIParent, "CENTER", -150, 0)
menuMain:Hide()
menuMain:SetFrameStrata("DIALOG")
menuMain:SetToplevel(true)
local function BringMainToFront()
    if menuMain and menuMain:IsShown() then menuMain:Raise() end
end
menuMain:HookScript("OnShow", BringMainToFront)
menuMain:HookScript("OnMouseDown", BringMainToFront)
menuMain:HookScript("OnDragStart", function(self)
    BringMainToFront()
    self:StartMoving()
end)
ApplyFrameChrome(menuMain)
menuMain.title = menuMain:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
menuMain.title:SetPoint("TOP", menuMain.TitleBg, "TOP", 0, -1)
menuMain.title:SetWidth(640)
menuMain.title:SetJustifyH("CENTER")

local menuFiltros = CreateThemedWindow("PremadeCDsFiltros", UIParent, 420, 700, "TOPLEFT", menuMain, "TOPRIGHT", 6, 0)
menuFiltros:Hide()
ApplyFrameChrome(menuFiltros)
menuFiltros.title = menuFiltros:CreateFontString(nil, "OVERLAY", "GameFontNormal")
menuFiltros.title:SetPoint("CENTER", menuFiltros.TitleBg, "CENTER", 0, 0)
menuFiltros:SetMovable(false)
menuFiltros:RegisterForDrag()
menuFiltros:SetScript("OnDragStart", nil)
menuFiltros:SetScript("OnDragStop", nil)

local function AnchorFiltersToMain()
    menuFiltros:ClearAllPoints()
    menuFiltros:SetPoint("TOPLEFT", menuMain, "TOPRIGHT", 6, 0)
end
menuFiltros:HookScript("OnShow", function(self)
    if selectorPopup and selectorPopup:IsShown() then selectorPopup:Hide() end
    AnchorFiltersToMain()
    self:Raise()
end)
menuFiltros:HookScript("OnMouseDown", function(self)
    AnchorFiltersToMain()
    self:Raise()
end)
menuMain:HookScript("OnShow", function()
    if menuFiltros:IsShown() then AnchorFiltersToMain() end
end)
menuMain:HookScript("OnDragStop", function()
    if menuFiltros:IsShown() then AnchorFiltersToMain() end
end)

menuMain.CloseButton:SetScript("OnClick", function() 
    menuMain:Hide(); 
    menuFiltros:Hide(); 
    if selectorPopup then selectorPopup:Hide() end 
end)

local function CrearPanelTabFiltros(parent)
    local sf = CreateFrame("ScrollFrame", nil, parent, "UIPanelScrollFrameTemplate")
    sf:SetSize(360, 590)
    sf:SetPoint("TOPLEFT", 16, -76)
    local sc = CreateFrame("Frame", nil, sf)
    sf:SetScrollChild(sc)
    sf:Hide()
    return sf, sc
end

local sCortes, cCortes = CrearPanelTabFiltros(menuFiltros)
local sDef, cDef = CrearPanelTabFiltros(menuFiltros)
local sOfen, cOfen = CrearPanelTabFiltros(menuFiltros)
local sCC, cCC = CrearPanelTabFiltros(menuFiltros)

addonTable.MostrarTabFiltros = function(tab) sCortes:Hide(); sDef:Hide(); sOfen:Hide(); sCC:Hide(); tab:Show() end

addonTable.ToggleMenu = function()
    if menuMain:IsShown() then 
        menuMain:Hide(); menuFiltros:Hide() 
    else 
        menuMain:Show()
        ApplyMenuTheme()
        if addonTable.ActualizarTodoEnVivo then addonTable.ActualizarTodoEnVivo() end
    end
end

local function StyleRectSlider(slider, globalName, minV, maxV)
    if slider._pcdRectSlider then return end
    slider._pcdRectSlider = true

    local regions = { slider:GetRegions() }
    for _, region in ipairs(regions) do
        if region and region.IsObjectType and region:IsObjectType("Texture") then
            region:SetAlpha(0)
            region:SetTexture(nil)
        end
    end

    local tr, tg, tb = GetClassTint(1.0, 1)

    slider.trackBg = slider:CreateTexture(nil, "BACKGROUND")
    slider.trackBg:SetPoint("LEFT", slider, "LEFT", 0, 0)
    slider.trackBg:SetPoint("RIGHT", slider, "RIGHT", 0, 0)
    slider.trackBg:SetHeight(8)
    slider.trackBg:SetTexture(SLIDER_TEXTURE_PATH)
    slider.trackBg:SetVertexColor(0.18, 0.18, 0.20, 0.95)

    slider.trackInset = slider:CreateTexture(nil, "ARTWORK")
    slider.trackInset:SetPoint("TOPLEFT", slider.trackBg, "TOPLEFT", 1, -1)
    slider.trackInset:SetPoint("BOTTOMRIGHT", slider.trackBg, "BOTTOMRIGHT", -1, 1)
    slider.trackInset:SetTexture(SLIDER_TEXTURE_PATH)
    slider.trackInset:SetVertexColor(0.10, 0.10, 0.11, 0.96)

    slider.trackFill = CreateFrame("StatusBar", nil, slider)
    slider.trackFill:SetPoint("TOPLEFT", slider.trackBg, "TOPLEFT", 1, -1)
    slider.trackFill:SetPoint("BOTTOMRIGHT", slider.trackBg, "BOTTOMRIGHT", -1, 1)
    slider.trackFill:SetMinMaxValues(minV, maxV)
    slider.trackFill:SetStatusBarTexture(SLIDER_TEXTURE_PATH)
    slider.trackFill:SetStatusBarColor(tr, tg, tb, 0.32)
    slider.trackFill:SetFrameLevel(slider:GetFrameLevel())

    slider.trackBorderTop = slider:CreateTexture(nil, "OVERLAY")
    slider.trackBorderTop:SetColorTexture(1, 1, 1, 0.18)
    slider.trackBorderTop:SetHeight(1)
    slider.trackBorderTop:SetPoint("TOPLEFT", slider.trackBg, "TOPLEFT", 0, 0)
    slider.trackBorderTop:SetPoint("TOPRIGHT", slider.trackBg, "TOPRIGHT", 0, 0)

    slider.trackBorderBottom = slider:CreateTexture(nil, "OVERLAY")
    slider.trackBorderBottom:SetColorTexture(0, 0, 0, 0.45)
    slider.trackBorderBottom:SetHeight(1)
    slider.trackBorderBottom:SetPoint("BOTTOMLEFT", slider.trackBg, "BOTTOMLEFT", 0, 0)
    slider.trackBorderBottom:SetPoint("BOTTOMRIGHT", slider.trackBg, "BOTTOMRIGHT", 0, 0)

    slider:SetThumbTexture(BUTTON_TEXTURE_PATH)
    local thumb = slider:GetThumbTexture()
    if thumb then
        thumb:SetDesaturated(true)
        thumb:SetVertexColor(tr, tg, tb, 1)
        thumb:SetSize(12, 18)
    end

    local title = _G[globalName .. "Text"]
    if title then title:SetTextColor(1, 0.82, 0, 1) end
    local low = _G[globalName .. "Low"]
    if low then low:SetText(""); low:Hide() end
    local high = _G[globalName .. "High"]
    if high then high:SetText(""); high:Hide() end
end

local function StyleScrollFrame(scrollFrame)
    if not scrollFrame or scrollFrame._pcdStyled then return end
    local sb = scrollFrame.ScrollBar or (scrollFrame.GetName and scrollFrame:GetName() and _G[scrollFrame:GetName() .. "ScrollBar"])
    if not sb then return end
    scrollFrame._pcdStyled = true

    sb:SetWidth(16)

    for _, region in ipairs({ sb:GetRegions() }) do
        if region and region.IsObjectType and region:IsObjectType("Texture") then
            region:SetAlpha(0)
            region:SetTexture(nil)
        end
    end

    local up = sb.ScrollUpButton or (sb.GetName and sb:GetName() and _G[sb:GetName() .. "ScrollUpButton"])
    local down = sb.ScrollDownButton or (sb.GetName and sb:GetName() and _G[sb:GetName() .. "ScrollDownButton"])

    local function StyleArrow(btn, text)
        if not btn then return end
        StripButtonTextures(btn)
        btn:SetSize(16, 16)
        btn:SetText(text)
        StyleActionButton(btn, "secondary")
        local fs = btn:GetFontString()
        if fs then fs:SetFont("Fonts\\FRIZQT__.TTF", 9, "OUTLINE") end
    end

    StyleArrow(up, "▲")
    StyleArrow(down, "▼")

    if up then
        up:ClearAllPoints()
        up:SetPoint("TOP", sb, "TOP", 0, 0)
    end
    if down then
        down:ClearAllPoints()
        down:SetPoint("BOTTOM", sb, "BOTTOM", 0, 0)
    end

    sb.trackBg = sb:CreateTexture(nil, "BACKGROUND")
    sb.trackBg:SetPoint("TOPLEFT", sb, "TOPLEFT", 2, -18)
    sb.trackBg:SetPoint("BOTTOMRIGHT", sb, "BOTTOMRIGHT", -2, 18)
    sb.trackBg:SetTexture(SLIDER_TEXTURE_PATH)
    sb.trackBg:SetVertexColor(0.10, 0.10, 0.11, 0.96)

    sb.trackBorderLeft = sb:CreateTexture(nil, "BORDER")
    sb.trackBorderLeft:SetColorTexture(1, 1, 1, 0.12)
    sb.trackBorderLeft:SetWidth(1)
    sb.trackBorderLeft:SetPoint("TOPLEFT", sb.trackBg, "TOPLEFT", 0, 0)
    sb.trackBorderLeft:SetPoint("BOTTOMLEFT", sb.trackBg, "BOTTOMLEFT", 0, 0)

    sb.trackBorderRight = sb:CreateTexture(nil, "BORDER")
    sb.trackBorderRight:SetColorTexture(0, 0, 0, 0.45)
    sb.trackBorderRight:SetWidth(1)
    sb.trackBorderRight:SetPoint("TOPRIGHT", sb.trackBg, "TOPRIGHT", 0, 0)
    sb.trackBorderRight:SetPoint("BOTTOMRIGHT", sb.trackBg, "BOTTOMRIGHT", 0, 0)

    sb:SetThumbTexture(BUTTON_TEXTURE_PATH)
    local thumb = sb:GetThumbTexture()
    if thumb then
        local tr, tg, tb = GetClassTint(1.0, 1)
        thumb:SetDesaturated(true)
        thumb:SetVertexColor(tr, tg, tb, 1)
        thumb:SetSize(10, 28)
    end
end

StyleScrollFrame(sCortes)
StyleScrollFrame(sDef)
StyleScrollFrame(sOfen)
StyleScrollFrame(sCC)

addonTable.ConstruirUI = function()
    if addonTable.GetDict then
        addonTable.L = addonTable.GetDict(db.language)
        L = addonTable.L
    end

    menuMain.title:SetText("M+ Interrupts CCs&Cds Tracker")
    menuFiltros.title:SetText(L.FILTERS_TITLE or "Spell Filters")

    local btnTabCortes, btnTabDef, btnTabOfen, btnTabCC
    btnTabCortes = CreateFrame("Button", nil, menuFiltros, "UIPanelButtonTemplate"); btnTabCortes:SetSize(86, 24); btnTabCortes:SetPoint("TOPLEFT", 16, -40); btnTabCortes:SetText(L.TAB_KICKS or "Kicks"); StyleTabButton(btnTabCortes)
    btnTabDef = CreateFrame("Button", nil, menuFiltros, "UIPanelButtonTemplate"); btnTabDef:SetSize(86, 24); btnTabDef:SetPoint("LEFT", btnTabCortes, "RIGHT", 6, 0); btnTabDef:SetText(L.TAB_DEF or "Def"); StyleTabButton(btnTabDef)
    btnTabOfen = CreateFrame("Button", nil, menuFiltros, "UIPanelButtonTemplate"); btnTabOfen:SetSize(86, 24); btnTabOfen:SetPoint("LEFT", btnTabDef, "RIGHT", 6, 0); btnTabOfen:SetText(L.TAB_OFF or "Off"); StyleTabButton(btnTabOfen)
    btnTabCC = CreateFrame("Button", nil, menuFiltros, "UIPanelButtonTemplate"); btnTabCC:SetSize(86, 24); btnTabCC:SetPoint("LEFT", btnTabOfen, "RIGHT", 6, 0); btnTabCC:SetText(L.TAB_CCS or "CCs"); StyleTabButton(btnTabCC)

    btnTabCortes:SetScript("OnClick", function() addonTable.MostrarTabFiltros(sCortes); SetTabButtonState(btnTabCortes, true); SetTabButtonState(btnTabDef, false); SetTabButtonState(btnTabOfen, false); SetTabButtonState(btnTabCC, false) end)
    btnTabDef:SetScript("OnClick", function() addonTable.MostrarTabFiltros(sDef); SetTabButtonState(btnTabCortes, false); SetTabButtonState(btnTabDef, true); SetTabButtonState(btnTabOfen, false); SetTabButtonState(btnTabCC, false) end)
    btnTabOfen:SetScript("OnClick", function() addonTable.MostrarTabFiltros(sOfen); SetTabButtonState(btnTabCortes, false); SetTabButtonState(btnTabDef, false); SetTabButtonState(btnTabOfen, true); SetTabButtonState(btnTabCC, false) end)
    btnTabCC:SetScript("OnClick", function() addonTable.MostrarTabFiltros(sCC); SetTabButtonState(btnTabCortes, false); SetTabButtonState(btnTabDef, false); SetTabButtonState(btnTabOfen, false); SetTabButtonState(btnTabCC, true) end)

    local tabGeneral = CreateFrame("Frame", "PremadeCDsTabGeneral", menuMain); tabGeneral:SetPoint("TOPLEFT", 0, -82); tabGeneral:SetPoint("BOTTOMRIGHT", 0, 52); tabGeneral:SetFrameLevel(menuMain:GetFrameLevel() + 5)
    local tabCortes = CreateFrame("Frame", "PremadeCDsTabCortes", menuMain); tabCortes:SetPoint("TOPLEFT", 0, -82); tabCortes:SetPoint("BOTTOMRIGHT", 0, 52); tabCortes:SetFrameLevel(menuMain:GetFrameLevel() + 5); tabCortes:Hide()
    local tabCCs = CreateFrame("Frame", "PremadeCDsTabCCs", menuMain); tabCCs:SetPoint("TOPLEFT", 0, -82); tabCCs:SetPoint("BOTTOMRIGHT", 0, 52); tabCCs:SetFrameLevel(menuMain:GetFrameLevel() + 5); tabCCs:Hide()
    local tabDefOfen = CreateFrame("Frame", "PremadeCDsTabDefOfen", menuMain); tabDefOfen:SetPoint("TOPLEFT", 0, -82); tabDefOfen:SetPoint("BOTTOMRIGHT", 0, 52); tabDefOfen:SetFrameLevel(menuMain:GetFrameLevel() + 5); tabDefOfen:Hide()

    local tabsDivider = menuMain:CreateTexture(nil, "ARTWORK")
    tabsDivider:SetColorTexture(1, 1, 1, 0.06)
    tabsDivider:SetHeight(1)
    tabsDivider:SetPoint("TOPLEFT", menuMain, "TOPLEFT", 24, -74)
    tabsDivider:SetPoint("TOPRIGHT", menuMain, "TOPRIGHT", -24, -74)

    local btnTabGen = CreateFrame("Button", nil, menuMain, "UIPanelButtonTemplate"); btnTabGen:SetSize(156, 26); btnTabGen:SetPoint("TOPLEFT", 36, -44); btnTabGen:SetText(L.TAB_GEN or "General"); StyleTabButton(btnTabGen)
    local btnTabCor = CreateFrame("Button", nil, menuMain, "UIPanelButtonTemplate"); btnTabCor:SetSize(156, 26); btnTabCor:SetPoint("LEFT", btnTabGen, "RIGHT", 8, 0); btnTabCor:SetText(L.TAB_KICKS or "Kicks"); StyleTabButton(btnTabCor)
    local btnTabCCMenu = CreateFrame("Button", nil, menuMain, "UIPanelButtonTemplate"); btnTabCCMenu:SetSize(156, 26); btnTabCCMenu:SetPoint("LEFT", btnTabCor, "RIGHT", 8, 0); btnTabCCMenu:SetText(L.TAB_CCS or "CCs"); StyleTabButton(btnTabCCMenu)
    local btnTabDefMenu = CreateFrame("Button", nil, menuMain, "UIPanelButtonTemplate"); btnTabDefMenu:SetSize(156, 26); btnTabDefMenu:SetPoint("LEFT", btnTabCCMenu, "RIGHT", 8, 0); btnTabDefMenu:SetText(L.TAB_DEFOFF or "Def / Off"); StyleTabButton(btnTabDefMenu)

    local function MostrarTabMenu(tab, activeBtn)
        tabGeneral:Hide(); tabCortes:Hide(); tabCCs:Hide(); tabDefOfen:Hide()
        SetTabButtonState(btnTabGen, false); SetTabButtonState(btnTabCor, false); SetTabButtonState(btnTabCCMenu, false); SetTabButtonState(btnTabDefMenu, false)
        tab:Show(); if activeBtn then SetTabButtonState(activeBtn, true) end
    end

    btnTabGen:SetScript("OnClick", function() MostrarTabMenu(tabGeneral, btnTabGen) end)
    btnTabCor:SetScript("OnClick", function() MostrarTabMenu(tabCortes, btnTabCor) end)
    btnTabCCMenu:SetScript("OnClick", function() MostrarTabMenu(tabCCs, btnTabCCMenu) end)
    btnTabDefMenu:SetScript("OnClick", function() MostrarTabMenu(tabDefOfen, btnTabDefMenu) end)

    local function CrearSlider(parent, n, txt, minV, maxV, x, y, key, opts)
        opts = opts or {}
        local sliderWidth = opts.width or 176
        local editWidth = opts.editWidth or 56
        local buttonSize = opts.buttonSize or 18
        local sliderToMinusGap = opts.sliderToMinusGap or 14
        local minusToEditGap = math.max(0, math.floor((opts.minusToEditGap or 6) * 0.5))
        local editToPlusGap = math.max(0, math.floor((opts.editToPlusGap or 6) * 0.5))

        local s = CreateFrame("Slider", n, parent, "OptionsSliderTemplate")
        s:SetWidth(sliderWidth)
        s:SetHeight(18)
        s:SetPoint("TOPLEFT", x, y)
        s:SetMinMaxValues(minV, maxV)
        s:SetValueStep(1)
        s:SetObeyStepOnDrag(true)
        if _G[n.."Text"] then
            _G[n.."Text"]:SetText(txt)
            _G[n.."Text"]:ClearAllPoints()
            _G[n.."Text"]:SetPoint("TOPLEFT", s, "TOPLEFT", 0, 26)
        end
        if _G[n.."Low"] then _G[n.."Low"]:SetText(""); _G[n.."Low"]:Hide() end
        if _G[n.."High"] then _G[n.."High"]:SetText(""); _G[n.."High"]:Hide() end

        local btnMinus = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
        btnMinus:SetSize(buttonSize, buttonSize)
        btnMinus:SetPoint("LEFT", s, "RIGHT", sliderToMinusGap, 0)
        btnMinus:SetText("-")
        StyleActionButton(btnMinus, "secondary")

        local editBox = CreateFrame("EditBox", n.."Edit", parent, "InputBoxTemplate")
        editBox:SetSize(editWidth, 20)
        editBox:SetPoint("LEFT", btnMinus, "RIGHT", minusToEditGap, 0)
        editBox:SetAutoFocus(false)
        editBox:SetNumeric(false)
        editBox:SetJustifyH("CENTER")
        if editBox.Left then editBox.Left:Hide() end
        if editBox.Middle then editBox.Middle:Hide() end
        if editBox.Right then editBox.Right:Hide() end
        editBox:SetJustifyH("CENTER")
        editBox:SetTextInsets(0, 0, 0, 0)

        local btnPlus = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
        btnPlus:SetSize(buttonSize, buttonSize)
        btnPlus:SetPoint("LEFT", editBox, "RIGHT", editToPlusGap, 0)
        btnPlus:SetText("+")
        StyleActionButton(btnPlus, "secondary")

        local function ClampValue(v)
            local val = math.floor(tonumber(v) or minV)
            if val < minV then val = minV end
            if val > maxV then val = maxV end
            return val
        end

        local function ApplySliderValue(val)
            val = ClampValue(val)
            if s:GetValue() ~= val then
                s:SetValue(val)
            else
                db[key] = val
                editBox:SetText(val)
                if s.trackFill then s.trackFill:SetValue(val) end
                if addonTable.ActualizarTodoEnVivo then addonTable.ActualizarTodoEnVivo() end
            end
        end

        s:SetScript("OnValueChanged", function(self, v)
            local val = ClampValue(v + 0.5)
            db[key] = val
            editBox:SetText(val)
            if self.trackFill then self.trackFill:SetValue(val) end
            if addonTable.ActualizarTodoEnVivo then addonTable.ActualizarTodoEnVivo() end
        end)

        btnMinus:SetScript("OnClick", function() ApplySliderValue((db[key] or s:GetValue()) - 1) end)
        btnPlus:SetScript("OnClick", function() ApplySliderValue((db[key] or s:GetValue()) + 1) end)
        editBox:SetScript("OnEnterPressed", function(self) local val = tonumber(self:GetText()); if val then ApplySliderValue(val) else self:SetText(math.floor(s:GetValue() + 0.5)) end; self:ClearFocus() end)
        editBox:SetScript("OnEditFocusLost", function(self) local val = tonumber(self:GetText()); if val then ApplySliderValue(val) else self:SetText(math.floor(s:GetValue() + 0.5)) end end)
        editBox:SetScript("OnEscapePressed", function(self) self:SetText(math.floor(s:GetValue() + 0.5)); self:ClearFocus() end)
        StyleRectSlider(s, n, minV, maxV)
        if s.trackFill then s.trackFill:SetValue(db[key] or minV) end
        uiElements.sliders[key] = s; uiElements.valStrs[key] = editBox
        return s, editBox, btnMinus, btnPlus
    end

    selectorPopup = CreateThemedWindow("PremadeCDsSelectorPopup", UIParent, 360, 430, "TOPLEFT", menuMain, "TOPRIGHT", 6, 0, "DIALOG")
    selectorPopup:Hide()
    ApplyFrameChrome(selectorPopup)
    selectorPopup:SetMovable(false)
    selectorPopup:RegisterForDrag()
    selectorPopup:SetScript("OnDragStart", nil)
    selectorPopup:SetScript("OnDragStop", nil)
    selectorPopup.title = selectorPopup:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    selectorPopup.title:SetPoint("TOP", selectorPopup.TitleBg, "TOP", 0, -3)
    selectorPopup.title:SetText(L.SELECT or "Select")

    local function AnchorSelectorPopupToMain()
        selectorPopup:ClearAllPoints()
        selectorPopup:SetPoint("TOPLEFT", menuMain, "TOPRIGHT", 6, 0)
    end
    selectorPopup:HookScript("OnShow", function(self)
        AnchorSelectorPopupToMain()
        self:Raise()
    end)
    selectorPopup:HookScript("OnMouseDown", function(self)
        AnchorSelectorPopupToMain()
        self:Raise()
    end)
    menuMain:HookScript("OnShow", function()
        if selectorPopup:IsShown() then AnchorSelectorPopupToMain() end
    end)
    menuMain:HookScript("OnDragStop", function()
        if selectorPopup:IsShown() then AnchorSelectorPopupToMain() end
    end)

    selectorPopup.scrollFrame = CreateFrame("ScrollFrame", nil, selectorPopup, "UIPanelScrollFrameTemplate")
    selectorPopup.scrollFrame:SetPoint("TOPLEFT", 16, -40)
    selectorPopup.scrollFrame:SetPoint("BOTTOMRIGHT", -34, 46)
    StyleScrollFrame(selectorPopup.scrollFrame)

    selectorPopup.scrollBg = selectorPopup:CreateTexture(nil, "BORDER")
    selectorPopup.scrollBg:SetPoint("TOPLEFT", selectorPopup.scrollFrame, "TOPLEFT", 0, 0)
    selectorPopup.scrollBg:SetPoint("BOTTOMRIGHT", selectorPopup.scrollFrame, "BOTTOMRIGHT", -16, 0)
    selectorPopup.scrollBg:SetTexture("Interface\\Buttons\\WHITE8X8")
    selectorPopup.scrollBg:SetVertexColor(0, 0, 0, 1)

    selectorPopup.content = CreateFrame("Frame", nil, selectorPopup.scrollFrame)
    selectorPopup.content:SetSize(1, 1)
    selectorPopup.scrollFrame:SetScrollChild(selectorPopup.content)

    selectorPopup.contentBg = selectorPopup.content:CreateTexture(nil, "BACKGROUND")
    selectorPopup.contentBg:SetPoint("TOPLEFT", selectorPopup.content, "TOPLEFT", 0, 0)
    selectorPopup.contentBg:SetPoint("BOTTOMRIGHT", selectorPopup.content, "BOTTOMRIGHT", 0, 0)
    selectorPopup.contentBg:SetTexture("Interface\\Buttons\\WHITE8X8")
    selectorPopup.contentBg:SetVertexColor(0, 0, 0, 1)

    selectorPopup.emptyText = selectorPopup.content:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    selectorPopup.emptyText:SetPoint("TOPLEFT", 8, -8)
    selectorPopup.emptyText:SetText(L.NO_RESULTS or "No results")
    selectorPopup.emptyText:Hide()

    selectorPopup.closeBtn = CreateFrame("Button", nil, selectorPopup, "UIPanelButtonTemplate")
    selectorPopup.closeBtn:SetSize(120, 26)
    selectorPopup.closeBtn:SetPoint("BOTTOM", selectorPopup, "BOTTOM", 0, 14)
    selectorPopup.closeBtn:SetText(L.CLOSE or "Close")
    StyleActionButton(selectorPopup.closeBtn, "primary")
    selectorPopup.closeBtn:SetScript("OnClick", function() selectorPopup:Hide() end)

    selectorPopup.rows = {}

    local function EnsureSelectorRow(index)
        if selectorPopup.rows[index] then return selectorPopup.rows[index] end
        local row = CreateFrame("Button", nil, selectorPopup.content)
        row:SetSize(300, 34)

        row.bg = row:CreateTexture(nil, "BACKGROUND")
        row.bg:SetAllPoints()
        row.bg:SetColorTexture(0.04, 0.04, 0.04, 0.96)

        row.hl = row:CreateTexture(nil, "HIGHLIGHT")
        row.hl:SetAllPoints()
        row.hl:SetColorTexture(1, 1, 1, 0.04)

        row.sel = row:CreateTexture(nil, "ARTWORK")
        row.sel:SetAllPoints()
        row.sel:SetColorTexture(1, 0.82, 0, 0.28)
        row.sel:Hide()

        row.label = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
        row.label:SetPoint("LEFT", 8, 0)
        row.label:SetJustifyH("LEFT")
        row.label:SetWidth(150)

        row.previewFont = row:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        row.previewFont:SetPoint("RIGHT", -8, 0)
        row.previewFont:SetWidth(130)
        row.previewFont:SetJustifyH("RIGHT")

        row.previewBarBg = row:CreateTexture(nil, "BORDER")
        row.previewBarBg:SetPoint("RIGHT", -8, 0)
        row.previewBarBg:SetSize(128, 14)
        row.previewBarBg:SetColorTexture(0.02, 0.02, 0.02, 1)
        row.previewBarBg:Hide()

        row.previewBar = CreateFrame("StatusBar", nil, row)
        row.previewBar:SetPoint("CENTER", row.previewBarBg, "CENTER", 0, 0)
        row.previewBar:SetSize(124, 10)
        row.previewBar:SetMinMaxValues(0, 1)
        row.previewBar:SetValue(1)
        row.previewBar:Hide()

        row.previewSwatchBg = row:CreateTexture(nil, "BORDER")
        row.previewSwatchBg:SetPoint("RIGHT", -8, 0)
        row.previewSwatchBg:SetSize(128, 18)
        row.previewSwatchBg:SetColorTexture(0.02, 0.02, 0.02, 1)
        row.previewSwatchBg:Hide()

        row.previewSwatch = row:CreateTexture(nil, "ARTWORK")
        row.previewSwatch:SetPoint("CENTER", row.previewSwatchBg, "CENTER", 0, 0)
        row.previewSwatch:SetSize(124, 14)
        row.previewSwatch:Hide()

        row.previewBorderSample = CreateFrame("Frame", nil, row, "BackdropTemplate")
        row.previewBorderSample:SetPoint("RIGHT", -8, 0)
        row.previewBorderSample:SetSize(128, 20)
        row.previewBorderSample:Hide()

        if selectorPopup and selectorPopup.GetFrameStrata then
            row:SetFrameStrata(selectorPopup:GetFrameStrata())
            row:SetFrameLevel((selectorPopup:GetFrameLevel() or 0) + 4)
        end
        selectorPopup.rows[index] = row
        return row
    end

    local function SelectorMatches(op, query)
        if not query or query == "" then return true end
        local q = string.lower(query)
        return string.find(string.lower(op.label or op.name or ""), q, 1, true) ~= nil
            or string.find(string.lower(op.name or ""), q, 1, true) ~= nil
    end

    local function RefreshSelectorPopup()
        if not selectorPopup.config then return end
        local cfg = selectorPopup.config
        local visibleIndex = 0
        local rowWidth = 300
        local query = ""

        for _, row in ipairs(selectorPopup.rows) do row:Hide() end

        for _, op in ipairs(cfg.options or {}) do
            if SelectorMatches(op, query) then
                visibleIndex = visibleIndex + 1
                local row = EnsureSelectorRow(visibleIndex)
                row:SetWidth(rowWidth)
                row:SetPoint("TOPLEFT", 0, -((visibleIndex - 1) * 36))
                row.option = op
                row.key = cfg.key
                row.buttonToUpdate = cfg.button
                row.label:SetText(op.label or op.name)
                
                if cfg.key and db[cfg.key] == op.name then
                    row.sel:Show()
                else
                    row.sel:Hide()
                end

                row.previewFont:Hide()
                row.previewBarBg:Hide()
                row.previewBar:Hide()
                row.previewSwatchBg:Hide()
                row.previewSwatch:Hide()
                row.previewBorderSample:Hide()

                if cfg.previewType == "font" then
                    row.previewFont:Show()
                    local ok = row.previewFont:SetFont(op.path or "Fonts\\FRIZQT__.TTF", 14, "OUTLINE")
                    if not ok then row.previewFont:SetFont("Fonts\\FRIZQT__.TTF", 14, "OUTLINE") end
                    row.previewFont:SetText("Abc 123")
                elseif cfg.previewType == "texture" then
                    row.previewBarBg:Show()
                    row.previewBar:Show()
                    row.previewBar:SetStatusBarTexture(op.path or "Interface\\TargetingFrame\\UI-StatusBar")
                    row.previewBar:SetStatusBarColor(1, 0.82, 0)
                elseif cfg.previewType == "background" then
                    row.previewSwatchBg:Show()
                    row.previewSwatch:Show()
                    row.previewSwatch:SetTexture(op.path or "Interface\\Buttons\\WHITE8X8")
                    row.previewSwatch:SetHorizTile(true)
                    row.previewSwatch:SetVertTile(true)
                    row.previewSwatch:SetVertexColor(1, 1, 1, 1)
                elseif cfg.previewType == "border" then
                    row.previewBorderSample:Show()
                    row.previewBorderSample:SetBackdrop({
                        bgFile = "Interface\\Buttons\\WHITE8X8",
                        edgeFile = op.path or "Interface\\Tooltips\\UI-Tooltip-Border",
                        tile = true,
                        tileSize = 8,
                        edgeSize = 8,
                        insets = { left = 2, right = 2, top = 2, bottom = 2 },
                    })
                    row.previewBorderSample:SetBackdropColor(0, 0, 0, 0.85)
                    row.previewBorderSample:SetBackdropBorderColor(1, 1, 1, 0.9)
                end

                -- ¡EL CÓDIGO BLINDADO ANTIFALLOS!
                row:SetScript("OnClick", function(self)
                    local optName = self.option and self.option.name
                    local optLabel = self.option and (self.option.label or self.option.name)
                    
                    if self.key ~= nil then 
                        db[self.key] = optName 
                    end
                    
                    if self.buttonToUpdate then 
                        self.buttonToUpdate:SetText(optLabel) 
                    end
                    
                    selectorPopup:Hide()
                    
                    if selectorPopup.config and selectorPopup.config.onSelect then 
                        selectorPopup.config.onSelect(optName) 
                    end
                    
                    if addonTable.ActualizarTodoEnVivo then 
                        addonTable.ActualizarTodoEnVivo() 
                    end
                end)
                row:Show()
            end
        end

        selectorPopup.emptyText:SetShown(visibleIndex == 0)
        selectorPopup.content:SetSize(rowWidth, math.max(visibleIndex * 36, 1))
        if selectorPopup.contentBg then selectorPopup.contentBg:SetAllPoints(selectorPopup.content) end
    end

    local function AbrirSelectorPopup(config)
        selectorPopup.config = config
        selectorPopup.title:SetText(config.title or L.SELECT or "Select")
        RefreshSelectorPopup()
        if menuFiltros and menuFiltros:IsShown() then menuFiltros:Hide() end
        selectorPopup:Show()
    end

    local function CrearSelectorPopup(parent, nombre, titulo, x, y, key, opciones, previewType, onSelect, buttonWidth)
        local lbl = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        lbl:SetPoint("TOPLEFT", x, y)
        lbl:SetText(titulo)

        local btn = CreateFrame("Button", nombre, parent, "UIPanelButtonTemplate")
        btn:SetSize(buttonWidth or 160, 24)
        btn:SetPoint("TOPLEFT", x, y - 22)

        local selectedLabel = L.SELECT or "Select..."
        for _, op in ipairs(opciones) do
            if op.name == db[key] then
                selectedLabel = op.label or op.name
                break
            end
        end
        btn:SetText(selectedLabel)
        StyleActionButton(btn, "accent")

        customSelectors[key] = { button = btn, options = opciones }

        btn:SetScript("OnClick", function()
            AbrirSelectorPopup({
                key = key,
                title = titulo,
                options = opciones,
                previewType = previewType,
                button = btn,
                onSelect = onSelect,
            })
        end)

        return btn
    end

    local function CrearDropdownOpciones(parent, nombre, titulo, x, y, key, opciones, width)
        local lbl = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        lbl:SetPoint("TOPLEFT", x, y)
        lbl:SetText(titulo)

        local btn = CreateFrame("Button", nombre, parent, "UIPanelButtonTemplate")
        btn:SetSize(width or 220, 24)
        btn:SetPoint("TOPLEFT", x, y - 22)
        StyleActionButton(btn, "accent")

        customSelectors[key] = { button = btn, options = opciones }

        local function RefreshLabel()
            local selectedLabel = db[key] or L.SELECT or "Select..."
            for _, op in ipairs(opciones) do
                if op.name == db[key] then
                    selectedLabel = op.label or op.name
                    break
                end
            end
            btn:SetText(selectedLabel)
        end
        RefreshLabel()

        btn:SetScript("OnClick", function()
            AbrirSelectorPopup({
                key = key,
                title = titulo,
                options = opciones,
                previewType = nil,
                button = btn,
                onSelect = function(selectedName)
                    db[key] = selectedName
                    RefreshLabel()
                    if addonTable.ActualizarTodoEnVivo then addonTable.ActualizarTodoEnVivo() end
                end,
            })
        end)

        return btn
    end

    local function StyleSquareCheck(cb, labelText, width)
        width = width or 280
        cb:SetSize(width, 20)

        cb.box = cb:CreateTexture(nil, "BACKGROUND")
        cb.box:SetSize(16, 16)
        cb.box:SetPoint("LEFT", 0, 0)
        cb.box:SetColorTexture(0.02, 0.02, 0.03, FRAME_OPACITY * 0.95)

        cb.fill = cb:CreateTexture(nil, "ARTWORK")
        cb.fill:SetSize(10, 10)
        cb.fill:SetPoint("CENTER", cb.box, "CENTER", 0, 0)
        cb.fill:SetColorTexture(playerClassColor.r or 1, playerClassColor.g or 1, playerClassColor.b or 1, 0.95)

        cb.borderTop = cb:CreateTexture(nil, "BORDER")
        cb.borderTop:SetHeight(1)
        cb.borderTop:SetPoint("TOPLEFT", cb.box, "TOPLEFT", 0, 0)
        cb.borderTop:SetPoint("TOPRIGHT", cb.box, "TOPRIGHT", 0, 0)

        cb.borderBottom = cb:CreateTexture(nil, "BORDER")
        cb.borderBottom:SetHeight(1)
        cb.borderBottom:SetPoint("BOTTOMLEFT", cb.box, "BOTTOMLEFT", 0, 0)
        cb.borderBottom:SetPoint("BOTTOMRIGHT", cb.box, "BOTTOMRIGHT", 0, 0)

        cb.borderLeft = cb:CreateTexture(nil, "BORDER")
        cb.borderLeft:SetWidth(1)
        cb.borderLeft:SetPoint("TOPLEFT", cb.box, "TOPLEFT", 0, 0)
        cb.borderLeft:SetPoint("BOTTOMLEFT", cb.box, "BOTTOMLEFT", 0, 0)

        cb.borderRight = cb:CreateTexture(nil, "BORDER")
        cb.borderRight:SetWidth(1)
        cb.borderRight:SetPoint("TOPRIGHT", cb.box, "TOPRIGHT", 0, 0)
        cb.borderRight:SetPoint("BOTTOMRIGHT", cb.box, "BOTTOMRIGHT", 0, 0)

        local br, bg, bb = GetClassTint(1.0, 1)
        cb.borderTop:SetColorTexture(br, bg, bb, 0.95)
        cb.borderBottom:SetColorTexture(br, bg, bb, 0.95)
        cb.borderLeft:SetColorTexture(br, bg, bb, 0.95)
        cb.borderRight:SetColorTexture(br, bg, bb, 0.95)

        cb.highlight = cb:CreateTexture(nil, "HIGHLIGHT")
        cb.highlight:SetSize(width, 20)
        cb.highlight:SetPoint("CENTER")
        cb.highlight:SetColorTexture(br, bg, bb, 0.08)

        cb.label = cb:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
        cb.label:SetPoint("LEFT", cb.box, "RIGHT", 8, 0)
        cb.label:SetJustifyH("LEFT")
        cb.label:SetText(labelText or "")

        function cb:RefreshVisual()
            if self:GetChecked() then
                self.fill:Show()
                self.box:SetColorTexture(0.03, 0.03, 0.04, FRAME_OPACITY * 0.95)
            else
                self.fill:Hide()
                self.box:SetColorTexture(0.02, 0.02, 0.03, FRAME_OPACITY * 0.95)
            end
        end

        cb:SetScript("OnShow", function(self) self:RefreshVisual() end)
        cb:RefreshVisual()
    end

    local function CrearCheck(parent, n, txt, x, y, key, width)
        local cb = CreateFrame("CheckButton", n, parent)
        cb:SetPoint("TOPLEFT", x, y)
        StyleSquareCheck(cb, txt, width or 280)
        cb:SetScript("OnClick", function(self)
            db[key] = self:GetChecked()
            self:RefreshVisual()
            if addonTable.ActualizarTodoEnVivo then addonTable.ActualizarTodoEnVivo() end
        end)
        uiElements.checks[key] = cb
        return cb
    end

    local titleGeneral = CreateTabHeading(tabGeneral, L.HEADER_GEN or "General Settings")
    local titleKicks = CreateTabHeading(tabCortes, L.HEADER_KICKS or "Interrupt Cooldowns")
    local titleCCs = CreateTabHeading(tabCCs, L.HEADER_CCS or "Crowd Control")
    local titleDef = CreateTabHeading(tabDefOfen, L.HEADER_DEF or "Defensive & Offensive Cooldowns")

    -- KICKS TAB
    local secKickBars = CreateSection(tabCortes, L.SEC_BARS or "Bars", 24, -42, 322, 288)
    CrearSlider(secKickBars, "PCD_SAncho", L.BAR_WIDTH or "Width", 50, 600, 18, -72, "width", { width = 180, editWidth = 56, sliderToMinusGap = 14, minusToEditGap = 6, editToPlusGap = 6 })
    CrearSlider(secKickBars, "PCD_SAlto", L.BAR_HEIGHT or "Height", 10, 100, 18, -154, "height", { width = 180, editWidth = 56, sliderToMinusGap = 14, minusToEditGap = 6, editToPlusGap = 6 })
    CrearSlider(secKickBars, "PCD_SFuente", L.TIMER_SIZE or "Timer Size", 6, 64, 18, -236, "fontSizeName", { width = 180, editWidth = 56, sliderToMinusGap = 14, minusToEditGap = 6, editToPlusGap = 6 })

    local secKickText = CreateSection(tabCortes, L.SEC_TEXT or "Text & Alerts", 374, -42, 322, 288)
    CrearSlider(secKickText, "PCD_SFuenteNombre", L.NAME_SIZE or "Name Size", 6, 64, 18, -72, "nameFontSize", { width = 180, editWidth = 56, sliderToMinusGap = 14, minusToEditGap = 6, editToPlusGap = 6 })
    CrearCheck(secKickText, "PCD_CBTTS", L.VOICE_ALERT or "TTS Voice Alert", 18, -154, "ttsEnabled")
    CrearCheck(secKickText, "PCD_CBListo", L.SHOW_READY or "Show 'READY' text", 18, -194, "showListo")

    local secKickBehavior = CreateSection(tabCortes, L.SEC_BEHAVIOR or "Behavior", 24, -346, 672, 132)
    CrearSelectorPopup(secKickBehavior, "PCDSortDrop", L.KICK_ORDER or "Interrupt Sort:", 18, -54, "sortMode", {
        {name = "CD_ASC", label = L.ASCENDING or "Ascending"},
        {name = "CD_DESC", label = L.DESCENDING or "Descending"},
        {name = "NONE", label = L.NONE or "None"}
    }, nil, nil, 220)

    -- CCS TAB
    local secCCLayout = CreateSection(tabCCs, L.SEC_LAYOUT or "Layout", 24, -42, 322, 272)
    CrearSlider(secCCLayout, "PCD_SCCSize", L.CC_SIZE or "CC Size", 10, 100, 18, -72, "ccSize", { width = 180, editWidth = 56, sliderToMinusGap = 14, minusToEditGap = 6, editToPlusGap = 6 })
    CrearSlider(secCCLayout, "PCD_SCCRow", L.CCS_PER_ROW or "CCs per Row", 1, 20, 18, -154, "ccPerRow", { width = 180, editWidth = 56, sliderToMinusGap = 14, minusToEditGap = 6, editToPlusGap = 6 })
    CrearSlider(secCCLayout, "PCD_SCCSpacing", L.SPACING or "Spacing", 0, 50, 18, -236, "ccSpacing", { width = 180, editWidth = 56, sliderToMinusGap = 14, minusToEditGap = 6, editToPlusGap = 6 })

    local secCCBehavior = CreateSection(tabCCs, L.SEC_BEHAVIOR or "Behavior", 374, -42, 322, 272)
    CrearSelectorPopup(secCCBehavior, "PCDCCGrowDir", L.GROW_DIR or "Grow Direction:", 18, -64, "ccGrowDirection", {
        {name = "RIGHT_DOWN", label = L.RD or "Right / Down"},
        {name = "LEFT_DOWN", label = L.LD or "Left / Down"},
        {name = "RIGHT_UP", label = L.RU or "Right / Up"},
        {name = "LEFT_UP", label = L.LU or "Left / Up"}
    }, nil, nil, 220)

    local ccHint = secCCBehavior:CreateFontString(nil, "OVERLAY", "GameFontDisableSmall")
    ccHint:SetPoint("TOPLEFT", 18, -144)
    ccHint:SetWidth(270)
    ccHint:SetJustifyH("LEFT")
    ccHint:SetText(L.CC_HINT or "Choose how crowd control icons expand.")

    -- DEF / OFF TAB
    local secDefIcons = CreateSection(tabDefOfen, L.SEC_ICONS or "Icons", 24, -42, 322, 404)
    CrearSlider(secDefIcons, "PCD_SIconSize", L.ICON_SIZE or "Size", 10, 100, 18, -72, "iconSize", { width = 180, editWidth = 56, sliderToMinusGap = 14, minusToEditGap = 6, editToPlusGap = 6 })
    CrearSlider(secDefIcons, "PCD_SPerRow", L.PER_ROW or "Per Row", 1, 20, 18, -154, "iconsPerRow", { width = 180, editWidth = 56, sliderToMinusGap = 14, minusToEditGap = 6, editToPlusGap = 6 })
    CrearSlider(secDefIcons, "PCD_SSpacing", L.SPACING or "Spacing", 0, 50, 18, -236, "iconSpacing", { width = 180, editWidth = 56, sliderToMinusGap = 14, minusToEditGap = 6, editToPlusGap = 6 })
    CrearSelectorPopup(secDefIcons, "PCDGrowDir", L.GROW_DIR or "Grow Direction:", 18, -314, "growDirection", {
        {name = "AUTO", label = L.AUTO or "Auto"},
        {name = "RIGHT_DOWN", label = L.RD or "Right / Down"},
        {name = "LEFT_DOWN", label = L.LD or "Left / Down"},
        {name = "RIGHT_UP", label = L.RU or "Right / Up"},
        {name = "LEFT_UP", label = L.LU or "Left / Up"}
    }, nil, nil, 220)
    CrearCheck(secDefIcons, "PCD_CBDefFirst", L.SHOW_DEF_FIRST or "Defensives on 1st Row", 18, -370, "defensivosFirst")

    local secAnchors = CreateSection(tabDefOfen, L.SEC_ANCHORS or "Anchors", 374, -42, 322, 404)
    CrearSelectorPopup(secAnchors, "PCDAnchorMode", L.ANCHOR_MODE or "Anchor Mode:", 18, -64, "anchorMode", {
        {name = "Auto", label = L.AUTO or "Auto"},
        {name = "Manual", label = L.MANUAL or "Manual"}
    }, nil, nil, 220)
    CrearSelectorPopup(secAnchors, "PCDAnchorSide", L.ANCHOR_SIDE or "Anchor Side:", 18, -150, "anchorSide", {
        {name = "LEFT", label = L.LEFT or "Left"},
        {name = "RIGHT", label = L.RIGHT or "Right"},
        {name = "TOP", label = L.TOP or "Top"},
        {name = "BOTTOM", label = L.BOTTOM or "Bottom"}
    }, nil, nil, 220)
    CrearSlider(secAnchors, "PCD_SOffsetX", L.OFFSET_X or "Offset X", -500, 500, 18, -258, "offsetX", { width = 166, editWidth = 56, sliderToMinusGap = 14, minusToEditGap = 6, editToPlusGap = 6 })
    CrearSlider(secAnchors, "PCD_SOffsetY", L.OFFSET_Y or "Offset Y", -500, 500, 18, -342, "offsetY", { width = 166, editWidth = 56, sliderToMinusGap = 14, minusToEditGap = 6, editToPlusGap = 6 })

    -- ===================================================
    -- GENERAL TAB RE-AJUSTADO (Secciones en su tamaño original)
    -- ===================================================
    local secCategories = CreateSection(tabGeneral, L.SEC_CAT or "Categories", 24, -42, 322, 178)
    CrearCheck(secCategories, "PCD_CBCatCortes", L.SHOW_KICKS or "Show Kicks", 18, -42, "showCortes")
    CrearCheck(secCategories, "PCD_CBCatDef", L.SHOW_DEF or "Show Defensives", 18, -78, "showDefensivos")
    CrearCheck(secCategories, "PCD_CBCatOfen", L.SHOW_OFF or "Show Offensives", 18, -114, "showOfensivos")
    CrearCheck(secCategories, "PCD_CBCatCC", L.SHOW_CCS or "Show CCs", 18, -150, "showCCs")

    local secZone = CreateSection(tabGeneral, L.SEC_ZONES or "Zones", 374, -42, 322, 178)
    CrearCheck(secZone, "PCD_CBDungeon", L.DUNGEONS or "Dungeons", 18, -42, "activeDungeon")
    CrearCheck(secZone, "PCD_CBRaid", L.RAID or "Raids", 18, -78, "activeRaid")
    CrearCheck(secZone, "PCD_CBWorld", L.OPEN_WORLD or "Open World", 18, -114, "activeWorld")
    CrearCheck(secZone, "PCD_CBPvP", L.PVP or "PvP", 18, -150, "activePvp")

    local secVisuals = CreateSection(tabGeneral, L.SEC_VISUALS or "Visuals", 24, -238, 672, 136)
    local fonts = addonTable.Media and addonTable.Media.GetAvailableFonts and addonTable.Media:GetAvailableFonts() or {}
    local textures = addonTable.Media and addonTable.Media.GetAvailableTextures and addonTable.Media:GetAvailableTextures() or {}
    
    local fontOpts = {}; for _, f in ipairs(fonts) do table.insert(fontOpts, {name=f.name, label=f.name, path=f.path}) end
    local texOpts = {}; for _, t in ipairs(textures) do table.insert(texOpts, {name=t.name, label=t.name, path=t.path}) end
    
    CrearSelectorPopup(secVisuals, "PCDFontSelector", L.FONT or "Font:", 54, -64, "fontName", fontOpts, "font")
    CrearSelectorPopup(secVisuals, "PCDTexSelector", L.TEXTURE or "Texture:", 282, -64, "textureName", texOpts, "texture")
    CrearCheck(secVisuals, "PCD_CBPixelPerfect", L.PIXEL_PERFECT or "Pixel Perfect", 502, -86, "pixelPerfect", 140)

    local secProfiles = CreateSection(tabGeneral, L.SEC_PROFILES or "Profiles", 24, -392, 672, 184)
    lblPerfilActual = secProfiles:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    lblPerfilActual:SetPoint("TOPLEFT", 18, -42)

    local btnGuardarPerfil = CreateFrame("Button", nil, secProfiles, "UIPanelButtonTemplate")
    btnGuardarPerfil:SetSize(132, 26)
    btnGuardarPerfil:SetPoint("TOPLEFT", 18, -72)
    btnGuardarPerfil:SetText(L.SAVE_PROFILE or "Save Profile")
    StyleActionButton(btnGuardarPerfil, "accent")

    btnGuardarPerfil:SetScript("OnClick", function()
        if addonTable.GuardarTodasLasAnclas then addonTable.GuardarTodasLasAnclas() end
        if db.profileName and PremadeCDsDB and PremadeCDsDB.profiles then
            PremadeCDsDB.profiles[db.profileName] = {}
            DeepCopy(db, PremadeCDsDB.profiles[db.profileName])
        end
        print("|cffffd100[PremadeCDs]|r " .. (L.PROFILE_SAVED or "Profile saved successfully."))
    end)

    local editBoxPerfil = CreateFrame("EditBox", "PremadeCDsProfileEditBox", secProfiles, "InputBoxTemplate")
    editBoxPerfil:SetSize(160, 22)
    editBoxPerfil:SetPoint("TOPLEFT", 18, -114)
    editBoxPerfil:SetAutoFocus(false)
    editBoxPerfil:SetScript("OnEnterPressed", function(self) self:ClearFocus() end)

    local btnCrearPerfil = CreateFrame("Button", nil, secProfiles, "UIPanelButtonTemplate")
    btnCrearPerfil:SetSize(112, 26)
    btnCrearPerfil:SetPoint("LEFT", editBoxPerfil, "RIGHT", 12, 0)
    btnCrearPerfil:SetText(L.CREATE or "Create")
    StyleActionButton(btnCrearPerfil, "secondary")
    btnCrearPerfil:SetScript("OnClick", function()
        local txt = editBoxPerfil:GetText()
        if txt and txt ~= "" then
            if PremadeCDsDB.profiles[txt] then return end
            if addonTable.GuardarTodasLasAnclas then addonTable.GuardarTodasLasAnclas() end
            PremadeCDsDB.profiles[txt] = {}; DeepCopy(db, PremadeCDsDB.profiles[txt])
            PremadeCDsDB.profiles[txt].profileName = txt
            addonTable.AplicarPerfil(txt); editBoxPerfil:SetText(""); editBoxPerfil:ClearFocus()
        end
    end)

    local lblCopiar = secProfiles:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    lblCopiar:SetPoint("TOPLEFT", 18, -150)
    lblCopiar:SetText(L.LOAD or "Load Profile:")

    local function BuildProfileOptions()
        local opts = {}
        if PremadeCDsDB and PremadeCDsDB.profiles then
            for pName, _ in pairs(PremadeCDsDB.profiles) do
                table.insert(opts, { name = pName, label = pName })
            end
            table.sort(opts, function(a, b) return a.label < b.label end)
        end
        return opts
    end

    -- AL CARGAR PERFILES LE DECIMOS A QUÉ "KEY" PERTENECE
    dropdownPerfiles = CreateFrame("Button", "PremadeCDsProfileDropdown", secProfiles, "UIPanelButtonTemplate")
    dropdownPerfiles:SetPoint("LEFT", lblCopiar, "RIGHT", 10, 0)
    dropdownPerfiles:SetSize(170, 24)
    StyleActionButton(dropdownPerfiles, "accent")
    dropdownPerfiles:SetText(db.profileName or "Default")
    dropdownPerfiles:SetScript("OnClick", function()
        AbrirSelectorPopup({
            key = "profileName",
            title = L.LOAD or "Load Profile:",
            options = BuildProfileOptions(),
            previewType = nil,
            button = dropdownPerfiles,
            onSelect = function(selectedName)
                addonTable.AplicarPerfil(selectedName)
                dropdownPerfiles:SetText(selectedName or "Default")
            end,
        })
    end)

    local btnEliminar = CreateFrame("Button", nil, secProfiles, "UIPanelButtonTemplate")
    btnEliminar:SetSize(96, 26)
    btnEliminar:SetPoint("LEFT", dropdownPerfiles, "RIGHT", 12, 0)
    btnEliminar:SetText(L.DELETE or "Delete")
    StyleActionButton(btnEliminar, "secondary")
    btnEliminar:SetScript("OnClick", function() if db.profileName == "Default" then return end; PremadeCDsDB.profiles[db.profileName] = nil; addonTable.AplicarPerfil("Default") end)

    local tCredits = secProfiles:CreateFontString(nil, "OVERLAY", "GameFontDisableSmall")
    tCredits:SetWidth(220)
    tCredits:SetJustifyH("RIGHT")
    tCredits:SetPoint("BOTTOMRIGHT", secProfiles, "BOTTOMRIGHT", -12, 10)
    tCredits:SetText("|cff9f9f9fCreated by |cffffd100Skorms|r |cff9f9f9f&|r |cffffd100Ankito|r")

    local footerDivider = menuMain:CreateTexture(nil, "ARTWORK")
    footerDivider:SetColorTexture(1, 1, 1, 0.06)
    footerDivider:SetHeight(1)
    footerDivider:SetPoint("BOTTOMLEFT", menuMain, "BOTTOMLEFT", 16, 48)
    footerDivider:SetPoint("BOTTOMRIGHT", menuMain, "BOTTOMRIGHT", -16, 48)

    -- ===================================================
    -- BARRA INFERIOR (Test, IDIOMA en el centro, Filtros)
    -- ===================================================
    local btnTestGlobal = CreateFrame("Button", nil, menuMain, "UIPanelButtonTemplate")
    btnTestGlobal:SetSize(116, 30)
    btnTestGlobal:SetPoint("BOTTOMLEFT", menuMain, "BOTTOMLEFT", 18, 12)
    btnTestGlobal:SetText(L.TEST_MODE or "Test Mode")
    StyleActionButton(btnTestGlobal, "secondary")
    btnTestGlobal:SetScript("OnClick", function() if addonTable.IniciarModoTest then addonTable.IniciarModoTest() end end)
    addonTable.btnTestGlobal = btnTestGlobal

    -- Botón Central de Idiomas
    local langOpts = {
        {name = "Auto", label = L.LANG_AUTO or "Auto-Detect"},
        {name = "enUS", label = "English"},
        {name = "esES", label = "Español"}
    }
    local btnLanguage = CreateFrame("Button", nil, menuMain, "UIPanelButtonTemplate")
    btnLanguage:SetSize(164, 30)
    btnLanguage:SetPoint("BOTTOM", menuMain, "BOTTOM", 0, 12)
    customSelectors["language"] = { button = btnLanguage, options = langOpts }
    
    local function UpdateLanguageButtonText()
        local selLabel = L.LANG_AUTO or "Auto-Detect"
        for _, op in ipairs(langOpts) do
            if op.name == (db.language or "Auto") then selLabel = op.label or op.name break end
        end
        btnLanguage:SetText((L.LANGUAGE or "Language:") .. " " .. selLabel)
    end
    UpdateLanguageButtonText()
    StyleActionButton(btnLanguage, "primary")
    
    btnLanguage:SetScript("OnClick", function()
        AbrirSelectorPopup({
            key = "language",
            title = L.LANGUAGE or "Language",
            options = langOpts,
            previewType = nil,
            button = nil,
            onSelect = function(sel)
                UpdateLanguageButtonText()
                print("|cffffd100[PremadeCDs]|r " .. (L.RELOAD_REQ or "Please type /reload to apply language changes."))
            end,
        })
    end)

    local btnFiltro = CreateFrame("Button", nil, menuMain, "UIPanelButtonTemplate")
    btnFiltro:SetSize(116, 30)
    btnFiltro:SetPoint("BOTTOMRIGHT", menuMain, "BOTTOMRIGHT", -18, 12)
    btnFiltro:SetText(L.FILTERS or "Filters")
    StyleActionButton(btnFiltro, "accent")
    btnFiltro:SetScript("OnClick", function()
        if menuFiltros:IsShown() then
            menuFiltros:Hide()
        else
            if selectorPopup and selectorPopup:IsShown() then selectorPopup:Hide() end
            menuFiltros:Show()
        end
    end)

    local btnMarcar = CreateFrame("Button", nil, menuFiltros, "UIPanelButtonTemplate")
    btnMarcar:SetSize(156, 26)
    btnMarcar:SetPoint("BOTTOMLEFT", 16, 12)
    btnMarcar:SetText(L.MARK_ALL or "Mark All")
    StyleActionButton(btnMarcar, "accent")
    btnMarcar:SetScript("OnClick", function()
        for id, info in pairs(spellDB) do
            if (sCortes:IsShown() and info.cat == "Cortes") or (sDef:IsShown() and info.cat == "Defensivos") or (sOfen:IsShown() and info.cat == "Ofensivos") or (sCC:IsShown() and info.cat == "CCs") then
                db.disabledSpells[id] = false; if filterCBs[id] then filterCBs[id]:SetChecked(true) end
            end
        end; if addonTable.ActualizarTodoEnVivo then addonTable.ActualizarTodoEnVivo() end
    end)

    local btnDesmarcar = CreateFrame("Button", nil, menuFiltros, "UIPanelButtonTemplate"); btnDesmarcar:SetSize(156, 26); btnDesmarcar:SetPoint("BOTTOMRIGHT", -16, 12); btnDesmarcar:SetText(L.UNMARK_ALL or "Unmark All"); StyleActionButton(btnDesmarcar, "secondary")
    btnDesmarcar:SetScript("OnClick", function()
        for id, info in pairs(spellDB) do
            if (sCortes:IsShown() and info.cat == "Cortes") or (sDef:IsShown() and info.cat == "Defensivos") or (sOfen:IsShown() and info.cat == "Ofensivos") or (sCC:IsShown() and info.cat == "CCs") then
                db.disabledSpells[id] = true; if filterCBs[id] then filterCBs[id]:SetChecked(false) end
            end
        end; if addonTable.ActualizarTodoEnVivo then addonTable.ActualizarTodoEnVivo() end
    end)

    local spellsOrdenados = {}
    for id, info in pairs(spellDB) do table.insert(spellsOrdenados, {id = id, info = info}) end
    table.sort(spellsOrdenados, function(a, b)
        local claseA = mapaClases[a.info.clase] or a.info.clase
        local claseB = mapaClases[b.info.clase] or b.info.clase
        if claseA == claseB then return a.id < b.id end
        return claseA < claseB
    end)

    local yC, yD, yO, yCC = -5, -5, -5, -5
    for _, data in ipairs(spellsOrdenados) do
        local id = data.id; local info = data.info
        local parent = cCortes; local curY = yC
        if info.cat == "Defensivos" then parent = cDef; curY = yD elseif info.cat == "Ofensivos" then parent = cOfen; curY = yO elseif info.cat == "CCs" then parent = cCC; curY = yCC end
        
        local cb = CreateFrame("CheckButton", nil, parent)
        cb:SetPoint("TOPLEFT", 10, curY)
        local si = C_Spell.GetSpellInfo(id)
        local spellName = si and si.name or tostring(id)
        local iconID = si and si.iconID or 0
        StyleSquareCheck(cb, "|T"..iconID..":16:16:0:0|t " .. spellName .. " ("..(mapaClases[info.clase] or info.clase)..")", 334)
        cb:SetScript("OnClick", function(self)
            db.disabledSpells[id] = not self:GetChecked()
            self:RefreshVisual()
            if addonTable.ActualizarTodoEnVivo then addonTable.ActualizarTodoEnVivo() end
        end)
        filterCBs[id] = cb
        if info.cat == "Cortes" then yC = yC - 30 elseif info.cat == "Defensivos" then yD = yD - 30 elseif info.cat == "Ofensivos" then yO = yO - 30 else yCC = yCC - 30 end
    end
    
    cCortes:SetSize(360, math.max(2000, math.abs(yC) + 50)); cDef:SetSize(360, math.max(2000, math.abs(yD) + 50))
    cOfen:SetSize(360, math.max(2000, math.abs(yO) + 50)); cCC:SetSize(360, math.max(2000, math.abs(yCC) + 50))

    MostrarTabMenu(tabGeneral, btnTabGen)
    addonTable.MostrarTabFiltros(sCortes)
    SetTabButtonState(btnTabCortes, true)
    ApplyMenuTheme()
end

-- ==========================================
-- REGISTRO EN EL MENÚ DE OPCIONES DE BLIZZARD
-- ==========================================
local category = Settings.RegisterCanvasLayoutCategory(menuMain, "|cff00ff00PremadeCDs|r")
category.ID = "|cff00ff00PremadeCDs|r"
Settings.RegisterAddOnCategory(category)

menuMain:SetScript("OnShow", function()
    if addonTable.ActualizarTodoEnVivo then addonTable.ActualizarTodoEnVivo() end
end)