local _, GF = ...

GF.FRAME_W_LEGACY_DEFAULT = 1024
-- 840px browse columns + 4px ColumnDisplay compensation + current panel/nav/scroll insets.
GF.FRAME_W = 1120
GF.FRAME_H = 550
GF.FRAME_MIN_W = GF.FRAME_W
GF.FRAME_MIN_H = GF.FRAME_H
GF.FRAME_FOOTER_LAYOUT_VERSION = 3
GF.FRAME_PREVIOUS_DEFAULT_H = 552
GF.FRAME_LEGACY_PANEL_BOTTOM = 24
GF.FRAME_INTERIM_PANEL_BOTTOM = 44
GF.FRAME_INTERIM_DEFAULT_H = 560
GF.PANEL_SCALE_MIN_PCT = 100
GF.PANEL_SCALE_MAX_PCT = 150
GF.PANEL_SCALE_DEFAULT_PCT = 100
GF.FONT_SCALE_MIN_PCT = 100
GF.FONT_SCALE_MAX_PCT = 150
GF.FONT_SCALE_DEFAULT_PCT = 100
GF.LIST_BACKGROUND_ALPHA_MIN_PCT = 30
GF.LIST_BACKGROUND_ALPHA_MAX_PCT = 100
GF.LIST_BACKGROUND_ALPHA_DEFAULT_PCT = 100
GF.DEFAULT_REQUIRED_ITEM_LEVEL_MIN = 0
GF.DEFAULT_REQUIRED_ITEM_LEVEL_DEFAULT = 0
GF.FRAME_PAD = 4
GF.FRAME_TITLE_TOP = 24
GF.FRAME_BODY_BOTTOM = 41
GF.FRAME_CONTENT_BOTTOM = GF.FRAME_BODY_BOTTOM + GF.FRAME_PAD
GF.MAIN_PANEL_INSET_LEFT = 26
GF.MAIN_PANEL_INSET_RIGHT = 26
GF.MAIN_PANEL_INSET_TOP = 64
GF.MAIN_PANEL_INSET_BOTTOM = 36
GF.MAIN_PANEL_BACKPLATE_BG_INSET_LEFT = 5
GF.MAIN_PANEL_BACKPLATE_BG_INSET_RIGHT = 5
GF.MAIN_PANEL_BACKPLATE_BG_INSET_TOP = 2
GF.MAIN_PANEL_BACKPLATE_BG_INSET_BOTTOM = 10
GF.MAIN_PANEL_BACKPLATE_BG_COLOR = { 0, 0, 0, 1 }
GF.PLAYER_CONTEXT_DIALOG_BACKGROUND_COLOR = { 0, 0, 0, 0.82 }
GF.MAIN_PANEL_DECORATIVE_BORDER_ATLAS = "transmog-tabs-frame"
GF.MAIN_PANEL_DECORATIVE_BACKGROUND_ATLAS = "transmog-tabs-frame-bg"
GF.MAIN_PANEL_DECORATIVE_BACKGROUND_INSET_LEFT = 15
GF.MAIN_PANEL_DECORATIVE_BACKGROUND_INSET_RIGHT = 15
GF.MAIN_PANEL_DECORATIVE_BACKGROUND_INSET_TOP = 16
GF.MAIN_PANEL_DECORATIVE_BACKGROUND_INSET_BOTTOM = 14
GF.MAIN_PANEL_DECORATIVE_BACKGROUND_ALPHA = 0.42
GF.MAIN_PANEL_CONTENT_PADDING_X = GF.MAIN_PANEL_BACKPLATE_BG_INSET_LEFT
GF.MAIN_PANEL_CONTENT_PADDING_TOP = GF.MAIN_PANEL_BACKPLATE_BG_INSET_TOP
GF.MAIN_PANEL_CONTENT_PADDING_BOTTOM = GF.MAIN_PANEL_BACKPLATE_BG_INSET_BOTTOM
GF.MAIN_PANEL_TAB_MIN_WIDTH = 95
GF.MAIN_PANEL_TAB_MAX_WIDTH = 170
GF.MAIN_PANEL_TAB_HEIGHT = 32
GF.MAIN_PANEL_TAB_GAP = 1
GF.MAIN_PANEL_TAB_SELECTED_FONT_OBJECT = "GameFontHighlight"
GF.MAIN_PANEL_TAB_UNSELECTED_FONT_OBJECT = "GameFontNormal"
GF.MAIN_PANEL_TAB_DISABLED_FONT_OBJECT = "GameFontDisable"
GF.MAIN_WINDOW_TITLE_OFFSET_Y = -6
GF.MAIN_WINDOW_DRAG_HANDLE_LEFT_INSET = 18
GF.MAIN_WINDOW_DRAG_HANDLE_RIGHT_INSET = 46
GF.MAIN_WINDOW_DRAG_HANDLE_TOP_OFFSET = 0
GF.MAIN_WINDOW_DRAG_HANDLE_BOTTOM_OFFSET = -40
GF.MAIN_WINDOW_ROLE_BUTTON_SIZE = 32
GF.MAIN_WINDOW_ROLE_BUTTON_GAP = 9
GF.MAIN_WINDOW_ROLE_BUTTON_RIGHT_INSET = 48
GF.MAIN_WINDOW_ROLE_BUTTON_CENTER_OFFSET = 46
GF.MAIN_WINDOW_ROLE_BUTTON_TOP_OFFSET = GF.MAIN_WINDOW_ROLE_BUTTON_CENTER_OFFSET - (GF.MAIN_WINDOW_ROLE_BUTTON_SIZE / 2)
GF.MAIN_WINDOW_EYE_SIZE = 44
GF.MAIN_WINDOW_EYE_HOST_SIZE = 68
GF.MAIN_WINDOW_EYE_BACKGROUND_SIZE = 54
GF.MAIN_WINDOW_EYE_BACKGROUND_MASK = "Interface\\CharacterFrame\\TempPortraitAlphaMask"
GF.ADDON_LOGO_TEXTURE = "Interface\\AddOns\\GroupFinder\\Art\\Logo\\GroupFinderIcon.png"
GF.ADDON_MENU_LOGO_TEXTURE = "Interface\\AddOns\\GroupFinder\\Art\\Logo\\GroupFinder.png"
GF.ADDON_ART_UI_PATH = "Interface\\AddOns\\GroupFinder\\Art\\UI\\"
GF.ADDON_ART_ICON_PATH = GF.ADDON_ART_UI_PATH .. "Icon\\"
GF.ADDON_SOUNDS_PATH = "Interface\\AddOns\\GroupFinder\\Sounds\\"
GF.FOOTER_ACTION_BUTTON_SIZE = 35
GF.FOOTER_ACTION_BUTTON_GAP = 0
GF.FOOTER_ACTION_BUTTON_NORMAL_ATLAS = "ui-journeys-greatvault-button"
GF.FOOTER_ACTION_BUTTON_PRESSED_ATLAS =
	"ui-journeys-greatvault-button-pressed"
GF.FOOTER_ACTION_BORDER_TEXTURE =
	GF.ADDON_ART_UI_PATH .. "ApertureBorder.png"
GF.FOOTER_ACTION_BORDER_SIZE = 37
GF.FOOTER_ACTION_BORDER_COLUMNS = 5
GF.FOOTER_ACTION_BORDER_ROWS = 6
GF.GREAT_VAULT_BUTTON_SIZE = GF.FOOTER_ACTION_BUTTON_SIZE
GF.GREAT_VAULT_BUTTON_NORMAL_ATLAS =
	GF.FOOTER_ACTION_BUTTON_NORMAL_ATLAS
GF.GREAT_VAULT_BUTTON_PRESSED_ATLAS =
	GF.FOOTER_ACTION_BUTTON_PRESSED_ATLAS
GF.GREAT_VAULT_READY_BORDER_TEXTURE =
	GF.FOOTER_ACTION_BORDER_TEXTURE
GF.GREAT_VAULT_READY_BORDER_SIZE = GF.FOOTER_ACTION_BORDER_SIZE
GF.GREAT_VAULT_READY_BORDER_COLUMNS = GF.FOOTER_ACTION_BORDER_COLUMNS
GF.GREAT_VAULT_READY_BORDER_ROWS = GF.FOOTER_ACTION_BORDER_ROWS
GF.GREAT_VAULT_READY_BORDER_FPS = 24
GF.KEYSTONE_LOOT_ADDON_NAME = "KeystoneLoot"
GF.KEYSTONE_LOOT_BUTTON_SIZE = GF.GREAT_VAULT_BUTTON_SIZE
GF.KEYSTONE_LOOT_BUTTON_GAP = GF.FOOTER_ACTION_BUTTON_GAP
GF.KEYSTONE_LOOT_BUTTON_ATLAS_TEXTURE =
	GF.ADDON_ART_UI_PATH .. "AddonButtonsAtlas.png"
GF.KEYSTONE_LOOT_BUTTON_ICON_TEXTURE =
	GF.ADDON_ART_ICON_PATH .. "Gear.png"
GF.KEYSTONE_LOOT_BUTTON_NORMAL_TEXCOORD = {
	0.00390625, 0.49609375, 0.0078125, 0.9921875,
}
GF.KEYSTONE_LOOT_BUTTON_PRESSED_TEXCOORD = {
	0.50390625, 0.99609375, 0.0078125, 0.9921875,
}
GF.KEYSTONE_LOOT_BUTTON_VISUAL_SIZE = 30
GF.KEYSTONE_LOOT_BUTTON_VISUAL_OFFSET_X = 0
GF.KEYSTONE_LOOT_BUTTON_VISUAL_OFFSET_Y = 0
GF.KEYSTONE_LOOT_BUTTON_ICON_SIZE = 17
GF.KEYSTONE_LOOT_BUTTON_ICON_OFFSET_X = -0.5
GF.KEYSTONE_LOOT_BUTTON_ICON_OFFSET_Y = 0.5
GF.KEYSTONE_LOOT_BUTTON_PRESSED_ICON_OFFSET_X = 0.5
GF.KEYSTONE_LOOT_BUTTON_PRESSED_ICON_OFFSET_Y = -0.5
GF.KEYSTONE_LOOT_BUTTON_DISABLED_ALPHA = 0.45
GF.WHITE_TEXTURE = "Interface\\Buttons\\WHITE8X8"
GF.BUTTON_VISUAL_STATE = {
	NORMAL = "normal",
	HOVER = "hover",
	PRESSED = "pressed",
	DISABLED = "disabled",
}
GF.COMMON_BUTTON_TEXTURE = GF.ADDON_ART_UI_PATH .. "RedButton.png"
GF.COMMON_BUTTON_ATLAS_WIDTH = 392
GF.COMMON_BUTTON_ATLAS_HEIGHT = 168
GF.COMMON_BUTTON_SLICE_PIXELS = {
	medium = { 0, 144 },
	wide = { 156, 332 },
	square = { 344, 392 },
}
GF.COMMON_BUTTON_STATE_PIXELS = {
	normal = { 0, 48 },
	highlight = { 60, 108 },
	pressed = { 120, 168 },
}
GF.COMMON_BUTTON_SLICE_COORDS = {}
for key, range in pairs(GF.COMMON_BUTTON_SLICE_PIXELS) do
	GF.COMMON_BUTTON_SLICE_COORDS[key] = {
		range[1] / GF.COMMON_BUTTON_ATLAS_WIDTH,
		range[2] / GF.COMMON_BUTTON_ATLAS_WIDTH,
	}
end
GF.COMMON_BUTTON_STATE_COORDS = {}
for key, range in pairs(GF.COMMON_BUTTON_STATE_PIXELS) do
	GF.COMMON_BUTTON_STATE_COORDS[key] = {
		range[1] / GF.COMMON_BUTTON_ATLAS_HEIGHT,
		range[2] / GF.COMMON_BUTTON_ATLAS_HEIGHT,
	}
end
GF.COMMON_BUTTON_VISUALS = {
	normal = {
		atlasState = "normal",
		textColor = { 1, 0.82, 0, 1 },
		textureColor = { 1, 1, 1, 1 },
		iconColor = { 1, 1, 1, 1 },
		textOffset = { 0, 0 },
		desaturated = false,
	},
	hover = {
		atlasState = "highlight",
		textColor = { 1, 0.95, 0.45, 1 },
		textureColor = { 1, 1, 1, 1 },
		iconColor = { 1, 0.96, 0.58, 1 },
		textOffset = { 0, 0 },
		desaturated = false,
	},
	pressed = {
		atlasState = "pressed",
		textColor = { 1, 0.68, 0.12, 1 },
		textureColor = { 1, 1, 1, 1 },
		iconColor = { 1, 1, 1, 1 },
		textOffset = { 1, -1 },
		desaturated = false,
	},
	disabled = {
		atlasState = "normal",
		textColor = { 0.55, 0.55, 0.55, 1 },
		textureColor = { 0.55, 0.55, 0.55, 0.82 },
		iconColor = { 1, 1, 1, 0.45 },
		textOffset = { 0, 0 },
		desaturated = true,
	},
}
GF.CONTROL_FRAME_ATLAS_STATES = {
	normal = "house-chest-list-Item-pressed",
	hover = "house-chest-list-Item-active",
	focus = "house-chest-list-Item-active",
	checked = "house-chest-list-Item-active",
	highlighted = "house-chest-list-Item-active",
}
-- Small square controls and input fields use the local two-state texture.
-- Each raw 64px state cell contains a weak antialiased fringe around the
-- visible outline. Sampling that fringe while minifying to 16-30px can skip
-- the one-pixel normal-state side border entirely, so every local renderer
-- starts from the same measured visible-content rectangle.
GF.FILTER_CHECK_ATLAS_TEXTURE =
	GF.ADDON_ART_UI_PATH .. "FilterCheckAtlas.png"
GF.FILTER_CHECK_ATLAS_WIDTH = 128
GF.FILTER_CHECK_ATLAS_HEIGHT = 64
GF.FILTER_CHECK_ATLAS_CELL_WIDTH = 64
GF.FILTER_CHECK_ATLAS_CELL_HEIGHT = 64
GF.FILTER_CHECK_ATLAS_CONTENT_INSETS = {
	left = 1,
	top = 1,
	right = 2,
	bottom = 1,
}
GF.FILTER_CHECK_ATLAS_CONTENT_WIDTH =
	GF.FILTER_CHECK_ATLAS_CELL_WIDTH
	- GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.left
	- GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.right
GF.FILTER_CHECK_ATLAS_CONTENT_HEIGHT =
	GF.FILTER_CHECK_ATLAS_CELL_HEIGHT
	- GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.top
	- GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.bottom
GF.FILTER_CHECK_ATLAS_REGIONS = {
	highlighted = {
		GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.left,
		GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.top,
		GF.FILTER_CHECK_ATLAS_CONTENT_WIDTH,
		GF.FILTER_CHECK_ATLAS_CONTENT_HEIGHT,
	},
	normal = {
		GF.FILTER_CHECK_ATLAS_CELL_WIDTH
			+ GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.left,
		GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.top,
		GF.FILTER_CHECK_ATLAS_CONTENT_WIDTH,
		GF.FILTER_CHECK_ATLAS_CONTENT_HEIGHT,
	},
}
GF.FILTER_CHECK_ATLAS_STATES = {
	normal = "normal",
	hover = "highlighted",
	focus = "highlighted",
	checked = "highlighted",
	highlighted = "highlighted",
}
GF.FILTER_INPUT_ATLAS_STATES = GF.FILTER_CHECK_ATLAS_STATES
GF.COMPACT_CONTROL_ATLAS_STATES = GF.FILTER_CHECK_ATLAS_STATES
GF.FILTER_CHECK_ATLAS_COORDS = {
	highlighted = {
		GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.left
			/ GF.FILTER_CHECK_ATLAS_WIDTH,
		(GF.FILTER_CHECK_ATLAS_CELL_WIDTH
			- GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.right)
			/ GF.FILTER_CHECK_ATLAS_WIDTH,
		GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.top
			/ GF.FILTER_CHECK_ATLAS_HEIGHT,
		(GF.FILTER_CHECK_ATLAS_CELL_HEIGHT
			- GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.bottom)
			/ GF.FILTER_CHECK_ATLAS_HEIGHT,
	},
	normal = {
		(GF.FILTER_CHECK_ATLAS_CELL_WIDTH
			+ GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.left)
			/ GF.FILTER_CHECK_ATLAS_WIDTH,
		(GF.FILTER_CHECK_ATLAS_WIDTH
			- GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.right)
			/ GF.FILTER_CHECK_ATLAS_WIDTH,
		GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.top
			/ GF.FILTER_CHECK_ATLAS_HEIGHT,
		(GF.FILTER_CHECK_ATLAS_CELL_HEIGHT
			- GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.bottom)
			/ GF.FILTER_CHECK_ATLAS_HEIGHT,
	},
}
GF.FILTER_CHECK_ATLAS_COORDS.hover =
	GF.FILTER_CHECK_ATLAS_COORDS.highlighted
GF.FILTER_CHECK_ATLAS_COORDS.checked =
	GF.FILTER_CHECK_ATLAS_COORDS.highlighted
GF.FILTER_INPUT_SLICE_RATIOS = { 0.45, 0.55 }
GF.FILTER_INPUT_CAP_W = 9
GF.FILTER_NUMBER_INPUT_CAP_W = GF.FILTER_INPUT_CAP_W
-- Source ratios preserve the current effective 16px cap proportions without
-- depending on a particular atlas file size or resolution scale.
GF.CONTROL_FRAME_SLICE_RATIOS = {
	normal = {
		left = 16 / 104,
		right = 1 - (16 / 104),
		top = 16 / 108,
		bottom = 1 - (16 / 108),
	},
	highlighted = {
		left = 16 / 108,
		right = 1 - (16 / 108),
		top = 16 / 108,
		bottom = 1 - (16 / 108),
	},
}
GF.CONTROL_FRAME_DISPLAY_MARGIN = 8
GF.FILTER_MULTILINE_INPUT_SOURCE_MARGIN = 16
GF.FILTER_MULTILINE_INPUT_DISPLAY_MARGIN = 8
GF.FILTER_MULTILINE_INPUT_SLICE_RATIOS = {
	left = (
		GF.FILTER_MULTILINE_INPUT_SOURCE_MARGIN
		- GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.left
	) / GF.FILTER_CHECK_ATLAS_CONTENT_WIDTH,
	right = (
		GF.FILTER_CHECK_ATLAS_CELL_WIDTH
		- GF.FILTER_MULTILINE_INPUT_SOURCE_MARGIN
		- GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.left
	) / GF.FILTER_CHECK_ATLAS_CONTENT_WIDTH,
	top = (
		GF.FILTER_MULTILINE_INPUT_SOURCE_MARGIN
		- GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.top
	) / GF.FILTER_CHECK_ATLAS_CONTENT_HEIGHT,
	bottom = (
		GF.FILTER_CHECK_ATLAS_CELL_HEIGHT
		- GF.FILTER_MULTILINE_INPUT_SOURCE_MARGIN
		- GF.FILTER_CHECK_ATLAS_CONTENT_INSETS.top
	) / GF.FILTER_CHECK_ATLAS_CONTENT_HEIGHT,
}
-- Compatibility names for callers that explicitly request the local compact
-- nine-slice. Checkbox and single-line renderers do not consume these values.
GF.FILTER_CHECK_ATLAS_SOURCE_MARGIN =
	GF.FILTER_MULTILINE_INPUT_SOURCE_MARGIN
GF.FILTER_CHECK_ATLAS_DISPLAY_MARGIN =
	GF.FILTER_MULTILINE_INPUT_DISPLAY_MARGIN
GF.FILTER_CHECK_ATLAS_SLICE_RATIOS =
	GF.FILTER_MULTILINE_INPUT_SLICE_RATIOS
GF.COMPACT_CONTROL_SLICE_RATIOS =
	GF.FILTER_MULTILINE_INPUT_SLICE_RATIOS
GF.INFO_ATLAS_TEXTURE = GF.ADDON_ART_UI_PATH .. "InfoAtlas.png"
GF.INFO_ATLAS_WIDTH = 1697
GF.INFO_ATLAS_HEIGHT = 696
GF.INFO_ATLAS_REGIONS = {
	title = { 4, 4, 1689, 348 },
	notice = { 4, 368, 1507, 324 },
}
GF.MYTHIC_PLUS_FRAME_ATLAS_TEXTURE = GF.ADDON_ART_UI_PATH .. "FrameAtlas.png"
GF.MYTHIC_PLUS_FRAME_ATLAS_WIDTH = 704
GF.MYTHIC_PLUS_FRAME_ATLAS_HEIGHT = 712
GF.MYTHIC_PLUS_FRAME_ATLAS_REGIONS = {
	dark = { 4, 4, 344, 200 },
	brown = { 356, 4, 344, 200 },
	class = { 4, 212, 344, 200 },
	border = { 356, 212, 344, 200 },
	hover = { 4, 420, 344, 200 },
	roleMask = { 4, 628, 695, 80 },
}
GF.REFRESH_TEXTURE = GF.ADDON_ART_UI_PATH .. "Refresh.png"
GF.TEAMUP_TEXTURE = GF.ADDON_ART_UI_PATH .. "TeamUp.png"
GF.FLOATING_TEXTURE = GF.ADDON_ART_UI_PATH .. "Floating.png"
GF.BLACKLIST_ICON_TEXTURE = GF.ADDON_ART_ICON_PATH .. "Blacklist.png"
GF.LEAVER_ICON_TEXTURE = GF.ADDON_ART_ICON_PATH .. "isLeaver.png"
GF.MYTHIC_PLUS_TELEPORT_ICON_ATLAS = "MagePortalAlliance"
GF.MYTHIC_PLUS_ACTION_BUTTON_HEIGHT = 26
GF.MYTHIC_PLUS_SEASON_DUNGEON_SORT_RULE = {
	scoreDirection = "DESC",
	missingScore = 0,
	orderDirection = "ASC",
	orderFields = {
		"seasonMapOrder",
		"orderIndex",
		"sourceOrder",
	},
	preserveInputOrder = true,
}
GF.MYTHIC_PLUS_WORKSPACE_SCROLLBAR_WIDTH = 17
GF.MYTHIC_PLUS_WORKSPACE_SCROLLBAR_OFFSET_X = 17
GF.MYTHIC_PLUS_WORKSPACE_SCROLLBAR_TOP_OFFSET = -4
GF.MYTHIC_PLUS_WORKSPACE_SCROLLBAR_BOTTOM_OFFSET = 4
GF.TOP_NOTICE_TOAST_ATLAS = "evergreen-scenario-TitleBG"
GF.TOP_NOTICE_TOAST_SOUND = GF.ADDON_SOUNDS_PATH .. "Glass.aiff"
-- 兼容现有进组通报入口；共享视觉与声音由 TopNoticeToast 所有。
GF.JOIN_ANNOUNCE_TOAST_ATLAS = GF.TOP_NOTICE_TOAST_ATLAS
GF.JOIN_ANNOUNCE_TOAST_SOUND = GF.TOP_NOTICE_TOAST_SOUND
GF.APPLICANT_ALERT_SOUND_COOLDOWN_SECONDS = 10
GF.APPLICANT_ALERT_SOUND_LEGACY_DEFAULT = "Glass.aiff"
GF.APPLICANT_ALERT_SOUND_DEFAULT = "xalatath.mp3"
GF.APPLICANT_ALERT_SOUND_OPTIONS = {
	{ file = "xalatath.mp3", labelKey = "SET_APPLICANT_ALERT_SOUND_XALATATH", label = "萨拉塔斯" },
	{ file = "millhouse.mp3", labelKey = "SET_APPLICANT_ALERT_SOUND_MILLHOUSE", label = "米尔豪斯" },
	{ file = "murloc.ogg", labelKey = "SET_APPLICANT_ALERT_SOUND_AIYURAS", label = "艾鱼拉斯" },
	{ file = "sylvanas.mp3", labelKey = "SET_APPLICANT_ALERT_SOUND_SYLVANAS", label = "希尔瓦娜斯" },
	{ file = "Glass.aiff", labelKey = "SET_APPLICANT_ALERT_SOUND_GLASS", label = "清脆玻璃提示音" },
	{ file = "", labelKey = "SET_APPLICANT_ALERT_SOUND_OFF", label = "关闭" },
}
GF.ROLE_VACANCY_THRESHOLD_MIN = 1
GF.ROLE_VACANCY_THRESHOLD_MAX = 4
-- 聊天消息格式与输出逻辑见 ChatMessages.lua。
GF.MAIN_WINDOW_LOGO_TEXTURE = GF.ADDON_LOGO_TEXTURE
GF.MAIN_WINDOW_LOGO_SIZE = 54
GF.MINIMAP_ICON_TEXTURE = GF.ADDON_LOGO_TEXTURE
GF.FLOAT_BUTTON_ICON_TEXTURE = GF.ADDON_MENU_LOGO_TEXTURE
GF.CONTEXT_MENU_TEXT_SIZE_EXTRA = 4
GF.ROLE_ICON_ATLAS = {
	LEADER = "UI-LFG-RoleIcon-Leader",
	GUIDE = "UI-LFG-RoleIcon-Leader",
	TANK = "UI-LFG-RoleIcon-Tank",
	HEALER = "UI-LFG-RoleIcon-Healer",
	DAMAGER = "UI-LFG-RoleIcon-DPS",
	DPS = "UI-LFG-RoleIcon-DPS",
	NONE = "groupfinder-icon-emptyslot",
	DEFAULT = "groupfinder-icon-emptyslot",
}
GF.SEASON_DUNGEON_ROLE_ATLAS = GF.ROLE_ICON_ATLAS
GF.LEADER_ICON_ATLAS = GF.ROLE_ICON_ATLAS.LEADER
GF.TOOLTIP_LEADER_ICON_ATLAS = GF.LEADER_ICON_ATLAS
GF.ROLE_ICON_SIZE = 18
GF.TOOLTIP_ROLE_ICON_SIZE = GF.ROLE_ICON_SIZE
GF.NON_ROLE_ICON_SIZE = 18
GF.MPLUS_BROWSE_PROJECTION_SLOT_SIZE = 17
-- Blizzard role atlases include about 1px of transparent edge padding. A
-- 17px draw box yields a visible 15px disc, matching the specialization icon
-- together with its full class-colored outer ring.
GF.MPLUS_BROWSE_ROLE_PROJECTION_ICON_SIZE = 17
GF.MPLUS_BROWSE_SPEC_PROJECTION_ICON_SIZE = 15
GF.MPLUS_BROWSE_SPEC_PROJECTION_ICON_INSET = 1.875
GF.MPLUS_BROWSE_PROJECTION_START_GAP = 2
GF.MPLUS_BROWSE_PROJECTION_ICON_GAP = 1
GF.MPLUS_BROWSE_MATCH_LABEL_W = 45
GF.MPLUS_BROWSE_MATCH_LABEL_FIT_W = 44
GF.MPLUS_BROWSE_MATCH_LABEL_MIN_FONT_SIZE = 7
GF.MPLUS_BROWSE_MATCH_CHECK_W = 16
GF.MPLUS_BROWSE_MATCH_CHECK_H = 16
GF.MPLUS_BROWSE_MATCH_CHECK_ATLAS_OFFSET_X = 1.5
GF.MPLUS_BROWSE_MATCH_CHECK_ATLAS_OFFSET_Y = 0
GF.MPLUS_BROWSE_MATCH_CHECK_MARK_OFFSET_X = 1.5
GF.MPLUS_BROWSE_MATCH_CHECK_MARK_OFFSET_Y = 0
GF.MPLUS_BROWSE_MATCH_CHECK_ATLAS = {
	normal = "keybind-bg",
	hover = "keybind-bg_active",
	checked = "keybind-bg_active",
}
GF.MPLUS_BROWSE_PROJECTION_MAX_MEMBERS = 5
GF.MPLUS_BROWSE_PROJECTION_EMPTY_ALPHA = 0.72
GF.MPLUS_BROWSE_PROJECTION_EMPTY_DISABLED_TINT = 0.72
GF.MPLUS_BROWSE_FILTER_DISABLED_ALPHA = 1
GF.FILTER_DISABLED_ICON_TINT = 0.58
GF.MPLUS_BROWSE_FILTER_DISABLED_ICON_TINT = GF.FILTER_DISABLED_ICON_TINT
GF.MPLUS_BROWSE_FILTER_DISABLED_TEXT_COLOR = { 0.48, 0.47, 0.44, 1 }
GF.MPLUS_BROWSE_CHECK_DISABLED_TINT = 0.72
GF.MPLUS_BROWSE_CHECK_DISABLED_ALPHA = 1
GF.MPLUS_BROWSE_ROLE_CARD_GAP = 2
GF.MPLUS_BROWSE_ROLE_CARD_WIDTHS = { 53, 54, 53 }
GF.MPLUS_BROWSE_THRESHOLD_COLUMN_GAP = 8
GF.MPLUS_BROWSE_THRESHOLD_OPEN_INPUT_W = 24
GF.MPLUS_BROWSE_THRESHOLD_SCORE_INPUT_W = 70
GF.MPLUS_BROWSE_THRESHOLD_OPEN_COLUMN_CENTER_OFFSET_X = 2
GF.MPLUS_BROWSE_THRESHOLD_SCORE_COLUMN_CENTER_OFFSET_X = -2
GF.MPLUS_BROWSE_THRESHOLD_ARROW_W = 8
GF.MPLUS_BROWSE_THRESHOLD_ARROW_H = 13
GF.MPLUS_BROWSE_THRESHOLD_STEP_BUTTON_OFFSET_Y = -0.5
GF.MPLUS_BROWSE_THRESHOLD_DIVIDER_COLOR = { 0.42, 0.34, 0.20, 1 }
GF.MPLUS_BROWSE_THRESHOLD_DIVIDER_ALPHA = 0.72
GF.MPLUS_BROWSE_THRESHOLD_DIVIDER_INSET = 8
GF.FACTION_ICON_TEXTURES = {
	Alliance = "Interface\\FriendsFrame\\PlusManz-Alliance",
	Horde = "Interface\\FriendsFrame\\PlusManz-Horde",
}
GF.RECOMMENDED_SEARCH_MASK = bit.bor(
	Enum.LFGListFilter.Recommended,
	Enum.LFGListFilter.NotRecommended)
-- PvP 评分分级逻辑见 PvpRating.lua。
-- 社交关系、玩家名规范化与老农堂识别逻辑见 PlayerIdentity.lua。
-- 主窗口底栏控件（活动数、屏蔽列表按钮等）锚点
GF.FRAME_BODY_BAR_LEFT = 12
-- SettingsFrameTemplate 内缘（与 Bar OptionsFrame / 暴雪 FlatPanel Bg 一致）
GF.FRAME_BG_INSET_LEFT = 7
GF.FRAME_BG_INSET_TOP = -18
GF.FRAME_BG_INSET_RIGHT = -2
GF.FRAME_BG_INSET_BOTTOM = 3
GF.NAV_WIDTH = 180
GF.NAV_WIDTH_MIN = 180
GF.NAV_WIDTH_MAX = 180
-- 大秘境寻找/创建左栏的下拉与搜索框共用内部控件宽度。
GF.MPLUS_LFG_SIDEBAR_CONTROL_W = GF.NAV_WIDTH - 16
-- 寻找队伍三组筛选卡与创建招募使用同一 164px 名义宽度基准。
GF.MPLUS_BROWSE_FILTER_OUTER_W = GF.MPLUS_LFG_SIDEBAR_CONTROL_W
GF.NAV_DIVIDER_GRIP_W = 6
-- 导航竖线（§3.4，改一处即联动）
GF.NAV_DIVIDER_W = 3
GF.NAV_DIVIDER_OFFSET_X = -3
GF.NAV_DIVIDER_TOP_OFFSET = 4
GF.NAV_DIVIDER_BOTTOM_OFFSET = 2
GF.NAV_DIVIDER_COLOR = { 0.38, 0.34, 0.24, 0.9 }
GF.NAV_DIVIDER_HIGHLIGHT_COLOR = { 0.62, 0.55, 0.38, 0.3 }
GF.NAV_DIVIDER_SHADOW_COLOR = { 0.08, 0.07, 0.05, 0.9 }
GF.NAV_DIVIDER_CENTER_ACCENT_W = 1
GF.NAV_DIVIDER_CENTER_ACCENT_COLOR = { 1, 0.82, 0 }
GF.NAV_LIST_PADDING_TOP = 8
GF.BROWSE_HEADER_TOP_OFFSET = -20
GF.BROWSE_HEADER_BOTTOM_OFFSET = -46
-- 黑名单、大秘境队伍与车队共用的列表表头几何基准。
GF.SHARED_TABLE_HEADER_HEIGHT = math.abs(
	GF.BROWSE_HEADER_BOTTOM_OFFSET - GF.BROWSE_HEADER_TOP_OFFSET)
GF.SHARED_TABLE_HEADER_LIST_GAP = 4
-- 黑名单直接以背板黑底为父级；大秘境工作区则恢复到了完整背板坐标。
-- 补回背板黑底内缩后，背景 atlas 才会落在相同的屏幕范围。
GF.SHARED_TABLE_HEADER_PANEL_INSET_LEFT =
	GF.MAIN_PANEL_BACKPLATE_BG_INSET_LEFT
GF.SHARED_TABLE_HEADER_PANEL_INSET_RIGHT =
	GF.MAIN_PANEL_BACKPLATE_BG_INSET_RIGHT
GF.SHARED_TABLE_HEADER_PANEL_INSET_TOP =
	GF.MAIN_PANEL_BACKPLATE_BG_INSET_TOP
		+ math.abs(GF.BROWSE_HEADER_TOP_OFFSET)
GF.BROWSE_HEADER_CONTENT_INSET_X = 4
GF.BROWSE_HEADER_CONTENT_OFFSET_Y = 4
GF.BROWSE_HEADER_LIST_GAP = 0
GF.SECTION_HEADER_TEXT_SIZE = 14
GF.BROWSE_HEADER_TEXT_SIZE = GF.SECTION_HEADER_TEXT_SIZE
GF.BROWSE_HEADER_TEXT_CENTER_OFFSET_Y = GF.BROWSE_HEADER_CONTENT_OFFSET_Y
GF.BROWSE_HEADER_TEXT_INSET_X = 3
GF.BROWSE_HEADER_TEXT_PRESSED_OFFSET_X = 1
GF.BROWSE_HEADER_TEXT_PRESSED_OFFSET_Y = -1
GF.BROWSE_HEADER_TEXT_PRESSED_ALPHA = 1
GF.BROWSE_HEADER_TEXT_COLOR = { 1, 0.82, 0, 1 }
GF.BROWSE_HEADER_HOVER_TEXT_COLOR = { 1, 0.96, 0.58, 1 }
GF.BROWSE_HEADER_PRESSED_TEXT_COLOR = { 0.95, 0.68, 0.18, 1 }
GF.CREATE_MANAGER_TITLE_TEXT_SIZE = GF.SECTION_HEADER_TEXT_SIZE
GF.CREATE_MANAGER_TITLE_TEXT_COLOR = GF.BROWSE_HEADER_TEXT_COLOR
-- 集合石只读与大秘境组队管理只共享正文禁用视觉；顶部标题条不读取此表。
GF.CREATE_MANAGER_DISABLED_VISUAL = {
	labelTextColor = { 0.72, 0.70, 0.64, 1 },
	inputTextColor = { 0.78, 0.77, 0.72, 1 },
	atlasTint = GF.FILTER_DISABLED_ICON_TINT,
	desaturated = true,
	alpha = 1,
	preserveButtonAlpha = true,
}
GF.CREATE_MANAGER_DROPDOWN_ARROW_ATLAS = "common-dropdown-a-button"
GF.BROWSE_HEADER_BACKGROUND_ATLAS = "housefinder_header-bg-gradient"
GF.BROWSE_HEADER_BACKGROUND_INSET_L = -8
GF.BROWSE_HEADER_BACKGROUND_FRAME_LEVEL_OFFSET = 1
GF.BROWSE_CONTROL_BACKGROUND_ATLAS = GF.BROWSE_HEADER_BACKGROUND_ATLAS
GF.BROWSE_CONTROL_BACKGROUND_ALPHA = 1
-- 正式服商城商品卡片（Blizzard_CatalogShopSharedTemplates）共享常量。
GF.STORE_CARD_BACKGROUND_ATLAS = "shop-card-bg"
GF.STORE_CARD_FRAME_ATLAS = "shop-card-small-frame-default"
GF.STORE_CARD_SELECTED_FRAME_ATLAS = "shop-card-small-frame-selected"
GF.STORE_CARD_HOVER_FRAME_ATLAS = "shop-card-small-frame-hover"
GF.STORE_WIDE_CARD_BACKGROUND_ATLAS = "shop-card-wide-bg"
GF.STORE_WIDE_CARD_FRAME_ATLAS = "shop-card-wide-frame-default"
GF.STORE_WIDE_CARD_SELECTED_FRAME_ATLAS = "shop-card-wide-frame-selected"
GF.STORE_WIDE_CARD_HOVER_FRAME_ATLAS = "shop-card-wide-frame-hover"
GF.STORE_CARD_MASK_ATLAS = "shop-card-wide-mask"
GF.STORE_CARD_BACKGROUND_ALPHA = 0.44
GF.STORE_CARD_BACKGROUND_COLOR = { 0.68, 0.54, 0.30, 1 }
GF.BROWSE_HEADER_ACCENT_WIDTH = 1.5
GF.BROWSE_HEADER_ACCENT_HEIGHT = 22
GF.BROWSE_HEADER_ACCENT_COLOR = { 126 / 255, 112 / 255, 82 / 255 }
GF.BROWSE_HEADER_ACCENT_ALPHA = 0.6
GF.BROWSE_HEADER_ACCENT_TEXTURE = GF.WHITE_TEXTURE
GF.EMPTY_PROMPT_TEXT_SIZE = 14
GF.BROWSE_EMPTY_TEXT_SIZE = GF.EMPTY_PROMPT_TEXT_SIZE
GF.BROWSE_EMPTY_ACTION_MIN_WIDTH = 120
GF.BROWSE_EMPTY_ACTION_MAX_WIDTH = 160
GF.BROWSE_EMPTY_ACTION_HORIZONTAL_PADDING = 28
GF.BROWSE_EMPTY_ACTION_GAP = 10
GF.BROWSE_HEADER_REFRESH_TEXTURE = GF.REFRESH_TEXTURE
GF.BROWSE_HEADER_REFRESH_BUTTON_SIZE = 35
GF.BROWSE_HEADER_REFRESH_ICON_SIZE = 21
GF.BROWSE_HEADER_REFRESH_ICON_HOVER_SIZE = 23
GF.BROWSE_HEADER_REFRESH_ICON_PRESSED_SIZE = 19
GF.BROWSE_HEADER_REFRESH_BUTTON_OFFSET_Y = 6
GF.APPLICANT_HEADER_REFRESH_BUTTON_OFFSET_Y = 0
GF.HEADER_REFRESH_ICON_VISUALS = {
	[GF.BUTTON_VISUAL_STATE.NORMAL] = {
		size = GF.BROWSE_HEADER_REFRESH_ICON_SIZE,
		offset = { 0, 0 },
		alpha = 1,
		desaturated = false,
		blendMode = "BLEND",
	},
	[GF.BUTTON_VISUAL_STATE.HOVER] = {
		size = GF.BROWSE_HEADER_REFRESH_ICON_HOVER_SIZE,
		offset = { 0, 0 },
		alpha = 1,
		desaturated = false,
		blendMode = "ADD",
	},
	[GF.BUTTON_VISUAL_STATE.PRESSED] = {
		size = GF.BROWSE_HEADER_REFRESH_ICON_PRESSED_SIZE,
		offset = { 1, -1 },
		alpha = 0.86,
		desaturated = false,
		blendMode = "BLEND",
	},
	[GF.BUTTON_VISUAL_STATE.DISABLED] = {
		size = GF.BROWSE_HEADER_REFRESH_ICON_SIZE,
		offset = { 0, 0 },
		alpha = 0.45,
		desaturated = true,
		blendMode = "BLEND",
	},
}
GF.BROWSE_LOADING_TEAMUP_TEXTURE = GF.TEAMUP_TEXTURE
GF.BROWSE_LOADING_ICON_COUNT = 3
GF.BROWSE_LOADING_ICON_WIDTH = 27
GF.BROWSE_LOADING_ICON_HEIGHT = 25
GF.BROWSE_LOADING_ICON_GAP = 6
GF.BROWSE_LOADING_TEXT_GAP = 7
GF.BROWSE_LOADING_STEP_SECONDS = 0.28
GF.BROWSE_LOADING_FADE_IN_SECONDS = 0.16
GF.BROWSE_LOADING_HOLD_SECONDS = 0.4
GF.BROWSE_LOADING_FADE_OUT_SECONDS = 0.45
GF.ROW_BACKGROUND_ATLAS = "UI-QuestTracker-Secondary-Objective-Header"
GF.ROW_BACKGROUND_FALLBACK_TEXTURE = GF.WHITE_TEXTURE
GF.ROW_BACKGROUND_SOURCE_WIDTH = 564
GF.ROW_BACKGROUND_SOURCE_HEIGHT = 52
GF.ROW_BACKGROUND_SOURCE_CAP_WIDTH = 18
GF.ROW_BACKGROUND_TOP_SOURCE_HEIGHT = 8
-- The native atlas ends with a faint bottom rule. Standard list surfaces crop
-- that rule and share one pixel-aligned geometry for base/hover/selected art.
GF.ROW_BACKGROUND_PROFILE = {
	sourceWidth = GF.ROW_BACKGROUND_SOURCE_WIDTH,
	sourceHeight = GF.ROW_BACKGROUND_SOURCE_HEIGHT,
	sourceCapWidth = GF.ROW_BACKGROUND_SOURCE_CAP_WIDTH,
	topSourceHeight = GF.ROW_BACKGROUND_TOP_SOURCE_HEIGHT,
	cropTopPixels = 0,
	cropBottomPixels = 2,
	maxDisplayHeight = 32,
	pixelAligned = true,
	verticalAlign = "CENTER",
	oddPixelBias = "UP",
}
GF.ROW_BACKGROUND_STATE_COLORS = {
	red = { 1, 0.16, 0.12, 1 },
	blue = { 0.36, 0.68, 1, 1 },
	green = { 0.14, 0.95, 0.24, 1 },
	grey = { 0.52, 0.52, 0.52, 1 },
}
GF.BROWSE_ROW_NORMAL_COLOR = { 1, 1, 1, 1 }
GF.LIST_BACKGROUND_STYLE_DEFAULTS = {
	normal = {
		r = GF.BROWSE_ROW_NORMAL_COLOR[1],
		g = GF.BROWSE_ROW_NORMAL_COLOR[2],
		b = GF.BROWSE_ROW_NORMAL_COLOR[3],
		alphaPct = GF.LIST_BACKGROUND_ALPHA_DEFAULT_PCT or 100,
	},
	friend = { r = 0.36, g = 0.68, b = 1, alphaPct = GF.LIST_BACKGROUND_ALPHA_DEFAULT_PCT or 100 },
	application = { r = 0.14, g = 0.95, b = 0.24, alphaPct = GF.LIST_BACKGROUND_ALPHA_DEFAULT_PCT or 100 },
	warning = { r = 1, g = 0.16, b = 0.12, alphaPct = GF.LIST_BACKGROUND_ALPHA_DEFAULT_PCT or 100 },
	disabled = { r = 0.52, g = 0.52, b = 0.52, alphaPct = GF.LIST_BACKGROUND_ALPHA_DEFAULT_PCT or 100 },
}
GF.LIST_BACKGROUND_STYLE_ORDER = { "normal", "friend", "application", "warning", "disabled" }
GF.LIST_BACKGROUND_STATE_TO_STYLE = {
	normal = "normal",
	green = "application",
	blue = "friend",
	red = "warning",
	grey = "disabled",
}
GF.BROWSE_ROW_BACKGROUND_ALPHA = 0.92
GF.BROWSE_ROW_BACKGROUND_FADE_SECONDS = 0.16
GF.BROWSE_DECLINED_FILTER_FEEDBACK_SECONDS = 0.8
GF.APPLICANT_DECLINED_MIN_VISIBLE_SECONDS = 0.8
GF.APPLICANT_ACTION_PENDING_TIMEOUT_SECONDS = 3
GF.APPLICANT_LISTING_LOSS_INVITE_GRACE_SECONDS = 1
GF.BROWSE_ROW_HOVER_HEIGHT = 28
GF.BROWSE_ROW_HOVER_INSET_X = 2
GF.BROWSE_ROW_HOVER_OFFSET_Y = 0
GF.BROWSE_ROW_HOVER_FADE_WIDTH = 96
GF.BROWSE_ROW_HOVER_COLOR = { 1, 0.74, 0.18, 0.13 }
GF.BROWSE_ROW_HOVER_RED_COLOR = { 1, 0.12, 0.08, 0.18 }
GF.BROWSE_ROW_HOVER_BLUE_COLOR = { 0.35, 0.75, 1, 0.16 }
GF.BROWSE_ROW_HOVER_GREY_COLOR = { 0.65, 0.65, 0.65, 0.18 }
GF.BROWSE_ROW_SELECTED_COLOR = { 1, 0.9, 0.08, 0.82 }
GF.BROWSE_ROW_SELECTED_ALPHA = 1
GF.CONTEXT_MENU_ROW_H = 28
GF.CONTEXT_MENU_TITLE_ROW_H = 30
GF.CONTEXT_MENU_TOP_GAP = 10
GF.CONTEXT_MENU_BOTTOM_GAP = 10
GF.CONTEXT_MENU_TITLE_BOTTOM_GAP = 4
GF.CONTEXT_MENU_MIN_W = 140
GF.CONTEXT_MENU_MAX_W = 280
GF.CONTEXT_MENU_CHROME_W = 25
GF.CONTEXT_MENU_TEXT_W_PAD = 32
GF.CONTEXT_MENU_HIGHLIGHT_TEXTURE = GF.WHITE_TEXTURE
GF.CONTEXT_MENU_HIGHLIGHT_TEXTURE_W = 1
GF.CONTEXT_MENU_HIGHLIGHT_TEXTURE_H = 1
GF.CONTEXT_MENU_HIGHLIGHT_CAP_W = 1
GF.CONTEXT_MENU_HIGHLIGHT_INSET_X = 2
GF.CONTEXT_MENU_HIGHLIGHT_EXTEND_X = 0
GF.CONTEXT_MENU_HIGHLIGHT_OFFSET_X = -12
GF.CONTEXT_MENU_HIGHLIGHT_ALPHA = 1
GF.CONTEXT_MENU_HIGHLIGHT_COLOR = { 1, 0.74, 0.18, 0.18 }
GF.BROWSE_ROW_MEMBER_ICON_SIZE = GF.ROLE_ICON_SIZE
GF.BROWSE_ROW_MEMBER_ICON_GAP = 2
GF.BROWSE_ROW_MEMBER_MAX_ICONS = 5
GF.BROWSE_ROW_MEMBER_EMPTY_SLOT_ATLAS = GF.ROLE_ICON_ATLAS.DEFAULT
GF.BROWSE_ROW_MEMBER_ROLE_BADGE_SIZE = 12
GF.BROWSE_ROW_MEMBER_ROLE_BADGE_LARGE_SIZE = 14
GF.BROWSE_ROW_MEMBER_ROLE_BADGE_OFFSET_X = 2
GF.BROWSE_ROW_MEMBER_ROLE_BADGE_OFFSET_Y = 2
GF.BROWSE_ROW_MEMBER_LEADER_BADGE_SIZE = GF.BROWSE_ROW_MEMBER_ROLE_BADGE_SIZE
GF.BROWSE_ROW_MEMBER_LEADER_BADGE_OFFSET_X = GF.BROWSE_ROW_MEMBER_ROLE_BADGE_OFFSET_X
GF.BROWSE_ROW_MEMBER_LEADER_BADGE_OFFSET_Y = GF.BROWSE_ROW_MEMBER_ROLE_BADGE_OFFSET_Y
GF.MEMBER_DISPLAY_MODE_ROLE = "role"
GF.MEMBER_DISPLAY_MODE_SPEC = "spec"
GF.MEMBER_DISPLAY_MODE_SPEC_LARGE = "spec_large"
GF.MEMBER_DISPLAY_MODE_DEFAULT = GF.MEMBER_DISPLAY_MODE_ROLE
GF.MEMBER_TOOLTIP_MODE_DETAILS = "details"
GF.MEMBER_TOOLTIP_MODE_SPEC_COUNT = "spec_count"
GF.MEMBER_TOOLTIP_MODE_DEFAULT = GF.MEMBER_TOOLTIP_MODE_DETAILS
GF.BROWSE_COLUMN_PRESET_VERSION = 5
GF.APPLICANT_COLUMN_PRESET_VERSION = 6
GF.APPLICANT_ROW_H = 33
GF.APPLICANT_ROW_BACKGROUND_INSET_TOP = 2
GF.APPLICANT_ROW_BACKGROUND_INSET_BOTTOM = 0
GF.APPLICANT_ROW_CONTENT_OFFSET_Y = -1
GF.APPLICANT_ACTION_BUTTON_SIZE = 24
GF.APPLICANT_ACTION_ICON_SIZE = 12
GF.SUBTITLE_H = 42
GF.SUBTITLE_TOOLBAR_H = 26
GF.SUBTITLE_TOOLBAR_HEADER_GAP = 10
GF.SUBTITLE_HEADER_H = 26
GF.BROWSE_CONTROL_BACKGROUND_H = GF.SUBTITLE_HEADER_H
GF.BROWSE_CONTROL_BACKGROUND_OFFSET_Y = 4
GF.SUBTITLE_CONTROL_CENTER_OFFSET_Y =
	((GF.SUBTITLE_H + GF.BROWSE_CONTROL_BACKGROUND_OFFSET_Y) / 2) - (GF.SUBTITLE_H / 2)
GF.SUBTITLE_CATEGORY_ACCENT_GAP = 10
GF.SUBTITLE_CATEGORY_MIN_W = 140
GF.SUBTITLE_CONTROL_LEFT_PAD = 15
GF.SUBTITLE_CONTROL_RIGHT_PAD = 10
GF.SUBTITLE_CONTROL_GAP = 7
GF.SUBTITLE_CONTROL_TOP_OFFSET = -8
GF.SUBTITLE_SEARCH_W = 220
GF.SUBTITLE_SEARCH_H = 26
GF.SUBTITLE_SEARCH_CENTER_OFFSET_Y = 1
GF.SUBTITLE_SEARCH_TEXT_SIZE = 12
GF.SUBTITLE_SEARCH_ICON_INSET = 8
GF.SUBTITLE_SEARCH_ICON_SIZE = 14
GF.SUBTITLE_SEARCH_TEXT_INSET_LEFT = 27
GF.SUBTITLE_SEARCH_TEXT_INSET_RIGHT = 24
GF.SUBTITLE_SEARCH_CLEAR_INSET = 6
GF.MPLUS_BROWSE_SEARCH_FIT_PADDING = 2
GF.MPLUS_BROWSE_SEARCH_MIN_TEXT_SIZE = 9
GF.SUBTITLE_SEARCH_TEXT_COLOR = { 1, 0.96, 0.86, 1 }
GF.SUBTITLE_SEARCH_PLACEHOLDER_COLOR = { 0.55, 0.55, 0.55, 1 }
GF.COMMON_DROPDOWN_BORDER_OUTSET_X = 8
GF.SUBTITLE_SEARCH_OWNERSHIP_POLL_SEC = 0.5
GF.SUBTITLE_OPTION_CHECK_SIZE = 20
GF.SUBTITLE_OPTION_TEXT_SIZE = 13
GF.SUBTITLE_CATEGORY_TEXT_SIZE = 13
GF.SUBTITLE_OPTION_TEXT_GAP = 1
GF.SUBTITLE_OPTION_GROUP_GAP = 12
GF.SUBTITLE_OPTION_TEXT_COLOR = { 1, 0.82, 0, 1 }
GF.FILTER_FOOTER_H = GF.SUBTITLE_H
GF.FILTER_FOOTER_INSET_L = GF.FRAME_BG_INSET_LEFT
GF.FILTER_FOOTER_INSET_R = GF.FRAME_BG_INSET_RIGHT
GF.FILTER_FOOTER_INSET_B = GF.FRAME_BG_INSET_BOTTOM
GF.FILTER_FOOTER_BUTTON_INSET_X = 12
GF.FILTER_FOOTER_BUTTON_OFFSET_Y = 12
GF.FILTER_FOOTER_BUTTON_GAP = 10
GF.FILTER_SCROLLBAR_WIDTH = 8
GF.FILTER_SCROLLBAR_RIGHT_INSET = 8
GF.FILTER_SCROLLBAR_TOP_INSET = 8
GF.FILTER_SCROLLBAR_BOTTOM_INSET = 8
GF.FILTER_TEXT_COLOR = GF.SUBTITLE_OPTION_TEXT_COLOR
GF.SIDE_PANEL_W = 260
GF.SATELLITE_PANEL_GAP = 2
GF.FILTER_PANEL_W = GF.SIDE_PANEL_W
GF.FILTER_CHECK_SIZE = 20
GF.FILTER_CHECK_LABEL_GAP = 6
GF.FILTER_NUMBER_INPUT_H = 20
GF.FILTER_STEP_BUTTON_SIZE = GF.FILTER_NUMBER_INPUT_H
GF.FILTER_STEP_BUTTON_GAP = 2
GF.FILTER_STEP_ARROW_CENTER_OFFSET_X = 1
GF.PANEL_BUTTON_H = 24
GF.PANEL_BUTTON_STANDARD_W = 72
GF.PANEL_BUTTON_TWO_CHAR_W = GF.PANEL_BUTTON_STANDARD_W
GF.PANEL_BUTTON_ACTION_W = GF.PANEL_BUTTON_STANDARD_W
GF.PANEL_CONFIRM_BUTTON_W = GF.PANEL_BUTTON_STANDARD_W
GF.APPLICANT_MANAGE_BUTTON_W = GF.PANEL_BUTTON_STANDARD_W
GF.PLAYER_CONTEXT_DIALOG_STYLE = {
	WIDTH = 420,
	HEIGHT = 176,
	LEVEL_OFFSET = 18,
	BACKGROUND_COLOR = GF.PLAYER_CONTEXT_DIALOG_BACKGROUND_COLOR,
	CONTENT_INSET_X = 36,
	CONTENT_TOP_INSET = 38,
	CONTENT_BOTTOM_INSET = 18,
	CONTENT_ACTION_GAP = 12,
	PRIMARY_TEXT_FONT_SIZE = 15,
	SECONDARY_TEXT_FONT_SIZE = 12,
	ACCENT_TEXT_FONT_SIZE = 15,
	PRIMARY_TEXT_COLOR = { 1, 1, 1, 1 },
	SECONDARY_TEXT_COLOR = { 0.78, 0.76, 0.70, 1 },
	ACCENT_TEXT_COLOR = { 1, 0.82, 0, 1 },
	TEXT_LINE_GAP = 5,
	TEXT_TO_INPUT_GAP = 8,
	COPY_HINT_TO_INPUT_GAP = 10,
	BLACKLIST_INPUT_CENTER_OFFSET_Y = -21,
	COPY_INPUT_CENTER_OFFSET_Y = -12,
	TELEPORT_MESSAGE_CENTER_OFFSET_Y = 4,
	TELEPORT_TEXT_LINE_GAP = 7,
	INPUT_WIDTH = 330,
	INPUT_HEIGHT = 30,
	INPUT_VALUE_FONT_SIZE = 15,
	INPUT_EDIT_FONT_SIZE = 14,
	INPUT_PLACEHOLDER_FONT_SIZE = 12,
	MIN_FITTED_TEXT_SIZE = 10,
	BUTTON_WIDTH = GF.PANEL_BUTTON_STANDARD_W,
	BUTTON_HEIGHT = GF.PANEL_BUTTON_H,
	BUTTON_GAP = 12,
	BUTTON_FONT_SIZE = 15,
	SCREEN_OFFSET_Y = 20,
}
GF.APPLICANT_ACTIVE_ROLE_SUMMARY_W = 168
GF.APPLICANT_ACTIVE_ROLE_SUMMARY_X = 6
GF.NAV_INDENT = 12
GF.NAV_L0_ROW_H = 45
GF.NAV_L0_BUTTON_H = 43
GF.NAV_ROW_H = { [0] = GF.NAV_L0_ROW_H, [1] = 38, [2] = 34, [3] = 30 }
GF.NAV_TRANSMOG_BUTTON_H = { [0] = GF.NAV_L0_BUTTON_H, [1] = 34, [2] = 30, [3] = 26 }
GF.NAV_TRANSMOG_BUTTON_OFFSET_X = 0
GF.NAV_TRANSMOG_BUTTON_WIDTH_PAD = { [0] = 20, [1] = 32, [2] = 44, [3] = 56 }
GF.NAV_TRANSMOG_BUTTON_TEXT_LEFT = { [0] = 12, [1] = 14, [2] = 16, [3] = 18 }
GF.NAV_TRANSMOG_BUTTON_TEXT_RIGHT = 8
GF.NAV_L0_ROW_SPACING = 2
GF.NAV_ROW_H_DEFAULT = 28
GF.NAV_FLYOUT_PANEL_MIN_W = 120
GF.NAV_FLYOUT_PANEL_MAX_W = 260
GF.NAV_FLYOUT_ROOT_GAP = 2
GF.NAV_FLYOUT_ROOT_ANCHOR_GAP_X = 4
GF.NAV_FLYOUT_ROOT_ANCHOR_GAP_Y = 2
GF.NAV_FLYOUT_PANEL_GAP = 6
GF.NAV_FLYOUT_STAIR_STEP_Y = 9
GF.NAV_FLYOUT_SCREEN_MARGIN_TOP = 12
GF.NAV_FLYOUT_WINDOW_BOTTOM_GAP = 0
GF.NAV_FLYOUT_ROW_H = { [1] = 32, [2] = 32, [3] = 30 }
GF.NAV_FLYOUT_ROW_H_DEFAULT = 30
GF.NAV_FLYOUT_ROW_TEXT_L = 12
GF.NAV_FLYOUT_ROW_TEXT_R = 10
GF.NAV_FLYOUT_ARROW_ATLAS = "bag-arrow"
GF.NAV_FLYOUT_ARROW_W = 10
GF.NAV_FLYOUT_ARROW_H = 16
GF.NAV_FLYOUT_ARROW_R = 8
GF.NAV_FLYOUT_ARROW_RESERVE_W = 28
GF.NAV_FLYOUT_LABEL_EXTRA_W = 8
GF.NAV_FLYOUT_HIGHLIGHT_INSET_X = 3
GF.NAV_FLYOUT_HIGHLIGHT_INSET_TOP = 3
GF.NAV_FLYOUT_HIGHLIGHT_INSET_BOTTOM = 1
GF.NAV_FLYOUT_ROW_TEXTURE_EXTEND_X = 8
GF.NAV_FLYOUT_HIGHLIGHT_ATLAS = GF.ROW_BACKGROUND_ATLAS
GF.NAV_FLYOUT_HIGHLIGHT_DISPLAY_H = 28
GF.NAV_FLYOUT_BG_ATLAS = "common-dropdown-bg"
GF.NAV_FLYOUT_BG_EXTEND_X = 10
GF.NAV_FLYOUT_BG_EXTEND_TOP = 3
GF.NAV_FLYOUT_BG_EXTEND_BOTTOM = 3
GF.NAV_FLYOUT_BG_ALPHA = 0.925
GF.NAV_FLYOUT_CONTENT_INSET_L = 8
GF.NAV_FLYOUT_CONTENT_INSET_R = 8
GF.NAV_FLYOUT_CONTENT_INSET_T = 8
GF.NAV_FLYOUT_CONTENT_INSET_B = 15
GF.LIST_ROW_H = 32
GF.LIST_ROW_H_DEFAULT = 32
GF.BROWSE_TEXT_CELL_INSET_X = 2
GF.ROLE_COUNT_ICON_DEFAULT = GF.ROLE_ICON_SIZE
GF.ROLE_COUNT_NUM_ICON_GAP = 5
local function publishConstants(values)
	for name, value in pairs(values) do
		GF[name] = value
	end
end

-- 内容区 scroll 右缘留白 + 滚动条贴窗右（各内容页共用，仅改此处）
publishConstants({
	COL_MIN_WIDTH_MIN = 20,
	COL_MIN_WIDTH_MAX = 300,
	COL_WEIGHT_MIN = 0,
	COL_WEIGHT_MAX = 3,
	CONTENT_SCROLL_INSET_L = 5,
	CONTENT_SCROLL_INSET_R = 18,
	CONTENT_SCROLL_INSET_B = 0,
	CONTENT_SCROLLBAR_OFFSET_X = 9,
	LIST_CONTENT_EDGE_PAD = 18,
	LIST_CONTENT_EDGE_PAD_MAX = 30,
	LIST_COL_REF_W = 930,
	ACTIVITY_COUNT_RIGHT = 28,
	LIST_WHEEL_ROWS_MIN = 1,
	LIST_WHEEL_ROWS_MAX = 10,
	LIST_WHEEL_ROWS_DEFAULT = 3,
	AUTO_INVITE_MEMBER_LIMIT_MIN = 1,
	AUTO_INVITE_MEMBER_LIMIT_MAX = 40,
	AUTO_INVITE_MEMBER_LIMIT_DEFAULT = 40,
	NAV_WHEEL_ROW_H = 28,
	SETTINGS_WHEEL_ROW_H = 24,
	SETTINGS_COL_W = 280,
	SETTINGS_GUTTER_MIN = 50,
	SETTINGS_GUTTER_WEIGHT = 1,
})
-- 内容区相对 nav 右缘水平偏移（负=向左靠分割线）
GF.CONTENT_NAV_OFFSET_X = 0
-- 列表行四列左边界（在 LIST_COL_REF_W 参考行宽下的 px）
-- host 左缘到石纹内缘；右缘 CONTENT_SCROLL_INSET_R 为滚动条走廊
GF.SETTINGS_LAYOUT_INSET_L = (GF.FRAME_BG_INSET_LEFT or 7) - (GF.FRAME_PAD or 4)
GF.SETTINGS_LAYOUT_INSET_R = GF.CONTENT_SCROLL_INSET_R or 18
-- 设置页最外层分区标题与滚动条走廊。
publishConstants({
	SETTINGS_SCROLLBAR_WIDTH = 17,
	SETTINGS_SCROLLBAR_GAP = 2,
	SETTINGS_SCROLLBAR_RIGHT_INSET = 10,
	SETTINGS_SCROLLBAR_TOP_INSET = 8,
	SETTINGS_SCROLLBAR_BOTTOM_INSET = 8,
})
GF.SETTINGS_VISIBLE_CONTENT_INSET_R =
	GF.SETTINGS_SCROLLBAR_WIDTH
	+ GF.SETTINGS_SCROLLBAR_GAP
	+ GF.SETTINGS_SCROLLBAR_RIGHT_INSET
-- WowStyle1Dropdown 等控件相对列 Frame 左缘的视觉外溢
-- 设置页控件行距：下拉/滑块底留白 8 + 分区表头前 12 + 表头内锚 8 = 表头上方 28px
publishConstants({
	SETTINGS_CONTENT_TOP_OFFSET = 20,
	SETTINGS_SECTION_TITLE_H = 40,
	SETTINGS_COL_EDGE_INSET_L = 10,
	SETTINGS_ROW_BOTTOM_PAD = 8,
	SETTINGS_SECTION_TOP_PAD = 12,
	SETTINGS_DROPDOWN_W = 260,
	SETTINGS_DROPDOWN_H = 26,
	SETTINGS_SLIDER_W = 220,
	SETTINGS_SLIDER_H = 19,
	FILTER_WHEEL_ROW_H = 28,
	BLOCKLIST_WHEEL_ROW_H = 28,
})
-- 屏蔽列表列左边界（参考行宽 900；第 1 列文字在 +/- 占位与勾选框之后）
GF.BLOCKLIST_COL_X = { 62, 380, 560 }
GF.APPLICANTS_WHEEL_ROW_H = 30
GF.CREATE_DRAWER_W = 600
GF.CREATE_DRAWER_H = 390
GF.CREATE_DRAWER_HORIZONTAL_MIN_W = 560
GF.CREATE_FORM_COLUMN_GAP = 16
GF.CREATE_DRAWER_AVOID_ALPHA = 0.64
GF.CREATE_DRAWER_MAIN_ALPHA = GF.CREATE_DRAWER_AVOID_ALPHA
publishConstants({
	CREATE_WHEEL_ROW_H = 24,
	LIST_REFRESH_DEBOUNCE = 0.2,
	BROWSE_LISTEN_HOLD_SEC = 60,
	BROWSE_SORT_KEY_BATCH = 25,
	FILTER_BATCH = 25,
	ROW_UPDATE_DEBOUNCE = 0.2,
	LAYOUT_RESIZE_DEBOUNCE = 0.1,
	SEARCH_COOLDOWN = 3,
	SEARCH_COOLDOWN_QUEUE_DELAY = 0.15,
	SEARCH_TIMEOUT_SECONDS = 8,
})

GF.TAB_BROWSE = 1
GF.TAB_CREATE = 2
GF.TAB_BLOCKLIST = 3
GF.TAB_SETTINGS = 4
GF.TAB_DEBUG = 5
GF.TAB_MPLUS_CHARACTER = 101
GF.TAB_MPLUS_GROUP = 102
GF.TAB_MPLUS_CARPOOL = 103
GF.TAB_MPLUS_DUNGEON = 104

GF.WORKSPACE_MEETING_STONE = "standard"
GF.WORKSPACE_STANDARD = GF.WORKSPACE_MEETING_STONE
GF.WORKSPACE_MYTHIC_PLUS = "mythic_plus"
GF.WORKSPACE_RAID = "raid"
GF.WORKSPACE_DEFAULT = GF.WORKSPACE_MEETING_STONE
GF.WORKSPACE_TAB_HEIGHT = GF.MAIN_PANEL_TAB_HEIGHT
GF.WORKSPACE_TAB_GAP = GF.MAIN_PANEL_TAB_GAP
GF.WORKSPACE_TAB_TEXT_PADDING = 40
GF.WORKSPACE_TAB_LEFT_INSET = 32
GF.GREAT_VAULT_BUTTON_OFFSET_X = GF.WORKSPACE_TAB_LEFT_INSET
GF.GREAT_VAULT_BUTTON_OFFSET_Y = 2


GF.APPLY_MANUAL = "manual"
GF.APPLY_CLICK_CONFIRM = "click_confirm"
GF.APPLY_DBLCLICK_AUTO = "dblclick_auto"

GF.LIST_HOVER_TOOLTIP_HIDE_DELAY = 0.1

publishConstants({
	FRAME_STRATA_DEFAULT = "MEDIUM",
	FRAME_STRATA_CHOICES = { "LOW", "MEDIUM", "HIGH", "DIALOG" },
	CAT_QUEST = 1,
	CAT_DUNGEON = 2,
	CAT_RAID = 3,
	CAT_CUSTOM = 6,
	CAT_DELVE = 121,
	ACTIVITY_CUSTOM_PVE = 16,
	ACTIVITY_CUSTOM_PVP = 17,
	ACTIVITY_HOUSEWARMING = 1972,
	BODY_BACKGROUND_COLOR = { 0.05, 0.05, 0.08, 0.75 },
	SEL_TEX = "Interface\\PVPFrame\\PvPMegaQueue",
	SEL_TEX_HOVER = { 0.00195313, 0.63867188, 0.70703125, 0.76757813 },
	SEL_TEX_SELECTED = { 0.00195313, 0.63867188, 0.76953125, 0.83007813 },
})

local pvpCategoryDefinitions = {
	{ 8, "PVP_BG" },
	{ 4, "PVP_ARENA" },
	{ 9, "PVP_RATED" },
	{ 7, "PVP_SKIRMISH" },
}
GF.PVP_CATEGORIES = {}
for index = 1, #pvpCategoryDefinitions do
	local definition = pvpCategoryDefinitions[index]
	GF.PVP_CATEGORIES[index] = { id = definition[1], key = definition[2] }
end

-- 列表 scroll 内容区右留白：参考宽以下随 scroll 变窄而增大（仅 resize 时算一次）
function GF.GetListContentEdgePad(scrollW)
	local width = tonumber(scrollW)
	local limits = {
		minimum = GF.LIST_CONTENT_EDGE_PAD or 18,
		maximum = GF.LIST_CONTENT_EDGE_PAD_MAX or 30,
		referenceWidth = GF.LIST_COL_REF_W or 900,
	}
	if not width or width <= 0 or width >= limits.referenceWidth then
		return limits.minimum
	end
	local scaled = math.floor(limits.minimum * limits.referenceWidth / width)
	return math.min(limits.maximum, math.max(limits.minimum, scaled))
end

function GF.GetBrowseListLayoutWidth()
	local owner = GF.FindGroupTab
	local measure = owner and owner.GetLayoutWidth
	return measure and measure(owner) or 1
end

function GF.GetApplicantListLayoutWidth()
	local list = GF.ApplicantsPanel and GF.ApplicantsPanel.scrollList
	local measure = list and list.GetLayoutWidth
	return measure and measure(list) or 1
end
