local ADDON_NAME, RPAL = ...

local skillUI = {
    frame = nil,
    content = nil,
    scroll = nil,
    expanded = {},
    initialized = false,
    mode = "proficiencies",
    modeButtons = {},
}
RPAL.SkillSetUI = skillUI

local GI = "Interface\\AddOns\\"..tostring(ADDON_NAME or "ODYN").."\\Textures\\IconPack\\"
local LEVEL_NAMES = {"UNTRAINED", "NOVICE", "COMPETENT", "SKILLED", "EXPERT", "MASTER"}

local CATEGORY_ICONS = {
    one_handed = "Interface\\Icons\\INV_Sword_04",
    two_handed = "Interface\\Icons\\INV_Axe_09",
    armor      = "Interface\\Icons\\INV_Chest_Plate04",
    magic      = "Interface\\Icons\\Spell_Arcane_Arcane01",
    skill      = "Interface\\Icons\\Ability_Hunter_FocusedAim",
    work       = "Interface\\Icons\\Trade_BlackSmithing",
}

local function Palette()
    return (RPAL.GetCurrentThemePalette and RPAL.GetCurrentThemePalette()) or {
        gold={0.82,0.62,0.25,1}, pale={0.9,0.86,0.76,1}, muted={0.5,0.48,0.43,1},
        panel={0.06,0.05,0.04,1}, panel2={0.08,0.07,0.055,1}, border={0.24,0.20,0.14,1},
        button={0.10,0.08,0.06,1}, buttonHover={0.17,0.12,0.06,1},
        accent={0.12,0.09,0.04,1}, accentHover={0.18,0.13,0.06,1},
        page={0.055,0.045,0.035,1}, pageAlt={0.08,0.065,0.05,1},
    }
end

local function Backdrop(frame,bg,border)
    frame:SetBackdrop({
        bgFile="Interface\\Buttons\\WHITE8X8",
        edgeFile="Interface\\Buttons\\WHITE8X8",
        tile=false, edgeSize=1,
        insets={left=0,right=0,top=0,bottom=0},
    })
    frame:SetBackdropColor(unpack(bg))
    frame:SetBackdropBorderColor(unpack(border))
end

local function Font(parent,text,size,color)
    local fs=parent:CreateFontString(nil,"ARTWORK","GameFontNormal")
    local currentFont=select(1,fs:GetFont()) or "Fonts\\FRIZQT__.TTF";local base=size or 10;local final=RPAL.GetScaledFontSize and RPAL.GetScaledFontSize(base) or base
    fs:SetText(text or "")
    fs:SetFont(currentFont,final,"OUTLINE")
    if RPAL.RegisterScalableFontObject then RPAL.RegisterScalableFontObject(fs,currentFont,base,"OUTLINE") end
    fs:SetTextColor(unpack(color or Palette().pale))
    return fs
end

local function SetIcon(tex,path,size)
    tex:SetTexture(path)
    tex:SetTexCoord(0.07,0.93,0.07,0.93)
    tex:SetSize(size or 22,size or 22)
end

local function AnimateHover(frame,goal)
    frame._hoverGoal=goal and 1 or 0
    if frame:GetScript("OnUpdate") then return end
    frame:SetScript("OnUpdate",function(self,elapsed)
        local cur=tonumber(self._hoverT) or 0
        local g=tonumber(self._hoverGoal) or 0
        cur=cur+((g-cur)*math.min(1,(elapsed or 0)*13))
        if math.abs(g-cur)<0.01 then cur=g end
        self._hoverT=cur
        if self._hoverScale then self:SetScale(1+(cur*self._hoverScale)) end
        if self.hoverGlow then self.hoverGlow:SetAlpha(cur) end
        if cur==g then self:SetScript("OnUpdate",nil) end
    end)
end

local function MakeButton(parent,text,width,height,active)
    local p=Palette()
    local b=CreateFrame("Button",nil,parent,"BackdropTemplate")
    b:SetSize(width,height)
    b._active=active and true or false
    b._hoverScale=0.018
    Backdrop(b,active and p.accent or p.button,active and p.gold or p.border)

    local glow=b:CreateTexture(nil,"BACKGROUND",nil,-1)
    glow:SetTexture("Interface\\Buttons\\WHITE8X8")
    glow:SetPoint("TOPLEFT",2,-2);glow:SetPoint("BOTTOMRIGHT",-2,2)
    glow:SetBlendMode("ADD");glow:SetVertexColor(p.gold[1],p.gold[2],p.gold[3],0)
    b.hoverGlow=glow

    local label=Font(b,text,11,active and p.pale or p.muted)
    label:SetPoint("CENTER",0,1);b.label=label

    b:SetScript("OnEnter",function(self)
        local pp=Palette();AnimateHover(self,true)
        self:SetBackdropColor(unpack(pp.buttonHover));self:SetBackdropBorderColor(unpack(pp.gold))
        label:SetTextColor(unpack(pp.pale));glow:SetVertexColor(pp.gold[1],pp.gold[2],pp.gold[3],0.11)
    end)
    b:SetScript("OnLeave",function(self)
        local pp=Palette();AnimateHover(self,false)
        self:SetBackdropColor(unpack(self._active and pp.accent or pp.button))
        self:SetBackdropBorderColor(unpack(self._active and pp.gold or pp.border))
        label:SetTextColor(unpack(self._active and pp.pale or pp.muted));glow:SetVertexColor(pp.gold[1],pp.gold[2],pp.gold[3],0)
    end)
    return b
end

local function EnsureFrame()
    if skillUI.frame and RPAL.UI and RPAL.UI.content and skillUI.frame:GetParent()==RPAL.UI.content then
        return skillUI.frame
    end

    skillUI.frame=nil;skillUI.content=nil;skillUI.scroll=nil
    if not RPAL.UI or not RPAL.UI.content then return nil end

    local p=Palette()
    local host=CreateFrame("Frame",nil,RPAL.UI.content)
    skillUI.frame=host
    host:SetAllPoints(RPAL.UI.content)
    host:SetFrameLevel((RPAL.UI.content:GetFrameLevel() or 0)+8)
    host:EnableMouse(true)

    local title=Font(host,"SKILL SET",21,p.gold)
    title:SetPoint("TOPLEFT",18,-18);skillUI.title=title

    local subtitle=Font(host,"Character knowledge and proficiency for roleplay.",10,p.muted)
    subtitle:SetPoint("TOPLEFT",19,-43);skillUI.subtitle=subtitle

    local legend=Font(host,"0–5 PROFICIENCY  •  + / − TO ADJUST",9,p.muted)
    legend:SetPoint("TOPRIGHT",-128,-20);skillUI.legend=legend

    local reset=MakeButton(host,"RESET PAGE",100,28,false)
    reset:SetPoint("TOPRIGHT",-18,-15);skillUI.reset=reset
    reset:SetScript("OnClick",function()
        local sheetMode=skillUI.mode=="sheet"
        StaticPopupDialogs.RPAL_SKILL_RESET={
            text=sheetMode and "Reset the Character Sheet to default values?" or "Reset every Skill Set proficiency to 0?",
            button1="Reset",button2="Cancel",hideOnEscape=true,
            OnAccept=function()if sheetMode and RPAL.ResetCharacterSheet then RPAL.ResetCharacterSheet() else RPAL.ResetSkillSet() end end,
            timeout=0,whileDead=true,preferredIndex=3,
        }
        StaticPopup_Show("RPAL_SKILL_RESET")
    end)

    local prof=MakeButton(host,"PROFICIENCIES",150,28,true);prof:SetPoint("TOPLEFT",18,-69)
    local sheet=MakeButton(host,"CHARACTER SHEET",170,28,false);sheet:SetPoint("LEFT",prof,"RIGHT",8,0)
    skillUI.modeButtons={proficiencies=prof,sheet=sheet}
    prof:SetScript("OnClick",function()skillUI.mode="proficiencies";RPAL.RenderSkillSet()end)
    sheet:SetScript("OnClick",function()skillUI.mode="sheet";RPAL.RenderSkillSet()end)

    local rule=host:CreateTexture(nil,"ARTWORK")
    rule:SetTexture("Interface\\Buttons\\WHITE8X8");rule:SetHeight(1)
    rule:SetPoint("TOPLEFT",18,-104);rule:SetPoint("TOPRIGHT",-18,-104)
    rule:SetVertexColor(p.gold[1],p.gold[2],p.gold[3],0.34)

    local scroll=CreateFrame("ScrollFrame",nil,host,"UIPanelScrollFrameTemplate")
    if RPAL.SkinScrollFrame then RPAL.SkinScrollFrame(scroll) end
    scroll:SetPoint("TOPLEFT",18,-116);scroll:SetPoint("BOTTOMRIGHT",-30,16)
    skillUI.scroll=scroll

    local content=CreateFrame("Frame",nil,scroll)
    content:SetSize(1,1)
    scroll:SetScrollChild(content)
    skillUI.content=content

    return host
end

-- Skill Set is a primary content page, not a translucent overlay.  Claim the
-- shared content surface before drawing so a stale Overview/Achievement frame
-- can never remain visible (or receive mouse input) underneath it.  Keeping
-- this guard beside the renderer also protects direct refresh calls and future
-- navigation paths that do not go through BookChromeUI.
local function ClaimContentSurface()
    local ui=RPAL.UI
    if not ui then return end
    if ui.statistics then ui.statistics:Hide() end
    if ui.ledger then ui.ledger:Hide() end
    if ui.editor then ui.editor:Hide() end
    if ui.addCategory then ui.addCategory:Hide() end
end

local function MakePips(parent,value)
    local p=Palette()
    local holder=CreateFrame("Frame",nil,parent)
    holder:SetSize(106,14)
    holder:SetPoint("LEFT",112,0)
    for i=1,5 do
        local pip=holder:CreateTexture(nil,"ARTWORK")
        pip:SetTexture("Interface\\Buttons\\WHITE8X8")
        pip:SetSize(15,5);pip:SetPoint("LEFT",(i-1)*19,0)
        pip:SetVertexColor(p.gold[1],p.gold[2],p.gold[3],i<=value and 0.95 or 0.20)
    end
    return holder
end

local function RenderRow(parent,skill,x,y,width)
    local p=Palette();local value=RPAL.GetSkillProficiency(skill)
    local row=CreateFrame("Button",nil,parent,"BackdropTemplate")
    row:SetSize(width,60);row:SetPoint("TOPLEFT",x,-y)
    row._hoverScale=0.012
    Backdrop(row,p.panel2,p.border)

    local accent=row:CreateTexture(nil,"BACKGROUND",nil,-1)
    accent:SetTexture("Interface\\Buttons\\WHITE8X8")
    accent:SetWidth(2);accent:SetPoint("TOPLEFT",1,-1);accent:SetPoint("BOTTOMLEFT",1,1)
    accent:SetVertexColor(p.gold[1],p.gold[2],p.gold[3],0.16)
    row.accent=accent

    local hover=row:CreateTexture(nil,"BACKGROUND",nil,-2)
    hover:SetTexture("Interface\\Buttons\\WHITE8X8");hover:SetAllPoints();hover:SetBlendMode("ADD")
    hover:SetVertexColor(p.gold[1],p.gold[2],p.gold[3],0);row.hoverGlow=hover

    local name=Font(row,skill,12.5,p.pale)
    name:SetPoint("TOPLEFT",14,-10);name:SetWidth(math.max(150,width-215));name:SetJustifyH("LEFT");name:SetWordWrap(false)

    local level=Font(row,LEVEL_NAMES[value+1],8.5,p.gold)
    level:SetPoint("TOPLEFT",14,-34)

    MakePips(row,value)

    local minus=MakeButton(row,"−",30,30,false);minus:SetPoint("RIGHT",-48,0)
    minus:SetScript("OnClick",function()RPAL.AdjustSkillProficiency(skill,-1)end)
    local plus=MakeButton(row,"+",30,30,true);plus:SetPoint("RIGHT",-10,0)
    plus:SetScript("OnClick",function()RPAL.AdjustSkillProficiency(skill,1)end)

    row:SetScript("OnEnter",function(self)
        local pp=Palette();AnimateHover(self,true)
        self:SetBackdropColor(unpack(pp.buttonHover));self:SetBackdropBorderColor(unpack(pp.gold))
        self.hoverGlow:SetVertexColor(pp.gold[1],pp.gold[2],pp.gold[3],0.055)
        self.accent:SetVertexColor(pp.gold[1],pp.gold[2],pp.gold[3],0.72)
    end)
    row:SetScript("OnLeave",function(self)
        local pp=Palette();AnimateHover(self,false)
        self:SetBackdropColor(unpack(pp.panel2));self:SetBackdropBorderColor(unpack(pp.border))
        self.hoverGlow:SetVertexColor(pp.gold[1],pp.gold[2],pp.gold[3],0)
        self.accent:SetVertexColor(pp.gold[1],pp.gold[2],pp.gold[3],0.16)
    end)
    return row
end

local function RenderCategoryHeader(parent,category,width,y,expanded)
    local p=Palette()
    local header=CreateFrame("Button",nil,parent,"BackdropTemplate")
    header:SetSize(width,46);header:SetPoint("TOPLEFT",0,-y)
    Backdrop(header,p.panel,p.border)
    header._hoverScale=0.008

    local accent=header:CreateTexture(nil,"BACKGROUND",nil,-1)
    accent:SetTexture("Interface\\Buttons\\WHITE8X8");accent:SetWidth(3)
    accent:SetPoint("TOPLEFT",1,-1);accent:SetPoint("BOTTOMLEFT",1,1)
    accent:SetVertexColor(p.gold[1],p.gold[2],p.gold[3],expanded and 0.85 or 0.35)
    header.accent=accent

    local hover=header:CreateTexture(nil,"BACKGROUND",nil,-2)
    hover:SetTexture("Interface\\Buttons\\WHITE8X8");hover:SetAllPoints();hover:SetBlendMode("ADD")
    hover:SetVertexColor(p.gold[1],p.gold[2],p.gold[3],0);header.hoverGlow=hover

    local icon=header:CreateTexture(nil,"ARTWORK")
    SetIcon(icon,CATEGORY_ICONS[category.id] or (GI.."badge.tga"),22)
    icon:SetPoint("LEFT",12,0);icon:SetVertexColor(p.gold[1],p.gold[2],p.gold[3],expanded and 0.95 or 0.72)

    local arrow=Font(header,expanded and "v" or ">",10,p.gold)
    arrow:SetPoint("LEFT",icon,"RIGHT",9,0);header.arrow=arrow

    local heading=Font(header,category.name,12.5,p.gold)
    heading:SetPoint("LEFT",arrow,"RIGHT",8,5);header.heading=heading

    local desc=Font(header,category.description,8.5,p.muted)
    desc:SetPoint("LEFT",arrow,"RIGHT",8,-13);desc:SetPoint("RIGHT",-12,-13)
    desc:SetJustifyH("LEFT");desc:SetWordWrap(false)

    header:SetScript("OnEnter",function(self)
        local pp=Palette();AnimateHover(self,true)
        self:SetBackdropColor(unpack(pp.buttonHover));self:SetBackdropBorderColor(unpack(pp.gold))
        self.hoverGlow:SetVertexColor(pp.gold[1],pp.gold[2],pp.gold[3],0.08)
        self.accent:SetVertexColor(pp.gold[1],pp.gold[2],pp.gold[3],0.92)
    end)
    header:SetScript("OnLeave",function(self)
        local pp=Palette();AnimateHover(self,false)
        self:SetBackdropColor(unpack(pp.panel));self:SetBackdropBorderColor(unpack(pp.border))
        self.hoverGlow:SetVertexColor(pp.gold[1],pp.gold[2],pp.gold[3],0)
        self.accent:SetVertexColor(pp.gold[1],pp.gold[2],pp.gold[3],expanded and 0.85 or 0.35)
    end)
    header:SetScript("OnClick",function()
        skillUI.expanded[category.id]=not skillUI.expanded[category.id]
        RPAL.RenderSkillSet()
    end)
    return header
end

local function SetModeButtonActive(button,active)
    if not button then return end
    local p=Palette();button._active=active and true or false
    button:SetBackdropColor(unpack(active and p.accent or p.button))
    button:SetBackdropBorderColor(unpack(active and p.gold or p.border))
    if button.label then button.label:SetTextColor(unpack(active and p.pale or p.muted)) end
end

local function Signed(value)
    value=math.floor(tonumber(value) or 0)
    return value>=0 and ("+"..value) or tostring(value)
end

local function RenderSheetValueCard(parent,x,y,width,title,value,subtitle,onMinus,onPlus,stepLabel)
    local p=Palette();local card=CreateFrame("Frame",nil,parent,"BackdropTemplate")
    card:SetSize(width,92);card:SetPoint("TOPLEFT",x,-y);Backdrop(card,p.panel2,p.border)
    local head=Font(card,title,9,p.gold);head:SetPoint("TOPLEFT",12,-10)
    local val=Font(card,tostring(value),24,p.pale);val:SetPoint("CENTER",0,4)
    local sub=Font(card,subtitle or "",8,p.muted);sub:SetPoint("BOTTOM",0,9);sub:SetWidth(math.max(80,width-86));sub:SetJustifyH("CENTER")
    if onMinus and onPlus then
        local minus=MakeButton(card,"−",28,28,false);minus:SetPoint("LEFT",8,-2);minus:SetScript("OnClick",onMinus)
        local plus=MakeButton(card,"+",28,28,false);plus:SetPoint("RIGHT",-8,-2);plus:SetScript("OnClick",onPlus)
    end
    if stepLabel and stepLabel~="" then local hint=Font(card,stepLabel,7,p.muted);hint:SetPoint("TOPRIGHT",-10,-10) end
    return card
end

local function RenderAbilityCard(parent,entry,x,y,width)
    local p=Palette();local score=RPAL.GetCharacterSheetAbility(entry.id);local mod=RPAL.GetCharacterSheetModifier(entry.id)
    local card=CreateFrame("Frame",nil,parent,"BackdropTemplate");card:SetSize(width,116);card:SetPoint("TOPLEFT",x,-y);Backdrop(card,p.panel2,p.border)
    local accent=card:CreateTexture(nil,"BACKGROUND");accent:SetTexture("Interface\\Buttons\\WHITE8X8");accent:SetWidth(3);accent:SetPoint("TOPLEFT",1,-1);accent:SetPoint("BOTTOMLEFT",1,1);accent:SetVertexColor(p.gold[1],p.gold[2],p.gold[3],.72)
    local abbr=Font(card,entry.id,9,p.gold);abbr:SetPoint("TOPLEFT",12,-10)
    local name=Font(card,entry.name:upper(),9,p.muted);name:SetPoint("TOPRIGHT",-12,-10)
    local value=Font(card,tostring(score),31,p.pale);value:SetPoint("CENTER",0,5)
    local modifier=Font(card,Signed(mod),12,p.gold);modifier:SetPoint("TOP",value,"BOTTOM",0,-1)
    local minus=MakeButton(card,"−",30,27,false);minus:SetPoint("BOTTOMLEFT",10,8);minus:SetScript("OnClick",function()RPAL.AdjustCharacterSheetAbility(entry.id,-1)end)
    local plus=MakeButton(card,"+",30,27,false);plus:SetPoint("BOTTOMRIGHT",-10,8);plus:SetScript("OnClick",function()RPAL.AdjustCharacterSheetAbility(entry.id,1)end)
    return card
end

local function RenderCharacterSheet(parent,width)
    local p=Palette();local sheet=RPAL.GetCharacterSheet and RPAL.GetCharacterSheet() or {}
    local intro=CreateFrame("Frame",nil,parent,"BackdropTemplate");intro:SetSize(width,64);intro:SetPoint("TOPLEFT",0,0);Backdrop(intro,p.panel,p.border)
    local h=Font(intro,"CHARACTER SHEET",14,p.gold);h:SetPoint("TOPLEFT",14,-12)
    local d=Font(intro,"Optional D20-style RP statistics. DM Kit stat checks automatically add the modifier from this sheet when you roll.",9,p.muted);d:SetPoint("TOPLEFT",14,-34);d:SetPoint("RIGHT",-14,-34);d:SetJustifyH("LEFT");d:SetWordWrap(true)
    local gap=10;local colW=math.floor((width-(gap*2))/3);local y=76
    for i,entry in ipairs(RPAL.CHARACTER_SHEET_ABILITIES or {}) do
        local col=(i-1)%3;local row=math.floor((i-1)/3)
        RenderAbilityCard(parent,entry,col*(colW+gap),y+(row*128),colW)
    end
    y=y+264
    local derived=Font(parent,"COMBAT & DERIVED",11,p.gold);derived:SetPoint("TOPLEFT",0,-y);y=y+24
    local derivedGap=10;local derivedW=math.floor((width-(derivedGap*2))/3)
    RenderSheetValueCard(parent,0,y,derivedW,"LEVEL",sheet.level or 1,"Proficiency "..Signed(RPAL.GetCharacterSheetDerived("proficiencyBonus")),function()RPAL.AdjustCharacterSheetDerived("level",-1)end,function()RPAL.AdjustCharacterSheetDerived("level",1)end,"1–20")
    RenderSheetValueCard(parent,derivedW+derivedGap,y,derivedW,"ARMOR CLASS",sheet.armorClass or 10,"Defense reference",function()RPAL.AdjustCharacterSheetDerived("armorClass",-1)end,function()RPAL.AdjustCharacterSheetDerived("armorClass",1)end)
    RenderSheetValueCard(parent,(derivedW+derivedGap)*2,y,derivedW,"MAX HP",sheet.maxHP or 10,"Campaign reference",function()RPAL.AdjustCharacterSheetDerived("maxHP",-1)end,function()RPAL.AdjustCharacterSheetDerived("maxHP",1)end)
    y=y+104
    RenderSheetValueCard(parent,0,y,derivedW,"SPEED",sheet.speed or 30,"Movement reference",function()RPAL.AdjustCharacterSheetDerived("speed",-5)end,function()RPAL.AdjustCharacterSheetDerived("speed",5)end,"±5")
    RenderSheetValueCard(parent,derivedW+derivedGap,y,derivedW,"INITIATIVE",Signed(RPAL.GetCharacterSheetDerived("initiative")),"DEX + custom bonus",function()RPAL.AdjustCharacterSheetDerived("initiativeBonus",-1)end,function()RPAL.AdjustCharacterSheetDerived("initiativeBonus",1)end)
    RenderSheetValueCard(parent,(derivedW+derivedGap)*2,y,derivedW,"PROFICIENCY",Signed(RPAL.GetCharacterSheetDerived("proficiencyBonus")),"Derived from level")
    y=y+118
    local foot=Font(parent,"Stat checks are opt-in. A normal DM roll ignores this sheet unless the DM explicitly chooses STR, DEX, CON, INT, WIS or CHA.",8.5,p.muted);foot:SetPoint("TOPLEFT",2,-y);foot:SetWidth(width-4);foot:SetWordWrap(true)
    return y+46
end

function RPAL.RenderSkillSet()
    ClaimContentSurface()
    local host=EnsureFrame();if not host then return end
    if not skillUI.content then return end
    host:Show();host:SetAlpha(1)

    for _,child in ipairs({skillUI.content:GetChildren()}) do child:Hide();child:SetParent(nil) end

    if not skillUI.initialized then skillUI.expanded={};skillUI.initialized=true end

    local content=skillUI.content
    local width=math.max(700,(skillUI.scroll:GetWidth() or 760)-10)
    SetModeButtonActive(skillUI.modeButtons and skillUI.modeButtons.proficiencies,skillUI.mode~="sheet")
    SetModeButtonActive(skillUI.modeButtons and skillUI.modeButtons.sheet,skillUI.mode=="sheet")
    if skillUI.subtitle then skillUI.subtitle:SetText(skillUI.mode=="sheet" and "Optional tabletop statistics for campaign roleplay." or "Character knowledge and proficiency for roleplay.") end
    if skillUI.legend then skillUI.legend:SetText(skillUI.mode=="sheet" and "D20 MODIFIER = FLOOR((SCORE − 10) / 2)" or "0–5 PROFICIENCY  •  + / − TO ADJUST") end

    local y=0
    if skillUI.mode=="sheet" then
        y=RenderCharacterSheet(content,width)
    else
        local gap=12;local colWidth=math.floor((width-gap)/2)
        for _,category in ipairs(RPAL.SKILL_SET_CATEGORIES or {}) do
            local expanded=skillUI.expanded[category.id] == true
            RenderCategoryHeader(content,category,width,y,expanded);y=y+54
            if expanded then
                local rows=math.ceil(#category.skills/2)
                for i,skill in ipairs(category.skills) do
                    local col=(i-1)%2;local row=math.floor((i-1)/2)
                    RenderRow(content,skill,col*(colWidth+gap),y+row*70,colWidth)
                end
                y=y+rows*70+12
            else y=y+8 end
        end
    end
    content:SetSize(width,math.max(1,y+12))
end

function RPAL.RefreshSkillSet()
    if RPAL.IsSkillSetOpen and RPAL.IsSkillSetOpen() then RPAL.RenderSkillSet() end
end

function RPAL.ResetSkillSetUI()
    if skillUI.frame then
        skillUI.frame:Hide()
        skillUI.frame:SetScript("OnUpdate",nil)
        skillUI.frame:SetParent(nil)
    end
    skillUI.frame=nil
    skillUI.content=nil
    skillUI.scroll=nil
    skillUI.expanded={}
    skillUI.modeButtons={}
    skillUI.initialized=false
end

function RPAL.OpenSkillSet()
    if not RPAL.UI or not RPAL.UI.content then return end
    if RPAL.IsSkillSetOpen and RPAL.IsSkillSetOpen() then
        -- The navigation is a page selector, not a toggle. Clicking the active
        -- item again leaves Skill Set open, matching Achievements/Overview.
        return
    end

    local open=function()
        -- Sessions/Chronicle is a separate full-content frame and intentionally
        -- sits above normal pages. Close it before revealing Skill Set so the
        -- Skill Set page always owns the central content area.
        if RPAL.HideChronicle then RPAL.HideChronicle(true) end
        -- Do not skip the main refresh here: it is the transaction that hides
        -- Overview's statistics tree before Skill Set is rendered.  The former
        -- skipRefresh path drew both siblings at once and caused the visible
        -- Overview/Skill Set overlap.
        if RPAL.SetSkillSetMode then
            RPAL.SetSkillSetMode(true)
        else
            ClaimContentSurface()
            RPAL.RenderSkillSet()
            if RPAL.RefreshBookChrome then RPAL.RefreshBookChrome(true) end
        end
    end

    if RPAL.TransitionContent then
        RPAL.TransitionContent(open)
    else
        open()
    end
end

RPAL.GetSkillSetLevelName=function(value)
    return LEVEL_NAMES[math.max(0,math.min(5,tonumber(value) or 0))+1]
end
