local API = rawget(_G, "LIDCOUNCIL_API")
local INTERNAL_API = type(API) == "table" and type(API.__internal) == "table" and API.__internal or nil
if type(INTERNAL_API) ~= "table" then
  error("LidCouncil missing internal API registry.")
end

local shared = INTERNAL_API.LIDCOUNCIL_LootEditorShared_Impl
if type(shared) ~= "table" then
  error("LidCouncil missing loot editor shared helpers.")
end

local RequireApi = shared.RequireApi
local BindMouseWheelScroll = shared.BindMouseWheelScroll
local RootDB = shared.RootDB
local ApplyFrameSkin = shared.ApplyFrameSkin
local MakeYellowSubHeader = shared.MakeYellowSubHeader
local GetCharacterKey = shared.GetCharacterKey
local GetEnabledLootProfileName = shared.GetEnabledLootProfileName or RequireApi("LIDCOUNCIL_GetEnabledLootProfileName", _G.LIDCOUNCIL_GetEnabledLootProfileName)
local GetLootProfile = shared.GetLootProfile
local GetPrimaryLootProfileName = shared.GetPrimaryLootProfileName
local GetLootProfileNames = shared.GetLootProfileNames
local IsLootProfileVisibleInEditor = shared.IsLootProfileVisibleInEditor or function(_, profileName)
  return profileName ~= nil and profileName ~= ""
end
local GetLootProfileAccessInfo = shared.GetLootProfileAccessInfo
local SetCurrentLootProfile = shared.SetCurrentLootProfile
local CreateLootProfile = shared.CreateLootProfile
local DeleteLootProfile = shared.DeleteLootProfile
local CopyLootProfile = shared.CopyLootProfile
local SetLootProfileEnabled = shared.SetLootProfileEnabled
local SetLootProfileRaid = shared.SetLootProfileRaid
local AddLootRollOption = shared.AddLootRollOption
local UpdateLootRollOption = shared.UpdateLootRollOption
local RemoveLootRollOption = shared.RemoveLootRollOption
local UpdateLootPointMode = shared.UpdateLootPointMode
local UpdateLootLidTableRow = shared.UpdateLootLidTableRow
local AddLootPointRule = shared.AddLootPointRule
local RemoveLootPointRule = shared.RemoveLootPointRule
local StartLootSession = shared.StartLootSession
local StopLootSession = shared.StopLootSession
local GetActiveLootSession = shared.GetActiveLootSession
local AddLootLedgerEntry = shared.AddLootLedgerEntry
local GetLootLedgerCharacters = shared.GetLootLedgerCharacters
local ResolveOptionalApiFunction = shared.ResolveOptionalApiFunction
local CreateCustomDropdownControl = shared.CreateCustomDropdownControl
local TrimText = shared.TrimText
local FormatDateTime = shared.FormatDateTime
local FormatDuration = shared.FormatDuration
local CreateSimpleEditBox = shared.CreateSimpleEditBox
local SetListButtonSelected = shared.SetListButtonSelected
local SetTextListButtonTextColor = shared.SetTextListButtonTextColor
local EnsureTextListButtons = shared.EnsureTextListButtons
local CreateSectionShell = shared.CreateSectionShell
local ClampLayoutValue = shared.ClampLayoutValue
local GetResponsiveSectionLayout = shared.GetResponsiveSectionLayout
local SetControlWidth = shared.SetControlWidth
local GetFontStringWidth = shared.GetFontStringWidth
local CreateSectionDivider = shared.CreateSectionDivider
local FlowLayoutControls = shared.FlowLayoutControls
local LayoutRollOptionRow = shared.LayoutRollOptionRow
local LayoutLidTableEditorRow = shared.LayoutLidTableEditorRow
local BuildRollOptionsText = shared.BuildRollOptionsText
local DEFAULT_ROLL_OPTION_ICON_CHOICES = shared.DEFAULT_ROLL_OPTION_ICON_CHOICES
local ResolveTextureAsset = shared.ResolveTextureAsset
local ResolveDefaultRollOptionIcon = shared.ResolveDefaultRollOptionIcon
local ResolveRollOptionIcon = shared.ResolveRollOptionIcon
local GetRollOptionIconLabel = shared.GetRollOptionIconLabel
local EnsureRollOptionRows = shared.EnsureRollOptionRows
local EnsureLidTableEditorRows = shared.EnsureLidTableEditorRows
local ExtractItemID = shared.ExtractItemID
local ExtractItemLinkName = shared.ExtractItemLinkName
local FormatPointRuleItemLabel = shared.FormatPointRuleItemLabel
local FormatRaidLootItemLabel = shared.FormatRaidLootItemLabel
local LOOT_ITEM_MENU_PAGE_SIZE = shared.LOOT_ITEM_MENU_PAGE_SIZE
local NormalizeInstanceTuple = shared.NormalizeInstanceTuple
local NormalizeEncounterTuple = shared.NormalizeEncounterTuple
local NormalizeLootInfo = shared.NormalizeLootInfo
local EnsureEncounterJournalLoaded = shared.EnsureEncounterJournalLoaded
local CollectRaidEntries = shared.CollectRaidEntries
local CollectRaidLootEntries = shared.CollectRaidLootEntries
local FindRaidEntryByProfile = shared.FindRaidEntryByProfile
local FindRaidLootEntry = shared.FindRaidLootEntry
local EnsureLootLiveBoardMode = shared.EnsureLootLiveBoardMode
local ClampMenuPage = shared.ClampMenuPage
local GetSelectedValuePage = shared.GetSelectedValuePage
local RequestEditorPageRefresh = shared.RequestEditorPageRefresh

local ACTIVATE_PROFILE_REQUIRED_TEXT = "Please go to Profile and activate one Profile first"
local NO_ACTIVE_PROFILE_CURRENT_TEXT = "Current Profile: No profile activated :("
local NO_ACTIVE_PROFILE_TEXT_COLOR = { 1.00, 0.35, 0.25, 1.00 }
local EMBEDDED_BOARD_MIN_HEIGHT = 460

local function SetCurrentProfileFont(fontString, text, color)
  if not fontString then
    return
  end
  fontString:SetText(text)
  fontString.__lid_customTextColor = color
  if color and fontString.SetTextColor then
    fontString:SetTextColor(color[1], color[2], color[3], color[4] or 1)
  elseif fontString.SetTextColor then
    fontString:SetTextColor(0.92, 0.96, 1.00, 1.00)
  end
end

local function GetLiveBoardContextProfileName()
  local root = RootDB()
  local enabledProfileName = TrimText(GetEnabledLootProfileName() or "")
  if enabledProfileName ~= "" and IsLootProfileVisibleInEditor(root, enabledProfileName) then
    return enabledProfileName
  end
  return nil
end
local EnsureLootProfileGroups = shared.EnsureLootProfileGroups
local FindLootProfileGroupIndex = shared.FindLootProfileGroupIndex
local RemoveLootProfileFromGroups = shared.RemoveLootProfileFromGroups
local ToggleLootProfileGroupCollapsed = shared.ToggleLootProfileGroupCollapsed
local GetLootProfileGroupName = shared.GetLootProfileGroupName
local BuildLootProfileNavRows = shared.BuildLootProfileNavRows
local BuildPointRulesText = shared.BuildPointRulesText
local ResolvePointMode = shared.ResolvePointMode
local GetLidTableRows = shared.GetLidTableRows
local BuildLidTableSummaryText = shared.BuildLidTableSummaryText
local POINT_MODE_CHOICES = shared.POINT_MODE_CHOICES
local GetSelectedProfileName = shared.GetSelectedProfileName

local function BuildLootLiveBoardPage(editor, page)
  if not editor or not page then return end

  local function RequestLiveBoardPageRefresh(owner)
    if type(owner) ~= "table" then
      return false
    end
    if type(RequestEditorPageRefresh) == "function" then
      local handled = RequestEditorPageRefresh(owner, "LiveBoard", "RefreshLootLiveBoardPage")
      if handled then
        return true
      end
    end
    if owner.RequestLootLiveBoardPageRefresh and owner.RequestLootLiveBoardPageRefresh ~= RequestLiveBoardPageRefresh then
      owner:RequestLootLiveBoardPageRefresh()
      return true
    end
    if owner.RefreshLootLiveBoardPage then
      owner:RefreshLootLiveBoardPage()
      return true
    end
    if owner.Refresh then
      owner:Refresh()
      return true
    end
    return false
  end

  editor.RequestLootLiveBoardPageRefresh = function(self)
    return RequestLiveBoardPageRefresh(type(self) == "table" and self or editor)
  end

  local function RefreshLiveBoardView()
    return RequestLiveBoardPageRefresh(editor)
  end

  local function SetLiveBoardStatusOverride(owner, text, color)
    if type(owner) ~= "table" then
      return
    end
    text = TrimText(text)
    if text == "" then
      owner.__lootLiveBoardStatusOverride = nil
      return
    end
    owner.__lootLiveBoardStatusOverride = {
      text = text,
      color = type(color) == "table" and color or { 1.00, 0.35, 0.25, 1.00 },
    }
    if owner.lootLiveBoardStatus then
      owner.lootLiveBoardStatus:SetText(text)
      owner.lootLiveBoardStatus:SetTextColor(
        owner.__lootLiveBoardStatusOverride.color[1],
        owner.__lootLiveBoardStatusOverride.color[2],
        owner.__lootLiveBoardStatusOverride.color[3],
        owner.__lootLiveBoardStatusOverride.color[4] or 1
      )
    end
  end

  local function ClearLiveBoardStatusOverride(owner)
    if type(owner) == "table" then
      owner.__lootLiveBoardStatusOverride = nil
    end
  end

  local function ApplyLiveBoardStatusOverride(owner)
    local override = type(owner) == "table" and owner.__lootLiveBoardStatusOverride or nil
    if type(override) ~= "table" or not owner.lootLiveBoardStatus then
      return
    end
    local color = type(override.color) == "table" and override.color or { 1.00, 0.35, 0.25, 1.00 }
    owner.lootLiveBoardStatus:SetText(tostring(override.text or ""))
    owner.lootLiveBoardStatus:SetTextColor(color[1], color[2], color[3], color[4] or 1)
  end

  local function RunLiveBoardAction(actionLabel, fn, ...)
    if type(fn) ~= "function" then
      SetLiveBoardStatusOverride(editor, tostring(actionLabel or "Live Board action") .. " is unavailable.", { 1.00, 0.55, 0.44, 1.00 })
      return false
    end
    local ok, result = pcall(fn, ...)
    if not ok then
      SetLiveBoardStatusOverride(editor, tostring(actionLabel or "Live Board action") .. " failed: " .. tostring(result), { 1.00, 0.35, 0.25, 1.00 })
      return false
    end
    ClearLiveBoardStatusOverride(editor)
    return true, result
  end

  local function ReadLiveBoardState(actionLabel, fn, fallback, ...)
    if type(fn) ~= "function" then
      return fallback
    end
    local ok, result = pcall(fn, ...)
    if not ok then
      SetLiveBoardStatusOverride(editor, tostring(actionLabel or "Live Board state") .. " failed: " .. tostring(result), { 1.00, 0.35, 0.25, 1.00 })
      return fallback
    end
    return result
  end

  local function RefreshLiveBoardSummaryOnly(owner)
    if type(owner) ~= "table" or owner.currentPage ~= "LiveBoard" or not owner.lootLiveBoardSummary then
      return false
    end
    local summaryProvider = ResolveOptionalApiFunction("LIDCOUNCIL_GetLiveLootBoardSummary")
    local summary = ReadLiveBoardState("Read Live Board summary", summaryProvider, nil)
    if type(summary) ~= "table" or (tonumber(summary.itemCount) or 0) <= 0 then
      return false
    end
    local latestText = summary.latestItem and (" | Latest: " .. tostring(summary.latestItem)) or ""
    local prefix = summary.isPreview and "Simulation" or "Tracked"
    owner.lootLiveBoardSummary:SetText(
      string.format(
        "Embedded View: Live Board | %s Items: %d | Pending Choices: %d%s",
        prefix,
        tonumber(summary.itemCount) or 0,
        tonumber(summary.pendingChoices) or 0,
        latestText
      )
    )
    return true
  end

  editor.RefreshLootLiveBoardSummaryOnly = function(self)
    return RefreshLiveBoardSummaryOnly(type(self) == "table" and self or editor)
  end

  local function AddLiveBoardTooltip(button, titleText, detailText)
    if not button or not button.SetScript then
      return
    end
    button:SetScript("OnEnter", function(self)
      if not GameTooltip then
        return
      end
      GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
      GameTooltip:SetText(tostring(titleText or "Live Board"), 1.00, 0.82, 0.28)
      GameTooltip:AddLine(tostring(detailText or ""), 0.88, 0.92, 0.96, true)
      GameTooltip:Show()
    end)
    button:SetScript("OnLeave", function()
      if GameTooltip then
        GameTooltip:Hide()
      end
    end)
  end

  local function EnsureLootLiveBoardEditorView(root)
    root = type(root) == "table" and root or RootDB()
    root.ui = root.ui or {}
    if root.ui.lootLiveBoardMode ~= "POPOUT" and root.ui.lootLiveBoardMode ~= "EMBEDDED" then
      root.ui.lootLiveBoardMode = "EMBEDDED"
    end
    if root.ui.lootLiveBoardView ~= "BOARD" then
      root.ui.lootLiveBoardView = "BOARD"
    end
    return "BOARD"
  end

  local status = page:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
  status:SetPoint("TOPLEFT", 0, -46)
  status:SetText("Live Board ready")
  editor.lootLiveBoardStatus = status

  local summary = page:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  summary:SetPoint("TOPLEFT", 0, -70)
  summary:SetWidth(720)
  summary:SetJustifyH("LEFT")
  summary:SetText("")
  editor.lootLiveBoardSummary = summary

  local embedBtn = CreateFrame("Button", nil, page, "UIPanelButtonTemplate")
  embedBtn:SetSize(98, 22)
  embedBtn:SetPoint("TOPLEFT", 0, -102)
  embedBtn:SetText("Live")
  editor.lootLiveBoardEmbedBtn = embedBtn

  local function AddLiveBoardTabUnderline(button)
    local underline = button:CreateTexture(nil, "OVERLAY")
    underline:SetPoint("BOTTOMLEFT", 6, 2)
    underline:SetPoint("BOTTOMRIGHT", -6, 2)
    underline:SetHeight(2)
    underline:SetTexture("Interface\\Buttons\\WHITE8x8")
    underline:SetVertexColor(1.00, 0.82, 0.28, 1.00)
    underline:Hide()
    button.__lidLiveBoardTabUnderline = underline
  end
  AddLiveBoardTabUnderline(embedBtn)

  local popoutBtn = CreateFrame("Button", nil, page, "UIPanelButtonTemplate")
  popoutBtn:SetSize(100, 22)
  popoutBtn:SetPoint("LEFT", embedBtn, "RIGHT", 10, 0)
  popoutBtn:SetText("Pop Out")
  editor.lootLiveBoardPopoutBtn = popoutBtn

  local simulateBtn = CreateFrame("Button", nil, page, "UIPanelButtonTemplate")
  simulateBtn:SetSize(130, 22)
  simulateBtn:SetPoint("LEFT", popoutBtn, "RIGHT", 10, 0)
  simulateBtn:SetText("Preview Simulation")
  simulateBtn:Hide()
  editor.lootLiveBoardSimulateBtn = simulateBtn

  local realSimulateBtn = CreateFrame("Button", nil, page, "UIPanelButtonTemplate")
  realSimulateBtn:SetSize(130, 22)
  realSimulateBtn:SetPoint("LEFT", simulateBtn, "RIGHT", 10, 0)
  realSimulateBtn:SetText("Test Raid Items")
  realSimulateBtn:Hide()
  editor.lootLiveBoardRealSimulateBtn = realSimulateBtn

  editor.lootLiveBoardTransportTestBtn = CreateFrame("Button", nil, page, "UIPanelButtonTemplate")
  editor.lootLiveBoardTransportTestBtn:SetSize(142, 22)
  editor.lootLiveBoardTransportTestBtn:SetPoint("LEFT", realSimulateBtn, "RIGHT", 10, 0)
  editor.lootLiveBoardTransportTestBtn:SetText("Test Live Delivery")
  editor.lootLiveBoardTransportTestBtn:Hide()

  AddLiveBoardTooltip(embedBtn, "Live", "Show dropped items, selections, votes, and assignments for the active session.")
  AddLiveBoardTooltip(popoutBtn, "Pop Out", "Open the active Live Board in a separate resizable window.")
  AddLiveBoardTooltip(simulateBtn, "Preview Simulation", "Developer tool: show isolated simulation data without Loot List points.")
  AddLiveBoardTooltip(realSimulateBtn, "Test Raid Items", "Developer tool: load real item metadata, then send one receipt-tracked simulated raid board for the active host session. Repeated clicks are coalesced while a board is still syncing.")
  AddLiveBoardTooltip(
    editor.lootLiveBoardTransportTestBtn,
    "Test Live Delivery",
    "Developer tool: send one simulation-only item through the same ITEM_OPEN transport and receiver gate used by a real loot drop."
  )

  local hint = page:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  hint:SetPoint("TOPLEFT", 0, -132)
  hint:SetWidth(720)
  hint:SetJustifyH("LEFT")
  hint:SetText("")
  hint:Hide()
  editor.lootLiveBoardHint = hint

  local holder = CreateFrame("Frame", nil, page)
  holder:SetPoint("TOPLEFT", 0, -166)
  holder:SetPoint("TOPRIGHT", -6, -166)
  holder:SetHeight(EMBEDDED_BOARD_MIN_HEIGHT)
  editor.lootLiveBoardHolder = holder

  local landing = CreateFrame("Frame", nil, holder, "BackdropTemplate")
  ApplyFrameSkin(landing)
  landing:SetAllPoints(holder)
  landing:SetFrameStrata("DIALOG")
  landing:SetFrameLevel((holder.GetFrameLevel and holder:GetFrameLevel() or 0) + 40)
  landing:EnableMouse(true)
  landing:Hide()
  editor.lootLiveBoardLanding = landing

  local landingTitle = landing:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
  landingTitle:SetPoint("CENTER", landing, "CENTER", 0, 58)
  landingTitle:SetWidth(560)
  landingTitle:SetJustifyH("CENTER")
  landingTitle:SetText("Nothing live yet")
  editor.lootLiveBoardLandingTitle = landingTitle

  local landingDetail = landing:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  landingDetail:SetPoint("TOP", landingTitle, "BOTTOM", 0, -18)
  landingDetail:SetWidth(560)
  landingDetail:SetJustifyH("CENTER")
  landingDetail:SetJustifyV("TOP")
  landingDetail:SetText("Dropped items, selections, votes, and assignments will appear here once a session starts.")
  editor.lootLiveBoardLandingDetail = landingDetail

  local landingAction = CreateFrame("Button", nil, landing, "UIPanelButtonTemplate")
  landingAction:SetSize(204, 28)
  landingAction:SetPoint("TOP", landingDetail, "BOTTOM", 0, -24)
  landingAction:SetText("Open Session Setup")
  landingAction.__lid_customBg = { 0.05, 0.18, 0.34, 0.98 }
  landingAction.__lid_customHover = { 0.10, 0.32, 0.58, 1.00 }
  landingAction.__lid_customPushed = { 0.04, 0.12, 0.24, 1.00 }
  landingAction.__lid_customBorder = { 0.40, 0.66, 0.98, 0.98 }
  landingAction.__lid_customText = { 0.94, 0.97, 1.00, 1.00 }
  landingAction:SetScript("OnClick", function()
    if type(editor.ShowPage) == "function" then
      editor.ShowPage("Panels")
    end
  end)
  editor.lootLiveBoardLandingAction = landingAction

  local function HideEmbeddedLiveBoard()
    local board = rawget(_G, "LIDCOUNCIL_LiveLootBoard")
    if board and board.__embeddedParent == holder then
      board:Hide()
    end
  end

  local function SetLiveBoardLanding(visible, titleText, detailText, actionText)
    if editor.lootLiveBoardLandingTitle then
      editor.lootLiveBoardLandingTitle:SetText(tostring(titleText or ""))
      editor.lootLiveBoardLandingTitle:SetTextColor(1.00, 0.82, 0.28, 1.00)
    end
    if editor.lootLiveBoardLandingDetail then
      editor.lootLiveBoardLandingDetail:SetText(tostring(detailText or ""))
      editor.lootLiveBoardLandingDetail:SetTextColor(0.86, 0.90, 0.95, 1.00)
    end
    if editor.lootLiveBoardLandingAction then
      editor.lootLiveBoardLandingAction:SetText(tostring(actionText or "Open Session Setup"))
    end
    if editor.lootLiveBoardLanding then
      editor.lootLiveBoardLanding:SetShown(visible == true)
    end
    if visible then
      HideEmbeddedLiveBoard()
    end
  end

  holder:HookScript("OnSizeChanged", function(self)
    -- The board is anchored to this holder. Refresh after a viewport resize so
    -- every internal panel uses the final embedded dimensions.
    local board = rawget(_G, "LIDCOUNCIL_LiveLootBoard")
    if board and board.__embeddedParent == self and type(board.RefreshBoard) == "function" then
      board:RefreshBoard()
    end
  end)

  local inactiveOverlay = CreateFrame("Frame", nil, page, "BackdropTemplate")
  ApplyFrameSkin(inactiveOverlay)
  inactiveOverlay:SetPoint("TOPLEFT", page, "TOPLEFT", 0, 0)
  inactiveOverlay:SetPoint("BOTTOMRIGHT", page, "BOTTOMRIGHT", 0, 0)
  inactiveOverlay:EnableMouse(true)
  inactiveOverlay:SetFrameStrata("HIGH")
  inactiveOverlay:SetFrameLevel((page.GetFrameLevel and page:GetFrameLevel() or 0) + 20)
  inactiveOverlay:Hide()
  editor.lootLiveBoardInactiveOverlay = inactiveOverlay

  local inactiveText = inactiveOverlay:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
  inactiveText:SetPoint("CENTER", 0, 0)
  inactiveText:SetWidth(520)
  inactiveText:SetJustifyH("CENTER")
  inactiveText:SetJustifyV("MIDDLE")
  inactiveText:SetText(ACTIVATE_PROFILE_REQUIRED_TEXT)
  editor.lootLiveBoardInactiveText = inactiveText

  page.__contentHeight = 700

  local function LayoutLootLiveBoardPage(self)
    if not self then
      return
    end

    local contentWidth = math.max(260, math.floor(((page.GetWidth and page:GetWidth()) or 760) - 12))
    local viewportHeight = (
      editor.scrollFrame and editor.scrollFrame.GetHeight and editor.scrollFrame:GetHeight()
    ) or (
      page.GetHeight and page:GetHeight()
    ) or 680
    local pageHeight = math.max(320, math.floor(viewportHeight))
    local buttonHeight
    local hintTop
    local hintHeight
    local holderTop
    local holderHeight

    if self.lootLiveBoardSummary then
      self.lootLiveBoardSummary:SetWidth(contentWidth)
    end
    if self.lootLiveBoardHint then
      self.lootLiveBoardHint:SetWidth(contentWidth)
    end
    local landingTextWidth = math.max(220, math.min(560, contentWidth - 32))
    if self.lootLiveBoardLandingTitle then
      self.lootLiveBoardLandingTitle:SetWidth(landingTextWidth)
    end
    if self.lootLiveBoardLandingDetail then
      self.lootLiveBoardLandingDetail:SetWidth(landingTextWidth)
    end

    local controlsTop = self.__lootLiveBoardIdleLanding == true and -46 or -102
    buttonHeight = FlowLayoutControls({
      self.lootLiveBoardEmbedBtn,
      self.lootLiveBoardPopoutBtn,
      self.lootLiveBoardSimulateBtn,
      self.lootLiveBoardRealSimulateBtn,
      self.lootLiveBoardTransportTestBtn,
    }, 0, controlsTop, contentWidth, 10, 8)
    hintTop = controlsTop - buttonHeight - 8
    if self.lootLiveBoardHint then
      self.lootLiveBoardHint:ClearAllPoints()
      self.lootLiveBoardHint:SetPoint("TOPLEFT", 0, hintTop)
    end

    hintHeight = self.lootLiveBoardHint and self.lootLiveBoardHint:IsShown()
      and math.max(18, math.ceil(self.lootLiveBoardHint:GetStringHeight() or 0))
      or 0
    holderTop = hintTop - hintHeight - (hintHeight > 0 and 12 or 10)
    -- Keep the operational board or idle landing inside the page. Smaller
    -- editor heights use the outer scroll bar instead of an unbounded frame.
    holderHeight = math.max(EMBEDDED_BOARD_MIN_HEIGHT, pageHeight - math.abs(holderTop) - 8)
    if self.lootLiveBoardHolder then
      self.lootLiveBoardHolder:ClearAllPoints()
      self.lootLiveBoardHolder:SetPoint("TOPLEFT", 0, holderTop)
      self.lootLiveBoardHolder:SetPoint("TOPRIGHT", -6, holderTop)
      self.lootLiveBoardHolder:SetHeight(holderHeight)
    end

    page.__contentHeight = math.max(pageHeight, math.abs(holderTop) + holderHeight + 8)
  end

  embedBtn:SetScript("OnClick", function()
    local selectedProfileName = TrimText(GetLiveBoardContextProfileName())
    if selectedProfileName == "" then
      return
    end
    local access = GetLootProfileAccessInfo(selectedProfileName)
    if not access.canOpenLiveBoard then
      return
    end
    local root = RootDB()
    root.ui = root.ui or {}
    root.ui.lootLiveBoardMode = "EMBEDDED"
    root.ui.lootLiveBoardView = "BOARD"
    RefreshLiveBoardView()
  end)

  popoutBtn:SetScript("OnClick", function()
    local selectedProfileName = TrimText(GetLiveBoardContextProfileName())
    if selectedProfileName == "" then
      return
    end
    local access = GetLootProfileAccessInfo(selectedProfileName)
    if not access.canOpenLiveBoard then
      return
    end
    local root = RootDB()
    root.ui = root.ui or {}
    root.ui.lootLiveBoardMode = "POPOUT"
    local popoutBoard = ResolveOptionalApiFunction("LIDCOUNCIL_PopoutLiveLootBoard")
    if not RunLiveBoardAction("Pop Out Board", popoutBoard) then
      local openBoard = ResolveOptionalApiFunction("LIDCOUNCIL_OpenLiveLootBoard")
      RunLiveBoardAction("Open Live Board", openBoard)
    end
    RefreshLiveBoardView()
  end)

  simulateBtn:SetScript("OnClick", function()
    local selectedProfileName = TrimText(GetLiveBoardContextProfileName())
    if selectedProfileName == "" then
      return
    end
    local access = GetLootProfileAccessInfo(selectedProfileName)
    if not access.canOpenLiveBoard then
      return
    end
    local root = RootDB()
    root.ui = root.ui or {}
    root.ui.lootLiveBoardMode = "EMBEDDED"
    root.ui.lootLiveBoardView = "BOARD"
    local attachBoard = ResolveOptionalApiFunction("LIDCOUNCIL_AttachLiveLootBoard")
    local attached = RunLiveBoardAction("Show Live Board", attachBoard, holder)
    local runSimulation = ResolveOptionalApiFunction("LIDCOUNCIL_RunLiveLootSimulation")
    if attached then
      RunLiveBoardAction("Run Fake Simulation", runSimulation, selectedProfileName)
    end
    RefreshLiveBoardView()
  end)

  realSimulateBtn:SetScript("OnClick", function()
    local selectedProfileName = TrimText(GetLiveBoardContextProfileName())
    if selectedProfileName == "" then
      return
    end
    local access = GetLootProfileAccessInfo(selectedProfileName)
    if not access.canOpenLiveBoard then
      return
    end
    local root = RootDB()
    root.ui = root.ui or {}
    root.ui.lootLiveBoardMode = "EMBEDDED"
    root.ui.lootLiveBoardView = "BOARD"
    local attachBoard = ResolveOptionalApiFunction("LIDCOUNCIL_AttachLiveLootBoard")
    local attached = RunLiveBoardAction("Show Live Board", attachBoard, holder)
    local runRealSimulation = ResolveOptionalApiFunction("LIDCOUNCIL_RunLiveLootRealSimulation")
    if attached then
      if type(runRealSimulation) ~= "function" then
        RefreshLiveBoardSummaryOnly(editor)
        SetLiveBoardStatusOverride(editor, "Test Raid Items is unavailable.", { 1.00, 0.55, 0.44, 1.00 })
        return
      end
      local executed, result = pcall(runRealSimulation, selectedProfileName)
      RefreshLiveBoardSummaryOnly(editor)
      if not executed then
        SetLiveBoardStatusOverride(editor, "Test Raid Items failed: " .. tostring(result), { 1.00, 0.35, 0.25, 1.00 })
        return
      end
      if type(result) ~= "table" then
        SetLiveBoardStatusOverride(editor, "Test Raid Items returned no diagnostic result.", { 1.00, 0.55, 0.44, 1.00 })
        return
      end
      local color = result.ok == true and { 0.30, 0.82, 1.00, 1.00 } or { 1.00, 0.55, 0.30, 1.00 }
      if TrimText(result.dispatchState) == "acknowledged" then
        color = { 0.20, 0.90, 0.20, 1.00 }
      elseif TrimText(result.dispatchState) == "failed" then
        color = { 1.00, 0.35, 0.25, 1.00 }
      end
      SetLiveBoardStatusOverride(
        editor,
        TrimText(result.statusText) ~= "" and result.statusText or result.message,
        color
      )
    else
      RefreshLiveBoardSummaryOnly(editor)
      SetLiveBoardStatusOverride(editor, "Test Raid Items could not open the Live Board.", { 1.00, 0.35, 0.25, 1.00 })
    end
  end)

  editor.lootLiveBoardTransportTestBtn:SetScript("OnClick", function()
    local selectedProfileName = TrimText(GetLiveBoardContextProfileName())
    if selectedProfileName == "" then
      return
    end
    local root = RootDB()
    root.ui = root.ui or {}
    root.ui.lootLiveBoardMode = "EMBEDDED"
    root.ui.lootLiveBoardView = "BOARD"
    local attachBoard = ResolveOptionalApiFunction("LIDCOUNCIL_AttachLiveLootBoard")
    local attached = RunLiveBoardAction("Show Live Board", attachBoard, holder)
    local runTransportTest = ResolveOptionalApiFunction("LIDCOUNCIL_RunLiveLootTransportTest")
    if not attached or type(runTransportTest) ~= "function" then
      RefreshLiveBoardView()
      SetLiveBoardStatusOverride(editor, "Live delivery test is unavailable.", { 1.00, 0.35, 0.25, 1.00 })
      return
    end
    local executed, result = pcall(runTransportTest, selectedProfileName)
    RefreshLiveBoardView()
    if not executed then
      SetLiveBoardStatusOverride(editor, "Live delivery test failed: " .. tostring(result), { 1.00, 0.35, 0.25, 1.00 })
      return
    end
    local resultText = type(result) == "table" and TrimText(result.statusText or result.message) or ""
    local resultOk = type(result) == "table" and result.ok == true
    SetLiveBoardStatusOverride(
      editor,
      resultText ~= "" and resultText or "Live delivery test returned no diagnostic result.",
      resultOk and { 0.30, 0.82, 1.00, 1.00 } or { 1.00, 0.55, 0.30, 1.00 }
    )
  end)

  editor.RefreshLootLiveBoardPage = function(self)
    local root = RootDB()
    local profileName = TrimText(GetLiveBoardContextProfileName())
    local hasActiveProfile = profileName ~= ""
    ClearLiveBoardStatusOverride(self)
    if self.lootLiveBoardInactiveOverlay then
      self.lootLiveBoardInactiveOverlay:SetShown(not hasActiveProfile)
    end
    if self.liveBoardTitle then
      self.liveBoardTitle:SetText(hasActiveProfile and "Live Board" or "Profile")
    end
    if hasActiveProfile then
      SetCurrentProfileFont(self.liveBoardCurrentLabel, "Current Profile: " .. profileName, nil)
    else
      SetCurrentProfileFont(self.liveBoardCurrentLabel, NO_ACTIVE_PROFILE_CURRENT_TEXT, NO_ACTIVE_PROFILE_TEXT_COLOR)
    end
    if self.lootLiveBoardHolder then
      self.lootLiveBoardHolder:SetShown(hasActiveProfile)
    end
    if self.lootLiveBoardStatus then
      self.lootLiveBoardStatus:SetShown(hasActiveProfile)
    end
    if self.lootLiveBoardSummary then
      self.lootLiveBoardSummary:SetShown(hasActiveProfile)
    end
    if self.lootLiveBoardHint then
      self.lootLiveBoardHint:SetShown(hasActiveProfile)
    end
    for _, control in ipairs({
      self.lootLiveBoardEmbedBtn,
      self.lootLiveBoardPopoutBtn,
      self.lootLiveBoardSimulateBtn,
      self.lootLiveBoardRealSimulateBtn,
      self.lootLiveBoardTransportTestBtn,
    }) do
      if control and control.SetShown then
        control:SetShown(hasActiveProfile)
      end
    end
    if not hasActiveProfile then
      self.__lootLiveBoardIdleLanding = false
      SetLiveBoardLanding(false)
      if self.lootLiveBoardStatus then
        self.lootLiveBoardStatus:SetText("No active profile")
        self.lootLiveBoardStatus:SetTextColor(1.00, 0.35, 0.25, 1.00)
      end
      for _, button in ipairs({
        self.lootLiveBoardEmbedBtn,
        self.lootLiveBoardPopoutBtn,
        self.lootLiveBoardSimulateBtn,
        self.lootLiveBoardRealSimulateBtn,
        self.lootLiveBoardTransportTestBtn,
      }) do
        if button and button.Disable then
          button:Disable()
        end
      end
      LayoutLootLiveBoardPage(self)
      if self.currentPage == "LiveBoard" and self.UpdateScrollLayout then
        self:UpdateScrollLayout(true)
      end
      return
    end
    local stateStartedAt = INTERNAL_API.LIDCOUNCIL_BeginSyncPerformanceSample_Impl("editor_live_board_state", 1)
    local access = GetLootProfileAccessInfo(profileName)
    EnsureLootLiveBoardEditorView(root)
    local mode = EnsureLootLiveBoardMode(root)
    local liveSummaryProvider = ResolveOptionalApiFunction("LIDCOUNCIL_GetLiveLootBoardSummary")
    local liveSummaryState = ReadLiveBoardState("Read Live Board summary", liveSummaryProvider, nil)
    local realSimulationStatusProvider = ResolveOptionalApiFunction("LIDCOUNCIL_GetLiveLootRealSimulationStatus")
    local realSimulationStatus = ReadLiveBoardState("Read Live Board simulation status", realSimulationStatusProvider, nil)
    local activeSession, activeProfileName = GetActiveLootSession()
    local selfKey = TrimText(GetCharacterKey() or "")
    local sessionMatchesProfile = type(activeSession) == "table"
      and tostring(activeProfileName or "") == tostring(profileName)
    local sessionStatus = string.upper(TrimText(type(activeSession) == "table" and activeSession.status or ""))
    local hasActiveSessionBoard = sessionMatchesProfile and sessionStatus == "ACTIVE"
    local hasPreparationLobby = sessionMatchesProfile and sessionStatus == "PREPARING"
    local hasPreviewBoard = type(liveSummaryState) == "table" and liveSummaryState.isPreview == true
    local developerMode = type(root.ui) == "table" and root.ui.developerMode == true
    local simulationAvailable = type(root.profiles) == "table" and type(root.profiles.Simulation) == "table"
    local canRunSimulation = access.canOpenLiveBoard and simulationAvailable
    local canRunRealSimulation = access.canOpenLiveBoard
      and hasActiveSessionBoard
      and selfKey ~= ""
      and string.lower(TrimText(activeSession.host or "")) == string.lower(selfKey)
    local canPopOutBoard = access.canOpenLiveBoard and (hasActiveSessionBoard or hasPreviewBoard)

    local showOperationalBoard = access.canOpenLiveBoard and (hasActiveSessionBoard or hasPreviewBoard)
    local showLanding = access.canOpenLiveBoard and not showOperationalBoard
    local showPopoutBoard = mode == "POPOUT" and canPopOutBoard
    INTERNAL_API.LIDCOUNCIL_RecordSyncPerformance_Impl("editor_live_board_state", stateStartedAt)

    local attachStartedAt = INTERNAL_API.LIDCOUNCIL_BeginSyncPerformanceSample_Impl("editor_live_board_attach", 1)
    if self.lootLiveBoardHolder then
      self.lootLiveBoardHolder:SetShown(access.canOpenLiveBoard and not showPopoutBoard)
    end

    if self.currentPage == "LiveBoard" then
      if mode == "EMBEDDED" and showOperationalBoard then
        local attachBoard = ResolveOptionalApiFunction("LIDCOUNCIL_AttachLiveLootBoard")
        RunLiveBoardAction("Open Live Board", attachBoard, holder)
      end
    end
    INTERNAL_API.LIDCOUNCIL_RecordSyncPerformance_Impl("editor_live_board_attach", attachStartedAt)

    local controlsStartedAt = INTERNAL_API.LIDCOUNCIL_BeginSyncPerformanceSample_Impl("editor_live_board_controls", 1)
    if showLanding then
      if hasPreparationLobby then
        SetLiveBoardLanding(
          true,
          "Ready to start",
          "The Live Board becomes operational when the session starts. Continue preparing members in Current Session.",
          "Open Current Session"
        )
      else
        SetLiveBoardLanding(
          true,
          "Nothing live yet",
          "Dropped items, selections, votes, and assignments will appear here once a LidCouncil session starts.",
          "Open Session Setup"
        )
      end
    else
      SetLiveBoardLanding(false)
    end
    local showIdleLanding = showLanding and not hasPreparationLobby
    self.__lootLiveBoardIdleLanding = showIdleLanding

    local disabledTextColor = { 0.46, 0.46, 0.50, 1.00 }
    local normalTextColor = { 0.92, 0.92, 0.96, 1.00 }
    local embeddedSelected = access.canOpenLiveBoard and not showPopoutBoard
    SetListButtonSelected(self.lootLiveBoardEmbedBtn, embeddedSelected)
    if self.lootLiveBoardEmbedBtn and self.lootLiveBoardEmbedBtn.__lidLiveBoardTabUnderline then
      self.lootLiveBoardEmbedBtn.__lidLiveBoardTabUnderline:SetShown(embeddedSelected)
    end
    SetListButtonSelected(self.lootLiveBoardPopoutBtn, showPopoutBoard)
    if self.lootLiveBoardPopoutBtn and self.lootLiveBoardPopoutBtn.__lidLiveBoardTabUnderline then
      self.lootLiveBoardPopoutBtn.__lidLiveBoardTabUnderline:SetShown(showPopoutBoard)
    end
    SetTextListButtonTextColor(self.lootLiveBoardEmbedBtn, embeddedSelected and { 1.00, 0.88, 0.32, 1.00 } or (access.canOpenLiveBoard and normalTextColor or disabledTextColor))
    SetTextListButtonTextColor(self.lootLiveBoardPopoutBtn, showPopoutBoard and { 1.00, 0.88, 0.32, 1.00 } or (canPopOutBoard and normalTextColor or disabledTextColor))
    SetTextListButtonTextColor(self.lootLiveBoardSimulateBtn, canRunSimulation and normalTextColor or disabledTextColor)
    SetTextListButtonTextColor(self.lootLiveBoardRealSimulateBtn, canRunRealSimulation and normalTextColor or disabledTextColor)
    SetTextListButtonTextColor(self.lootLiveBoardTransportTestBtn, canRunRealSimulation and normalTextColor or disabledTextColor)
    if self.lootLiveBoardEmbedBtn and self.lootLiveBoardEmbedBtn.Enable then
      if access.canOpenLiveBoard then self.lootLiveBoardEmbedBtn:Enable() else self.lootLiveBoardEmbedBtn:Disable() end
    end
    if self.lootLiveBoardEmbedBtn and self.lootLiveBoardEmbedBtn.EnableMouse then
      self.lootLiveBoardEmbedBtn:EnableMouse(access.canOpenLiveBoard and true or false)
    end
    if self.lootLiveBoardPopoutBtn and self.lootLiveBoardPopoutBtn.Enable then
      if canPopOutBoard then self.lootLiveBoardPopoutBtn:Enable() else self.lootLiveBoardPopoutBtn:Disable() end
    end
    if self.lootLiveBoardPopoutBtn and self.lootLiveBoardPopoutBtn.EnableMouse then
      self.lootLiveBoardPopoutBtn:EnableMouse(canPopOutBoard and true or false)
    end
    if self.lootLiveBoardSimulateBtn and self.lootLiveBoardSimulateBtn.Enable then
      if canRunSimulation then self.lootLiveBoardSimulateBtn:Enable() else self.lootLiveBoardSimulateBtn:Disable() end
    end
    if self.lootLiveBoardSimulateBtn and self.lootLiveBoardSimulateBtn.EnableMouse then
      self.lootLiveBoardSimulateBtn:EnableMouse(canRunSimulation and true or false)
    end
    if self.lootLiveBoardRealSimulateBtn and self.lootLiveBoardRealSimulateBtn.Enable then
      if canRunRealSimulation then self.lootLiveBoardRealSimulateBtn:Enable() else self.lootLiveBoardRealSimulateBtn:Disable() end
    end
    if self.lootLiveBoardRealSimulateBtn and self.lootLiveBoardRealSimulateBtn.EnableMouse then
      self.lootLiveBoardRealSimulateBtn:EnableMouse(canRunRealSimulation and true or false)
    end
    if self.lootLiveBoardTransportTestBtn and self.lootLiveBoardTransportTestBtn.Enable then
      if canRunRealSimulation then self.lootLiveBoardTransportTestBtn:Enable() else self.lootLiveBoardTransportTestBtn:Disable() end
    end
    if self.lootLiveBoardTransportTestBtn and self.lootLiveBoardTransportTestBtn.EnableMouse then
      self.lootLiveBoardTransportTestBtn:EnableMouse(canRunRealSimulation and true or false)
    end
    if self.lootLiveBoardPopoutBtn and self.lootLiveBoardPopoutBtn.SetButtonState then
      self.lootLiveBoardPopoutBtn:SetButtonState(canPopOutBoard and "NORMAL" or "DISABLED", false)
    end
    if self.lootLiveBoardEmbedBtn and self.lootLiveBoardEmbedBtn.SetAlpha then
      self.lootLiveBoardEmbedBtn:SetAlpha(access.canOpenLiveBoard and 1 or 0.55)
    end
    if self.lootLiveBoardPopoutBtn and self.lootLiveBoardPopoutBtn.SetAlpha then
      self.lootLiveBoardPopoutBtn:SetAlpha(canPopOutBoard and 1 or 0.55)
    end
    if self.lootLiveBoardSimulateBtn and self.lootLiveBoardSimulateBtn.SetAlpha then
      self.lootLiveBoardSimulateBtn:SetAlpha(canRunSimulation and 1 or 0.55)
    end
    if self.lootLiveBoardRealSimulateBtn and self.lootLiveBoardRealSimulateBtn.SetAlpha then
      self.lootLiveBoardRealSimulateBtn:SetAlpha(canRunRealSimulation and 1 or 0.55)
    end
    if self.lootLiveBoardTransportTestBtn and self.lootLiveBoardTransportTestBtn.SetAlpha then
      self.lootLiveBoardTransportTestBtn:SetAlpha(canRunRealSimulation and 1 or 0.55)
    end

    if self.lootLiveBoardPopoutBtn then
      self.lootLiveBoardPopoutBtn:SetShown(canPopOutBoard)
    end
    if self.lootLiveBoardSimulateBtn then
      self.lootLiveBoardSimulateBtn:SetShown(developerMode)
    end
    if self.lootLiveBoardRealSimulateBtn then
      self.lootLiveBoardRealSimulateBtn:SetShown(developerMode)
    end
    if self.lootLiveBoardTransportTestBtn then
      self.lootLiveBoardTransportTestBtn:SetShown(developerMode)
    end
    if self.lootLiveBoardHint then
      self.lootLiveBoardHint:SetShown(false)
    end
    if self.lootLiveBoardStatus then
      self.lootLiveBoardStatus:SetShown(not showIdleLanding)
    end
    if self.lootLiveBoardSummary then
      self.lootLiveBoardSummary:SetShown(not showIdleLanding)
    end

    if showPopoutBoard then
      self.lootLiveBoardStatus:SetText("Live Board open in pop-out")
      self.lootLiveBoardStatus:SetTextColor(0.20, 0.90, 0.20, 1.00)
      self.lootLiveBoardSummary:SetText("The current Live Board is open in a separate window.")
    elseif hasActiveSessionBoard then
      self.lootLiveBoardStatus:SetText("Active session board")
      self.lootLiveBoardStatus:SetTextColor(0.20, 0.90, 0.20, 1.00)
      self.lootLiveBoardSummary:SetText("Live items, selections, votes, and assignments for the current session.")
    elseif hasPreviewBoard then
      self.lootLiveBoardStatus:SetText("Simulation board")
      self.lootLiveBoardStatus:SetTextColor(1.00, 0.82, 0.32, 1.00)
      self.lootLiveBoardSummary:SetText("Preview data is active. No Loot List points are written.")
    elseif hasPreparationLobby then
      self.lootLiveBoardStatus:SetText("Preparation lobby open")
      self.lootLiveBoardStatus:SetTextColor(1.00, 0.72, 0.22, 1.00)
      self.lootLiveBoardSummary:SetText("Start the session when members are ready.")
    else
      self.lootLiveBoardStatus:SetText("No active session")
      self.lootLiveBoardStatus:SetTextColor(0.72, 0.78, 0.84, 1.00)
      self.lootLiveBoardSummary:SetText("Start or join a session to manage live loot.")
    end

    if not access.canOpenLiveBoard then
      self.lootLiveBoardStatus:SetText("Live Board access unavailable")
      self.lootLiveBoardStatus:SetTextColor(1.00, 0.82, 0.32, 1.00)
      self.lootLiveBoardSummary:SetText("Use Loot List > Item History to review past assignments.")
    end

    if not showPopoutBoard and showOperationalBoard and type(liveSummaryState) == "table" and tonumber(liveSummaryState.itemCount) and tonumber(liveSummaryState.itemCount) > 0 then
      local latestText = liveSummaryState.latestItem and (" | Latest: " .. tostring(liveSummaryState.latestItem)) or ""
      local prefix = liveSummaryState.isPreview and "Simulation" or "Tracked"
      self.lootLiveBoardSummary:SetText(
        string.format(
          "Embedded View: %s | %s Items: %d | Pending Choices: %d%s",
          "Live Board",
          prefix,
          tonumber(liveSummaryState.itemCount) or 0,
          tonumber(liveSummaryState.pendingChoices) or 0,
          latestText
        )
      )
    end

    if hasActiveSessionBoard
      and type(realSimulationStatus) == "table"
      and TrimText(realSimulationStatus.sessionId) == TrimText(activeSession.id)
      and TrimText(realSimulationStatus.statusText) ~= ""
    then
      local dispatchState = TrimText(realSimulationStatus.dispatchState)
      local color = { 0.30, 0.82, 1.00, 1.00 }
      if dispatchState == "acknowledged" then
        color = { 0.20, 0.90, 0.20, 1.00 }
      elseif dispatchState == "failed" then
        color = { 1.00, 0.35, 0.25, 1.00 }
      elseif dispatchState == "partial" or dispatchState == "local_only" then
        color = { 1.00, 0.72, 0.22, 1.00 }
      end
      self.lootLiveBoardStatus:SetText(realSimulationStatus.statusText)
      self.lootLiveBoardStatus:SetTextColor(color[1], color[2], color[3], color[4])
    end

    ApplyLiveBoardStatusOverride(self)
    INTERNAL_API.LIDCOUNCIL_RecordSyncPerformance_Impl("editor_live_board_controls", controlsStartedAt)

    local layoutStartedAt = INTERNAL_API.LIDCOUNCIL_BeginSyncPerformanceSample_Impl("editor_live_board_layout", 1)
    LayoutLootLiveBoardPage(self)
    INTERNAL_API.LIDCOUNCIL_RecordSyncPerformance_Impl("editor_live_board_layout", layoutStartedAt)

    local scrollStartedAt = INTERNAL_API.LIDCOUNCIL_BeginSyncPerformanceSample_Impl("editor_live_board_scroll", 1)
    if self.currentPage == "LiveBoard" and self.UpdateScrollLayout then
      self:UpdateScrollLayout(true)
    end
    INTERNAL_API.LIDCOUNCIL_RecordSyncPerformance_Impl("editor_live_board_scroll", scrollStartedAt)
  end

  editor.RefreshLootLiveBoardPage = (function(refreshPage)
    return function(self)
      local pageStartedAt = INTERNAL_API.LIDCOUNCIL_BeginSyncPerformanceSample_Impl("editor_page_live_board", 1)
      local result = refreshPage(self)
      INTERNAL_API.LIDCOUNCIL_RecordSyncPerformance_Impl("editor_page_live_board", pageStartedAt, {
        context = tostring(self and (self.__lootLiveBoardOpenSection or self.lootLiveBoardView) or "live"),
      })
      return result
    end
  end)(editor.RefreshLootLiveBoardPage)

  if page and page.HookScript then
    page:HookScript("OnSizeChanged", function()
      LayoutLootLiveBoardPage(editor)
    end)
  end
  editor.LayoutLootLiveBoardPage = LayoutLootLiveBoardPage
end

INTERNAL_API.LIDCOUNCIL_BuildLootLiveBoardPage_Impl = BuildLootLiveBoardPage

