#include "headers/includes.h"

#include <Windows.h>
#include <array>
#include <cstdlib>
#include <string>

#include "Overlay/MenuBridge.h"   // project header (src/ is on the include path)

// -------------------------------------------------------------------------
// DayZ overlay integration
//
// This is the original Lumin demo `gui.cpp`, stripped of the login screen and
// the placeholder "visual" feature panels.  The window/sidebar/feature
// scaffolding is preserved verbatim; only the tab list and per-tab content
// were swapped to drive this project's real ESP state via `g_menu`
// (see src/Overlay/MenuBridge.h).  https://discord.gg/jxqVWub6Dk
// -------------------------------------------------------------------------

static void sync_layout_preferences()
{
	elements->padding = var->gui.compact_layout ? c_vec2(8, 8) : c_vec2(10, 10);
	elements->window.rounding = var->gui.window_rounding;
}

static constexpr float visual_window_width = 900.f;
static constexpr float visual_window_height = 527.f;
static constexpr float visual_sidebar_width = 162.5f;
static constexpr float visual_outer_padding = 10.f;
static constexpr float visual_column_gap = 14.f;
static constexpr float visual_panel_scale = 1.0f;
static constexpr float visual_section_width_scale = 0.98f;
static constexpr float visual_feature_padding_x = 0.f;
static constexpr float visual_feature_padding_y = 0.f;

struct visual_panel_density_state
{
	float dpi;
	float font_scale;
};

static float unscale_visual(float value)
{
	return value / ImMax(var->gui.dpi, 0.01f);
}

static float visual_section_height(int section_count)
{
	const float content_height = unscale_visual(gui->content_avail().y);
	const float gaps = visual_column_gap * static_cast<float>(ImMax(section_count - 1, 0));
	return ImMax(220.f, (content_height - gaps) / static_cast<float>(ImMax(section_count, 1)));
}

extern c_vec4 g_pill_selected_rect;
extern c_vec4 g_sidebar_selected_rect;

static int g_panel_number = 0;

// ---- search filtering -----------------------------------------------------

static char visual_search_lower(char value)
{
	return value >= 'A' && value <= 'Z' ? static_cast<char>(value - 'A' + 'a') : value;
}

static std::string visual_search_query()
{
	std::string query = var->gui.feature_search;
	size_t first = 0;
	while (first < query.size() && (query[first] == ' ' || query[first] == '\t'))
		first++;

	size_t last = query.size();
	while (last > first && (query[last - 1] == ' ' || query[last - 1] == '\t'))
		last--;

	return query.substr(first, last - first);
}

static bool visual_contains_ci(std::string_view text, std::string_view query)
{
	if (query.empty())
		return true;

	if (query.size() > text.size())
		return false;

	for (size_t i = 0; i <= text.size() - query.size(); i++)
	{
		size_t j = 0;
		while (j < query.size() && visual_search_lower(text[i + j]) == visual_search_lower(query[j]))
			j++;

		if (j == query.size())
			return true;
	}

	return false;
}

static bool visual_search_matches(std::string_view name, std::string_view description = {})
{
	const std::string query = visual_search_query();
	if (query.empty())
		return true;

	return visual_contains_ci(name, query) || visual_contains_ci(description, query);
}

struct visual_widget_filter
{
	bool checkbox(std::string name, std::string description, bool* callback, title_status_icon status = title_status_none) const
	{
		if (!visual_search_matches(name, description))
			return false;

		return ::widgets->checkbox(name, description, callback, status);
	}

	bool slider(std::string name, std::string description, float* callback, float vmin, float vmax, std::string format = "%.1f") const
	{
		if (!visual_search_matches(name, description))
			return false;

		return ::widgets->slider(name, description, callback, vmin, vmax, format);
	}
};

// ---- section helpers ------------------------------------------------------

static void begin_visual_section(std::string_view name, float height)
{
	const int panel_number = g_panel_number + 1;
	const float section_width = elements->child_width * visual_section_width_scale;
	const float content_padding_x = ImMax(0.f, section_width * 0.05f);
	gui->begin_content(name, c_vec2(section_width, s_(height)), c_vec2(content_padding_x, s_(5)), s_(0, 0), window_flags_no_move | window_flags_no_scrollbar, child_flags_none);
	c_window* window = gui->get_window();
	draw->rect_filled(window->DrawList, window->Rect().Min, window->Rect().Max, draw->get_clr(clr->child), s_(14));

	g_panel_number = panel_number;
}

static void end_visual_section()
{
	gui->end_content();
}

static visual_panel_density_state begin_visual_panel_density()
{
	c_window* window = gui->get_window();
	visual_panel_density_state state{ var->gui.dpi, window->FontWindowScale };

	var->gui.dpi = ImMax(0.01f, state.dpi * visual_panel_scale);
	ImGui::SetWindowFontScale(state.font_scale * visual_panel_scale);
	return state;
}

static void end_visual_panel_density(visual_panel_density_state state)
{
	ImGui::SetWindowFontScale(state.font_scale);
	var->gui.dpi = state.dpi;
}

static void draw_visual_sidebar_glass(const c_rect& rect)
{
	ImDrawList* draw_list = gui->get_window()->DrawList;
	const float rounding = s_(14);
	draw->rect_filled(draw_list, rect.Min, rect.Max, draw->get_clr(clr->child), rounding);
}

// Full-width single-column panel (used by Info / Radar / Settings).
static void begin_full_section(std::string_view name, float height, bool scroll = false)
{
	const float section_width = gui->content_avail().x;
	const float content_padding_x = ImMax(0.f, section_width * 0.035f);
	const window_flags flags = window_flags_no_move | (scroll ? 0 : window_flags_no_scrollbar);
	gui->begin_content(name, c_vec2(section_width, s_(height)), c_vec2(content_padding_x, s_(10)), s_(0, 6), flags, child_flags_none);
	c_window* window = gui->get_window();
	draw->rect_filled(window->DrawList, window->Rect().Min, window->Rect().Max, draw->get_clr(clr->child), s_(14));
}

// Accent section heading.
static void lumin_heading(const char* text)
{
	c_window* w = gui->get_window();
	const c_vec2 pos = w->DC.CursorPos;
	const c_vec2 size = c_vec2(gui->content_avail().x, s_(22));
	const c_rect rect(pos, pos + size);
	gui->item_size(rect);
	if (!gui->item_add(rect, w->GetID(text)))
		return;
	draw->text_clipped(w->DrawList, font->get(inter_semibold, 13), rect.Min, rect.Max, draw->get_clr(clr->accent), text, 0, 0, { 0.f, 0.5f });
}

// Muted single-line note.
static void lumin_note(const char* text)
{
	c_window* w = gui->get_window();
	const c_vec2 pos = w->DC.CursorPos;
	const c_vec2 size = c_vec2(gui->content_avail().x, s_(16));
	const c_rect rect(pos, pos + size);
	gui->item_size(rect);
	if (!gui->item_add(rect, w->GetID(text)))
		return;
	draw->text_clipped(w->DrawList, font->get(inter_medium, 11), rect.Min, rect.Max, draw->get_clr(clr->text), text, 0, 0, { 0.f, 0.5f });
}

// Read-only "label .... value" row on a rounded widget background.
static void lumin_kv(const char* label, const std::string& value, const c_vec4& value_clr)
{
	c_window* w = gui->get_window();
	const c_vec2 pos = w->DC.CursorPos;
	const c_vec2 size = c_vec2(gui->content_avail().x, s_(34));
	const c_rect rect(pos, pos + size);
	gui->item_size(rect);
	if (!gui->item_add(rect, w->GetID(label)))
		return;
	draw->rect_filled(w->DrawList, rect.Min, rect.Max, draw->get_clr(clr->widget), s_(8));
	draw->text_clipped(w->DrawList, font->get(inter_semibold, 12), rect.Min + s_(12, 0), rect.Max, draw->get_clr(clr->white), label, 0, 0, { 0.f, 0.5f });
	draw->text_clipped(w->DrawList, font->get(inter_medium, 11), rect.Min, rect.Max - s_(12, 0), draw->get_clr(value_clr), value.data(), 0, 0, { 1.f, 0.5f });
}

// ---- ESP / Items content --------------------------------------------------

static void render_esp_tab(const visual_widget_filter& w, float section_height)
{
	if (!g_menu)
		return;

	gui->begin_group();
	{
		begin_visual_section("Entities", section_height);
		w.checkbox("Players",        "Show player ESP",          g_menu->showPlayers,   title_status_safe);
		w.checkbox("Animals",        "Show animal ESP",          g_menu->showAnimals);
		w.checkbox("Zombies",        "Show infected ESP",        g_menu->showZombies);
		w.checkbox("Items",          "Show loot ESP",            g_menu->showItems);
		w.checkbox("Corpses",        "Show dead bodies",         g_menu->showCorpses);
		w.checkbox("Bounding Box",   "Draw entity box",          g_menu->showBox);
		w.checkbox("Skeleton",       "Draw bone skeleton",       g_menu->showSkeleton);
		w.checkbox("Head Circle",    "Draw head highlight",      g_menu->showHeadDot);
		w.checkbox("Weapon In Hand", "Show held weapon name",    g_menu->showWeapon);
		w.checkbox("Health Bar",     "Draw player health bar",   g_menu->showHealthBar);
		w.checkbox("Health Number",  "Draw numeric health",      g_menu->showHealthNumber);
		w.checkbox("Skeleton Debug", "Label every named bone",   g_menu->debugSkeleton, title_status_warning);
		end_visual_section();
	}
	gui->end_group();

	gui->sameline();

	gui->begin_group();
	{
		begin_visual_section("Draw Distance", section_height);
		w.slider("Players",  "Max player draw distance", g_menu->playerMaxDist, 50.f, 1000.f, "%.0f m");
		w.slider("Animals",  "Max animal draw distance", g_menu->animalMaxDist, 50.f, 1000.f, "%.0f m");
		w.slider("Zombies",  "Max zombie draw distance", g_menu->zombieMaxDist, 50.f,  500.f, "%.0f m");
		w.slider("Items",    "Max loot draw distance",   g_menu->itemMaxDist,   20.f,  200.f, "%.0f m");
		end_visual_section();
	}
	gui->end_group();
}

static void render_items_tab(const visual_widget_filter& w, float section_height)
{
	if (!g_menu || !g_menu->itemCategories)
		return;

	struct cat_t { const char* key; const char* label; };
	static const std::array<cat_t, 17> kCats = { {
		{ "isWeapon",            "Weapons"            },
		{ "isAmmo",              "Ammo"               },
		{ "isMelee",             "Melee"              },
		{ "isExplosives",        "Explosives"         },
		{ "isMedical",           "Medical"            },
		{ "isFood",              "Food"               },
		{ "isConsumables",       "Consumables"        },
		{ "isClothing",          "Clothing"           },
		{ "isBackpack",          "Backpacks"          },
		{ "isOptics",            "Optics"             },
		{ "isWeaponAttachments", "Weapon Attachments" },
		{ "isTool",              "Tools"              },
		{ "isCrafting",          "Crafting"           },
		{ "isVehiclePart",       "Vehicle Parts"      },
		{ "isForBuilding",       "Building"           },
		{ "isHouse",             "House / Terrain"    },
		{ "isOtherLoot",         "Other"              },
	} };

	auto& cats = *g_menu->itemCategories;

	auto draw_category = [&](const cat_t& c)
	{
		// Missing key defaults to enabled; widget mutates the map slot directly.
		auto it = cats.find(c.key);
		if (it == cats.end())
			it = cats.emplace(c.key, true).first;
		w.checkbox(c.label, "Toggle loot category", &it->second);
	};

	const size_t split = (kCats.size() + 1) / 2;

	gui->begin_group();
	{
		begin_visual_section("Loot Categories", section_height);
		for (size_t i = 0; i < split; i++)
			draw_category(kCats[i]);
		end_visual_section();
	}
	gui->end_group();

	gui->sameline();

	gui->begin_group();
	{
		begin_visual_section("Loot Categories##2", section_height);
		for (size_t i = split; i < kCats.size(); i++)
			draw_category(kCats[i]);
		end_visual_section();
	}
	gui->end_group();
}

static void render_info_tab(float section_height)
{
	const c_vec4 green  = c_col(75, 225, 145).Value;
	const c_vec4 orange = c_col(255, 175, 75).Value;

	begin_full_section("Info", section_height);
	{
		lumin_heading("Server");
		if (g_menu && g_menu->connected)
		{
			lumin_kv("Status", "Connected", green);
			if (!g_menu->serverName.empty()) lumin_kv("Server", g_menu->serverName, clr->white.Value);
			if (!g_menu->mapName.empty())    lumin_kv("Map", g_menu->mapName, clr->white.Value);
			if (g_menu->hasPos)
			{
				char pos[64];
				ImFormatString(pos, IM_ARRAYSIZE(pos), "%.1f / %.1f / %.1f", g_menu->px, g_menu->py, g_menu->pz);
				lumin_kv("Position", pos, clr->accent.Value);
			}

			gui->dummy(c_vec2(0, s_(6)));
			lumin_heading("Entity Counts");
			lumin_kv("Players",  std::to_string(g_menu->nPlayers),  clr->accent.Value);
			lumin_kv("Animals",  std::to_string(g_menu->nAnimals),  clr->accent.Value);
			lumin_kv("Zombies",  std::to_string(g_menu->nZombies),  clr->accent.Value);
			lumin_kv("Vehicles", std::to_string(g_menu->nVehicles), clr->accent.Value);
			lumin_kv("Items",    std::to_string(g_menu->nItems),    clr->accent.Value);
			lumin_kv("Bullets",  std::to_string(g_menu->nBullets),  clr->accent.Value);
		}
		else
		{
			lumin_kv("Status", (g_menu && !g_menu->status.empty()) ? g_menu->status : "Offline", orange);
		}
	}
	end_visual_section();
}

static constexpr const char* kRadarDomain = "radar.charliecharliekirky.christmas";

static void render_radar_tab(float section_height)
{
	begin_full_section("Radar", section_height, true);
	{
		lumin_heading("Web Radar");
		lumin_note("Open this address in a browser:");
		gui->dummy(c_vec2(0, s_(4)));
		if (widgets->action_button(kRadarDomain, "copy"))
			ImGui::SetClipboardText(kRadarDomain);

		if (g_menu)
		{
			gui->dummy(c_vec2(0, s_(6)));
			lumin_heading("Connection");
			lumin_kv("Port", std::to_string(g_menu->webPort), clr->accent.Value);
			lumin_kv("Password", "Set in config.cfg", clr->text.Value);
		}
	}
	end_visual_section();
}

static void render_exit_tab(float section_height)
{
	begin_full_section("Exit", section_height);
	{
		lumin_heading("Exit Application");
		lumin_note("This will close the overlay and exit the program.");
		gui->dummy(c_vec2(0, s_(10)));

		const c_col saved_accent = clr->accent;
		clr->accent = c_col(225, 70, 70);
		if (widgets->primary_button("Exit", "back") && g_menu && g_menu->onExit)
			g_menu->onExit();
		clr->accent = saved_accent;
	}
	end_visual_section();
}

static void render_settings_tab(float section_height)
{
	if (!g_menu)
		return;

	// Persistent text buffers backing the four resolution fields.  Seeded once
	// from the live values, then treated as the source of truth (parsed back
	// into the int pointers every frame).
	static char ovr_w[8], ovr_h[8], rnd_w[8], rnd_h[8];
	static bool buffers_ready = false;
	if (!buffers_ready)
	{
		ImFormatString(ovr_w, IM_ARRAYSIZE(ovr_w), "%d", *g_menu->pendingW);
		ImFormatString(ovr_h, IM_ARRAYSIZE(ovr_h), "%d", *g_menu->pendingH);
		ImFormatString(rnd_w, IM_ARRAYSIZE(rnd_w), "%d", *g_menu->pendingRW);
		ImFormatString(rnd_h, IM_ARRAYSIZE(rnd_h), "%d", *g_menu->pendingRH);
		buffers_ready = true;
	}

	begin_full_section("Settings", section_height, true);
	{
		lumin_heading("Overlay (Monitor) Resolution");
		lumin_note("Set to your MONITOR size. 0 x 0 = auto-detect.");
		gui->push_id("ovr_res");
		widgets->text_field("Width", ovr_w, IM_ARRAYSIZE(ovr_w));
		widgets->text_field("Height", ovr_h, IM_ARRAYSIZE(ovr_h));
		gui->pop_id();
		*g_menu->pendingW = ImMax(0, atoi(ovr_w));
		*g_menu->pendingH = ImMax(0, atoi(ovr_h));
		if (widgets->primary_button("Apply Monitor Resolution") && g_menu->onApplyDisplayRes)
			g_menu->onApplyDisplayRes();

		gui->dummy(c_vec2(0, s_(8)));
		lumin_heading("Game Render Resolution");
		lumin_note("Set to the in-game resolution when it differs from the");
		lumin_note("monitor. 0 x 0 = no stretched-res correction.");
		gui->push_id("rnd_res");
		widgets->text_field("Width", rnd_w, IM_ARRAYSIZE(rnd_w));
		widgets->text_field("Height", rnd_h, IM_ARRAYSIZE(rnd_h));
		gui->pop_id();
		*g_menu->pendingRW = ImMax(0, atoi(rnd_w));
		*g_menu->pendingRH = ImMax(0, atoi(rnd_h));
		widgets->checkbox("Stretch to fill", "GPU stretches game to fill the monitor", g_menu->stretchToFill);
		if (widgets->primary_button("Apply Render Resolution") && g_menu->onApplyRenderRes)
			g_menu->onApplyRenderRes();

		gui->dummy(c_vec2(0, s_(10)));
		lumin_heading("General");
		lumin_note("Press INSERT to toggle this menu.");
		gui->dummy(c_vec2(0, s_(4)));
		if (widgets->primary_button("Save Config", "active") && g_menu->onSaveConfig)
			g_menu->onSaveConfig();
	}
	end_visual_section();
}

// ---------------------------------------------------------------------------

void c_gui::render()
{
	gui->initialize();
	sync_layout_preferences();

	gui->easing(var->gui.tab_alpha, var->gui.tab != var->gui.tab_stored ? 0.f : 1.f, 7.f, static_easing);
	if (var->gui.tab_alpha == 0)
		var->gui.tab = var->gui.tab_stored;

	const c_vec2 target(s_(visual_window_width), s_(visual_window_height));
	gui->easing(elements->window.size.x, target.x, 24.f, dynamic_easing);
	gui->easing(elements->window.size.y, target.y, 24.f, dynamic_easing);

	const ImVec2 disp = ImGui::GetIO().DisplaySize;
	gui->set_next_window_size(elements->window.size);
	gui->set_next_window_pos(c_vec2(ImMax(0.f, (disp.x - elements->window.size.x) * 0.5f),
	                                ImMax(0.f, (disp.y - elements->window.size.y) * 0.5f)));

	gui->begin(elements->window.name, nullptr, window_flags_no_scrollbar | window_flags_no_scroll_with_mouse | window_flags_no_bring_to_front_on_focus | window_flags_no_focus_on_appearing | window_flags_no_background | window_flags_no_decoration | window_flags_no_move);
	{
		gui->set_style();
		gui->draw_decorations();

		const float top_row_y = visual_outer_padding;
		const float top_row_height = 50.f;
		const float top_row_gap = 2.f;
		const float bottom_row_y = top_row_y + top_row_height + top_row_gap;
		const float bottom_row_height = visual_window_height - bottom_row_y - visual_outer_padding;
		const float sidebar_tabs_y = top_row_y + top_row_height;
		const float sidebar_tabs_height = visual_window_height - sidebar_tabs_y - visual_outer_padding;

		draw_visual_sidebar_glass(c_rect(c_vec2(s_(visual_outer_padding), s_(top_row_y)), c_vec2(s_(visual_outer_padding + visual_sidebar_width), s_(visual_window_height - visual_outer_padding))));

		gui->set_pos(c_vec2(s_(visual_outer_padding), s_(top_row_y)), pos_all);
		gui->begin_content("TopBrand", c_vec2(s_(visual_sidebar_width), s_(top_row_height)), s_(0, 0), s_(0, 0), window_flags_no_scrollbar | window_flags_no_background, child_flags_none);
		{
			widgets->brand_header("KarachiHook", var->gui.profile_name[0] != '\0' ? var->gui.profile_name : "DayZ Overlay");
		}
		gui->end_content();

		gui->set_pos(c_vec2(s_(visual_outer_padding), s_(sidebar_tabs_y)), pos_all);
		gui->begin_content("Tabs", c_vec2(s_(visual_sidebar_width), s_(sidebar_tabs_height)), s_(10, 10), s_(0, 4), window_flags_no_scrollbar | window_flags_no_background, child_flags_none);
		{
			var->gui.sidebar_glass = true;

			{
				c_window* tabs_inner_bg = gui->get_window();
				static c_vec4 sidebar_overlay = c_vec4(0, 0, 0, 0);
				gui->easing(sidebar_overlay, g_sidebar_selected_rect, 18.f, dynamic_easing);
				if (sidebar_overlay.z > sidebar_overlay.x + 1.f)
				{
					draw->rect_filled(tabs_inner_bg->DrawList,
						c_vec2(sidebar_overlay.x, sidebar_overlay.y), c_vec2(sidebar_overlay.z, sidebar_overlay.w),
						draw->get_clr(clr->widget), s_(9.1f));
				}
			}

			widgets->tab_button("ESP",      "visuals", 1);
			widgets->tab_button("Items",    "loot",    2);
			widgets->tab_button("Radar",    "world",   3);
			widgets->tab_button("Settings", "polish",  4);
			widgets->tab_button("Exit",     "back",    5);
			widgets->tab_button("Info",     "stats",   6);

			{
				static c_vec4 sidebar_indicator = c_vec4(0, 0, 0, 0);
				gui->easing(sidebar_indicator, g_sidebar_selected_rect, 18.f, dynamic_easing);
				if (sidebar_indicator.w > sidebar_indicator.y + 1.f)
				{
					c_window* tabs_inner = gui->get_window();
					const float bar_w = s_(2);
					const float bar_inset_y = s_(6);
					const float bar_x = sidebar_indicator.x + s_(2);
					const c_vec2 bar_min = c_vec2(bar_x, sidebar_indicator.y + bar_inset_y);
					const c_vec2 bar_max = c_vec2(bar_x + bar_w, sidebar_indicator.w - bar_inset_y);
					draw->rect_filled(tabs_inner->DrawList, bar_min, bar_max,
						draw->get_clr(clr->accent), bar_w * 0.5f);
				}
			}

			gui->easing(elements->tab_window_width, gui->get_window()->Size.x, 24.f, dynamic_easing);
			var->gui.sidebar_glass = false;
		}
		gui->end_content();

		gui->push_var(style_var_alpha, var->gui.tab_alpha);

		const float feature_x = visual_outer_padding + visual_sidebar_width + visual_outer_padding;
		const float feature_width = visual_window_width - feature_x - visual_outer_padding;
		const float feature_header_height = top_row_height * 0.8f;
		const float feature_header_y = top_row_y;

		gui->set_pos(c_vec2(s_(feature_x), s_(feature_header_y) + s_(10) * (1.f - var->gui.tab_alpha)), pos_all);
		{
			const c_vec2 pill_pos = gui->get_window()->DC.CursorPos;
			draw->rect_filled(gui->get_window()->DrawList, pill_pos, pill_pos + c_vec2(s_(feature_width), s_(feature_header_height)), draw->get_clr(clr->child), s_(14));

			gui->begin_content("FeatureHeader", c_vec2(s_(feature_width), s_(feature_header_height)), s_(8, 4), s_(8, 0), window_flags_no_scrollbar | window_flags_no_background, child_flags_none);
			{
				const float search_width = s_(178.f);
				widgets->search_field("Search", var->gui.feature_search, IM_ARRAYSIZE(var->gui.feature_search), c_vec2(search_width, s_(32.f)));
			}
			gui->end_content();
		}

		gui->set_pos(c_vec2(s_(feature_x), s_(bottom_row_y) + s_(10) * (1.f - var->gui.tab_alpha)), pos_all);
		gui->begin_content("Features", c_vec2(s_(feature_width), s_(bottom_row_height)), s_(visual_feature_padding_x, visual_feature_padding_y), c_vec2(s_(visual_column_gap), 0.f), window_flags_no_scrollbar);
		{
			const visual_panel_density_state density_state = begin_visual_panel_density();

			g_panel_number = 3;
			gui->easing(elements->child_width, (gui->content_avail().x - s_(visual_column_gap)) / 2, 24.f, dynamic_easing);
			const float section_height = visual_section_height(1);
			const visual_widget_filter visual_widgets;

			switch (var->gui.tab)
			{
			case 1: render_esp_tab(visual_widgets, section_height);   break;
			case 2: render_items_tab(visual_widgets, section_height); break;
			case 3: render_radar_tab(section_height);                 break;
			case 4: render_settings_tab(section_height);              break;
			case 5: render_exit_tab(section_height);                  break;
			case 6: render_info_tab(section_height);                  break;
			default: break;
			}

			end_visual_panel_density(density_state);
		}
		gui->end_content();

		gui->pop_var();
	}
	gui->end();
}

// Shim called by GameOverlay (declared in src/Overlay/MenuBridge.h).
void RenderLuminMenu()
{
	gui->render();
}
