// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3

#include "settings_page.h"
#include "../../app.h"
#include "../../config/version.h"
#include "../../config/settings.h"
#include "../../wallet/lite_wallet_lifecycle_ui_adapter.h"
#include "../../wallet/lite_wallet_server_selection_adapter.h"
#include "../../wallet/lite_wallet_controller.h"
#include <sodium.h>
#include "../../util/logger.h"
#include "../windows/balance_tab.h"
#include "../windows/console_tab.h"
#include "../../util/i18n.h"
#include "../../util/platform.h"
#include "../../rpc/rpc_client.h"
#include "../../rpc/connection.h"
#include "../../rpc/rpc_worker.h"
#include "../theme.h"
#include "../layout.h"
#include "../schema/ui_schema.h"
#include "../schema/skin_manager.h"
#include "../notifications.h"
#include "../effects/imgui_acrylic.h"
#include "../effects/theme_effects.h"
#include "../effects/low_spec.h"
#include "../effects/scroll_fade_shader.h"
#include "../material/draw_helpers.h"
#include "../material/type.h"
#include "../material/colors.h"
#include "../windows/validate_address_dialog.h"
#include "../windows/address_book_dialog.h"
#include "../windows/shield_dialog.h"
#include "../windows/request_payment_dialog.h"
#include "../windows/block_info_dialog.h"
#include "../windows/export_all_keys_dialog.h"
#include "../windows/export_transactions_dialog.h"
#include "../windows/bootstrap_download_dialog.h"
#include "../../embedded/IconsMaterialDesign.h"
#include "imgui.h"
#include <nlohmann/json.hpp>
#include <vector>
#include <set>
#include <filesystem>
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstring>

namespace dragonx {
namespace ui {

using namespace material;

// Helper: build "TranslatedLabel##id" for ImGui widgets that use label as ID
static std::string TrId(const char* tr_key, const char* id) {
    std::string s = TR(tr_key);
    s += "##";
    s += id;
    return s;
}

// ============================================================================
// Settings state loaded from config::Settings on first render
// ============================================================================
struct LowSpecSnapshot {
    bool valid = false;
    bool acrylic_enabled;
    float blur_amount;
    float ui_opacity;
    float window_opacity;
    bool theme_effects_enabled;
    bool scanline_enabled;
};

struct SettingsPageState {
    bool initialized = false;
    int language_index = 0;
    bool save_ztxs = true;
    bool allow_custom_fees = false;
    bool auto_shield = false;
    bool fetch_prices = true;
    bool use_tor = false;
    char rpc_host[128] = DRAGONX_DEFAULT_RPC_HOST;
    char rpc_port[16] = DRAGONX_DEFAULT_RPC_PORT;
    char rpc_user[64] = "";
    char rpc_password[64] = "";
    bool rpc_plaintext_remote = false;
    char tx_explorer[256] = "https://explorer.dragonx.is/tx/";
    char addr_explorer[256] = "https://explorer.dragonx.is/address/";
    bool acrylic_enabled = true;
    float blur_amount = 1.5f;
    float noise_opacity = 0.5f;
    float ui_opacity = 1.0f;
    float window_opacity = 1.0f;
    std::string balance_layout = "classic";
    bool scanline_enabled = true;
    bool theme_effects_enabled = true;
    bool gradient_background = false;
    bool low_spec_mode = false;
    bool reduce_motion = false;
    float font_scale = 1.0f;
    LowSpecSnapshot low_spec_snapshot;
    bool keep_daemon_running = false;
    bool stop_external_daemon = false;
    int lite_server_mode = 0;
    char lite_server_url[256] = "https://lite.dragonx.is";
    int lite_random_seed = 0;
    bool lite_persist_selected_server = true;
    std::vector<wallet::LiteServerEndpoint> lite_servers;
    std::string lite_server_status;
    bool lite_lifecycle_expanded = false;
    int lite_lifecycle_operation = 0;
    char lite_wallet_path[256] = "";
    char lite_lifecycle_passphrase[128] = "";
    char lite_restore_seed[512] = "";
    int lite_restore_birthday = 0;
    int lite_restore_account = 0;
    bool lite_restore_overwrite = false;
    std::string lite_lifecycle_status;
    std::string lite_lifecycle_summary;
    bool mine_when_idle = false;
    int mine_idle_delay = 120;
    bool idle_thread_scaling = false;
    int idle_threads_active = 0;
    int idle_threads_idle = 0;
    bool verbose_logging = false;
    std::set<std::string> debug_categories;
    bool debug_cats_dirty = false;
    bool debug_expanded = false;
    bool effects_expanded = false;
    bool tools_expanded = false;
    bool confirm_clear_ztx = false;
    bool confirm_delete_blockchain = false;
    effects::ScrollFadeShader fade_shader;
};

static SettingsPageState s_settingsState;

static void copyToSettingsBuffer(char* dest, std::size_t destSize, const std::string& value) {
    if (!dest || destSize == 0) return;
    std::strncpy(dest, value.c_str(), destSize - 1);
    dest[destSize - 1] = '\0';
}

static wallet::LiteConnectionSettings liteConnectionSettingsFromPageState(config::Settings* settings) {
    wallet::LiteConnectionSettings connectionSettings = settings
        ? wallet::liteConnectionSettingsFromAppSettings(*settings)
        : wallet::defaultLiteConnectionSettings();
    if (!s_settingsState.lite_servers.empty()) {
        connectionSettings.servers = s_settingsState.lite_servers;
    }
    connectionSettings.selectionMode = s_settingsState.lite_server_mode == 1
        ? wallet::LiteServerSelectionMode::Random
        : wallet::LiteServerSelectionMode::Sticky;
    connectionSettings.stickyServerUrl = s_settingsState.lite_server_url;
    connectionSettings.chainName = wallet::kDragonXLiteChainName;
    connectionSettings.randomSelectionSeed = static_cast<std::size_t>(std::max(0, s_settingsState.lite_random_seed));
    return connectionSettings;
}

static wallet::LiteWalletLifecycleOperation liteLifecycleOperationFromPageState() {
    switch (s_settingsState.lite_lifecycle_operation) {
        case 1: return wallet::LiteWalletLifecycleOperation::OpenExisting;
        case 2: return wallet::LiteWalletLifecycleOperation::RestoreFromSeed;
        default: return wallet::LiteWalletLifecycleOperation::CreateNew;
    }
}

static void saveLiteServerSelectionFromPageState(App* app) {
    if (!app || !app->settings()) return;

    const auto connectionSettings = liteConnectionSettingsFromPageState(app->settings());
    wallet::LiteWalletServerSelectionUiExecutionInput input;
    input.capabilities = app->walletCapabilities();
    input.intent.selectedServerIntentProvided = true;
    input.intent.selectionMode = connectionSettings.selectionMode;
    input.intent.selectedServerUrl = connectionSettings.stickyServerUrl;
    input.intent.randomSelectionSeed = connectionSettings.randomSelectionSeed;
    input.intent.chainName = connectionSettings.chainName;
    input.intent.replaceServers = true;
    input.intent.servers = connectionSettings.servers;
    input.persistence.settingsLoaded = true;
    input.persistence.havePersistedSelectionIntent = true;
    input.persistence.persistSelectedServer = s_settingsState.lite_persist_selected_server;
    input.persistence.persistenceOwnerReady = true;
    input.persistence.writeSettings = true;
    input.ui.selectedServerDisplayReady = true;
    input.ui.lifecycleUiOwnerReady = true;
    input.ui.operationConfirmed = true;
    input.ui.privateDataRedactionReady = true;
    input.ui.syncPlannerFeedReady = true;
    input.requireLifecycleReadiness = false;

    const auto result = wallet::executeLiteWalletServerSelectionUi(*app->settings(), input);
    if (result.settingsWritten) {
        s_settingsState.lite_server_status = "Saved";
    } else if (!result.error.empty()) {
        s_settingsState.lite_server_status = result.error;
        Notifications::instance().warning(result.error);
    }
}

static void evaluateLiteLifecycleRequestFromPageState(App* app) {
    if (!app || !app->settings()) return;

    wallet::LiteWalletLifecycleUiExecutionInput input;
    input.capabilities = app->walletCapabilities();
    input.settingsLoaded = true;
    input.requirePersistedServerSelectionIntent = true;
    input.ui.selectedServerDisplayReady = true;
    input.ui.lifecycleUiOwnerReady = true;
    input.ui.operationConfirmed = true;
    input.ui.privateDataRedactionReady = true;
    input.ui.syncPlannerFeedReady = true;
    input.request.requestProvided = true;
    input.request.operation = liteLifecycleOperationFromPageState();

    switch (input.request.operation) {
        case wallet::LiteWalletLifecycleOperation::CreateNew:
            input.request.createRequest.passphrase = s_settingsState.lite_lifecycle_passphrase;
            break;
        case wallet::LiteWalletLifecycleOperation::OpenExisting:
            input.request.openRequest.walletPath = s_settingsState.lite_wallet_path;
            input.request.openRequest.passphrase = s_settingsState.lite_lifecycle_passphrase;
            break;
        case wallet::LiteWalletLifecycleOperation::RestoreFromSeed:
            input.request.restoreRequest.walletPath = s_settingsState.lite_wallet_path;
            input.request.restoreRequest.seedPhrase = s_settingsState.lite_restore_seed;
            input.request.restoreRequest.passphrase = s_settingsState.lite_lifecycle_passphrase;
            input.request.restoreRequest.birthday = static_cast<unsigned long long>(std::max(0, s_settingsState.lite_restore_birthday));
            input.request.restoreRequest.account = static_cast<unsigned long long>(std::max(0, s_settingsState.lite_restore_account));
            input.request.restoreRequest.overwrite = s_settingsState.lite_restore_overwrite;
            break;
    }

    // Wipe ALL secret material when leaving this function, on every path (real execution,
    // validation-only fallback, or early return): the UI char buffers AND the std::string
    // copies inside `input.request.*Request`. The controller wipes its own by-value request
    // copy, but these page-local copies are separate; leaving them would defeat the wipe.
    struct LiteSecretScrubber {
        wallet::LiteWalletLifecycleUiExecutionInput& in;
        ~LiteSecretScrubber() {
            sodium_memzero(s_settingsState.lite_lifecycle_passphrase,
                           sizeof(s_settingsState.lite_lifecycle_passphrase));
            sodium_memzero(s_settingsState.lite_restore_seed,
                           sizeof(s_settingsState.lite_restore_seed));
            wallet::secureWipeLiteSecret(in.request.createRequest.passphrase);
            wallet::secureWipeLiteSecret(in.request.openRequest.passphrase);
            wallet::secureWipeLiteSecret(in.request.restoreRequest.seedPhrase);
            wallet::secureWipeLiteSecret(in.request.restoreRequest.passphrase);
        }
    } liteSecretScrubber{input};

    // When a linked lite backend is present, execute the operation for real through the
    // App-owned controller. Otherwise fall back to the validation-only adapter.
    if (auto* lite = app->liteWallet()) {
        wallet::LiteWalletLifecycleResult result;
        switch (input.request.operation) {
            case wallet::LiteWalletLifecycleOperation::CreateNew:
                result = lite->createWallet(input.request.createRequest);
                break;
            case wallet::LiteWalletLifecycleOperation::OpenExisting:
                result = lite->openWallet(input.request.openRequest);
                break;
            case wallet::LiteWalletLifecycleOperation::RestoreFromSeed:
                result = lite->restoreWallet(input.request.restoreRequest);
                break;
        }

        // (Secret wiping is handled unconditionally by liteSecretScrubber at function exit.)
        s_settingsState.lite_lifecycle_summary = result.bridgeResponseRedacted;
        if (result.walletReady) {
            s_settingsState.lite_lifecycle_status = "Wallet ready";
        } else {
            s_settingsState.lite_lifecycle_status = result.error.empty()
                ? result.status.message
                : result.error;
            Notifications::instance().warning(s_settingsState.lite_lifecycle_status);
        }
        return;
    }

    const auto result = wallet::executeLiteWalletLifecycleUiRequest(*app->settings(), input);
    s_settingsState.lite_lifecycle_summary = result.requestSummaryRedacted;
    if (result.ok) {
        s_settingsState.lite_lifecycle_status = "Ready";
    } else {
        s_settingsState.lite_lifecycle_status = result.error.empty()
            ? wallet::liteWalletLifecycleUiExecutionStatusName(result.status)
            : result.error;
        Notifications::instance().warning(s_settingsState.lite_lifecycle_status);
    }
}

// (APPEARANCE card now uses ChannelsSplit like all other cards)

static void loadSettingsPageState(config::Settings* settings) {
    if (!settings) return;

    s_settingsState.save_ztxs = settings->getSaveZtxs();
    s_settingsState.allow_custom_fees = settings->getAllowCustomFees();
    s_settingsState.auto_shield = settings->getAutoShield();
    s_settingsState.fetch_prices = settings->getFetchPrices();
    s_settingsState.use_tor = settings->getUseTor();

    strncpy(s_settingsState.tx_explorer, settings->getTxExplorerUrl().c_str(), sizeof(s_settingsState.tx_explorer) - 1);
    strncpy(s_settingsState.addr_explorer, settings->getAddressExplorerUrl().c_str(), sizeof(s_settingsState.addr_explorer) - 1);

    auto& i18n = util::I18n::instance();
    const auto& languages = i18n.getAvailableLanguages();
    std::string current_lang = settings->getLanguage();
    if (current_lang.empty()) current_lang = "en";

    s_settingsState.language_index = 0;
    int idx = 0;
    for (const auto& lang : languages) {
        if (lang.first == current_lang) {
            s_settingsState.language_index = idx;
            break;
        }
        idx++;
    }

    // Load blur amount directly from saved multiplier
    s_settingsState.blur_amount = settings->getBlurMultiplier();
    s_settingsState.acrylic_enabled = (s_settingsState.blur_amount > 0.001f);
    s_settingsState.ui_opacity = settings->getUIOpacity();
    s_settingsState.window_opacity = settings->getWindowOpacity();
    s_settingsState.noise_opacity = settings->getNoiseOpacity();

    s_settingsState.gradient_background = settings->getGradientBackground();

    s_settingsState.balance_layout = settings->getBalanceLayout();
    s_settingsState.scanline_enabled = settings->getScanlineEnabled();
    ConsoleTab::s_scanline_enabled = s_settingsState.scanline_enabled;
    s_settingsState.theme_effects_enabled = settings->getThemeEffectsEnabled();
    s_settingsState.low_spec_mode = settings->getLowSpecMode();
    effects::setLowSpecMode(s_settingsState.low_spec_mode);
    s_settingsState.reduce_motion = settings->getReduceMotion();
    s_settingsState.font_scale = settings->getFontScale();
    Layout::setUserFontScale(s_settingsState.font_scale);  // sync with Layout on load
    s_settingsState.keep_daemon_running = settings->getKeepDaemonRunning();
    s_settingsState.stop_external_daemon = settings->getStopExternalDaemon();
    {
        const auto liteSettings = wallet::liteConnectionSettingsFromAppSettings(*settings);
        s_settingsState.lite_server_mode = liteSettings.selectionMode == wallet::LiteServerSelectionMode::Random ? 1 : 0;
        copyToSettingsBuffer(s_settingsState.lite_server_url,
                             sizeof(s_settingsState.lite_server_url),
                             liteSettings.stickyServerUrl);
        s_settingsState.lite_random_seed = static_cast<int>(liteSettings.randomSelectionSeed);
        s_settingsState.lite_persist_selected_server = settings->getLitePersistSelectedServer();
        s_settingsState.lite_servers = liteSettings.servers;
        s_settingsState.lite_server_status.clear();
    }
    s_settingsState.mine_when_idle = settings->getMineWhenIdle();
    s_settingsState.mine_idle_delay = settings->getMineIdleDelay();
    s_settingsState.idle_thread_scaling = settings->getIdleThreadScaling();
    s_settingsState.idle_threads_active = settings->getIdleThreadsActive();
    s_settingsState.idle_threads_idle   = settings->getIdleThreadsIdle();
    s_settingsState.verbose_logging = settings->getVerboseLogging();
    s_settingsState.debug_categories = settings->getDebugCategories();
    s_settingsState.debug_cats_dirty = false;
    s_settingsState.rpc_plaintext_remote = rpc::Connection::usesPlaintextRemote(rpc::Connection::autoDetectConfig());

    // Apply loaded visual effects settings
    effects::ImGuiAcrylic::ApplyBlurAmount(s_settingsState.blur_amount);
    effects::ImGuiAcrylic::SetUIOpacity(s_settingsState.ui_opacity);
    effects::ImGuiAcrylic::SetNoiseOpacity(s_settingsState.noise_opacity);
    effects::ThemeEffects::instance().setEnabled(s_settingsState.theme_effects_enabled);

    s_settingsState.initialized = true;
}

static void saveSettingsPageState(config::Settings* settings) {
    if (!settings) return;

    settings->setTheme(settings->getSkinId());
    settings->setSaveZtxs(s_settingsState.save_ztxs);
    settings->setAllowCustomFees(s_settingsState.allow_custom_fees);
    settings->setAutoShield(s_settingsState.auto_shield);
    settings->setFetchPrices(s_settingsState.fetch_prices);
    settings->setUseTor(s_settingsState.use_tor);
    settings->setTxExplorerUrl(s_settingsState.tx_explorer);
    settings->setAddressExplorerUrl(s_settingsState.addr_explorer);

    auto& i18n = util::I18n::instance();
    const auto& languages = i18n.getAvailableLanguages();
    auto it = languages.begin();
    std::advance(it, s_settingsState.language_index);
    if (it != languages.end()) {
        settings->setLanguage(it->first);
    }

    // Visual effects settings
    settings->setAcrylicEnabled(s_settingsState.acrylic_enabled);
    settings->setAcrylicQuality(s_settingsState.blur_amount > 0.001f ? static_cast<int>(effects::AcrylicQuality::Low) : static_cast<int>(effects::AcrylicQuality::Off));
    settings->setBlurMultiplier(s_settingsState.blur_amount);
    settings->setUIOpacity(s_settingsState.ui_opacity);
    settings->setWindowOpacity(s_settingsState.window_opacity);
    settings->setNoiseOpacity(s_settingsState.noise_opacity);
    settings->setGradientBackground(s_settingsState.gradient_background);
    settings->setScanlineEnabled(s_settingsState.scanline_enabled);
    settings->setThemeEffectsEnabled(s_settingsState.theme_effects_enabled);
    settings->setLowSpecMode(s_settingsState.low_spec_mode);
    settings->setReduceMotion(s_settingsState.reduce_motion);
    settings->setFontScale(s_settingsState.font_scale);
    settings->setKeepDaemonRunning(s_settingsState.keep_daemon_running);
    settings->setStopExternalDaemon(s_settingsState.stop_external_daemon);
    {
        auto liteSettings = liteConnectionSettingsFromPageState(settings);
        wallet::applyLiteConnectionSettingsToAppSettings(*settings, liteSettings);
        settings->setLitePersistSelectedServer(s_settingsState.lite_persist_selected_server);
    }
    settings->setMineWhenIdle(s_settingsState.mine_when_idle);
    settings->setMineIdleDelay(s_settingsState.mine_idle_delay);
    settings->setIdleThreadScaling(s_settingsState.idle_thread_scaling);
    settings->setIdleThreadsActive(s_settingsState.idle_threads_active);
    settings->setIdleThreadsIdle(s_settingsState.idle_threads_idle);
    settings->setVerboseLogging(s_settingsState.verbose_logging);
    settings->setDebugCategories(s_settingsState.debug_categories);

    settings->save();
}

// ============================================================================
// Settings Page Renderer
// ============================================================================

void RenderSettingsPage(App* app) {
    // Load settings state on first render
    if (!s_settingsState.initialized && app->settings()) {
        loadSettingsPageState(app->settings());
    }

    // Sync low-spec / theme-effects state from runtime each frame
    // so that hotkey toggles are reflected in the checkboxes.
    {
        bool runtimeLowSpec = effects::isLowSpecMode();
        if (s_settingsState.low_spec_mode != runtimeLowSpec) {
            if (runtimeLowSpec) {
                // Hotkey turned low-spec ON — save snapshot, override statics
                s_settingsState.low_spec_snapshot.valid = true;
                s_settingsState.low_spec_snapshot.acrylic_enabled = s_settingsState.acrylic_enabled;
                s_settingsState.low_spec_snapshot.blur_amount = s_settingsState.blur_amount;
                s_settingsState.low_spec_snapshot.ui_opacity = s_settingsState.ui_opacity;
                s_settingsState.low_spec_snapshot.window_opacity = s_settingsState.window_opacity;
                s_settingsState.low_spec_snapshot.theme_effects_enabled = s_settingsState.theme_effects_enabled;
                s_settingsState.low_spec_snapshot.scanline_enabled = s_settingsState.scanline_enabled;
                s_settingsState.acrylic_enabled = false;
                s_settingsState.blur_amount = 0.0f;
                s_settingsState.ui_opacity = 1.0f;
                s_settingsState.window_opacity = 1.0f;
                s_settingsState.theme_effects_enabled = false;
                s_settingsState.scanline_enabled = false;
            } else if (s_settingsState.low_spec_snapshot.valid) {
                // Hotkey turned low-spec OFF — restore snapshot
                s_settingsState.blur_amount = s_settingsState.low_spec_snapshot.blur_amount;
                s_settingsState.acrylic_enabled = (s_settingsState.blur_amount > 0.001f);
                s_settingsState.ui_opacity = s_settingsState.low_spec_snapshot.ui_opacity;
                s_settingsState.window_opacity = s_settingsState.low_spec_snapshot.window_opacity;
                s_settingsState.theme_effects_enabled = s_settingsState.low_spec_snapshot.theme_effects_enabled;
                s_settingsState.scanline_enabled = s_settingsState.low_spec_snapshot.scanline_enabled;
                s_settingsState.low_spec_snapshot.valid = false;
            } else if (app->settings()) {
                // No snapshot — read prefs from settings file
                s_settingsState.blur_amount = app->settings()->getBlurMultiplier();
                s_settingsState.acrylic_enabled = (s_settingsState.blur_amount > 0.001f);
                s_settingsState.ui_opacity = app->settings()->getUIOpacity();
                s_settingsState.window_opacity = app->settings()->getWindowOpacity();
                s_settingsState.theme_effects_enabled = app->settings()->getThemeEffectsEnabled();
                s_settingsState.scanline_enabled = app->settings()->getScanlineEnabled();
            }
            s_settingsState.low_spec_mode = runtimeLowSpec;
        }
        bool runtimeThemeEffects = effects::ThemeEffects::instance().isEnabled();
        if (s_settingsState.theme_effects_enabled != runtimeThemeEffects) {
            s_settingsState.theme_effects_enabled = runtimeThemeEffects;
        }
    }

    auto& S = schema::UI();

    // Responsive layout — matches other tabs
    ImVec2 contentAvail = ImGui::GetContentRegionAvail();
    float scrollbarMargin = ImGui::GetStyle().ScrollbarSize + Layout::spacingSm();
    float availWidth = contentAvail.x - scrollbarMargin;
    float hs = Layout::hScale(availWidth);
    float vs = Layout::vScale(contentAvail.y);
    float pad = Layout::cardInnerPadding();
    float bottomPad = std::max(0.0f, pad - ImGui::GetStyle().ItemSpacing.y);
    float gap = Layout::cardGap();
    float glassRound = Layout::glassRounding();

    char buf[256];

    // Label column position — adaptive to width
    float labelW = std::max(S.drawElement("components.settings-page", "label-min-width").size, S.drawElement("components.settings-page", "label-width").size * hs);
    // Widen labelW if any translated label is wider (prevents overflow)
    {
        ImFont* mf = Type().body2();
        const char* labelKeys[] = {"theme", "balance_layout", "language", "acrylic", "noise",
                                    "ui_opacity", "window_opacity", "font_scale",
                                    "rpc_host", "rpc_port", "rpc_user", "rpc_pass",
                                    "transaction_url", "address_url"};
        for (const char* k : labelKeys) {
            float tw = mf->CalcTextSizeA(mf->LegacySize, FLT_MAX, 0, TR(k)).x + Layout::spacingMd();
            if (tw > labelW) labelW = tw;
        }
    }
    // Input field width — fill remaining space in card
    float inputW = std::max(S.drawElement("components.settings-page", "input-min-width").size, availWidth - labelW - pad * 2);

    // Scrollable content area — NoBackground matches other tabs

    ImGui::BeginChild("##SettingsPageScroll", ImVec2(0, 0), false,
        ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoScrollWithMouse);
    ApplySmoothScroll();

    // Capture the ACTUAL clip boundaries from inside the child window
    ImVec2 childClipMin = ImGui::GetWindowPos();
    ImVec2 childClipMax(childClipMin.x + ImGui::GetWindowSize().x,
                        childClipMin.y + ImGui::GetWindowSize().y);
    const float dp = Layout::dpiScale();
    const float fadeH = schema::UI().drawElement("components.settings-page", "edge-fade-zone").size * dp;
    const float fadeOffTop = schema::UI().drawElement("components.settings-page", "edge-fade-offset-top").size * dp;
    const float fadeOffBot = schema::UI().drawElement("components.settings-page", "edge-fade-offset-bottom").size * dp;

    // Get draw list AFTER BeginChild so we draw on the child window's list
    ImDrawList* dl = ImGui::GetWindowDrawList();
    (void)dl; // used by cards below

    // Capture ForegroundDrawList vertex start — DrawGlassPanel draws
    // theme effects (rainbow border, shimmer, specular glare, edge trace)
    // on the ForegroundDrawList; those bypass the shader fade so we'll
    // apply a vertex-based alpha fade to them after rendering.
    ImDrawList* fgDL = ImGui::GetForegroundDrawList();
    int fgVtxStart = fgDL->VtxBuffer.Size;

    // --- Shader-based scroll fade: bind custom fragment shader ---
    // The shader multiplies output alpha by a smoothstep gradient based
    // on screen Y, giving a true per-pixel alpha mask at scroll edges.
    float settingsScrollY_pre    = ImGui::GetScrollY();
    float settingsScrollMaxY_pre = ImGui::GetScrollMaxY();
    float settingsFadeTopY    = childClipMin.y + fadeOffTop;
    float settingsFadeBottomY = childClipMax.y - fadeOffBot;
    float settingsFadeZoneTop    = (settingsScrollY_pre > 1.0f) ? fadeH : 0.0f;
    float settingsFadeZoneBot    = (settingsScrollMaxY_pre > 0 && settingsScrollY_pre < settingsScrollMaxY_pre - 1.0f) ? fadeH : 0.0f;
    if (fadeH > 0.0f && !s_settingsState.low_spec_mode && s_settingsState.fade_shader.init()) {
        s_settingsState.fade_shader.fadeTopY       = settingsFadeTopY;
        s_settingsState.fade_shader.fadeBottomY    = settingsFadeBottomY;
        s_settingsState.fade_shader.fadeZoneTop    = settingsFadeZoneTop;
        s_settingsState.fade_shader.fadeZoneBottom = settingsFadeZoneBot;
        s_settingsState.fade_shader.addBind(dl);
    }

    // Top margin from schema
    float topMargin = schema::UI().drawElement("components.settings-page", "top-margin").size;
    if (topMargin > 0.0f)
        ImGui::Dummy(ImVec2(0, topMargin));

    GlassPanelSpec glassSpec;
    glassSpec.rounding = glassRound;
    ImFont* capFont = Type().caption();
    ImFont* body2   = Type().body2();
    ImFont* sub1    = Type().subtitle1();

    // ====================================================================
    // THEME & LANGUAGE — card (draw-first approach; avoids ChannelsSplit
    //   which breaks BeginCombo popup rendering in some ImGui versions)
    // ====================================================================
    {
        Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("theme_language"));
        ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

        ImVec2 cardMin = ImGui::GetCursorScreenPos();
        dl->ChannelsSplit(2);
        dl->ChannelsSetCurrent(1);

        ImGui::SetCursorScreenPos(ImVec2(cardMin.x, cardMin.y + pad));
        ImGui::Indent(pad);

        float contentW = availWidth - pad * 2;
        float comboGap = S.drawElement("components.settings-page", "combo-row-gap").size;
        float compactBP = S.drawElement("components.settings-page", "compact-breakpoint").size;
        bool wideLayout = availWidth >= compactBP;
        float refreshBtnW = S.drawElement("components.settings-page", "refresh-btn-width").size;

        // --- Skin data ---
        auto& skinMgr = schema::SkinManager::instance();
        const auto& skins = skinMgr.available();
        std::string active_preview = "DragonX";
        bool active_is_custom = false;
        for (const auto& skin : skins) {
            if (skin.id == skinMgr.activeSkinId()) {
                active_preview = skin.name;
                active_is_custom = !skin.bundled;
                break;
            }
        }

        // --- Language data ---
        auto& i18n = util::I18n::instance();
        const auto& languages = i18n.getAvailableLanguages();
        std::vector<const char*> lang_names;
        lang_names.reserve(languages.size());
        for (const auto& lang : languages) {
            lang_names.push_back(lang.second.c_str());
        }

        // --- Balance layout data ---
        const auto& layouts = GetBalanceLayouts();
        std::string balPreview = s_settingsState.balance_layout;
        for (const auto& l : layouts) {
            if (l.id == s_settingsState.balance_layout) { balPreview = l.name; break; }
        }

        // --- Theme combo popup (shared between wide and narrow paths) ---
        auto renderThemeComboPopup = [&]() {
            ImGui::TextDisabled("%s", TR("settings_builtin"));
            ImGui::Separator();
            for (size_t i = 0; i < skins.size(); i++) {
                const auto& skin = skins[i];
                if (!skin.bundled) continue;
                bool is_selected = (skin.id == skinMgr.activeSkinId());
                if (ImGui::Selectable(skin.name.c_str(), is_selected)) {
                    skinMgr.setActiveSkin(skin.id);
                    if (app->settings()) {
                        app->settings()->setSkinId(skin.id);
                        app->settings()->save();
                    }
                }
                if (is_selected) ImGui::SetItemDefaultFocus();
            }
            bool has_custom = false;
            for (const auto& skin : skins) {
                if (!skin.bundled) { has_custom = true; break; }
            }
            if (has_custom) {
                ImGui::Spacing();
                ImGui::TextDisabled("%s", TR("settings_custom"));
                ImGui::Separator();
                for (size_t i = 0; i < skins.size(); i++) {
                    const auto& skin = skins[i];
                    if (skin.bundled) continue;
                    bool is_selected = (skin.id == skinMgr.activeSkinId());
                    if (!skin.valid) {
                        ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.3f, 0.3f, 1.0f));
                        ImGui::BeginDisabled(true);
                        std::string lbl = skin.name + " (invalid)";
                        ImGui::Selectable(lbl.c_str(), false);
                        ImGui::EndDisabled();
                        ImGui::PopStyleColor();
                        if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
                            ImGui::SetTooltip("%s", skin.validationError.c_str());
                    } else {
                        std::string lbl = skin.name;
                        if (!skin.author.empty()) lbl += "  (" + skin.author + ")";
                        if (ImGui::Selectable(lbl.c_str(), is_selected)) {
                            skinMgr.setActiveSkin(skin.id);
                            if (app->settings()) {
                                app->settings()->setSkinId(skin.id);
                                app->settings()->save();
                            }
                        }
                        if (is_selected) ImGui::SetItemDefaultFocus();
                    }
                }
            }
        };

        if (wideLayout) {
            // ============================================================
            // Wide: 3 combos on one row + compact 3-column effects grid
            // ============================================================

            // --- Combo row: Theme | Layout | Language  [Refresh] ---
            {
                ImGui::PushFont(body2);
                float lblGap = Layout::spacingXs();
                float lblThemeW = ImGui::CalcTextSize(TR("theme")).x + lblGap;
                float lblLayoutW = ImGui::CalcTextSize(TR("balance_layout")).x + lblGap;
                float lblLangW = ImGui::CalcTextSize(TR("language")).x + lblGap;
                float totalFixed = lblThemeW + lblLayoutW + lblLangW
                                 + comboGap * 2 + Layout::spacingSm() + refreshBtnW;
                float comboW = std::max(80.0f, (contentW - totalFixed) / 3.0f);

                ImGui::AlignTextToFramePadding();
                ImGui::TextUnformatted(TR("theme"));
                ImGui::SameLine(0, lblGap);
                ImGui::SetNextItemWidth(comboW);
                if (ImGui::BeginCombo("##Theme", active_preview.c_str())) {
                    renderThemeComboPopup();
                    ImGui::EndCombo();
                }
                if (ImGui::IsItemHovered())
                    ImGui::SetTooltip("%s", TR("tt_theme_hotkey"));

                ImGui::SameLine(0, comboGap);
                ImGui::AlignTextToFramePadding();
                ImGui::TextUnformatted(TR("balance_layout"));
                ImGui::SameLine(0, lblGap);
                ImGui::SetNextItemWidth(comboW);
                if (ImGui::BeginCombo("##BalanceLayout", balPreview.c_str())) {
                    for (const auto& l : layouts) {
                        if (!l.enabled) continue;
                        bool selected = (l.id == s_settingsState.balance_layout);
                        if (ImGui::Selectable(l.name.c_str(), selected)) {
                            s_settingsState.balance_layout = l.id;
                            if (app->settings()) {
                                app->settings()->setBalanceLayout(s_settingsState.balance_layout);
                                app->settings()->save();
                            }
                        }
                        if (selected) ImGui::SetItemDefaultFocus();
                    }
                    ImGui::EndCombo();
                }
                if (ImGui::IsItemHovered())
                    ImGui::SetTooltip("%s", TR("tt_layout_hotkey"));

                ImGui::SameLine(0, comboGap);
                ImGui::AlignTextToFramePadding();
                ImGui::TextUnformatted(TR("language"));
                ImGui::SameLine(0, lblGap);
                ImGui::SetNextItemWidth(comboW);
                if (ImGui::Combo("##Language", &s_settingsState.language_index, lang_names.data(),
                                 static_cast<int>(lang_names.size()))) {
                    auto it = languages.begin();
                    std::advance(it, s_settingsState.language_index);
                    i18n.loadLanguage(it->first);
                    if (app->settings()) {
                        app->settings()->setLanguage(it->first);
                        app->settings()->save();
                    }
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_language"));

                ImGui::SameLine(0, Layout::spacingSm());
                if (TactileButton(TR("refresh"), ImVec2(refreshBtnW, 0), S.resolveFont("button"))) {
                    schema::SkinManager::instance().refresh();
                    Notifications::instance().info("Theme list refreshed");
                }
                if (ImGui::IsItemHovered()) {
                    ImGui::SetTooltip(TR("tt_scan_themes"),
                        schema::SkinManager::getUserSkinsDirectory().c_str());
                }
                ImGui::PopFont();
            }

            ImGui::Dummy(ImVec2(0, Layout::spacingSm()));

            // --- Font Scale slider (always visible) ---
            {
                ImGui::PushFont(body2);
                ImGui::TextUnformatted(TR("font_scale"));
                float fontSliderW = std::max(S.drawElement("components.settings-page", "effects-input-min-width").size, contentW);
                ImGui::SetNextItemWidth(fontSliderW);
                s_settingsState.font_scale = Layout::userFontScale();
                float prev_font_scale = s_settingsState.font_scale;
                {
                    char fs_fmt[16];
                    snprintf(fs_fmt, sizeof(fs_fmt), "%.2fx", s_settingsState.font_scale);
                    ImGui::SliderFloat("##FontScale", &s_settingsState.font_scale, 1.0f, 1.5f, fs_fmt,
                                       ImGuiSliderFlags_AlwaysClamp);
                }
                s_settingsState.font_scale = std::max(1.0f, std::min(1.5f,
                    std::round(s_settingsState.font_scale * 20.0f) / 20.0f));
                if (s_settingsState.font_scale != prev_font_scale)
                    Layout::setUserFontScaleVisual(s_settingsState.font_scale);
                if (ImGui::IsItemDeactivatedAfterEdit()) {
                    Layout::setUserFontScale(s_settingsState.font_scale);
                    saveSettingsPageState(app->settings());
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_font_scale"));
                ImGui::PopFont();
            }

            ImGui::Dummy(ImVec2(0, Layout::spacingSm()));

            // --- Collapsible: Advanced Effects... ---
            {
                const char* arrow = s_settingsState.effects_expanded ? ICON_MD_EXPAND_LESS : ICON_MD_EXPAND_MORE;
                ImGui::PushFont(body2);
                ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0,0,0,0));
                ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1,1,1,0.05f));
                ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1,1,1,0.08f));
                {
                    ImVec2 hdrPos = ImGui::GetCursorScreenPos();
                    if (ImGui::Button("##EffectsToggle", ImVec2(contentW, ImGui::GetFrameHeight()))) {
                        s_settingsState.effects_expanded = !s_settingsState.effects_expanded;
                    }
                    float textY = hdrPos.y + (ImGui::GetFrameHeight() - body2->LegacySize) * 0.5f;
                    dl->AddText(body2, body2->LegacySize, ImVec2(hdrPos.x, textY), OnSurfaceMedium(), TR("advanced_effects"));
                    ImFont* iconFont = Type().iconSmall();
                    if (!iconFont) iconFont = body2;
                    float arrowW = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, arrow).x;
                    dl->AddText(iconFont, iconFont->LegacySize, ImVec2(hdrPos.x + contentW - arrowW, textY), OnSurfaceMedium(), arrow);
                }
                ImGui::PopStyleColor(3);
                ImGui::PopFont();
            }

            if (s_settingsState.effects_expanded) {
                ImGui::PushFont(body2);

                // Checkbox row: Low-spec | Console scanline | Theme effects | Gradient background
                if (ImGui::Checkbox(TrId("low_spec_mode", "low_spec").c_str(), &s_settingsState.low_spec_mode)) {
                    effects::setLowSpecMode(s_settingsState.low_spec_mode);
                    if (s_settingsState.low_spec_mode) {
                        s_settingsState.low_spec_snapshot.valid = true;
                        s_settingsState.low_spec_snapshot.acrylic_enabled = s_settingsState.acrylic_enabled;
                        s_settingsState.low_spec_snapshot.blur_amount = s_settingsState.blur_amount;
                        s_settingsState.low_spec_snapshot.ui_opacity = s_settingsState.ui_opacity;
                        s_settingsState.low_spec_snapshot.window_opacity = s_settingsState.window_opacity;
                        s_settingsState.low_spec_snapshot.theme_effects_enabled = s_settingsState.theme_effects_enabled;
                        s_settingsState.low_spec_snapshot.scanline_enabled = s_settingsState.scanline_enabled;
                        s_settingsState.acrylic_enabled = false;
                        s_settingsState.blur_amount = 0.0f;
                        s_settingsState.ui_opacity = 1.0f;
                        s_settingsState.window_opacity = 1.0f;
                        s_settingsState.theme_effects_enabled = false;
                        s_settingsState.scanline_enabled = false;
                        effects::ImGuiAcrylic::ApplyBlurAmount(0.0f);
                        effects::ImGuiAcrylic::SetUIOpacity(1.0f);
                        effects::ThemeEffects::instance().setEnabled(false);
                        ConsoleTab::s_scanline_enabled = false;
                    } else if (s_settingsState.low_spec_snapshot.valid) {
                        s_settingsState.blur_amount = s_settingsState.low_spec_snapshot.blur_amount;
                        s_settingsState.acrylic_enabled = (s_settingsState.blur_amount > 0.001f);
                        s_settingsState.ui_opacity = s_settingsState.low_spec_snapshot.ui_opacity;
                        s_settingsState.window_opacity = s_settingsState.low_spec_snapshot.window_opacity;
                        s_settingsState.theme_effects_enabled = s_settingsState.low_spec_snapshot.theme_effects_enabled;
                        s_settingsState.scanline_enabled = s_settingsState.low_spec_snapshot.scanline_enabled;
                        effects::ImGuiAcrylic::ApplyBlurAmount(s_settingsState.blur_amount);
                        effects::ImGuiAcrylic::SetUIOpacity(s_settingsState.ui_opacity);
                        effects::ThemeEffects::instance().setEnabled(s_settingsState.theme_effects_enabled);
                        ConsoleTab::s_scanline_enabled = s_settingsState.scanline_enabled;
                        s_settingsState.low_spec_snapshot.valid = false;
                    }
                    saveSettingsPageState(app->settings());
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_low_spec"));

                ImGui::SameLine(0, Layout::spacingLg());
                if (ImGui::Checkbox(TrId("simple_background", "simple_bg").c_str(), &s_settingsState.gradient_background)) {
                    schema::SkinManager::instance().setGradientMode(s_settingsState.gradient_background);
                    saveSettingsPageState(app->settings());
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_simple_bg"));

                ImGui::SameLine(0, Layout::spacingLg());
                if (ImGui::Checkbox(TrId("reduce_motion", "reduce_motion").c_str(), &s_settingsState.reduce_motion)) {
                    saveSettingsPageState(app->settings());
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_reduce_motion"));

                ImGui::BeginDisabled(s_settingsState.low_spec_mode);

                ImGui::SameLine(0, Layout::spacingLg());
                if (ImGui::Checkbox(TrId("console_scanline", "scanline").c_str(), &s_settingsState.scanline_enabled)) {
                    ConsoleTab::s_scanline_enabled = s_settingsState.scanline_enabled;
                    app->settings()->setScanlineEnabled(s_settingsState.scanline_enabled);
                    app->settings()->save();
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_scanline"));

                ImGui::SameLine(0, Layout::spacingLg());
                if (ImGui::Checkbox(TrId("theme_effects", "effects").c_str(), &s_settingsState.theme_effects_enabled)) {
                    effects::ThemeEffects::instance().setEnabled(s_settingsState.theme_effects_enabled);
                    saveSettingsPageState(app->settings());
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_theme_effects"));

                // Row 1: Acrylic preset slider + Noise slider (side by side, labels above)
                float effCtrlMinW = S.drawElement("components.settings-page", "effects-input-min-width").size;
                float halfW = (contentW - Layout::spacingLg()) * 0.5f;
                float ctrlW = std::max(effCtrlMinW, halfW);
                float baseX = ImGui::GetCursorScreenPos().x;
                float rightX = baseX + ctrlW + Layout::spacingLg();

                ImGui::TextUnformatted(TR("acrylic"));
                float row1Y = ImGui::GetCursorScreenPos().y;
                ImGui::SetNextItemWidth(ctrlW);
                {
                    char blur_fmt[16];
                    if (s_settingsState.blur_amount < 0.01f)
                        snprintf(blur_fmt, sizeof(blur_fmt), "%s", TR("slider_off"));
                    else
                        snprintf(blur_fmt, sizeof(blur_fmt), "%.0f%%%%", s_settingsState.blur_amount * 25.0f);
                    if (ImGui::SliderFloat("##AcrylicBlur", &s_settingsState.blur_amount, 0.0f, 4.0f, blur_fmt,
                                           ImGuiSliderFlags_AlwaysClamp)) {
                        if (s_settingsState.blur_amount > 0.0f && s_settingsState.blur_amount < 0.15f) s_settingsState.blur_amount = 0.0f;
                        s_settingsState.acrylic_enabled = (s_settingsState.blur_amount > 0.001f);
                        effects::ImGuiAcrylic::ApplyBlurAmount(s_settingsState.blur_amount);
                    }
                }
                if (ImGui::IsItemDeactivatedAfterEdit()) saveSettingsPageState(app->settings());
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_blur"));
                float afterRow1Y = ImGui::GetCursorScreenPos().y;

                float lblH = ImGui::GetTextLineHeight() + ImGui::GetStyle().ItemSpacing.y;
                ImGui::SetCursorScreenPos(ImVec2(rightX, row1Y - lblH));
                ImGui::TextUnformatted(TR("noise"));
                ImGui::SetCursorScreenPos(ImVec2(rightX, row1Y));
                ImGui::SetNextItemWidth(ctrlW);
                {
                    char noise_fmt[16];
                    if (s_settingsState.noise_opacity < 0.01f)
                        snprintf(noise_fmt, sizeof(noise_fmt), "%s", TR("slider_off"));
                    else
                        snprintf(noise_fmt, sizeof(noise_fmt), "%.0f%%%%", s_settingsState.noise_opacity * 100.0f);
                    if (ImGui::SliderFloat("##NoiseOpacity", &s_settingsState.noise_opacity, 0.0f, 1.0f, noise_fmt,
                                           ImGuiSliderFlags_AlwaysClamp)) {
                        effects::ImGuiAcrylic::SetNoiseOpacity(s_settingsState.noise_opacity);
                        saveSettingsPageState(app->settings());
                    }
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_noise"));

                ImGui::SetCursorScreenPos(ImVec2(baseX, afterRow1Y));

                ImGui::TextUnformatted(TR("ui_opacity"));
                float row2Y = ImGui::GetCursorScreenPos().y;
                ImGui::SetNextItemWidth(ctrlW);
                {
                    char uiop_fmt[16];
                    snprintf(uiop_fmt, sizeof(uiop_fmt), "%.0f%%%%", s_settingsState.ui_opacity * 100.0f);
                    if (ImGui::SliderFloat("##UIOpacity", &s_settingsState.ui_opacity, 0.3f, 1.0f, uiop_fmt,
                                           ImGuiSliderFlags_AlwaysClamp)) {
                        effects::ImGuiAcrylic::SetUIOpacity(s_settingsState.ui_opacity);
                        saveSettingsPageState(app->settings());
                    }
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_ui_opacity"));
                float afterRow2Y = ImGui::GetCursorScreenPos().y;

                ImGui::SetCursorScreenPos(ImVec2(rightX, row2Y - lblH));
                ImGui::TextUnformatted(TR("window_opacity"));
                ImGui::SetCursorScreenPos(ImVec2(rightX, row2Y));
                ImGui::SetNextItemWidth(ctrlW);
                {
                    char winop_fmt[16];
                    snprintf(winop_fmt, sizeof(winop_fmt), "%.0f%%%%", s_settingsState.window_opacity * 100.0f);
                    if (ImGui::SliderFloat("##WindowOpacity", &s_settingsState.window_opacity, 0.3f, 1.0f, winop_fmt,
                                           ImGuiSliderFlags_AlwaysClamp)) {
                        saveSettingsPageState(app->settings());
                    }
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_window_opacity"));

                ImGui::SetCursorScreenPos(ImVec2(baseX, afterRow2Y));

                ImGui::EndDisabled(); // low-spec
                ImGui::PopFont();
            } // s_settingsState.effects_expanded
        } else {
            // ============================================================
            // Narrow: stacked combos + 2-column effects (original layout)
            // ============================================================

            // --- Theme row ---
            {
                ImGui::PushFont(body2);
                ImGui::AlignTextToFramePadding();
                ImGui::TextUnformatted(TR("theme"));
                ImGui::SameLine(labelW);

                float themeComboW = std::max(S.drawElement("components.settings-page", "theme-combo-min-width").size,
                    availWidth - pad * 2 - labelW - refreshBtnW - Layout::spacingSm());
                ImGui::SetNextItemWidth(themeComboW);
                if (ImGui::BeginCombo("##Theme", active_preview.c_str())) {
                    renderThemeComboPopup();
                    ImGui::EndCombo();
                }
                if (ImGui::IsItemHovered())
                    ImGui::SetTooltip("%s", TR("tt_theme_hotkey"));
                if (active_is_custom) {
                    ImGui::SameLine();
                    ImGui::TextColored(ImVec4(0.4f, 0.8f, 1.0f, 1.0f), "*");
                    if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_custom_theme"));
                }
                ImGui::SameLine();
                if (TactileButton(TR("refresh"), ImVec2(refreshBtnW, 0), S.resolveFont("button"))) {
                    schema::SkinManager::instance().refresh();
                    Notifications::instance().info("Theme list refreshed");
                }
                if (ImGui::IsItemHovered()) {
                    ImGui::SetTooltip(TR("tt_scan_themes"),
                        schema::SkinManager::getUserSkinsDirectory().c_str());
                }
                ImGui::PopFont();
            }

            ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

            // --- Balance Layout row ---
            {
                ImGui::PushFont(body2);
                ImGui::AlignTextToFramePadding();
                ImGui::TextUnformatted(TR("balance_layout"));
                ImGui::SameLine(labelW);
                ImGui::SetNextItemWidth(std::max(180.0f, inputW));
                if (ImGui::BeginCombo("##BalanceLayout", balPreview.c_str())) {
                    for (const auto& l : layouts) {
                        if (!l.enabled) continue;
                        bool selected = (l.id == s_settingsState.balance_layout);
                        if (ImGui::Selectable(l.name.c_str(), selected)) {
                            s_settingsState.balance_layout = l.id;
                            if (app->settings()) {
                                app->settings()->setBalanceLayout(s_settingsState.balance_layout);
                                app->settings()->save();
                            }
                        }
                        if (selected) ImGui::SetItemDefaultFocus();
                    }
                    ImGui::EndCombo();
                }
                if (ImGui::IsItemHovered())
                    ImGui::SetTooltip("%s", TR("tt_layout_hotkey"));
                ImGui::PopFont();
            }

            ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

            // --- Language row ---
            {
                ImGui::PushFont(body2);
                ImGui::AlignTextToFramePadding();
                ImGui::TextUnformatted(TR("language"));
                ImGui::SameLine(labelW);
                ImGui::SetNextItemWidth(inputW);
                if (ImGui::Combo("##Language", &s_settingsState.language_index, lang_names.data(),
                                 static_cast<int>(lang_names.size()))) {
                    auto it = languages.begin();
                    std::advance(it, s_settingsState.language_index);
                    i18n.loadLanguage(it->first);
                    if (app->settings()) {
                        app->settings()->setLanguage(it->first);
                        app->settings()->save();
                    }
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_language"));
                ImGui::PopFont();
            }

            ImGui::Dummy(ImVec2(0, Layout::spacingSm()));

            // --- Font Scale slider (always visible) ---
            {
                ImGui::PushFont(body2);
                ImGui::TextUnformatted(TR("font_scale"));
                float fontSliderW = std::max(S.drawElement("components.settings-page", "effects-input-min-width").size,
                    availWidth - pad * 2);
                ImGui::SetNextItemWidth(fontSliderW);
                s_settingsState.font_scale = Layout::userFontScale();
                float prev_font_scale = s_settingsState.font_scale;
                {
                    char fs_fmt[16];
                    snprintf(fs_fmt, sizeof(fs_fmt), "%.2fx", s_settingsState.font_scale);
                    ImGui::SliderFloat("##FontScale", &s_settingsState.font_scale, 1.0f, 1.5f, fs_fmt,
                                       ImGuiSliderFlags_AlwaysClamp);
                }
                s_settingsState.font_scale = std::max(1.0f, std::min(1.5f,
                    std::round(s_settingsState.font_scale * 20.0f) / 20.0f));
                if (s_settingsState.font_scale != prev_font_scale)
                    Layout::setUserFontScaleVisual(s_settingsState.font_scale);
                if (ImGui::IsItemDeactivatedAfterEdit()) {
                    Layout::setUserFontScale(s_settingsState.font_scale);
                    saveSettingsPageState(app->settings());
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_font_scale"));
                ImGui::PopFont();
            }

            ImGui::Dummy(ImVec2(0, Layout::spacingSm()));

            // --- Collapsible: Advanced Effects... ---
            {
                const char* arrow = s_settingsState.effects_expanded ? ICON_MD_EXPAND_LESS : ICON_MD_EXPAND_MORE;
                ImGui::PushFont(body2);
                ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0,0,0,0));
                ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1,1,1,0.05f));
                ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1,1,1,0.08f));
                {
                    float narrowContentW = availWidth - pad * 2;
                    ImVec2 hdrPos = ImGui::GetCursorScreenPos();
                    if (ImGui::Button("##EffectsToggleN", ImVec2(narrowContentW, ImGui::GetFrameHeight()))) {
                        s_settingsState.effects_expanded = !s_settingsState.effects_expanded;
                    }
                    float textY = hdrPos.y + (ImGui::GetFrameHeight() - body2->LegacySize) * 0.5f;
                    dl->AddText(body2, body2->LegacySize, ImVec2(hdrPos.x, textY), OnSurfaceMedium(), TR("advanced_effects"));
                    ImFont* iconFont = Type().iconSmall();
                    if (!iconFont) iconFont = body2;
                    float arrowW = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, arrow).x;
                    dl->AddText(iconFont, iconFont->LegacySize, ImVec2(hdrPos.x + narrowContentW - arrowW, textY), OnSurfaceMedium(), arrow);
                }
                ImGui::PopStyleColor(3);
                ImGui::PopFont();
            }

            if (s_settingsState.effects_expanded) {
                ImGui::PushFont(body2);

                if (ImGui::Checkbox(TrId("low_spec_mode", "low_spec").c_str(), &s_settingsState.low_spec_mode)) {
                    effects::setLowSpecMode(s_settingsState.low_spec_mode);
                    if (s_settingsState.low_spec_mode) {
                        s_settingsState.low_spec_snapshot.valid = true;
                        s_settingsState.low_spec_snapshot.acrylic_enabled = s_settingsState.acrylic_enabled;
                        s_settingsState.low_spec_snapshot.blur_amount = s_settingsState.blur_amount;
                        s_settingsState.low_spec_snapshot.ui_opacity = s_settingsState.ui_opacity;
                        s_settingsState.low_spec_snapshot.window_opacity = s_settingsState.window_opacity;
                        s_settingsState.low_spec_snapshot.theme_effects_enabled = s_settingsState.theme_effects_enabled;
                        s_settingsState.low_spec_snapshot.scanline_enabled = s_settingsState.scanline_enabled;
                        s_settingsState.acrylic_enabled = false;
                        s_settingsState.blur_amount = 0.0f;
                        s_settingsState.ui_opacity = 1.0f;
                        s_settingsState.window_opacity = 1.0f;
                        s_settingsState.theme_effects_enabled = false;
                        s_settingsState.scanline_enabled = false;
                        effects::ImGuiAcrylic::ApplyBlurAmount(0.0f);
                        effects::ImGuiAcrylic::SetUIOpacity(1.0f);
                        effects::ThemeEffects::instance().setEnabled(false);
                        ConsoleTab::s_scanline_enabled = false;
                    } else if (s_settingsState.low_spec_snapshot.valid) {
                        s_settingsState.blur_amount = s_settingsState.low_spec_snapshot.blur_amount;
                        s_settingsState.acrylic_enabled = (s_settingsState.blur_amount > 0.001f);
                        s_settingsState.ui_opacity = s_settingsState.low_spec_snapshot.ui_opacity;
                        s_settingsState.window_opacity = s_settingsState.low_spec_snapshot.window_opacity;
                        s_settingsState.theme_effects_enabled = s_settingsState.low_spec_snapshot.theme_effects_enabled;
                        s_settingsState.scanline_enabled = s_settingsState.low_spec_snapshot.scanline_enabled;
                        effects::ImGuiAcrylic::ApplyBlurAmount(s_settingsState.blur_amount);
                        effects::ImGuiAcrylic::SetUIOpacity(s_settingsState.ui_opacity);
                        effects::ThemeEffects::instance().setEnabled(s_settingsState.theme_effects_enabled);
                        ConsoleTab::s_scanline_enabled = s_settingsState.scanline_enabled;
                        s_settingsState.low_spec_snapshot.valid = false;
                    }
                    saveSettingsPageState(app->settings());
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_low_spec"));

                if (ImGui::Checkbox(TrId("settings_gradient_bg", "gradient_bg").c_str(), &s_settingsState.gradient_background)) {
                    schema::SkinManager::instance().setGradientMode(s_settingsState.gradient_background);
                    saveSettingsPageState(app->settings());
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_simple_bg_alt"));

                if (ImGui::Checkbox(TrId("reduce_motion", "reduce_motion").c_str(), &s_settingsState.reduce_motion)) {
                    saveSettingsPageState(app->settings());
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_reduce_motion"));

                ImGui::BeginDisabled(s_settingsState.low_spec_mode);

                if (ImGui::Checkbox(TrId("console_scanline", "scanline").c_str(), &s_settingsState.scanline_enabled)) {
                    ConsoleTab::s_scanline_enabled = s_settingsState.scanline_enabled;
                    app->settings()->setScanlineEnabled(s_settingsState.scanline_enabled);
                    app->settings()->save();
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_scanline"));

                ImGui::SameLine(0, Layout::spacingLg());
                if (ImGui::Checkbox(TrId("theme_effects", "theme_fx").c_str(), &s_settingsState.theme_effects_enabled)) {
                    effects::ThemeEffects::instance().setEnabled(s_settingsState.theme_effects_enabled);
                    saveSettingsPageState(app->settings());
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_theme_effects"));

                float ctrlW = std::max(S.drawElement("components.settings-page", "effects-input-min-width").size,
                    availWidth - pad * 2.0f);
                ImGui::TextUnformatted(TR("acrylic"));
                ImGui::SetNextItemWidth(ctrlW);
                {
                    char blur_fmt[16];
                    if (s_settingsState.blur_amount < 0.01f)
                        snprintf(blur_fmt, sizeof(blur_fmt), "%s", TR("slider_off"));
                    else
                        snprintf(blur_fmt, sizeof(blur_fmt), "%.0f%%%%", s_settingsState.blur_amount * 25.0f);
                    if (ImGui::SliderFloat("##AcrylicBlur", &s_settingsState.blur_amount, 0.0f, 4.0f, blur_fmt,
                                           ImGuiSliderFlags_AlwaysClamp)) {
                        if (s_settingsState.blur_amount > 0.0f && s_settingsState.blur_amount < 0.15f) s_settingsState.blur_amount = 0.0f;
                        s_settingsState.acrylic_enabled = (s_settingsState.blur_amount > 0.001f);
                        effects::ImGuiAcrylic::ApplyBlurAmount(s_settingsState.blur_amount);
                    }
                }
                if (ImGui::IsItemDeactivatedAfterEdit()) saveSettingsPageState(app->settings());
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_blur"));

                ImGui::TextUnformatted(TR("noise"));
                ImGui::SetNextItemWidth(ctrlW);
                {
                    char noise_fmt[16];
                    if (s_settingsState.noise_opacity < 0.01f)
                        snprintf(noise_fmt, sizeof(noise_fmt), "%s", TR("slider_off"));
                    else
                        snprintf(noise_fmt, sizeof(noise_fmt), "%.0f%%%%", s_settingsState.noise_opacity * 100.0f);
                    if (ImGui::SliderFloat("##NoiseOpacity", &s_settingsState.noise_opacity, 0.0f, 1.0f, noise_fmt,
                                           ImGuiSliderFlags_AlwaysClamp)) {
                        effects::ImGuiAcrylic::SetNoiseOpacity(s_settingsState.noise_opacity);
                    }
                }
                if (ImGui::IsItemDeactivatedAfterEdit()) saveSettingsPageState(app->settings());
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_noise"));

                ImGui::TextUnformatted(TR("ui_opacity"));
                ImGui::SetNextItemWidth(ctrlW);
                {
                    char uiop_fmt[16];
                    snprintf(uiop_fmt, sizeof(uiop_fmt), "%.0f%%%%", s_settingsState.ui_opacity * 100.0f);
                    if (ImGui::SliderFloat("##UIOpacity", &s_settingsState.ui_opacity, 0.3f, 1.0f, uiop_fmt,
                                           ImGuiSliderFlags_AlwaysClamp)) {
                        effects::ImGuiAcrylic::SetUIOpacity(s_settingsState.ui_opacity);
                    }
                }
                if (ImGui::IsItemDeactivatedAfterEdit()) saveSettingsPageState(app->settings());
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_ui_opacity"));

                ImGui::TextUnformatted(TR("window_opacity"));
                ImGui::SetNextItemWidth(ctrlW);
                {
                    char winop_fmt[16];
                    snprintf(winop_fmt, sizeof(winop_fmt), "%.0f%%%%", s_settingsState.window_opacity * 100.0f);
                    if (ImGui::SliderFloat("##WindowOpacity", &s_settingsState.window_opacity, 0.3f, 1.0f, winop_fmt,
                                           ImGuiSliderFlags_AlwaysClamp)) {
                    }
                }
                if (ImGui::IsItemDeactivatedAfterEdit()) saveSettingsPageState(app->settings());
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_window_opacity"));

                ImGui::EndDisabled(); // low-spec
                ImGui::PopFont();
            } // s_settingsState.effects_expanded
        }

        // Bottom padding
        ImGui::Dummy(ImVec2(0, bottomPad));
        ImGui::Unindent(pad);

        // Draw glass panel behind content (auto-sized)
        ImVec2 cardMax(cardMin.x + availWidth, ImGui::GetCursorScreenPos().y);
        dl->ChannelsSetCurrent(0);
        DrawGlassPanel(dl, cardMin, cardMax, glassSpec);
        dl->ChannelsMerge();

        ImGui::SetCursorScreenPos(ImVec2(cardMin.x, cardMax.y));
        ImGui::Dummy(ImVec2(availWidth, 0));
    }

    ImGui::Dummy(ImVec2(0, gap));

    // ====================================================================
    // WALLET — card (privacy/daemon toggles + collapsible tools)
    // ====================================================================
    {
        Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("wallet"));
        ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

        ImVec2 cardMin = ImGui::GetCursorScreenPos();
        dl->ChannelsSplit(2);
        dl->ChannelsSetCurrent(1);
        ImGui::SetCursorScreenPos(ImVec2(cardMin.x, cardMin.y + pad));
        ImGui::Indent(pad);

        float contentW = availWidth - pad * 2;

        // Privacy, Network & Daemon checkboxes — all on one line, shrink text to fit
        {
            const bool showDaemonOptions = app->supportsFullNodeLifecycleActions();
            float cbSpacing = Layout::spacingMd();
            float fh = ImGui::GetFrameHeight();
            float inner = ImGui::GetStyle().ItemInnerSpacing.x;
            auto cbW = [&](const char* label) { return fh + inner + ImGui::CalcTextSize(label).x; };

            float totalW = cbW(TR("save_z_transactions")) + cbSpacing
                         + cbW(TR("auto_shield")) + cbSpacing
                         + cbW(TR("use_tor")) + cbSpacing;
            if (showDaemonOptions) {
                totalW += cbW(TR("keep_daemon")) + cbSpacing
                       + cbW(TR("stop_external")) + cbSpacing;
            }
            totalW += cbW(TR("verbose_logging"));
            float scale = (totalW > contentW) ? contentW / totalW : 1.0f;
            if (scale < 1.0f) ImGui::SetWindowFontScale(scale);
            float sp = cbSpacing * scale;

            ImGui::Checkbox(TrId("save_z_transactions", "save_ztx").c_str(), &s_settingsState.save_ztxs);
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_save_ztx"));
            ImGui::SameLine(0, sp);
            ImGui::Checkbox(TrId("auto_shield", "auto_shld").c_str(), &s_settingsState.auto_shield);
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_auto_shield"));
            ImGui::SameLine(0, sp);
            ImGui::Checkbox(TrId("use_tor", "tor").c_str(), &s_settingsState.use_tor);
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_tor"));
            if (showDaemonOptions) {
                ImGui::SameLine(0, sp);
                if (ImGui::Checkbox(TrId("keep_daemon", "keep_dmn").c_str(), &s_settingsState.keep_daemon_running)) {
                    saveSettingsPageState(app->settings());
                }
                if (ImGui::IsItemHovered())
                    ImGui::SetTooltip("%s", TR("tt_keep_daemon"));
                ImGui::SameLine(0, sp);
                if (ImGui::Checkbox(TrId("stop_external", "stop_ext").c_str(), &s_settingsState.stop_external_daemon)) {
                    saveSettingsPageState(app->settings());
                }
                if (ImGui::IsItemHovered())
                    ImGui::SetTooltip("%s", TR("tt_stop_external"));
            }
            ImGui::SameLine(0, sp);
            if (ImGui::Checkbox(TrId("verbose_logging", "verbose").c_str(), &s_settingsState.verbose_logging)) {
                dragonx::util::Logger::instance().setVerbose(s_settingsState.verbose_logging);
                saveSettingsPageState(app->settings());
            }
            if (ImGui::IsItemHovered())
                ImGui::SetTooltip("%s", TR("tt_verbose"));

            if (scale < 1.0f) ImGui::SetWindowFontScale(1.0f);
        }

        ImGui::Dummy(ImVec2(0, Layout::spacingSm()));

        // --- Collapsible: Tools & Actions... ---
        {
            const char* arrow = s_settingsState.tools_expanded ? ICON_MD_EXPAND_LESS : ICON_MD_EXPAND_MORE;
            ImGui::PushFont(body2);
            ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0,0,0,0));
            ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1,1,1,0.05f));
            ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1,1,1,0.08f));
            {
                ImVec2 hdrPos = ImGui::GetCursorScreenPos();
                if (ImGui::Button("##ToolsToggle", ImVec2(contentW, ImGui::GetFrameHeight()))) {
                    s_settingsState.tools_expanded = !s_settingsState.tools_expanded;
                }
                float textY = hdrPos.y + (ImGui::GetFrameHeight() - body2->LegacySize) * 0.5f;
                dl->AddText(body2, body2->LegacySize, ImVec2(hdrPos.x, textY), OnSurfaceMedium(), TR("tools_actions"));
                ImFont* iconFont = Type().iconSmall();
                if (!iconFont) iconFont = body2;
                float arrowW = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, arrow).x;
                dl->AddText(iconFont, iconFont->LegacySize, ImVec2(hdrPos.x + contentW - arrowW, textY), OnSurfaceMedium(), arrow);
            }
            ImGui::PopStyleColor(3);
            ImGui::PopFont();
        }

        if (s_settingsState.tools_expanded) {
            float btnSpacing = Layout::spacingMd();
            int btnsPerRow = (contentW >= 600.0f) ? 3 : 2;
            float bw = (contentW - btnSpacing * (btnsPerRow - 1)) / btnsPerRow;
            float minBtnW = S.drawElement("components.settings-page", "wallet-btn-min-width").sizeOr(100.0f);
            bw = std::max(minBtnW, bw);

            if (TactileButton(TR("settings_address_book"), ImVec2(bw, 0), S.resolveFont("button")))
                AddressBookDialog::show();
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_address_book"));
            ImGui::SameLine(0, btnSpacing);
            if (TactileButton(TR("settings_validate_address"), ImVec2(bw, 0), S.resolveFont("button")))
                ValidateAddressDialog::show();
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_validate"));
            if (btnsPerRow >= 3) { ImGui::SameLine(0, btnSpacing); } else { ImGui::Dummy(ImVec2(0, Layout::spacingXs())); }
            if (TactileButton(TR("settings_request_payment"), ImVec2(bw, 0), S.resolveFont("button")))
                RequestPaymentDialog::show();
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_request_payment"));
            if (btnsPerRow >= 3) { ImGui::Dummy(ImVec2(0, Layout::spacingXs())); } else { ImGui::SameLine(0, btnSpacing); }
            if (TactileButton(TR("settings_shield_mining"), ImVec2(bw, 0), S.resolveFont("button")))
                ShieldDialog::show(ShieldDialog::Mode::ShieldCoinbase);
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_shield_mining"));
            ImGui::SameLine(0, btnSpacing);
            if (TactileButton(TR("settings_merge_to_address"), ImVec2(bw, 0), S.resolveFont("button")))
                ShieldDialog::show(ShieldDialog::Mode::MergeToAddress);
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_merge"));
            if (btnsPerRow >= 3) { ImGui::SameLine(0, btnSpacing); } else { ImGui::Dummy(ImVec2(0, Layout::spacingXs())); }
            if (TactileButton(TR("settings_clear_ztx"), ImVec2(bw, 0), S.resolveFont("button"))) {
                s_settingsState.confirm_clear_ztx = true;
            }
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_clear_ztx"));
        }

        ImGui::Dummy(ImVec2(0, bottomPad));
        ImGui::Unindent(pad);

        ImVec2 cardMax(cardMin.x + availWidth, ImGui::GetCursorScreenPos().y);
        dl->ChannelsSetCurrent(0);
        DrawGlassPanel(dl, cardMin, cardMax, glassSpec);
        dl->ChannelsMerge();

        ImGui::SetCursorScreenPos(ImVec2(cardMin.x, cardMax.y));
        ImGui::Dummy(ImVec2(availWidth, 0));
    }

    ImGui::Dummy(ImVec2(0, gap));

    // ====================================================================
    // BACKUP & DATA — card
    // ====================================================================
    {
        Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("backup_data"));
        ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

        ImVec2 cardMin = ImGui::GetCursorScreenPos();
        dl->ChannelsSplit(2);
        dl->ChannelsSetCurrent(1);
        ImGui::SetCursorScreenPos(ImVec2(cardMin.x, cardMin.y + pad));
        ImGui::Indent(pad);

        float contentW = availWidth - pad * 2;
        float btnPad = S.drawElement("components.settings-page", "wallet-btn-padding").sizeOr(24.0f);

        {
            const char* r1[] = {TR("settings_import_key"), TR("settings_export_key"), TR("settings_export_all"), TR("settings_backup"), TR("settings_export_csv")};
            const char* t1[] = {
                TR("tt_import_key"),
                TR("tt_export_key"),
                TR("tt_export_all"),
                TR("tt_backup"),
                TR("tt_export_csv")
            };
            const bool showFullNodeLifecycleActions = app->supportsFullNodeLifecycleActions();
            const char* wizLabel = TR("setup_wizard");
            const char* bsLabel = TR("download_bootstrap");
            float sp = Layout::spacingSm();
            ImFont* btnFont = S.resolveFont("button");

            float btnPadX = btnPad * 2;
            float naturalW = 0;
            for (int i = 0; i < 5; i++)
                naturalW += ImGui::CalcTextSize(r1[i]).x + btnPadX;
            float wizW = showFullNodeLifecycleActions ? ImGui::CalcTextSize(wizLabel).x + btnPadX : 0.0f;
            float bsW = showFullNodeLifecycleActions ? ImGui::CalcTextSize(bsLabel).x + btnPadX : 0.0f;
            float totalW = naturalW + sp * 5;
            if (showFullNodeLifecycleActions) totalW += wizW + bsW + sp * 2;

            float scale = (totalW > contentW) ? contentW / totalW : 1.0f;
            if (scale < 1.0f) ImGui::SetWindowFontScale(scale);

            float scaledSp = sp * scale;

            if (TactileButton(r1[0], ImVec2(0, 0), btnFont))
                app->showImportKeyDialog();
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", t1[0]);
            ImGui::SameLine(0, scaledSp);
            if (TactileButton(r1[1], ImVec2(0, 0), btnFont))
                app->showExportKeyDialog();
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", t1[1]);
            ImGui::SameLine(0, scaledSp);
            if (TactileButton(r1[2], ImVec2(0, 0), btnFont))
                ExportAllKeysDialog::show();
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", t1[2]);
            ImGui::SameLine(0, scaledSp);
            if (TactileButton(r1[3], ImVec2(0, 0), btnFont))
                app->showBackupDialog();
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", t1[3]);
            ImGui::SameLine(0, scaledSp);
            if (TactileButton(r1[4], ImVec2(0, 0), btnFont))
                ExportTransactionsDialog::show();
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", t1[4]);

            if (showFullNodeLifecycleActions) {
                // Right-align Setup Wizard + Download Bootstrap
                float framePadX2 = ImGui::GetStyle().FramePadding.x * 2.0f;
                float curX = ImGui::GetCursorScreenPos().x;
                float wizBtnW = ImGui::CalcTextSize(wizLabel).x + framePadX2;
                float bsBtnW = ImGui::CalcTextSize(bsLabel).x + framePadX2;
                float rightEdge = cardMin.x + availWidth - pad;
                float rightGroupW = bsBtnW + scaledSp + wizBtnW;
                float groupX = rightEdge - rightGroupW;
                if (groupX > curX) {
                    ImGui::SameLine(0, 0);
                    ImGui::SetCursorScreenPos(ImVec2(groupX, ImGui::GetCursorScreenPos().y));
                } else {
                    ImGui::SameLine(0, scaledSp);
                }
                if (TactileButton(bsLabel, ImVec2(0, 0), btnFont))
                    BootstrapDownloadDialog::show(app);
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_download_bootstrap"));
                ImGui::SameLine(0, scaledSp);
                if (TactileButton(wizLabel, ImVec2(0, 0), btnFont))
                    app->restartWizard();
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_wizard"));
            }

            if (scale < 1.0f) ImGui::SetWindowFontScale(1.0f);
        }

        ImGui::Dummy(ImVec2(0, bottomPad));
        ImGui::Unindent(pad);

        ImVec2 cardMax(cardMin.x + availWidth, ImGui::GetCursorScreenPos().y);
        dl->ChannelsSetCurrent(0);
        DrawGlassPanel(dl, cardMin, cardMax, glassSpec);
        dl->ChannelsMerge();

        ImGui::SetCursorScreenPos(ImVec2(cardMin.x, cardMax.y));
        ImGui::Dummy(ImVec2(availWidth, 0));
    }

    ImGui::Dummy(ImVec2(0, gap));

    // ====================================================================
    // NODE & SECURITY — card
    // ====================================================================
    {
        Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("node_security"));
        ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

        ImVec2 cardMin = ImGui::GetCursorScreenPos();
        dl->ChannelsSplit(2);
        dl->ChannelsSetCurrent(1);
        ImGui::SetCursorScreenPos(ImVec2(cardMin.x, cardMin.y + pad));
        ImGui::Indent(pad);

        float contentW = availWidth - pad * 2;
        float minBtnW = S.drawElement("components.settings-page", "wallet-btn-min-width").sizeOr(130.0f);
        float btnPad = S.drawElement("components.settings-page", "wallet-btn-padding").sizeOr(24.0f);
        auto rowBtnW = [&](std::initializer_list<const char*> labels) -> float {
            float maxTextW = 0;
            for (auto* l : labels) maxTextW = std::max(maxTextW, ImGui::CalcTextSize(l).x);
            return std::max(minBtnW, maxTextW + btnPad * 2);
        };

        // --- NODE (left) + SECURITY (right) side by side ---
        {
            float colGap = Layout::spacingLg();
            float leftColW = (contentW - colGap) * 0.6f;
            float rightColW = (contentW - colGap) * 0.4f;
            ImVec2 sectionOrigin = ImGui::GetCursorScreenPos();
            float leftX = sectionOrigin.x;
            float rightX = sectionOrigin.x + leftColW + colGap;

            // ---- LEFT COLUMN: NODE ----
            ImGui::SetCursorScreenPos(ImVec2(leftX, sectionOrigin.y));
            ImGui::PushClipRect(ImVec2(leftX, sectionOrigin.y),
                                ImVec2(leftX + leftColW, sectionOrigin.y + 9999), true);

            Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("node"));
            ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

            {
                ImFont* body2Info = S.resolveFont("body2");
                if (!body2Info) body2Info = Type().body2();
                ImGui::PushFont(body2Info);

                if (app->isLiteBuild()) {
                    float liteLabelW = std::min(leftColW * 0.35f, 132.0f);
                    float liteInputW = std::max(80.0f, leftColW - liteLabelW - Layout::spacingSm());
                    const char* modeLabels[] = {"Sticky", "Random"};

                    ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                    ImGui::AlignTextToFramePadding();
                    ImGui::TextUnformatted("Mode");
                    ImGui::SameLine(leftX - sectionOrigin.x + liteLabelW);
                    ImGui::SetNextItemWidth(liteInputW);
                    if (ImGui::BeginCombo("##LiteServerMode", modeLabels[s_settingsState.lite_server_mode == 1 ? 1 : 0])) {
                        for (int modeIndex = 0; modeIndex < 2; ++modeIndex) {
                            const bool selected = s_settingsState.lite_server_mode == modeIndex;
                            if (ImGui::Selectable(modeLabels[modeIndex], selected)) {
                                s_settingsState.lite_server_mode = modeIndex;
                                saveLiteServerSelectionFromPageState(app);
                            }
                            if (selected) ImGui::SetItemDefaultFocus();
                        }
                        ImGui::EndCombo();
                    }

                    ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                    ImGui::AlignTextToFramePadding();
                    ImGui::TextUnformatted("Preset");
                    ImGui::SameLine(leftX - sectionOrigin.x + liteLabelW);
                    std::string presetPreview = s_settingsState.lite_server_url[0] != '\0'
                        ? std::string(s_settingsState.lite_server_url)
                        : std::string("Select");
                    for (const auto& server : s_settingsState.lite_servers) {
                        if (server.url == s_settingsState.lite_server_url && !server.label.empty()) {
                            presetPreview = server.label;
                            break;
                        }
                    }
                    ImGui::SetNextItemWidth(liteInputW);
                    if (ImGui::BeginCombo("##LiteServerPreset", presetPreview.c_str())) {
                        for (const auto& server : s_settingsState.lite_servers) {
                            if (!server.enabled) continue;
                            const std::string label = server.label.empty() ? server.url : server.label;
                            const bool selected = server.url == s_settingsState.lite_server_url;
                            if (ImGui::Selectable(label.c_str(), selected)) {
                                copyToSettingsBuffer(s_settingsState.lite_server_url,
                                                     sizeof(s_settingsState.lite_server_url),
                                                     server.url);
                                s_settingsState.lite_server_mode = 0;
                                saveLiteServerSelectionFromPageState(app);
                            }
                            if (selected) ImGui::SetItemDefaultFocus();
                        }
                        ImGui::EndCombo();
                    }

                    ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                    ImGui::AlignTextToFramePadding();
                    ImGui::TextUnformatted("Server");
                    ImGui::SameLine(leftX - sectionOrigin.x + liteLabelW);
                    ImGui::SetNextItemWidth(liteInputW);
                    ImGui::InputText("##LiteServerUrl", s_settingsState.lite_server_url,
                                     sizeof(s_settingsState.lite_server_url));
                    if (ImGui::IsItemDeactivatedAfterEdit()) {
                        s_settingsState.lite_server_mode = 0;
                        saveLiteServerSelectionFromPageState(app);
                    }

                    if (s_settingsState.lite_server_mode == 1) {
                        ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                        ImGui::AlignTextToFramePadding();
                        ImGui::TextUnformatted("Seed");
                        ImGui::SameLine(leftX - sectionOrigin.x + liteLabelW);
                        ImGui::SetNextItemWidth(std::min(160.0f, liteInputW));
                        if (ImGui::InputInt("##LiteRandomSeed", &s_settingsState.lite_random_seed)) {
                            if (s_settingsState.lite_random_seed < 0) s_settingsState.lite_random_seed = 0;
                        }
                        if (ImGui::IsItemDeactivatedAfterEdit()) saveLiteServerSelectionFromPageState(app);
                    }

                    ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                    if (ImGui::Checkbox("Persist selected server##LitePersistServer",
                                        &s_settingsState.lite_persist_selected_server)) {
                        saveLiteServerSelectionFromPageState(app);
                    }

                    if (!s_settingsState.lite_server_status.empty()) {
                        Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(),
                                           s_settingsState.lite_server_status.c_str());
                    }

                    ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
                    if (ImGui::Button("Lite wallet request##LiteLifecycleToggle", ImVec2(liteInputW, 0))) {
                        s_settingsState.lite_lifecycle_expanded = !s_settingsState.lite_lifecycle_expanded;
                    }

                    if (s_settingsState.lite_lifecycle_expanded) {
                        const char* lifecycleLabels[] = {"Create", "Open", "Restore"};
                        ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                        ImGui::AlignTextToFramePadding();
                        ImGui::TextUnformatted("Action");
                        ImGui::SameLine(leftX - sectionOrigin.x + liteLabelW);
                        ImGui::SetNextItemWidth(liteInputW);
                        if (ImGui::BeginCombo("##LiteLifecycleOperation",
                                              lifecycleLabels[std::max(0, std::min(2, s_settingsState.lite_lifecycle_operation))])) {
                            for (int operationIndex = 0; operationIndex < 3; ++operationIndex) {
                                const bool selected = s_settingsState.lite_lifecycle_operation == operationIndex;
                                if (ImGui::Selectable(lifecycleLabels[operationIndex], selected)) {
                                    s_settingsState.lite_lifecycle_operation = operationIndex;
                                    s_settingsState.lite_lifecycle_status.clear();
                                    s_settingsState.lite_lifecycle_summary.clear();
                                }
                                if (selected) ImGui::SetItemDefaultFocus();
                            }
                            ImGui::EndCombo();
                        }

                        if (s_settingsState.lite_lifecycle_operation == 1 ||
                            s_settingsState.lite_lifecycle_operation == 2) {
                            ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                            ImGui::AlignTextToFramePadding();
                            ImGui::TextUnformatted("Wallet");
                            ImGui::SameLine(leftX - sectionOrigin.x + liteLabelW);
                            ImGui::SetNextItemWidth(liteInputW);
                            ImGui::InputText("##LiteWalletPath", s_settingsState.lite_wallet_path,
                                             sizeof(s_settingsState.lite_wallet_path));
                        }

                        if (s_settingsState.lite_lifecycle_operation == 2) {
                            ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                            ImGui::AlignTextToFramePadding();
                            ImGui::TextUnformatted("Seed");
                            ImGui::SameLine(leftX - sectionOrigin.x + liteLabelW);
                            ImGui::SetNextItemWidth(liteInputW);
                            ImGui::InputText("##LiteRestoreSeed", s_settingsState.lite_restore_seed,
                                             sizeof(s_settingsState.lite_restore_seed),
                                             ImGuiInputTextFlags_Password);

                            ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                            ImGui::AlignTextToFramePadding();
                            ImGui::TextUnformatted("Birthday");
                            ImGui::SameLine(leftX - sectionOrigin.x + liteLabelW);
                            ImGui::SetNextItemWidth(std::min(160.0f, liteInputW));
                            ImGui::InputInt("##LiteRestoreBirthday", &s_settingsState.lite_restore_birthday);
                            if (s_settingsState.lite_restore_birthday < 0) s_settingsState.lite_restore_birthday = 0;

                            ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                            ImGui::AlignTextToFramePadding();
                            ImGui::TextUnformatted("Account");
                            ImGui::SameLine(leftX - sectionOrigin.x + liteLabelW);
                            ImGui::SetNextItemWidth(std::min(160.0f, liteInputW));
                            ImGui::InputInt("##LiteRestoreAccount", &s_settingsState.lite_restore_account);
                            if (s_settingsState.lite_restore_account < 0) s_settingsState.lite_restore_account = 0;

                            ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                            ImGui::Checkbox("Overwrite##LiteRestoreOverwrite",
                                            &s_settingsState.lite_restore_overwrite);
                        }

                        ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                        ImGui::AlignTextToFramePadding();
                        ImGui::TextUnformatted("Passphrase");
                        ImGui::SameLine(leftX - sectionOrigin.x + liteLabelW);
                        ImGui::SetNextItemWidth(liteInputW);
                        ImGui::InputText("##LiteLifecyclePassphrase",
                                         s_settingsState.lite_lifecycle_passphrase,
                                         sizeof(s_settingsState.lite_lifecycle_passphrase),
                                         ImGuiInputTextFlags_Password);

                        ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                        if (TactileButton("Validate##LiteLifecycleValidate", ImVec2(0, 0), S.resolveFont("button"))) {
                            evaluateLiteLifecycleRequestFromPageState(app);
                        }

                        if (!s_settingsState.lite_lifecycle_status.empty()) {
                            ImGui::SameLine(0, Layout::spacingSm());
                            Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(),
                                               s_settingsState.lite_lifecycle_status.c_str());
                        }
                        if (!s_settingsState.lite_lifecycle_summary.empty()) {
                            Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(),
                                               s_settingsState.lite_lifecycle_summary.c_str());
                        }
                    }
                } else {

                float rpcLblW = std::max(
                    S.drawElement("components.settings-page", "rpc-label-min-width").size,
                    std::min(leftColW * 0.35f, S.drawElement("components.settings-page", "rpc-label-width").size * hs));

                std::string wallet_path = util::Platform::getDragonXDataDir() + "wallet.dat";
                uint64_t wallet_size = util::Platform::getFileSize(wallet_path);

                // Data Dir + Wallet Size — same line with "Label: value" format
                ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                ImGui::AlignTextToFramePadding();
                {
                    // Measure the wallet size string first
                    std::string size_str = (wallet_size > 0) ? util::Platform::formatFileSize(wallet_size) : TR("settings_not_found");
                    std::string dirPath = util::Platform::getDragonXDataDir();

                    // Calculate space taken by "Wallet Size: <size>" on the right
                    float walletSizeLabelW = ImGui::CalcTextSize(TR("settings_wallet_size_label")).x + Layout::spacingXs();
                    float walletSizeValW = ImGui::CalcTextSize(size_str.c_str()).x;
                    float walletSizeTotalW = walletSizeLabelW + walletSizeValW + Layout::spacingLg();

                    // Available space for "Data Dir: <path>"
                    float dataDirLabelW = ImGui::CalcTextSize(TR("settings_data_dir")).x + Layout::spacingXs();
                    float availForPath = leftColW - walletSizeTotalW - dataDirLabelW;

                    ImGui::TextUnformatted(TR("settings_data_dir"));
                    ImGui::SameLine(0, Layout::spacingXs());
                    ImVec2 pathSize = ImGui::CalcTextSize(dirPath.c_str());
                    ImVec4 linkCol = ImGui::ColorConvertU32ToFloat4(Primary());
                    ImVec4 linkHoverCol = linkCol;
                    linkHoverCol.w = std::min(1.0f, linkCol.w + 0.2f);
                    bool hovered = false;
                    if (pathSize.x > availForPath && availForPath > 0) {
                        float scale = availForPath / pathSize.x;
                        float condensedSize = body2Info->LegacySize * std::max(scale, 0.65f);
                        ImGui::SetWindowFontScale(condensedSize / body2Info->LegacySize);
                        ImGui::AlignTextToFramePadding();
                        ImGui::TextColored(linkCol, "%s", dirPath.c_str());
                        hovered = ImGui::IsItemHovered();
                        if (hovered) {
                            ImVec2 tMin = ImGui::GetItemRectMin();
                            ImVec2 tMax = ImGui::GetItemRectMax();
                            dl->AddLine(ImVec2(tMin.x, tMax.y), ImVec2(tMax.x, tMax.y), ImGui::GetColorU32(linkHoverCol));
                        }
                        ImGui::SetWindowFontScale(1.0f);
                    } else {
                        ImGui::TextColored(linkCol, "%s", dirPath.c_str());
                        hovered = ImGui::IsItemHovered();
                        if (hovered) {
                            ImVec2 tMin = ImGui::GetItemRectMin();
                            ImVec2 tMax = ImGui::GetItemRectMax();
                            dl->AddLine(ImVec2(tMin.x, tMax.y), ImVec2(tMax.x, tMax.y), ImGui::GetColorU32(linkHoverCol));
                        }
                    }
                    if (hovered) {
                        ImGui::SetTooltip("%s", TR("tt_open_dir"));
                        ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
                    }
                    if (ImGui::IsItemClicked())
                        util::Platform::openFolder(dirPath);

                    ImGui::SameLine(0, Layout::spacingLg());
                    ImGui::TextUnformatted(TR("settings_wallet_size_label"));
                    ImGui::SameLine(0, Layout::spacingXs());
                    if (wallet_size > 0) {
                        ImGui::TextUnformatted(size_str.c_str());
                    } else {
                        ImGui::TextDisabled("%s", TR("settings_not_found"));
                    }
                }

                ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

                // RPC connection — two columns: (Host | Username) and (Port | Password)
                float rpcHalfW = (leftColW - Layout::spacingMd()) * 0.5f;
                float rpcHalfLblW = std::min(rpcLblW, rpcHalfW * 0.4f);
                float rpcHalfInputW = std::max(40.0f, rpcHalfW - rpcHalfLblW);
                float rpcRightColX = leftX + rpcHalfW + Layout::spacingMd();

                // Row 1: RPC Host + Username
                float row1Y = ImGui::GetCursorScreenPos().y;
                ImGui::SetCursorScreenPos(ImVec2(leftX, row1Y));
                ImGui::AlignTextToFramePadding();
                ImGui::TextUnformatted(TR("rpc_host"));
                ImGui::SameLine(leftX - sectionOrigin.x + rpcHalfLblW);
                ImGui::SetNextItemWidth(rpcHalfInputW);
                ImGui::InputText("##RPCHost", s_settingsState.rpc_host, sizeof(s_settingsState.rpc_host));
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_rpc_host"));

                float afterRow1Y = ImGui::GetCursorScreenPos().y;
                ImGui::SetCursorScreenPos(ImVec2(rpcRightColX, row1Y));
                ImGui::AlignTextToFramePadding();
                ImGui::TextUnformatted(TR("rpc_user"));
                ImGui::SameLine(rpcRightColX - sectionOrigin.x + rpcHalfLblW);
                ImGui::SetNextItemWidth(rpcHalfInputW);
                ImGui::InputText("##RPCUser", s_settingsState.rpc_user, sizeof(s_settingsState.rpc_user));
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_rpc_user"));

                ImGui::SetCursorScreenPos(ImVec2(leftX, std::max(afterRow1Y, ImGui::GetCursorScreenPos().y)));

                // Row 2: Port + Password
                float row2Y = ImGui::GetCursorScreenPos().y;
                ImGui::SetCursorScreenPos(ImVec2(leftX, row2Y));
                ImGui::AlignTextToFramePadding();
                ImGui::TextUnformatted(TR("rpc_port"));
                ImGui::SameLine(leftX - sectionOrigin.x + rpcHalfLblW);
                ImGui::SetNextItemWidth(rpcHalfInputW);
                ImGui::InputText("##RPCPort", s_settingsState.rpc_port, sizeof(s_settingsState.rpc_port));
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_rpc_port"));

                float afterRow2Y = ImGui::GetCursorScreenPos().y;
                ImGui::SetCursorScreenPos(ImVec2(rpcRightColX, row2Y));
                ImGui::AlignTextToFramePadding();
                ImGui::TextUnformatted(TR("rpc_pass"));
                ImGui::SameLine(rpcRightColX - sectionOrigin.x + rpcHalfLblW);
                ImGui::SetNextItemWidth(rpcHalfInputW);
                ImGui::InputText("##RPCPassword", s_settingsState.rpc_password, sizeof(s_settingsState.rpc_password),
                                 ImGuiInputTextFlags_Password);
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_rpc_pass"));

                ImGui::SetCursorScreenPos(ImVec2(leftX, std::max(afterRow2Y, ImGui::GetCursorScreenPos().y)));

                ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(),
                    TR("settings_auto_detected"));
                if (s_settingsState.rpc_plaintext_remote) {
                    ImGui::PushStyleColor(ImGuiCol_Text, ImGui::ColorConvertU32ToFloat4(Warning()));
                    ImGui::PushTextWrapPos(leftX + leftColW);
                    ImGui::TextWrapped("Remote RPC is using plaintext HTTP. Add rpctls=1 to DRAGONX.conf if your daemon supports TLS.");
                    ImGui::PopTextWrapPos();
                    ImGui::PopStyleColor();
                }

                ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
                // Node maintenance buttons (full-node build only)
                if (app->supportsFullNodeLifecycleActions()) {
                    ImFont* btnFont = S.resolveFont("button");
                    float nodeBtnW;
                    {
                        if (btnFont) ImGui::PushFont(btnFont);
                        nodeBtnW = rowBtnW({TR("test_connection"), TR("rescan")});
                        if (btnFont) ImGui::PopFont(/* btnFont */);
                    }
                    ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y));
                    ImGui::BeginDisabled(!app->isConnected());
                    if (TactileButton(TR("test_connection"), ImVec2(nodeBtnW, 0), btnFont)) {
                        if (app->rpc() && app->rpc()->isConnected() && app->worker()) {
                            app->worker()->post([rpc = app->rpc()]() -> rpc::RPCWorker::MainCb {
                                try {
                                    rpc::RPCClient::TraceScope trace("Settings / Test connection");
                                    rpc->call("getinfo");
                                    return []() {
                                        Notifications::instance().success("RPC connection OK");
                                    };
                                } catch (const std::exception& e) {
                                    std::string err = e.what();
                                    return [err]() {
                                        Notifications::instance().error("RPC error: " + err);
                                    };
                                }
                            });
                        } else {
                            Notifications::instance().warning("Not connected to daemon");
                        }
                    }
                    if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) ImGui::SetTooltip("%s", TR("tt_test_conn"));
                    ImGui::SameLine(0, Layout::spacingMd());
                    if (TactileButton(TR("rescan"), ImVec2(nodeBtnW, 0), btnFont)) {
                        app->rescanBlockchain();
                    }
                    if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) ImGui::SetTooltip("%s", TR("tt_rescan"));
                    ImGui::EndDisabled();

                    // Delete blockchain button (always available when using embedded daemon)
                    ImGui::SetCursorScreenPos(ImVec2(leftX, ImGui::GetCursorScreenPos().y + Layout::spacingSm()));
                    ImGui::BeginDisabled(!app->isUsingEmbeddedDaemon());
                    if (TactileButton(TR("delete_blockchain"), ImVec2(0, 0), btnFont)) {
                        s_settingsState.confirm_delete_blockchain = true;
                    }
                    if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) ImGui::SetTooltip("%s", TR("tt_delete_blockchain"));
                    ImGui::EndDisabled();
                }

                }

                ImGui::PopFont();
            }

            float leftBottom = ImGui::GetCursorScreenPos().y;
            ImGui::PopClipRect();

            // ---- RIGHT COLUMN: SECURITY ----
            ImGui::SetCursorScreenPos(ImVec2(rightX, sectionOrigin.y));
            ImGui::PushClipRect(ImVec2(rightX, sectionOrigin.y),
                                ImVec2(rightX + rightColW, sectionOrigin.y + 9999), true);

            Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("security"));
            ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

            {
                // Encrypt / Change passphrase / Lock buttons
                bool isEncrypted = app->state().isEncrypted();
                bool isLocked = app->state().isLocked();

                float secBtnW = std::min(rowBtnW({TR("settings_encrypt_wallet"), TR("settings_change_passphrase"), TR("settings_lock_now")}), (rightColW - Layout::spacingMd()) * 0.5f);

                ImGui::SetCursorScreenPos(ImVec2(rightX, ImGui::GetCursorScreenPos().y));
                if (!isEncrypted) {
                    if (TactileButton(TR("settings_encrypt_wallet"), ImVec2(secBtnW, 0), S.resolveFont("button")))
                        app->showEncryptDialog();
                    if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_encrypt"));
                    ImGui::SameLine(0, Layout::spacingMd());
                    ImGui::TextColored(ImVec4(1,1,1,0.5f), "%s", TR("settings_not_encrypted"));
                } else {
                    if (TactileButton(TR("settings_change_passphrase"), ImVec2(secBtnW, 0), S.resolveFont("button")))
                        app->showChangePassphraseDialog();
                    if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_change_pass"));
                    ImGui::SameLine(0, Layout::spacingMd());
                    if (isLocked) {
                        ImGui::PushFont(Type().iconSmall());
                        ImGui::TextColored(ImVec4(1,0.7f,0.3f,1.0f), ICON_MD_LOCK);
                        ImGui::PopFont();
                        ImGui::SameLine(0, Layout::spacingXs());
                        ImGui::TextColored(ImVec4(1,0.7f,0.3f,1.0f), "%s", TR("settings_locked"));
                    } else {
                        if (TactileButton(TR("settings_lock_now"), ImVec2(secBtnW, 0), S.resolveFont("button")))
                            app->lockWallet();
                        if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_lock"));
                        ImGui::SameLine(0, Layout::spacingSm());
                        ImGui::PushFont(Type().iconSmall());
                        ImGui::TextColored(ImVec4(0.3f,1.0f,0.5f,1.0f), ICON_MD_LOCK_OPEN);
                        ImGui::PopFont();
                        ImGui::SameLine(0, Layout::spacingXs());
                        ImGui::TextColored(ImVec4(0.3f,1.0f,0.5f,1.0f), "%s", TR("settings_unlocked"));
                    }
                    // Remove Encryption button
                    ImGui::SetCursorScreenPos(ImVec2(rightX, ImGui::GetCursorScreenPos().y + Layout::spacingXs()));
                    if (TactileButton(TR("settings_remove_encryption"), ImVec2(secBtnW, 0), S.resolveFont("button")))
                        app->showDecryptDialog();
                    if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_remove_encrypt"));
                }

                ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

                // Auto-Lock timeout
                {
                    float comboW = S.drawElement("components.settings-page", "security-combo-width").sizeOr(120.0f);

                    int timeout = app->settings()->getAutoLockTimeout();
                    const char* timeoutLabels[] = { TR("timeout_off"), TR("timeout_1min"), TR("timeout_5min"), TR("timeout_15min"), TR("timeout_30min"), TR("timeout_1hour") };
                    int timeoutValues[] = { 0, 60, 300, 900, 1800, 3600 };
                    int selTimeout = 0;
                    for (int i = 0; i < 6; i++) {
                        if (timeoutValues[i] == timeout) { selTimeout = i; break; }
                    }
                    ImGui::SetCursorScreenPos(ImVec2(rightX, ImGui::GetCursorScreenPos().y));
                    Type().textColored(TypeStyle::Caption, OnSurfaceMedium(), TR("settings_auto_lock"));
                    ImGui::SetCursorScreenPos(ImVec2(rightX, ImGui::GetCursorScreenPos().y));
                    ImGui::PushItemWidth(comboW);
                    if (ImGui::Combo("##autolock", &selTimeout, timeoutLabels, 6)) {
                        app->settings()->setAutoLockTimeout(timeoutValues[selTimeout]);
                        app->settings()->save();
                    }
                    if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_auto_lock"));
                    ImGui::PopItemWidth();
                }

                ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

                // PIN unlock section
                bool isEncryptedPIN = app->state().isEncrypted();
                if (isEncryptedPIN) {
                    bool hasPIN = app->hasPinVault();
                    float pinBtnW = std::min(rowBtnW({TR("settings_set_pin"), TR("settings_change_pin"), TR("settings_remove_pin")}), (rightColW - Layout::spacingSm()) * 0.5f);

                    ImGui::SetCursorScreenPos(ImVec2(rightX, ImGui::GetCursorScreenPos().y));
                    if (!hasPIN) {
                        if (TactileButton(TR("settings_set_pin"), ImVec2(pinBtnW, 0), S.resolveFont("button")))
                            app->showPinSetupDialog();
                        if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_set_pin"));
                        ImGui::SameLine(0, Layout::spacingMd());
                        ImGui::TextColored(ImVec4(1,1,1,0.5f), "%s", TR("settings_quick_unlock_pin"));
                    } else {
                        if (TactileButton(TR("settings_change_pin"), ImVec2(pinBtnW, 0), S.resolveFont("button")))
                            app->showPinChangeDialog();
                        if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_change_pin"));
                        ImGui::SameLine(0, Layout::spacingSm());
                        if (TactileButton(TR("settings_remove_pin"), ImVec2(pinBtnW, 0), S.resolveFont("button")))
                            app->showPinRemoveDialog();
                        if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_remove_pin"));
                        ImGui::SameLine(0, Layout::spacingMd());
                        ImGui::PushFont(Type().iconSmall());
                        ImGui::TextColored(ImVec4(0.3f,1.0f,0.5f,1.0f), ICON_MD_DIALPAD);
                        ImGui::PopFont();
                        ImGui::SameLine(0, Layout::spacingXs());
                        ImGui::TextColored(ImVec4(0.3f,1.0f,0.5f,1.0f), "%s", TR("settings_pin_active"));
                    }
                } else {
                    ImGui::SetCursorScreenPos(ImVec2(rightX, ImGui::GetCursorScreenPos().y));
                    ImGui::TextColored(ImVec4(1,1,1,0.3f), "%s", TR("settings_encrypt_first_pin"));
                }
            }

            float rightBottom = ImGui::GetCursorScreenPos().y;
            ImGui::PopClipRect();

            // Advance cursor past both columns
            float maxBottom = std::max(leftBottom, rightBottom);
            ImGui::SetCursorScreenPos(ImVec2(sectionOrigin.x, maxBottom));
        }

        ImGui::Dummy(ImVec2(0, bottomPad));
        ImGui::Unindent(pad);

        ImVec2 cardMax(cardMin.x + availWidth, ImGui::GetCursorScreenPos().y);
        dl->ChannelsSetCurrent(0);
        DrawGlassPanel(dl, cardMin, cardMax, glassSpec);
        dl->ChannelsMerge();

        ImGui::SetCursorScreenPos(ImVec2(cardMin.x, cardMax.y));
        ImGui::Dummy(ImVec2(availWidth, 0));
    }

    ImGui::Dummy(ImVec2(0, gap));

    // ====================================================================
    // EXPLORER & OPTIONS — full-width card
    // ====================================================================
    {
        Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("explorer_section"));
        ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

        ImVec2 cardMin = ImGui::GetCursorScreenPos();
        dl->ChannelsSplit(2);
        dl->ChannelsSetCurrent(1);
        ImGui::SetCursorScreenPos(ImVec2(cardMin.x, cardMin.y + pad));
        ImGui::Indent(pad);

        float contentW = availWidth - pad * 2;
        ImGui::PushFont(body2);

        // Row 1: Transaction URL | Address URL  (side-by-side)
        float halfW = (contentW - Layout::spacingLg()) * 0.5f;
        float lblTxW = ImGui::CalcTextSize("Transaction URL").x + Layout::spacingXs();
        float lblAddrW = ImGui::CalcTextSize("Address URL").x + Layout::spacingXs();
        float inputTxW = std::max(80.0f, halfW - lblTxW);
        float inputAddrW = std::max(80.0f, halfW - lblAddrW);

        ImGui::AlignTextToFramePadding();
        ImGui::TextUnformatted(TR("transaction_url"));
        ImGui::SameLine(0, Layout::spacingXs());
        ImGui::SetNextItemWidth(inputTxW);
        ImGui::InputText("##TxExplorer", s_settingsState.tx_explorer, sizeof(s_settingsState.tx_explorer));
        if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_tx_url"));
        ImGui::SameLine(pad + halfW + Layout::spacingLg());
        ImGui::AlignTextToFramePadding();
        ImGui::TextUnformatted(TR("address_url"));
        ImGui::SameLine(0, Layout::spacingXs());
        ImGui::SetNextItemWidth(inputAddrW);
        ImGui::InputText("##AddrExplorer", s_settingsState.addr_explorer, sizeof(s_settingsState.addr_explorer));
        if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_addr_url"));

        ImGui::PopFont();
        ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

        // Row 2: Checkboxes + Block Explorer button  (on one line)
        ImGui::Checkbox(TrId("custom_fees", "custom_fees").c_str(), &s_settingsState.allow_custom_fees);
        if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_custom_fees"));
        ImGui::SameLine(0, Layout::spacingLg());
        ImGui::Checkbox(TrId("fetch_prices", "fetch_prices").c_str(), &s_settingsState.fetch_prices);
        if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_fetch_prices"));
        ImGui::SameLine(0, Layout::spacingLg());
        if (TactileButton(TR("block_explorer"), ImVec2(0, 0), S.resolveFont("button"))) {
            util::Platform::openUrl("https://explorer.dragonx.is");
        }
        if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_block_explorer"));

        ImGui::Dummy(ImVec2(0, bottomPad));
        ImGui::Unindent(pad);

        ImVec2 cardMax(cardMin.x + availWidth, ImGui::GetCursorScreenPos().y);
        dl->ChannelsSetCurrent(0);
        DrawGlassPanel(dl, cardMin, cardMax, glassSpec);
        dl->ChannelsMerge();

        ImGui::SetCursorScreenPos(ImVec2(cardMin.x, cardMax.y));
        ImGui::Dummy(ImVec2(availWidth, 0));
    }

    ImGui::Dummy(ImVec2(0, gap));

    // ====================================================================
    // ABOUT — card
    // ====================================================================
    {
        Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("about"));
        ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

        ImVec2 cardMin = ImGui::GetCursorScreenPos();
        dl->ChannelsSplit(2);
        dl->ChannelsSetCurrent(1);
        ImGui::SetCursorScreenPos(ImVec2(cardMin.x, cardMin.y + pad));
        ImGui::Indent(pad);

        // Logo on the left side of the about card
        ImTextureID logoTex = app->getLogoTexture();
        float logoAreaW = 0;
        if (logoTex != 0) {
            float logoMaxH = schema::UI().drawElement("components.settings-page", "about-logo-size").sizeOr(64.0f);
            float logoH = logoMaxH;
            float aspect = (app->getLogoHeight() > 0) ? (float)app->getLogoWidth() / (float)app->getLogoHeight() : 1.0f;
            float logoW = logoH * aspect;
            ImVec2 logoPos = ImGui::GetCursorScreenPos();
            dl->AddImage(logoTex,
                         ImVec2(logoPos.x, logoPos.y),
                         ImVec2(logoPos.x + logoW, logoPos.y + logoH));
            logoAreaW = logoW + Layout::spacingLg();
            ImGui::Indent(logoAreaW);
        }

        float contentW = availWidth - pad * 2 - logoAreaW;

        // App name + version on same line
        ImGui::PushFont(sub1);
        ImGui::TextUnformatted(DRAGONX_APP_NAME);
        ImGui::PopFont();
        ImGui::SameLine(0, Layout::spacingLg());
        ImGui::PushFont(body2);
        snprintf(buf, sizeof(buf), "v%s", DRAGONX_VERSION);
        ImGui::TextUnformatted(buf);
        ImGui::SameLine(0, Layout::spacingLg());
        snprintf(buf, sizeof(buf), "ImGui %s", IMGUI_VERSION);
        ImGui::TextColored(ImVec4(1,1,1,0.4f), "%s", buf);
        ImGui::PopFont();

        // Daemon version
        {
            const auto& st = app->state();
            if (st.daemon_version > 0) {
                int dmaj = st.daemon_version / 1000000;
                int dmin = (st.daemon_version / 10000) % 100;
                int dpat = (st.daemon_version / 100) % 100;
                ImGui::PushFont(body2);
                snprintf(buf, sizeof(buf), "%s: %d.%d.%d", TR("daemon_version"), dmaj, dmin, dpat);
                ImGui::TextColored(ImVec4(1,1,1,0.5f), "%s", buf);
                ImGui::PopFont();
            }
        }

        ImGui::Dummy(ImVec2(0, Layout::spacingSm()));

        ImGui::PushFont(body2);
        ImGui::PushTextWrapPos(cardMin.x + availWidth - pad - logoAreaW);
        ImGui::TextUnformatted(TR("settings_about_text"));
        ImGui::PopTextWrapPos();
        ImGui::PopFont();

        ImGui::Dummy(ImVec2(0, Layout::spacingSm()));

        ImGui::PushFont(capFont);
        ImGui::TextColored(ImVec4(1,1,1,0.5f), "%s", TR("settings_copyright"));
        ImGui::PopFont();

        ImGui::Dummy(ImVec2(0, Layout::spacingMd()));

        // Buttons — consistent equal-width row (full card width)
        if (logoAreaW > 0) {
            ImGui::Unindent(logoAreaW);
        }
        {
            float fullContentW = availWidth - pad * 2;
            float aboutBtnW = (fullContentW - Layout::spacingMd() * 3) / 4.0f;

            if (TactileButton(TrId("website", "about_website").c_str(), ImVec2(aboutBtnW, 0), S.resolveFont("button"))) {
                util::Platform::openUrl("https://dragonx.is");
            }
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_website"));
            ImGui::SameLine(0, Layout::spacingMd());
            if (TactileButton(TrId("report_bug", "about_bug").c_str(), ImVec2(aboutBtnW, 0), S.resolveFont("button"))) {
                util::Platform::openUrl("https://git.dragonx.is/dragonx/ObsidianDragon/issues");
            }
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_report_bug"));
            ImGui::SameLine(0, Layout::spacingMd());
            if (TactileButton(TrId("save_settings", "about_save").c_str(), ImVec2(aboutBtnW, 0), S.resolveFont("button"))) {
                saveSettingsPageState(app->settings());
                Notifications::instance().success("Settings saved");
            }
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_save_settings"));
            ImGui::SameLine(0, Layout::spacingMd());
            if (TactileButton(TrId("reset_to_defaults", "about_reset").c_str(), ImVec2(aboutBtnW, 0), S.resolveFont("button"))) {
                if (app->settings()) {
                    loadSettingsPageState(app->settings());
                    Notifications::instance().info("Settings reloaded from disk");
                }
            }
            if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_reset_settings"));
        }

        ImGui::Dummy(ImVec2(0, bottomPad));
        ImGui::Unindent(pad);

        ImVec2 cardMax(cardMin.x + availWidth, ImGui::GetCursorScreenPos().y);
        dl->ChannelsSetCurrent(0);
        DrawGlassPanel(dl, cardMin, cardMax, glassSpec);
        dl->ChannelsMerge();

        ImGui::SetCursorScreenPos(ImVec2(cardMin.x, cardMax.y));
        ImGui::Dummy(ImVec2(availWidth, 0));
    }

    ImGui::Dummy(ImVec2(0, gap));

    // ====================================================================
    // DEBUG LOGGING — collapsible card with glass styling
    // ====================================================================
    {
        // Clickable header row
        ImVec2 headerPos = ImGui::GetCursorScreenPos();
        const char* arrow = s_settingsState.debug_expanded ? ICON_MD_EXPAND_LESS : ICON_MD_EXPAND_MORE;
        ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0,0,0,0));
        ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1,1,1,0.05f));
        ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1,1,1,0.08f));
        if (ImGui::Button("##DebugToggle", ImVec2(availWidth, ImGui::GetFrameHeight()))) {
            s_settingsState.debug_expanded = !s_settingsState.debug_expanded;
        }
        if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", s_settingsState.debug_expanded ? TR("tt_debug_collapse") : TR("tt_debug_expand"));
        ImGui::PopStyleColor(3);

        // Draw overline label + arrow on top of the invisible button
        {
            ImFont* ovFont = Type().overline();
            float textY = headerPos.y + (ImGui::GetFrameHeight() - ovFont->LegacySize) * 0.5f;
            dl->AddText(ovFont, ovFont->LegacySize, ImVec2(headerPos.x, textY), OnSurfaceMedium(), TR("debug_logging"));
            // Use the icon font for the expand/collapse arrow
            ImFont* iconFont = Type().iconSmall();
            if (!iconFont) iconFont = ovFont;
            float arrowW = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, arrow).x;
            dl->AddText(iconFont, iconFont->LegacySize, ImVec2(headerPos.x + availWidth - arrowW - pad, textY), OnSurfaceMedium(), arrow);
        }

        if (s_settingsState.debug_expanded) {
            ImGui::Dummy(ImVec2(0, Layout::spacingXs()));

            ImVec2 cardMin = ImGui::GetCursorScreenPos();
            dl->ChannelsSplit(2);
            dl->ChannelsSetCurrent(1);
            ImGui::SetCursorScreenPos(ImVec2(cardMin.x, cardMin.y + pad));
            ImGui::Indent(pad);

            ImGui::TextColored(ImVec4(1,1,1,0.5f), "%s", TR("settings_debug_select"));
            ImGui::TextColored(ImVec4(1,1,1,0.35f), "%s", TR("settings_debug_restart_note"));
            ImGui::Dummy(ImVec2(0, Layout::spacingSm()));

            // The 22 dragonxd debug categories
            static const char* debugCats[] = {
                "addrman", "alert", "bench", "coindb", "db", "estimatefee",
                "http", "libevent", "lock", "mempool", "net",
                "paymentdisclosure", "pow", "proxy", "prune", "rand",
                "reindex", "rpc", "selectcoins", "tor", "zmq", "zrpc"
            };
            static const char* debugTips[] = {
                "Peer address tracking and management",
                "Alert system messages",
                "Benchmark timings for operations",
                "Coin database read/write operations",
                "Berkeley DB operations",
                "Fee estimation algorithm",
                "HTTP RPC server activity",
                "Libevent networking library",
                "Lock contention debugging",
                "Transaction memory pool activity",
                "Network connections and messages",
                "Payment disclosure protocol",
                "Proof-of-work mining activity",
                "SOCKS5 proxy connections",
                "Block pruning operations",
                "Random number generation",
                "Blockchain reindexing progress",
                "RPC command processing",
                "Coin selection for transactions",
                "Tor integration and circuit info",
                "ZeroMQ notification system",
                "Shielded (z-addr) RPC operations"
            };
            constexpr int numCats = sizeof(debugCats) / sizeof(debugCats[0]);

            // Render as a 4-column grid of checkboxes
            int columns = 4;
            float dbgContentW = availWidth - pad * 2.0f;
            float colW = dbgContentW / columns;

            for (int i = 0; i < numCats; i++) {
                if (i > 0 && (i % columns) != 0) {
                    ImGui::SameLine(pad + colW * (i % columns));
                }
                bool enabled = s_settingsState.debug_categories.count(debugCats[i]) > 0;
                if (ImGui::Checkbox(debugCats[i], &enabled)) {
                    if (enabled) {
                        s_settingsState.debug_categories.insert(debugCats[i]);
                    } else {
                        s_settingsState.debug_categories.erase(debugCats[i]);
                    }
                    s_settingsState.debug_cats_dirty = true;
                    saveSettingsPageState(app->settings());
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", debugTips[i]);
            }

            ImGui::Dummy(ImVec2(0, Layout::spacingSm()));

            // "Restart daemon" button — only active when categories changed
            if (s_settingsState.debug_cats_dirty && app->supportsFullNodeLifecycleActions()) {
                ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 218, 0, 255));
                ImFont* iconFont = Type().iconSmall();
                if (iconFont) {
                    ImGui::PushFont(iconFont);
                    ImGui::AlignTextToFramePadding();
                    ImGui::TextUnformatted(ICON_MD_INFO);
                    ImGui::PopFont();
                    ImGui::SameLine(0, Layout::spacingXs());
                }
                ImGui::AlignTextToFramePadding();
                ImGui::TextUnformatted(TR("settings_debug_changed"));
                ImGui::PopStyleColor();
                ImGui::SameLine();
                if (TactileButton(TR("settings_restart_daemon"), ImVec2(0, 0), S.resolveFont("button"))) {
                    s_settingsState.debug_cats_dirty = false;
                    app->restartDaemon();
                }
                if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", TR("tt_restart_daemon"));
            }

            ImGui::Dummy(ImVec2(0, bottomPad));
            ImGui::Unindent(pad);

            ImVec2 cardMax(cardMin.x + availWidth, ImGui::GetCursorScreenPos().y);
            dl->ChannelsSetCurrent(0);
            DrawGlassPanel(dl, cardMin, cardMax, glassSpec);
            dl->ChannelsMerge();

            ImGui::SetCursorScreenPos(ImVec2(cardMin.x, cardMax.y));
            ImGui::Dummy(ImVec2(availWidth, 0));
        }
    }

    // --- Shader-based scroll fade: unbind (restore ImGui's default shader) ---
    if (fadeH > 0.0f && !s_settingsState.low_spec_mode && s_settingsState.fade_shader.ready) {
        effects::ScrollFadeShader::addUnbind(dl);
    }

    // --- Vertex-based alpha fade for ForegroundDrawList theme effects ---
    // DrawGlassPanel draws rainbow borders, shimmer, specular glare, and
    // edge traces on the ForegroundDrawList which bypasses the shader.
    // Apply the same fade boundaries via vertex alpha manipulation.
    if (fadeH > 0.0f) {
        int fgVtxEnd = fgDL->VtxBuffer.Size;
        float safeTop = settingsFadeTopY + settingsFadeZoneTop;
        float safeBot = settingsFadeBottomY - settingsFadeZoneBot;
        for (int vi = fgVtxStart; vi < fgVtxEnd; vi++) {
            ImDrawVert& v = fgDL->VtxBuffer[vi];
            if (v.pos.y >= safeTop && v.pos.y <= safeBot)
                continue;
            float alpha = 1.0f;
            if (settingsFadeZoneTop > 0.0f) {
                float dTop = v.pos.y - settingsFadeTopY;
                if (dTop < settingsFadeZoneTop)
                    alpha = std::min(alpha, std::max(0.0f, dTop / settingsFadeZoneTop));
            }
            if (settingsFadeZoneBot > 0.0f) {
                float dBot = settingsFadeBottomY - v.pos.y;
                if (dBot < settingsFadeZoneBot)
                    alpha = std::min(alpha, std::max(0.0f, dBot / settingsFadeZoneBot));
            }
            if (alpha < 1.0f) {
                int a = (v.col >> IM_COL32_A_SHIFT) & 0xFF;
                a = static_cast<int>(a * alpha);
                v.col = (v.col & ~IM_COL32_A_MASK) | (static_cast<ImU32>(a) << IM_COL32_A_SHIFT);
            }
        }
    }

    ImGui::EndChild(); // ##SettingsPageScroll

    // Confirmation dialog for clearing z-tx history
    if (s_settingsState.confirm_clear_ztx) {
        if (BeginOverlayDialog(TR("confirm_clear_ztx_title"), &s_settingsState.confirm_clear_ztx, 480.0f, 0.94f)) {
            ImGui::PushFont(Type().iconLarge());
            ImGui::TextColored(ImVec4(1.0f, 0.6f, 0.0f, 1.0f), ICON_MD_WARNING);
            ImGui::PopFont();
            ImGui::SameLine();
            ImGui::TextColored(ImVec4(1.0f, 0.6f, 0.0f, 1.0f), "%s", TR("warning"));
            
            ImGui::Spacing();
            ImGui::TextWrapped("%s", TR("confirm_clear_ztx_warning1"));
            ImGui::Spacing();
            ImGui::TextWrapped("%s", TR("confirm_clear_ztx_warning2"));
            ImGui::Spacing();
            ImGui::Separator();
            ImGui::Spacing();
            
            float btnW = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.x) * 0.5f;
            if (ImGui::Button(TR("cancel"), ImVec2(btnW, 40))) {
                s_settingsState.confirm_clear_ztx = false;
            }
            ImGui::SameLine();
            ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.2f, 0.2f, 1.0f));
            ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.9f, 0.3f, 0.3f, 1.0f));
            if (ImGui::Button(TrId("clear_anyway", "clear_ztx_btn").c_str(), ImVec2(btnW, 40))) {
                std::string ztx_file = util::Platform::getDragonXDataDir() + "ztx_history.json";
                if (util::Platform::deleteFile(ztx_file)) {
                    Notifications::instance().success("Z-transaction history cleared");
                } else {
                    Notifications::instance().info("No history file found");
                }
                s_settingsState.confirm_clear_ztx = false;
            }
            ImGui::PopStyleColor(2);
            EndOverlayDialog();
        }
    }

    // Confirmation dialog for deleting blockchain data
    if (s_settingsState.confirm_delete_blockchain) {
        if (BeginOverlayDialog(TR("confirm_delete_blockchain_title"), &s_settingsState.confirm_delete_blockchain, 500.0f, 0.94f)) {
            ImGui::PushFont(Type().iconLarge());
            ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f), ICON_MD_WARNING);
            ImGui::PopFont();
            ImGui::SameLine();
            ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f), "%s", TR("warning"));
            
            ImGui::Spacing();
            ImGui::TextWrapped("%s", TR("confirm_delete_blockchain_msg"));
            ImGui::Spacing();
            ImGui::TextColored(ImVec4(0.3f, 0.8f, 0.3f, 1.0f), "%s", TR("confirm_delete_blockchain_safe"));
            ImGui::Spacing();
            ImGui::Separator();
            ImGui::Spacing();
            
            float btnW = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.x) * 0.5f;
            if (ImGui::Button(TR("cancel"), ImVec2(btnW, 40))) {
                s_settingsState.confirm_delete_blockchain = false;
            }
            ImGui::SameLine();
            ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.2f, 0.2f, 1.0f));
            ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.9f, 0.3f, 0.3f, 1.0f));
            if (ImGui::Button(TrId("delete_blockchain_confirm", "del_bc_btn").c_str(), ImVec2(btnW, 40))) {
                if (app->supportsFullNodeLifecycleActions())
                    app->deleteBlockchainData();
                s_settingsState.confirm_delete_blockchain = false;
            }
            ImGui::PopStyleColor(2);
            EndOverlayDialog();
        }
    }

}

} // namespace ui
} // namespace dragonx
