local addonName, NS = ...
local GR = _G["GRS_MainFrame"]

-- Helpers from Shared
local CreateBg = NS.CreateBg
local SkinButton = NS.SkinButton
local CreateBorder = NS.CreateBorder

-- Colors
local C_GOLD = "|cffffd100"
local C_BLUE = "|cff00ccff"
local C_NORM = "|cffffffff"

-- =========================================================================
-- DATABASE INITIALIZATION (DEEP VALIDATION)
-- =========================================================================
local function InitMapDatabase()
    if not DB_Rmap_Tools then
        DB_Rmap_Tools = {
            sessions = {},
            lastRaid = nil,
            lastBoss = nil,
            canvasData = {},
            saves = {},
            macroProfiles = {}, 
            settings = {
                brushSize = 2,
                opacity = 1.0,
                isMenuHidden = false,
                disableHelpFlash = false,
                strategists = {},
                isMacroPanelOpen = false
            }
        }
    end
    
    -- Ensure structure integrity
    if not DB_Rmap_Tools.canvasData then DB_Rmap_Tools.canvasData = {} end
    if not DB_Rmap_Tools.saves then DB_Rmap_Tools.saves = {} end
    if not DB_Rmap_Tools.settings then DB_Rmap_Tools.settings = {} end
    if DB_Rmap_Tools.settings.isMenuHidden == nil then DB_Rmap_Tools.settings.isMenuHidden = false end
    if not DB_Rmap_Tools.settings.strategists then DB_Rmap_Tools.settings.strategists = {} end
    if not DB_Rmap_Tools.macroProfiles then DB_Rmap_Tools.macroProfiles = {} end
    
    -- [DEEP FIX] Validate that the saved "lastRaid" actually exists in our current data.
    -- If you renamed a raid or changed keys in the source code, the saved var points to nothing.
    local currentRaid = DB_Rmap_Tools.lastRaid
    local isValidRaid = currentRaid and GR.RAID_MAP_DATA and GR.RAID_MAP_DATA[currentRaid]
    
    if not isValidRaid then
        -- Force reset to the first raid in the order list
        DB_Rmap_Tools.lastRaid = GR.RAID_ORDER[1]
        DB_Rmap_Tools.lastBoss = nil
    end

    -- [DEEP FIX] Validate Boss
    if not DB_Rmap_Tools.lastBoss then
        local firstRaid = DB_Rmap_Tools.lastRaid
        if GR.RAID_MAP_DATA[firstRaid] and GR.RAID_MAP_DATA[firstRaid][1] then
            DB_Rmap_Tools.lastBoss = GR.RAID_MAP_DATA[firstRaid][1].name
        end
    else
        -- Check if boss exists in the current raid
        local rData = GR.RAID_MAP_DATA[DB_Rmap_Tools.lastRaid]
        local bossFound = false
        if rData then
            for _, b in ipairs(rData) do
                if b.name == DB_Rmap_Tools.lastBoss then bossFound = true; break end
            end
        end
        if not bossFound and rData and rData[1] then
            DB_Rmap_Tools.lastBoss = rData[1].name
        end
    end
end

-- =========================================================================
-- TOAST NOTIFICATION SYSTEM
-- =========================================================================
function GR:ShowMapToast(msg, isError)
    if not self.MapToast then
        local f = CreateFrame("Frame", "GRS_Map_Toast", UIParent, "BackdropTemplate")
        f:SetSize(300, 40); f:SetPoint("TOP", 0, -150); f:SetFrameStrata("FULLSCREEN_DIALOG"); f:SetAlpha(0)
        f:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = false, tileSize = 16, edgeSize = 16, insets = { left = 4, right = 4, top = 4, bottom = 4 } })
        f:SetBackdropColor(0.1, 0.1, 0.1, 0.9); f:SetBackdropBorderColor(0, 0, 0, 1)
        f.icon = f:CreateTexture(nil, "ARTWORK"); f.icon:SetSize(20, 20); f.icon:SetPoint("LEFT", 15, 0)
        f.fs = f:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge"); f.fs:SetPoint("CENTER", 10, 0); f.fs:SetJustifyH("CENTER")
        f.ag = f:CreateAnimationGroup()
        f.ag:CreateAnimation("Alpha"):SetFromAlpha(0); f.ag:CreateAnimation("Alpha"):SetToAlpha(1); f.ag:CreateAnimation("Alpha"):SetDuration(0.2); f.ag:CreateAnimation("Alpha"):SetOrder(1)
        f.ag:CreateAnimation("Alpha"):SetFromAlpha(1); f.ag:CreateAnimation("Alpha"):SetToAlpha(1); f.ag:CreateAnimation("Alpha"):SetDuration(2.0); f.ag:CreateAnimation("Alpha"):SetOrder(2)
        f.ag:CreateAnimation("Alpha"):SetFromAlpha(1); f.ag:CreateAnimation("Alpha"):SetToAlpha(0); f.ag:CreateAnimation("Alpha"):SetDuration(0.5); f.ag:CreateAnimation("Alpha"):SetOrder(3)
        f.ag:SetScript("OnFinished", function() f:Hide() end)
        self.MapToast = f
    end
    local f = self.MapToast; f.fs:SetText(msg)
    if isError then f:SetBackdropBorderColor(1, 0, 0, 1); f.fs:SetTextColor(1, 0.2, 0.2); f.icon:SetTexture("Interface\\DialogFrame\\UI-Dialog-Icon-AlertNew")
    else f:SetBackdropBorderColor(0, 1, 0, 1); f.fs:SetTextColor(0.2, 1, 0.2); f.icon:SetTexture("Interface\\FriendsFrame\\StatusIcon-Online") end
    f:Show(); f.ag:Stop(); f.ag:Play()
end

-- =========================================================================
-- RAID MAP DATA (PUBLIC / SHARED)
-- =========================================================================
GR.RAID_MAP_DATA = {
    ["The Dreamrift"] = { { name = "Chimaerus the Undreamt God", file = "Chimaerus.tga" } },
    ["The Voidspire"] = { { name = "Imperator Averzian", file = "Avverzian.tga" }, { name = "Vorasius", file = "Vorasius.tga" }, { name = "Fallen-King Salhadaar", file = "Salhadhaar.tga" }, { name = "Vaelgor & Ezzorak", file = "Vaelgor - Ezzorak.tga" }, { name = "Lightblinded Vanguard", file = "Vanguards.tga" }, { name = "Crown of the Cosmos", file = "CrownofCosmos.tga" } },
    ["March on Quel'Danas"] = { { name = "Belo'ren, Child of Al'ar", file = "Belo'ren.tga" }, { name = "Midnight Falls", file = "MidnightFalls.tga" } },
}
GR.RAID_ORDER = { "The Dreamrift", "The Voidspire", "March on Quel'Danas" }

-- =========================================================================
-- HELP / TUTORIAL SYSTEM
-- =========================================================================
local function OpenMapHelpDialog()
    local f = _G["GRS_Map_HelpDlg"]
    if f then f:Show(); return end
    
    f = CreateFrame("Frame", "GRS_Map_HelpDlg", UIParent, "BackdropTemplate")
    f:SetSize(400, 500); f:SetPoint("CENTER"); f:SetFrameStrata("DIALOG"); f:EnableMouse(true); f:SetMovable(true)
    f:RegisterForDrag("LeftButton"); f:SetScript("OnDragStart", f.StartMoving); f:SetScript("OnDragStop", f.StopMovingOrSizing)
    
    f:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = false, tileSize = 16, edgeSize = 16, insets = { left = 4, right = 4, top = 4, bottom = 4 } })
    f:SetBackdropColor(0, 0, 0, 0.9); f:SetBackdropBorderColor(1, 0.82, 0, 1)
    
    local title = f:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    title:SetPoint("TOP", 0, -15); title:SetText("A.X.I.O.M. Manual")
    
    local close = CreateFrame("Button", nil, f)
    close:SetSize(24, 24); close:SetPoint("TOPRIGHT", -5, -5); SkinButton(close)
    local cfs = close:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    cfs:SetPoint("CENTER"); cfs:SetText("X"); close:SetFontString(cfs)
    close:SetScript("OnClick", function() f:Hide() end)

    local sf = CreateFrame("ScrollFrame", nil, f, "UIPanelScrollFrameTemplate")
    sf:SetPoint("TOPLEFT", 15, -50); sf:SetPoint("BOTTOMRIGHT", -30, 15)
    local content = CreateFrame("Frame", nil, sf); content:SetSize(355, 1000); sf:SetScrollChild(content)
    
    local txt = content:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); txt:SetPoint("TOPLEFT", 0, 0); txt:SetWidth(350); txt:SetJustifyH("LEFT")
    
    local t = ""
    local function AddLine(str) t = t .. str .. "\n" end
    local function AddItem(head, desc) t = t .. "  • " .. C_BLUE .. head .. "|r: " .. C_GOLD .. desc .. "|r\n" end
    
    AddLine(C_GOLD .. "Welcome to the tactical map interface.|r\n")
    AddLine(C_NORM .. "1. Navigation|r")
    AddItem("Select Raid", "Choose the active raid wing from the top-left dropdown.")
    AddItem("Select Boss", "Pick a boss to load its tactical map. Defaults to the first boss.")
    AddLine("")
    AddLine(C_NORM .. "2. Tools & Canvas|r")
    AddItem("Drag & Drop", "Pull icons from the Left Panel onto the Map Overlay.")
    AddItem("Delete", "Drag any icon OFF the map raster to destroy it.")
    AddLine("")
    AddLine(C_NORM .. "3. Manipulation|r")
    AddItem("Move", "Left-Click and Drag any icon on the map.")
    AddItem("Scale", "Right-Click and Drag (Left/Right) to resize.")
    AddItem("Stretch", "Hold SHIFT + Right-Click Drag to stretch shapes non-uniformly.")
    AddItem("Rotate", "Use Mouse Wheel while hovering over an icon.")
    AddLine("")
    AddLine(C_NORM .. "4. Custom Labels|r")
    AddItem("Create", "Drag the 'A' icon onto the map.")
    AddItem("Edit", "Double-Click a label to enter text input mode.")
    AddItem("Format", "Use the popup bar for Bold, Italic, Underline, Color, and Size.")
    AddLine("")
    AddLine(C_NORM .. "5. Save System (Updated)|r")
    AddItem("Left Click", "Select/Target a Save Slot.")
    AddItem("Right Click", "LOAD Slot. If Live & Leader, broadcasts immediately.")
    AddItem("Live Saving", "Members can save the current Live View to any slot.")
    
    txt:SetText(t); content:SetHeight(txt:GetStringHeight() + 20); f:Show()
end

-- =========================================================================
-- STRATEGISTS POPUP
-- =========================================================================
local function OpenStrategistDialog()
    local f = _G["GRS_Map_StratDlg"]
    if not f then
        f = CreateFrame("Frame", "GRS_Map_StratDlg", UIParent, "BackdropTemplate")
        f:SetSize(300, 380)
        f:SetPoint("CENTER"); f:SetFrameStrata("FULLSCREEN_DIALOG")
        f:EnableMouse(true); f:SetMovable(true)
        f:RegisterForDrag("LeftButton"); f:SetScript("OnDragStart", f.StartMoving); f:SetScript("OnDragStop", f.StopMovingOrSizing)
        
        f:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8" })
        f:SetBackdropColor(0, 0, 0, 0.75)
        
        local title = f:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
        title:SetPoint("TOP", 0, -15); title:SetText("Strategists"); title:SetTextColor(1, 1, 1)
        
        local close = CreateFrame("Button", nil, f)
        close:SetSize(20, 20); close:SetPoint("TOPRIGHT", -5, -5); SkinButton(close)
        local cfs = close:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        cfs:SetPoint("CENTER"); cfs:SetText("X"); close:SetFontString(cfs)
        close:SetScript("OnClick", function() f:Hide() end)
        
        f.leaderLbl = f:CreateFontString(nil, "OVERLAY", "GameFontHighlightMedium")
        f.leaderLbl:SetPoint("TOP", 0, -45); f.leaderLbl:SetTextColor(1, 0.82, 0)
        
        f.dropdowns = {}
        local y = -80
        for i=1, 5 do
            local lbl = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
            lbl:SetPoint("TOPLEFT", 20, y); lbl:SetText("Raid Assistance / Strategist " .. i .. ":")
            lbl:SetTextColor(1, 1, 1)
            
            local btn = CreateFrame("Button", nil, f)
            btn:SetSize(260, 24); btn:SetPoint("TOPLEFT", 20, y - 15)
            CreateBg(btn, 0.2, 0.2, 0.2, 1)
            local txt = btn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
            txt:SetPoint("LEFT", 5, 0); txt:SetText("- None -"); btn.txt = txt
            
            local list = CreateFrame("Frame", nil, btn)
            list:SetSize(260, 150); list:SetPoint("TOPLEFT", btn, "BOTTOMLEFT", 0, -2)
            list:SetFrameStrata("TOOLTIP"); CreateBg(list, 0.1, 0.1, 0.1, 1); list:Hide()
            
            local scroll = CreateFrame("ScrollFrame", nil, list, "UIPanelScrollFrameTemplate")
            scroll:SetPoint("TOPLEFT", 5, -5); scroll:SetPoint("BOTTOMRIGHT", -25, 5)
            local content = CreateFrame("Frame", nil, scroll); content:SetSize(230, 200); scroll:SetScrollChild(content)
            
            btn:SetScript("OnClick", function() list:SetShown(not list:IsShown()) end)
            
            btn.RefreshList = function()
                local candidates = {}; local num = GetNumGroupMembers()
                if num == 0 then table.insert(candidates, {name=UnitName("player"), class=select(2, UnitClass("player"))}) 
                else
                    for j=1, num do
                        local unit = IsInRaid() and ("raid"..j) or ("party"..j)
                        if IsInRaid() or j < num then 
                            if not IsInRaid() and j == num then unit = "player" end 
                            local name = GetUnitName(unit, true)
                            local _, cls = UnitClass(unit)
                            if name then table.insert(candidates, {name=name, class=cls}) end
                        end
                    end
                    if not IsInRaid() then 
                        local pName, _, pCls = UnitName("player"), UnitClass("player")
                        local found = false
                        for _, c in ipairs(candidates) do if c.name == pName then found = true break end end
                        if not found then table.insert(candidates, {name=pName, class=select(2, UnitClass("player"))}) end
                    end
                end
                
                table.sort(candidates, function(a,b) return a.name < b.name end)
                table.insert(candidates, 1, {name="- None -", class=nil})
                
                local kids = {content:GetChildren()}; for _, k in ipairs(kids) do k:Hide() end
                local dy = 0
                for _, cand in ipairs(candidates) do
                    local b = CreateFrame("Button", nil, content)
                    b:SetSize(230, 20); b:SetPoint("TOPLEFT", 0, dy)
                    local t = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
                    t:SetPoint("LEFT", 5, 0)
                    if cand.class then
                        local cColor = RAID_CLASS_COLORS and RAID_CLASS_COLORS[cand.class] or (C_ClassColor and C_ClassColor.GetClassColor and C_ClassColor.GetClassColor(cand.class))
                        if cColor then t:SetText(cColor:WrapTextInColorCode(cand.name)) else t:SetText(cand.name) end
                    else t:SetText(cand.name) end
                    b:SetFontString(t)
                    b:SetScript("OnClick", function()
                        f.selections[i] = (cand.name ~= "- None -") and cand.name or nil
                        txt:SetText(t:GetText())
                        list:Hide()
                    end)
                    b:Show(); dy = dy - 20
                end
                content:SetHeight(math.abs(dy) + 10)
            end
            
            f.dropdowns[i] = btn
            y = y - 45
        end
        
        local save = CreateFrame("Button", nil, f)
        save:SetSize(80, 24); save:SetPoint("BOTTOMLEFT", 60, 20)
        CreateBg(save, 0, 0, 0, 1)
        local sFs = save:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        sFs:SetPoint("CENTER"); sFs:SetText("Save")
        save:SetFontString(sFs)
        save:SetScript("OnClick", function()
            DB_Rmap_Tools.settings.strategists = f.selections
            GR:ShowMapToast("Strategists Saved", false)
            -- [STRAT_SYNC] Immediately broadcast updated permissions to all members
            if GR.Session and GR.Session.isLive and GR.BroadcastStrategists then
                GR:BroadcastStrategists()
            end
            f:Hide()
        end)
        
        local closeBtn = CreateFrame("Button", nil, f)
        closeBtn:SetSize(80, 24); closeBtn:SetPoint("BOTTOMRIGHT", -60, 20)
        CreateBg(closeBtn, 0, 0, 0, 1)
        local cFs = closeBtn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        cFs:SetPoint("CENTER"); cFs:SetText("Close")
        closeBtn:SetFontString(cFs)
        closeBtn:SetScript("OnClick", function() f:Hide() end)
    end
    
    local leaderName = "Unknown"
    for i=1, GetNumGroupMembers() do
        local unit = IsInRaid() and ("raid"..i) or ("party"..i)
        if UnitIsGroupLeader(unit) then leaderName = GetUnitName(unit, true) break end
    end
    if not IsInGroup() then leaderName = UnitName("player") end
    
    f.leaderLbl:SetText("Raid Leader: " .. leaderName)
    f.selections = CopyTable(DB_Rmap_Tools.settings.strategists or {})
    
    for i, btn in ipairs(f.dropdowns) do
        btn:RefreshList()
        local saved = f.selections[i]
        if saved then btn.txt:SetText(saved) else btn.txt:SetText("- None -") end
    end
    
    f:Show()
end

local function CreateRobustVerticalScrollbar(parent, targetScrollFrame)
    local container = CreateFrame("Frame", nil, parent, "BackdropTemplate")
    container:SetWidth(18)
    container:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = false, tileSize = 16, edgeSize = 12, insets = { left = 3, right = 3, top = 3, bottom = 3 } })
    container:SetBackdropColor(0, 0, 0, 0.8); container:SetBackdropBorderColor(0.6, 0.6, 0.6, 1); container:SetFrameLevel(parent:GetFrameLevel() + 5)
    local upBtn = CreateFrame("Button", nil, container); upBtn:SetSize(16, 16); upBtn:SetPoint("TOP", 0, -2); upBtn:SetNormalTexture("Interface\\Buttons\\UI-ScrollBar-ScrollUpButton-Up")
    local downBtn = CreateFrame("Button", nil, container); downBtn:SetSize(16, 16); downBtn:SetPoint("BOTTOM", 0, 2); downBtn:SetNormalTexture("Interface\\Buttons\\UI-ScrollBar-ScrollDownButton-Up")
    local slider = CreateFrame("Slider", nil, container); slider:SetOrientation("VERTICAL"); slider:SetPoint("TOP", upBtn, "BOTTOM", 0, 0); slider:SetPoint("BOTTOM", downBtn, "TOP", 0, 0); slider:SetWidth(18)
    local thumb = slider:CreateTexture(nil, "ARTWORK"); thumb:SetSize(14, 24); thumb:SetColorTexture(0.5, 0.5, 0.5, 1); slider:SetThumbTexture(thumb)
    slider:SetScript("OnValueChanged", function(self, value) targetScrollFrame:SetVerticalScroll(value) end)
    container.SetMinMaxValues = function(self, min, max) slider:SetMinMaxValues(min, max); thumb:SetShown(max > min) end
    container.GetValue = function(self) return slider:GetValue() end
    container.SetValue = function(self, v) local min, max = slider:GetMinMaxValues(); slider:SetValue(math.max(min, math.min(max, v))) end
    return container
end

-- =========================================================================
-- SAVE LOGIC: PERFORM SAVE & REFLOW
-- =========================================================================
local function PerformSave(idx, name)
    local boss = DB_Rmap_Tools.lastBoss
    if not boss then return end
    
    local dataToSave = CopyTable(DB_Rmap_Tools.canvasData)
    
    if not DB_Rmap_Tools.saves[boss] then DB_Rmap_Tools.saves[boss] = {} end
    DB_Rmap_Tools.saves[boss][idx] = { name = name, data = dataToSave }
    GR:ShowMapToast("Saved: " .. name, false)
    if GR.ReflowSaveSlots then GR:ReflowSaveSlots() end
end

-- =========================================================================
-- SAVE NAME POPUP DIALOG (WITH OVERWRITE WARNING)
-- =========================================================================
local function OpenSaveNameDialog(slotIndex)
    local boss = DB_Rmap_Tools.lastBoss
    local isOverwrite = (DB_Rmap_Tools.saves[boss] and DB_Rmap_Tools.saves[boss][slotIndex])
    
    if isOverwrite then
        local confirm = _G["GRS_Overwrite_Confirm"]
        if not confirm then
            confirm = CreateFrame("Frame", "GRS_Overwrite_Confirm", UIParent, "BackdropTemplate")
            confirm:SetSize(300, 120); confirm:SetPoint("CENTER"); confirm:SetFrameStrata("FULLSCREEN_DIALOG")
            confirm:SetBackdrop({ bgFile="Interface\\Buttons\\WHITE8x8", edgeFile="Interface\\Tooltips\\UI-Tooltip-Border", edgeSize=16 })
            confirm:SetBackdropColor(0,0,0,0.95); confirm:SetBackdropBorderColor(1,0,0,1)
            
            confirm.lbl = confirm:CreateFontString(nil, "OVERLAY", "GameFontNormal")
            confirm.lbl:SetPoint("TOP", 0, -20); confirm.lbl:SetText("Overwrite existing save?")
            
            confirm.yes = CreateFrame("Button", nil, confirm, "UIPanelButtonTemplate")
            confirm.yes:SetSize(80, 24); confirm.yes:SetPoint("BOTTOMLEFT", 40, 20); confirm.yes:SetText("Yes")
            
            confirm.no = CreateFrame("Button", nil, confirm, "UIPanelButtonTemplate")
            confirm.no:SetSize(80, 24); confirm.no:SetPoint("BOTTOMRIGHT", -40, 20); confirm.no:SetText("No")
            confirm.no:SetScript("OnClick", function() confirm:Hide() end)
        end
        confirm.yes:SetScript("OnClick", function() confirm:Hide(); GR:InternalShowNamePopup(slotIndex) end)
        confirm:Show()
    else
        GR:InternalShowNamePopup(slotIndex)
    end
end

function GR:InternalShowNamePopup(slotIndex)
    local f = _G["GRS_Map_SaveDlg"]
    if not f then
        f = CreateFrame("Frame", "GRS_Map_SaveDlg", UIParent, "BackdropTemplate")
        f:SetSize(300, 150); f:SetPoint("CENTER"); f:SetFrameStrata("FULLSCREEN_DIALOG"); f:EnableMouse(true)
        f:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = false, tileSize = 16, edgeSize = 16, insets = { left = 4, right = 4, top = 4, bottom = 4 } })
        f:SetBackdropColor(0, 0, 0, 0.95); f:SetBackdropBorderColor(0.6, 0.6, 0.6, 1)
        f.lbl = f:CreateFontString(nil, "OVERLAY", "GameFontNormal"); f.lbl:SetPoint("TOP", 0, -20); f.lbl:SetText("Name this Save (Max 10):")
        f.eb = CreateFrame("EditBox", nil, f, "InputBoxTemplate"); f.eb:SetSize(180, 24); f.eb:SetPoint("TOP", 0, -50); f.eb:SetAutoFocus(true); f.eb:SetMaxLetters(10)
        f.ok = CreateFrame("Button", nil, f, "UIPanelButtonTemplate"); f.ok:SetSize(80, 24); f.ok:SetPoint("BOTTOMLEFT", 60, 20); f.ok:SetText("Save")
        f.cancel = CreateFrame("Button", nil, f, "UIPanelButtonTemplate"); f.cancel:SetSize(80, 24); f.cancel:SetPoint("BOTTOMRIGHT", -60, 20); f.cancel:SetText("Cancel"); f.cancel:SetScript("OnClick", function() f:Hide() end)
    end
    f.eb:SetText("")
    f.ok:SetScript("OnClick", function() local txt = f.eb:GetText() or ""; if txt ~= "" then PerformSave(slotIndex, txt) end; f:Hide() end)
    f:Show()
end

-- =========================================================================
-- MAIN WINDOW LOGIC
-- =========================================================================
function GR:RR_OpenMapWindow()
    InitMapDatabase()
    if self.MapWindow then self.MapWindow:Show(); return end
    
    local f = CreateFrame("Frame", "GRS_RR_MapWindow", UIParent)
    f:SetSize(1064, 720); f:SetPoint("CENTER"); f:SetFrameStrata("MEDIUM"); f:SetFrameLevel(10); f:SetMovable(true); f:SetResizable(true); f:EnableMouse(true); f:SetResizeBounds(800, 500, 2500, 2500)
    f:RegisterForDrag("LeftButton"); f:SetScript("OnDragStart", f.StartMoving); f:SetScript("OnDragStop", f.StopMovingOrSizing)
    f:CreateTexture(nil, "BACKGROUND"):SetAllPoints(); f:GetRegions():SetColorTexture(0, 0, 0, 0.8)
    
    -- Auto-Close on Combat
    f:RegisterEvent("PLAYER_REGEN_DISABLED")
    f:SetScript("OnEvent", function(self, event)
        if event == "PLAYER_REGEN_DISABLED" then
            self:Hide()
        end
    end)
    
    local mainTitle = f:CreateFontString(nil, "OVERLAY", "GameFontNormalHuge"); mainTitle:SetPoint("TOP", 0, -10); mainTitle:SetText("A.X.I.O.M. | Raid Map")
    mainTitle:SetTextColor(0, 0.8, 1, 0.8)
    
    local c = CreateFrame("Button", nil, f); c:SetSize(24, 24); c:SetPoint("TOPRIGHT", -5, -5); SkinButton(c)
    local cfs = c:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); cfs:SetPoint("CENTER"); cfs:SetText("X"); c:SetFontString(cfs); c:SetScript("OnClick", function() f:Hide() end)
    
    local helpBtn = CreateFrame("Button", nil, f); helpBtn:SetSize(24, 24); helpBtn:SetPoint("RIGHT", c, "LEFT", -5, 0)
    local glow = helpBtn:CreateTexture(nil, "BACKGROUND"); glow:SetTexture("Interface\\Buttons\\WHITE8x8"); glow:SetVertexColor(1, 0.82, 0, 1); glow:SetPoint("TOPLEFT", -2, 2); glow:SetPoint("BOTTOMRIGHT", 2, -2)
    local ag = glow:CreateAnimationGroup(); ag:SetLooping("BOUNCE"); local a1 = ag:CreateAnimation("Alpha"); a1:SetFromAlpha(0); a1:SetToAlpha(1); a1:SetDuration(2.0); ag:Play()
    local blackBg = helpBtn:CreateTexture(nil, "ARTWORK"); blackBg:SetAllPoints(); blackBg:SetColorTexture(0, 0, 0, 1)
    local hfs = helpBtn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); hfs:SetPoint("CENTER"); hfs:SetText("?"); helpBtn:SetScript("OnClick", function() OpenMapHelpDialog() end)
    
    local menuPane = CreateFrame("Frame", nil, f); menuPane:SetPoint("TOPLEFT", 0, -40); menuPane:SetPoint("TOPRIGHT", 0, -40); menuPane:SetFrameStrata("HIGH"); menuPane:SetFrameLevel(20); menuPane:CreateTexture(nil, "BACKGROUND"):SetAllPoints(); f.menuPane = menuPane
    
    local mapPane = CreateFrame("Frame", nil, f); mapPane:SetPoint("BOTTOMRIGHT", 0, 100); mapPane:SetFrameStrata("HIGH"); mapPane:SetFrameLevel(20); mapPane:EnableMouse(true)
    f.mapPane = mapPane; GR.mapPane = mapPane 
    local mapTex = mapPane:CreateTexture(nil, "BACKGROUND"); mapTex:SetPoint("CENTER"); mapTex:Hide(); f.mapTex = mapTex; GR.mapTex = mapTex 
    local mapOverlay = CreateFrame("Frame", "GRS_Map_Overlay", mapPane); mapOverlay:SetSize(1024, 512); mapOverlay:SetPoint("CENTER", mapTex, "CENTER"); mapOverlay:SetFrameStrata("LOW"); mapOverlay:SetAlpha(0); f.mapOverlay = mapOverlay
    GR.mapOverlay = mapOverlay -- Ensure Global Reference for Session Handler
    
    local slotContainer = CreateFrame("Frame", nil, f); slotContainer:SetPoint("TOPLEFT", mapPane, "BOTTOMLEFT", 10, -5); slotContainer:SetPoint("TOPRIGHT", mapPane, "BOTTOMRIGHT", -10, -5); slotContainer:SetHeight(60); f.slotContainer = slotContainer; f.saveSlots = {}; GR.selectedSaveSlot = nil

    local function ReflowSaveSlots()
        local boss = DB_Rmap_Tools.lastBoss; local saves = (boss and DB_Rmap_Tools.saves[boss]) or {}
        local x, y = 0, 0; local maxW = slotContainer:GetWidth()
        for i=1, 10 do
            local btn = f.saveSlots[i]; local savedData = saves[i]
            local display = savedData and savedData.name or tostring(i); btn:SetText(display)
            btn:SetWidth(math.max(30, btn:GetFontString():GetStringWidth() + 20))
            if (x + btn:GetWidth()) > maxW then x = 0; y = y - 25 end
            btn:ClearAllPoints(); btn:SetPoint("TOPLEFT", x, y); x = x + btn:GetWidth() + 5
            if GR.selectedSaveSlot == i then btn:SetBackdropBorderColor(1, 0.82, 0, 1) else if savedData then btn:SetBackdropBorderColor(0, 1, 0, 1) else btn:SetBackdropBorderColor(0.5, 0.5, 0.5, 1) end end
        end
        
        -- Live Slot Logic with State & Permission Handling
        if f.liveSlot then 
            if GR.selectedSaveSlot == 11 then 
                f.liveSlot.state = "ON" 
                f.liveSlot:SetBackdropBorderColor(0, 1, 0, 1)
                f.liveSlot:SetAlpha(1)
            else 
                f.liveSlot.state = "OFF" 
                f.liveSlot:SetBackdropBorderColor(1, 0.82, 0, 1)
            end
        end
        
        -- Permission Restriction + Cooldown Check
        local isLive = (f.liveSlot and f.liveSlot.state == "ON")
        local canEdit = (GR.CanEditMap and GR:CanEditMap()) or false
        local shouldDisable = isLive and (not canEdit)
        
        local restricted = { f.btnLive, f.btnPush, f.btnEnforce, f.btnResetLive, f.btnStrat }
        for _, btn in ipairs(restricted) do
            if btn then
                if btn.onCooldown then
                     -- Cooldown takes priority
                     btn:Disable()
                     btn:SetAlpha(0.5)
                elseif shouldDisable then
                    -- Special handling for ResetLive: Hide it if not relevant
                    if btn == f.btnResetLive then
                         btn:Hide()
                    else
                         btn:Disable(); btn:SetAlpha(0.5)
                    end
                else
                    if btn == f.btnResetLive then
                        if isLive then btn:Show(); btn:Enable() else btn:Hide() end
                    else
                        btn:Enable(); btn:SetAlpha(1)
                    end
                end
            end
        end
        
        if f.btnSave and f.btnSave.UpdateState then f.btnSave:UpdateState() end
        if f.btnReset and f.btnReset.UpdateState then f.btnReset:UpdateState() end
    end
    GR.ReflowSaveSlots = ReflowSaveSlots

    local function SelectSaveSlot(idx, button)
        local boss = DB_Rmap_Tools.lastBoss
        if not boss then return end
        if not DB_Rmap_Tools.saves[boss] then DB_Rmap_Tools.saves[boss] = {} end
        
        local entry = DB_Rmap_Tools.saves[boss][idx]
        local isPopulated = (entry ~= nil)
        local canEdit = (GR.CanEditMap and GR:CanEditMap()) or false
        
        -- [[ LIVE SLOT (11) ]]
        if idx == 11 then
            GR.selectedSaveSlot = 11
            if canEdit then
                GR:ShowMapToast("Broadcasting Live", false)
            else
                if GR.RenderLiveBuffer then GR:RenderLiveBuffer() end
            end
            ReflowSaveSlots()
            return
        end
    
        -- [[ REGULAR SLOTS (1-10) ]]
        if button == "LeftButton" then
            -- ACTION: TARGET/SELECT for Saving or Loading
            GR.selectedSaveSlot = idx
            GR:ShowMapToast("Selected Slot " .. idx, false)
    
        elseif button == "RightButton" then
            -- ACTION: EXECUTE (LOAD & BROADCAST)
            -- Restriction: Members cannot LOAD slots to disrupt view if watching Live
            if not canEdit and GR.Session and GR.Session.isLive then
                GR:ShowMapToast("Cannot load slots while watching Live", true)
                return
            end
            
            if not isPopulated then
                GR:ShowMapToast("Slot " .. idx .. " is Empty", true)
                return
            end
    
            GR:WipeCanvasData()
            DB_Rmap_Tools.canvasData = CopyTable(entry.data)
            GR:RefreshCanvasIcons() 
            GR:ShowMapToast("Loaded: " .. entry.name, false)
            
            -- BROADCAST IF LIVE (Leader Only)
            if GR.Session and GR.Session.isLive and canEdit then
                GR:BroadcastMap("PUSH")
                GR:ShowMapToast("Broadcasted Phase: " .. entry.name, false)
            end
            GR.selectedSaveSlot = idx
        end
        
        ReflowSaveSlots()
    end

    for i=1, 10 do
        local b = CreateFrame("Button", nil, slotContainer, "BackdropTemplate"); b:SetHeight(20)
        b:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Buttons\\WHITE8x8", edgeSize = 1 })
        b:SetBackdropColor(0.2, 0.2, 0.2, 1); b:SetBackdropBorderColor(0.5, 0.5, 0.5, 1)
        local fs = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); fs:SetPoint("CENTER"); b:SetFontString(fs)
        b:RegisterForClicks("LeftButtonUp", "RightButtonUp") -- [[ REQUIRED FOR RIGHT CLICK ]]
        b:SetScript("OnClick", function(self, btn) SelectSaveSlot(i, btn) end); f.saveSlots[i] = b
    end
    
    -- Live Slot (Rebuilt from scratch)
    local liveB = CreateFrame("Button", nil, slotContainer, "BackdropTemplate")
    liveB:SetSize(80, 24)
    liveB:SetPoint("RIGHT", f.saveSlots[1], "LEFT", -15, 0)
    
    -- 1. Define Backdrop
    liveB:SetBackdrop({ 
        bgFile = "Interface\\Buttons\\WHITE8x8", 
        edgeFile = "Interface\\Buttons\\WHITE8x8", 
        edgeSize = 1 
    })
    
    -- 2. CRITICAL FIX: Initialize Color to Black immediately to prevent "White Box"
    liveB:SetBackdropColor(0, 0, 0, 1) 
    liveB:SetBackdropBorderColor(0, 0, 0, 1)

    -- 3. Text Label
    local lfs = liveB:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    lfs:SetPoint("CENTER")
    lfs:SetText("LIVE STREAM")
    liveB:SetFontString(lfs)

    -- 4. State & Logic
    liveB.state = "OFF"
    liveB.timer = 0
    
    liveB:SetScript("OnUpdate", function(self, elapsed)
        self.timer = self.timer + elapsed
        if self.timer > 10 then self.timer = 0 end -- 10s Loop
        
        -- Sine wave 0.0 to 1.0
        -- (sin(t * 2pi / Period) + 1) / 2
        local norm = (math.sin(self.timer * 2 * math.pi / 10) + 1) / 2
        
        if self.state == "ON" then
            -- Vibrant Green (0, 1, 0) to Dark Green (0, 0.3, 0)
            local g = 0.3 + (0.7 * norm)
            self:SetBackdropColor(0, g, 0, 1)
            self:SetBackdropBorderColor(0, 1, 0, 1) -- Keep border distinct or match? Let's match or keep white/bright
            lfs:SetTextColor(1, 1, 1, 1)
        else
            -- Black (0, 0, 0) to Dark Dark Red (0.3, 0, 0)
            local r = 0.3 * norm
            self:SetBackdropColor(r, 0, 0, 1)
            self:SetBackdropBorderColor(0.5, 0.5, 0.5, 1) -- Grey border for OFF
            lfs:SetTextColor(0.8, 0.8, 0.8, 1)
        end
    end)
    
    liveB:SetScript("OnClick", function() SelectSaveSlot(11, "LeftButton") end); f.liveSlot = liveB

    local function CreateMapDropdown(parent, labelText)
        local lbl = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); lbl:SetText(labelText)
        local btn = CreateFrame("Button", nil, parent); btn:SetSize(200, 24); CreateBg(btn, 0.2, 0.2, 0.2, 1)
        local txt = btn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); txt:SetPoint("LEFT", 5, 0); txt:SetText("Select..."); btn.txt = txt
        local list = CreateFrame("Frame", nil, btn); CreateBg(list, 0.1, 0.1, 0.1, 1); list:SetSize(200, 10); list:SetPoint("TOPLEFT", btn, "BOTTOMLEFT", 0, -2); list:SetFrameStrata("DIALOG"); list:SetFrameLevel(100); list:Hide()
        btn:SetScript("OnClick", function() list:SetShown(not list:IsShown()) end); return btn, list, lbl
    end

    local raidBtn, raidList, raidLbl = CreateMapDropdown(menuPane, "Choose Raid:")
    local bossBtn, bossList, bossLbl = CreateMapDropdown(menuPane, "Choose Boss:")
    local sep = menuPane:CreateTexture(nil, "ARTWORK"); sep:SetSize(1, 16); sep:SetColorTexture(0.5, 0.5, 0.5, 0.8)

    local function UpdateLayout()
        local w, h = f:GetSize(); local isHidden = DB_Rmap_Tools.settings.isMenuHidden; local hasMap = mapTex:IsShown()
        raidLbl:ClearAllPoints(); raidBtn:ClearAllPoints(); bossLbl:ClearAllPoints(); bossBtn:ClearAllPoints(); sep:ClearAllPoints(); mapPane:ClearAllPoints()
        if self.RaidTools then self.RaidTools:ClearAllPoints(); self.RaidTools:SetShown(hasMap) end
        if isHidden then
            menuPane:Hide()
            if self.RaidTools and hasMap then self.RaidTools:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -25); self.RaidTools:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 0, 100); mapPane:SetPoint("TOPLEFT", self.RaidTools, "TOPRIGHT", 0, 0)
            else mapPane:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -25) end
            mapPane:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 100)
        else
            menuPane:Show()
            if self.RaidTools and hasMap then self.RaidTools:SetPoint("TOPLEFT", menuPane, "BOTTOMLEFT", 0, 0); self.RaidTools:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 0, 100); mapPane:SetPoint("TOPLEFT", self.RaidTools, "TOPRIGHT", 0, 0)
            else mapPane:SetPoint("TOPLEFT", menuPane, "BOTTOMLEFT", 0, 0) end
            mapPane:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 100)
            sep:Show(); menuPane:SetHeight(50)
            raidLbl:SetPoint("LEFT", menuPane, "LEFT", 20, 0); raidBtn:SetPoint("LEFT", raidLbl, "RIGHT", 10, 0)
            sep:SetPoint("LEFT", raidBtn, "RIGHT", 20, 0); bossLbl:SetPoint("LEFT", sep, "RIGHT", 20, 0); bossBtn:SetPoint("LEFT", bossLbl, "RIGHT", 10, 0)
        end
        if hasMap then
            local pW, pH = mapPane:GetSize(); local scale = math.min(pW / 1024, pH / 512)
            mapTex:SetSize(1024 * scale, 512 * scale); mapOverlay:SetSize(1024 * scale, 512 * scale)
            
            -- [SCALING FIX] Store the scale globally so icons can read it
            GR.currMapScale = scale
            
            if GR.RefreshCanvasIcons then GR:RefreshCanvasIcons() end
        end
        ReflowSaveSlots()
    end
    f:SetScript("OnSizeChanged", UpdateLayout)

    local function SpawnRaidTools()
        if self.RaidTools then return end
        local RaidTools = CreateFrame("Frame", "GRS_RR_RaidTools", f); RaidTools:SetWidth(256); RaidTools:SetFrameStrata("HIGH"); RaidTools:SetFrameLevel(mapPane:GetFrameLevel() + 10) 
        local rtBg = RaidTools:CreateTexture(nil, "BACKGROUND"); rtBg:SetAllPoints(); rtBg:SetColorTexture(0, 0, 0, 0.1); self.RaidTools = RaidTools
        local rtScroll = CreateFrame("ScrollFrame", nil, RaidTools); rtScroll:SetPoint("TOPLEFT", 5, -30); rtScroll:SetPoint("BOTTOMRIGHT", -25, 5); self.RaidToolsScroll = rtScroll
        local rtSlider = CreateRobustVerticalScrollbar(RaidTools, rtScroll); rtSlider:SetPoint("TOPRIGHT", -2, -30); rtSlider:SetPoint("BOTTOMRIGHT", -2, 5); self.RaidToolsSlider = rtSlider
        local rtContent = CreateFrame("Frame", nil, rtScroll); rtContent:SetSize(226, 1); rtScroll:SetScrollChild(rtContent); rtScroll:SetScript("OnMouseWheel", function(s, d) rtSlider:SetValue(rtSlider:GetValue() - (d * 30)) end); self.RaidToolsContent = rtContent
        if self.RT_PopulateToolGrid then self:RT_PopulateToolGrid() end
    end

    local function PopulateBossList(raidName)
        -- [DEEP FIX] Dropdown Safety Check
        if not raidName or not GR.RAID_MAP_DATA[raidName] then return end 
        local bosses = GR.RAID_MAP_DATA[raidName]; local kids = {bossList:GetChildren()}; for _, k in ipairs(kids) do k:Hide() end; local yIdx = 0
        for _, bData in ipairs(bosses) do
            local b = CreateFrame("Button", nil, bossList); b:SetSize(190, 20); b:SetPoint("TOPLEFT", 5, yIdx - 5)
            local t = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); t:SetPoint("LEFT", 2, 0); t:SetText(bData.name); b:SetFontString(t)
            b:SetScript("OnClick", function()
                bossBtn.txt:SetText(bData.name); mapTex:SetTexture("Interface\\AddOns\\GuildRecruiterManagement\\RaidRoster\\Resources\\Midnight\\" .. bData.file)
                mapTex:Show(); mapOverlay:Show(); bossList:Hide(); DB_Rmap_Tools.lastBoss = bData.name; GR.selectedSaveSlot = nil; SpawnRaidTools(); UpdateLayout()
                if GR.UpdateMacroPanel then GR:UpdateMacroPanel(bData.name) end
            end); b:Show(); yIdx = yIdx - 20
        end
        bossList:SetHeight(math.abs(yIdx) + 10)
    end

    local rY = 0
    for _, rName in ipairs(GR.RAID_ORDER) do
        local b = CreateFrame("Button", nil, raidList); b:SetSize(190, 20); b:SetPoint("TOPLEFT", 5, rY - 5)
        local t = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); t:SetPoint("LEFT", 2, 0); t:SetText(rName); b:SetFontString(t)
        b:SetScript("OnClick", function()
            raidBtn.txt:SetText(rName); DB_Rmap_Tools.lastRaid = rName; raidList:Hide(); PopulateBossList(rName)
            local firstBoss = GR.RAID_MAP_DATA[rName] and GR.RAID_MAP_DATA[rName][1]
            if firstBoss then
                DB_Rmap_Tools.lastBoss = firstBoss.name; bossBtn.txt:SetText(firstBoss.name)
                mapTex:SetTexture("Interface\\AddOns\\GuildRecruiterManagement\\RaidRoster\\Resources\\Midnight\\" .. firstBoss.file); mapTex:Show(); mapOverlay:Show(); SpawnRaidTools()
                if GR.UpdateMacroPanel then GR:UpdateMacroPanel(firstBoss.name) end
            else DB_Rmap_Tools.lastBoss = nil; bossBtn.txt:SetText("Select..."); mapTex:Hide(); mapOverlay:Hide(); if self.RaidTools then self.RaidTools:Hide() end end
            GR.selectedSaveSlot = nil; UpdateLayout()
        end); b:Show(); rY = rY - 20
    end
    raidList:SetHeight(math.abs(rY) + 10)

    local toggleBtn = CreateFrame("Button", nil, f); toggleBtn:SetSize(120, 24); toggleBtn:SetPoint("BOTTOMLEFT", 5, 5); toggleBtn:SetFrameLevel(30); CreateBg(toggleBtn, 0, 0, 0, 1)
    local toggleFs = toggleBtn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); toggleFs:SetPoint("CENTER"); toggleFs:SetText("Toggle Map Only"); toggleBtn:SetFontString(toggleFs); toggleBtn:SetScript("OnClick", function() DB_Rmap_Tools.settings.isMenuHidden = not DB_Rmap_Tools.settings.isMenuHidden; UpdateLayout() end)
    
    local buttons = { 
        { name = "Live", width = 60, key = "live", func = function(self)
            if GR.Session.isLive then
                GR:BroadcastMap("LIVE_STOP"); GR.Session.isLive = false; GR:ShowMapToast("Live Stream Stopped", true); if GR.selectedSaveSlot == 11 then GR.selectedSaveSlot = nil end
                self.onCooldown = true; self:SetText("Wait..."); GR:ReflowSaveSlots()
                if C_Timer and C_Timer.After then
                    C_Timer.After(3, function() if self then self.onCooldown = false; self:SetText("Live"); GR:ReflowSaveSlots() end end)
                elseif NS and NS.RunDelayed then
                    NS.RunDelayed(3, function() if self then self.onCooldown = false; self:SetText("Live"); GR:ReflowSaveSlots() end end)
                end
            else GR.Session.isLive = true; self:SetText("STOP"); GR:BroadcastMap("LIVE_START"); GR:ShowMapToast("Live Stream Started", false); GR.selectedSaveSlot = 11; GR:ReflowSaveSlots() end
        end},
        { name = "Push", width = 60, key = "push", func = function() GR:BroadcastMap("PUSH"); GR:ShowMapToast("Pushed", false) end },
        { name = "Reset Live", width = 80, key = "resetlive", func = function() if GR:CanEditMap() then GR:WipeCanvasData(); if GR.Session.isLive then GR:BroadcastMap("PUSH") end; GR:ShowMapToast("Live Layout Reset", false) end end },
        { name = "Awareness Enforcer", width = 140, key = "enforce", func = function() GR:BroadcastMap("ENFORCE"); GR:ShowMapToast("Enforced", false) end },
        { name = "Strategists", width = 100, key = "strat", func = function() OpenStrategistDialog() end },
        { name = "Reset Save", width = 80, key = "reset", func = function() if not GR.selectedSaveSlot then return end; local boss = DB_Rmap_Tools.lastBoss; if boss and DB_Rmap_Tools.saves[boss] then DB_Rmap_Tools.saves[boss][GR.selectedSaveSlot] = nil; GR:ShowMapToast("Slot " .. GR.selectedSaveSlot .. " Cleared", false); ReflowSaveSlots() end end },
        { name = "Save", width = 60, key = "save", func = function() if not GR.selectedSaveSlot then return end; OpenSaveNameDialog(GR.selectedSaveSlot) end } }
    
    local resizer = CreateFrame("Button", nil, f); resizer:SetSize(16, 16); resizer:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 0); resizer:SetFrameLevel(30); resizer:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Up")
    resizer:SetScript("OnMouseDown", function() f:StartSizing("BOTTOMRIGHT") end); resizer:SetScript("OnMouseUp", function() f:StopMovingOrSizing() end)
    local lastBtn = resizer
    for i, bData in ipairs(buttons) do
        local btn = CreateFrame("Button", nil, f); btn:SetSize(bData.width, 24)
        if i == 1 then btn:SetPoint("BOTTOMRIGHT", lastBtn, "BOTTOMLEFT", -5, 5) else btn:SetPoint("RIGHT", lastBtn, "LEFT", -5, 0) end
        btn:SetFrameLevel(30); CreateBg(btn, 0, 0, 0, 1); local fs = btn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); fs:SetPoint("CENTER"); fs:SetText(bData.name); btn:SetFontString(fs)
        if bData.key then
            if bData.key == "live" then f.btnLive = btn elseif bData.key == "push" then f.btnPush = btn elseif bData.key == "enforce" then f.btnEnforce = btn elseif bData.key == "strat" then f.btnStrat = btn elseif bData.key == "save" then f.btnSave = btn elseif bData.key == "reset" then f.btnReset = btn elseif bData.key == "resetlive" then f.btnResetLive = btn end
        end
        if bData.key == "save" then
            btn:SetScript("OnClick", function() if btn:IsEnabled() then bData.func() end end)
            btn.UpdateState = function() local canSave = false; if GR.selectedSaveSlot then if GR.CanEditMap and GR:CanEditMap() then canSave = true end; if GR.selectedSaveSlot == 11 or (GR.RR and GR.RR.LiveBuffer) then canSave = true end end; if canSave then btn:Enable(); fs:SetTextColor(1, 1, 1); btn:SetScript("OnEnter", nil) else btn:Disable(); fs:SetTextColor(0.5, 0.5, 0.5); btn:SetScript("OnEnter", function(s) GameTooltip:SetOwner(s, "ANCHOR_TOP"); GameTooltip:SetText("Select a slot to save current view", 1, 0.2, 0.2); GameTooltip:Show() end); btn:SetScript("OnLeave", function() GameTooltip:Hide() end) end end; btn:UpdateState()
        elseif bData.key == "reset" then
            btn:SetScript("OnClick", function() if btn:IsEnabled() then bData.func() end end)
            btn.UpdateState = function() local boss = DB_Rmap_Tools.lastBoss; local hasData = boss and DB_Rmap_Tools.saves[boss] and DB_Rmap_Tools.saves[boss][GR.selectedSaveSlot]; if GR.selectedSaveSlot and hasData then btn:Enable(); fs:SetTextColor(1, 1, 1) else btn:Disable(); fs:SetTextColor(0.5, 0.5, 0.5) end end; btn:UpdateState()
        elseif bData.func then btn:SetScript("OnClick", bData.func) end
        lastBtn = btn
    end
    
    if not DB_Rmap_Tools.lastRaid or not GR.RAID_MAP_DATA[DB_Rmap_Tools.lastRaid] then DB_Rmap_Tools.lastRaid = GR.RAID_ORDER[1]; DB_Rmap_Tools.lastBoss = nil end
    local currentRaid = DB_Rmap_Tools.lastRaid; raidBtn.txt:SetText(currentRaid); PopulateBossList(currentRaid)
    local bossDataList = GR.RAID_MAP_DATA[currentRaid]; local bossFound = false
    if DB_Rmap_Tools.lastBoss then for _, b in ipairs(bossDataList) do if b.name == DB_Rmap_Tools.lastBoss then bossFound = true; break end end end
    if not bossFound and bossDataList and bossDataList[1] then DB_Rmap_Tools.lastBoss = bossDataList[1].name end
    local currentBoss = DB_Rmap_Tools.lastBoss
    if currentBoss then
        local selectedBossData; for _, b in ipairs(bossDataList) do if b.name == currentBoss then selectedBossData = b; break end end
        if selectedBossData then bossBtn.txt:SetText(currentBoss); mapTex:SetTexture("Interface\\AddOns\\GuildRecruiterManagement\\RaidRoster\\Resources\\Midnight\\" .. selectedBossData.file); mapTex:Show(); mapOverlay:Show(); SpawnRaidTools() end
        if GR.UpdateMacroPanel then GR:UpdateMacroPanel(currentBoss) end
    end
    UpdateLayout()
    self.MapWindow = f
end