<?php
declare(strict_types=1);

$htmlAttributes = $localeContext->htmlAttributes();
$currentLocale = $htmlAttributes['lang'];
$languages = is_array($site['languages'] ?? null) ? $site['languages'] : [
    ['code' => 'ar', 'native_name' => 'العربية', 'name' => 'Arabic'],
    ['code' => 'en', 'native_name' => 'English', 'name' => 'English'],
];
// Settings -> General -> Site name is loaded into $site by the front
// controller, but the layout used to read only the app.name translation, so
// the field had no effect on any public page. The translation stays as the
// fallback for a site that never set one.
$applicationName = trim((string) ($site['name'] ?? ''));
if ($applicationName === '') {
    $applicationName = trim($translator->get('app.name'));
}
$documentTitle = $title === ''
    ? $applicationName
    : ($applicationName !== '' && str_contains($title, $applicationName) ? $title : $title . ' — ' . $applicationName);
$metaDescription = $metaDescription !== ''
    ? $metaDescription
    : (trim((string) ($site['description'] ?? '')) ?: $translator->get('home.intro'));
$canonical = $canonical ?? quaeriva_url();
$alternatePath = trim((string) ($alternatePath ?? ''));
$structuredData = is_array($structuredData ?? null) ? $structuredData : null;
$noIndex = !empty($noIndex);
$robotsMode = trim((string) ($robotsMode ?? ($noIndex ? 'noindex,follow' : 'index,follow')));
$ogImage = trim((string) ($ogImage ?? ''));
$twitterSite = trim((string) ($twitterSite ?? ''));
$googleVerification = trim((string) ($googleVerification ?? ''));
$bingVerification = trim((string) ($bingVerification ?? ''));
$customCodeHead = is_string($customCodeHead ?? null) ? $customCodeHead : '';
$customCodeBodyStart = is_string($customCodeBodyStart ?? null) ? $customCodeBodyStart : '';
$customCodeBodyEnd = is_string($customCodeBodyEnd ?? null) ? $customCodeBodyEnd : '';
$themeConfig = is_array($site['theme'] ?? null) ? $site['theme'] : [];
try {
    $themeAppearance = \App\Theme\ThemeAppearanceService::normalize($themeConfig, []);
} catch (Throwable) {
    $themeAppearance = \App\Theme\ThemeAppearanceService::defaults();
}
try {
    $themeTokens = \App\Theme\ThemeTokenService::normalize(
        is_array($site['theme_tokens'] ?? null) ? $site['theme_tokens'] : [],
        \App\Theme\ThemeTokenService::fromLegacyAppearance($themeAppearance)
    );
} catch (Throwable) {
    $themeTokens = \App\Theme\ThemeTokenService::fromLegacyAppearance($themeAppearance);
}
$layoutTokens = (array) ($themeTokens['layout'] ?? []);
$activeTheme = \App\Theme\ThemeManager::resolveActiveName((string) ($themeConfig['active'] ?? 'default'));
// The direction-specific stylesheet is optional; a theme without one is
$themeDirection = (string) ($htmlAttributes['dir'] ?? 'ltr');
$themeCssAssets = \App\Theme\ThemeManager::assets($activeTheme, 'css', $themeDirection);
$themeJsAssets = \App\Theme\ThemeManager::assets($activeTheme, 'js');
$brandText = trim((string) ($themeAppearance['brand_text'] ?? ''));
if ($brandText === '') {
    $brandText = $applicationName !== '' ? quaeriva_utf8_substr($applicationName, 0, 1) : 'Q';
}
$logoUrl = trim((string) ($themeAppearance['logo_url'] ?? ''));
$faviconUrl = trim((string) ($themeAppearance['favicon_url'] ?? ''));
$brandDisplayMode = (string) ($themeAppearance['brand_display_mode'] ?? 'logo_text');
if (!in_array($brandDisplayMode, \App\Theme\ThemeAppearanceService::BRAND_DISPLAY_MODES, true)) {
    $brandDisplayMode = 'logo_text';
}
// Logo-only still needs the site name in the accessibility tree, so the text is
// hidden visually rather than removed. Without a logo the mode is meaningless,
// and dropping the name would leave the link with no accessible name at all.
if ($logoUrl === '') {
    $brandDisplayMode = 'text_only';
}
$brandNameClass = $brandDisplayMode === 'logo_only' ? ' class="visually-hidden"' : '';
$mobileBottomNav = (string) ($themeAppearance['mobile_bottom_nav'] ?? '0') === '1';
$jsonLd = $structuredData === null
    ? ''
    : json_encode($structuredData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_THROW_ON_ERROR);
?>
<!doctype html>
<html lang="<?= quaeriva_escape($htmlAttributes['lang']) ?>" dir="<?= quaeriva_escape($htmlAttributes['dir']) ?>">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="<?= quaeriva_escape($metaDescription) ?>">
    <meta name="robots" content="<?= quaeriva_escape($robotsMode) ?>">
    <link rel="canonical" href="<?= quaeriva_escape($canonical) ?>">
    <?php if ($alternatePath !== '' && !$noIndex): ?>
        <?php foreach ($languages as $language): $alternateCode = trim((string) ($language['code'] ?? '')); if ($alternateCode === '') continue; ?>
            <link rel="alternate" hreflang="<?= quaeriva_escape($alternateCode) ?>" href="<?= quaeriva_escape(quaeriva_url($alternatePath, ['lang' => $alternateCode])) ?>">
        <?php endforeach; ?>
        <link rel="alternate" hreflang="x-default" href="<?= quaeriva_escape(quaeriva_url($alternatePath)) ?>">
    <?php endif; ?>
    <meta property="og:type" content="<?= $activeRoute === 'question' ? 'article' : 'website' ?>">
    <meta property="og:title" content="<?= quaeriva_escape($documentTitle) ?>">
    <meta property="og:description" content="<?= quaeriva_escape($metaDescription) ?>">
    <meta property="og:url" content="<?= quaeriva_escape($canonical) ?>">
    <meta property="og:site_name" content="<?= quaeriva_escape($applicationName) ?>">
    <?php
    $ogLocale = static function (string $code): string {
        $code = str_replace('-', '_', trim($code));
        if ($code === '') return '';

        $parts = explode('_', $code);
        $language = strtolower($parts[0]);

        $territories = [
            'en' => 'US', 'ja' => 'JP', 'zh' => 'CN', 'ko' => 'KR', 'hi' => 'IN',
            'fa' => 'IR', 'ur' => 'PK', 'he' => 'IL', 'el' => 'GR', 'cs' => 'CZ',
            'da' => 'DK', 'sv' => 'SE', 'uk' => 'UA', 'vi' => 'VN', 'ms' => 'MY',
        ];

        if (count($parts) > 1 && $parts[1] !== '') {
            return $language . '_' . strtoupper($parts[1]);
        }

        return $language . '_' . ($territories[$language] ?? strtoupper($language));
    };
    ?>
    <meta property="og:locale" content="<?= quaeriva_escape($ogLocale($currentLocale)) ?>">
    <?php foreach ($languages as $language): $altCode = (string) ($language['code'] ?? ''); if ($altCode === '' || $altCode === $currentLocale) continue; ?>
        <meta property="og:locale:alternate" content="<?= quaeriva_escape($ogLocale($altCode)) ?>">
    <?php endforeach; ?>
    <?php if ($ogImage !== ''): ?><meta property="og:image" content="<?= quaeriva_escape($ogImage) ?>"><?php endif; ?>
    <meta name="twitter:card" content="<?= $ogImage !== '' ? 'summary_large_image' : 'summary' ?>">
    <?php if ($twitterSite !== ''): ?><meta name="twitter:site" content="<?= quaeriva_escape($twitterSite) ?>"><?php endif; ?>
    <?php if ($googleVerification !== ''): ?><meta name="google-site-verification" content="<?= quaeriva_escape($googleVerification) ?>"><?php endif; ?>
    <?php if ($bingVerification !== ''): ?><meta name="msvalidate.01" content="<?= quaeriva_escape($bingVerification) ?>"><?php endif; ?>
    <title><?= quaeriva_escape($documentTitle) ?></title>
    <?= \App\Theme\ThemeAppearanceService::fontHeadTags((string) ($themeAppearance['font_stack'] ?? 'system')) ?>
    <link rel="stylesheet" href="<?= quaeriva_escape(quaeriva_url('assets/css/quaeriva.css', ['v' => quaeriva_asset_version('assets/css/quaeriva.css')])) ?>">
    <style><?= \App\Theme\ThemeAppearanceService::inlineStyle($themeAppearance) ?></style>
    <style data-theme-tokens><?= \App\Theme\ThemeTokenService::compileCss($themeTokens) ?></style>
    <?php $customThemeCss = \App\Theme\ThemeAppearanceService::customCss($themeAppearance); ?>
    <?php if ($customThemeCss !== ''): ?><style data-theme-custom-css><?= $customThemeCss ?></style><?php endif; ?>
    <?php if ($faviconUrl !== ''): ?>
        <link rel="icon" href="<?= quaeriva_escape($faviconUrl) ?>">
        <link rel="apple-touch-icon" href="<?= quaeriva_escape($faviconUrl) ?>">
    <?php endif; ?>
    <?php $themeColor = trim((string) ($themeAppearance['primary'] ?? '')); ?>
    <?php if (preg_match('/^#[0-9A-Fa-f]{6}$/', $themeColor) === 1): ?><meta name="theme-color" content="<?= quaeriva_escape($themeColor) ?>"><?php endif; ?>
    <?php foreach ($themeCssAssets as $asset): ?><link rel="stylesheet" href="<?= quaeriva_escape($asset['url']) ?>"><?php endforeach; ?>
    <?php if ($jsonLd !== ''): ?><script type="application/ld+json"><?= $jsonLd ?></script><?php endif; ?>
    <?php if ($customCodeHead !== ''): ?><?= $customCodeHead ?><?php endif; ?>
    <script>
    (function(){try{var m=localStorage.getItem('quaeriva_theme_mode');if(!m){m=window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';}document.documentElement.setAttribute('data-theme-mode',m);}catch(e){}})();
    </script>
</head>
<body class="page-<?= quaeriva_escape($activeRoute ?? 'home') ?> theme-<?= quaeriva_escape($activeTheme) ?><?= $mobileBottomNav ? ' has-bottom-nav' : '' ?>" data-home-layout="<?= quaeriva_escape($layoutTokens['home_preset'] ?? 'community') ?>" data-question-layout="<?= quaeriva_escape($layoutTokens['question_preset'] ?? 'classic') ?>" data-topic-layout="<?= quaeriva_escape($layoutTokens['topic_preset'] ?? 'discussion') ?>" data-header-layout="<?= quaeriva_escape($layoutTokens['header_preset'] ?? 'standard') ?>" data-density="<?= quaeriva_escape($layoutTokens['density'] ?? 'comfortable') ?>" data-sidebar-position="<?= quaeriva_escape($layoutTokens['sidebar_position'] ?? 'end') ?>">
    <?php if ($customCodeBodyStart !== ''): ?><?= $customCodeBodyStart ?><?php endif; ?>
    <?php /* Watched by an observer so the scroll-to-top button costs nothing per frame. */ ?>
    <div id="scroll-top-sentinel" aria-hidden="true"></div>
    <a class="skip-link" href="#main-content"><?= quaeriva_t($translator, 'common.skip_to_content') ?></a>

    <header class="site-header">
        <?php $headerTop = $renderSection('header_top'); ?>
        <?php if ($headerTop !== ''): ?><div class="container header-top"><?= $headerTop ?></div><?php endif; ?>
        <div class="container header-inner">
            <a class="brand" href="<?= quaeriva_escape(quaeriva_url()) ?>" title="<?= quaeriva_escape($applicationName) ?>">
                <?php if ($brandDisplayMode === 'text_only' && $logoUrl === ''): ?>
                    <span class="brand-mark" aria-hidden="true"><?= quaeriva_escape($brandText) ?></span>
                <?php elseif ($brandDisplayMode !== 'text_only'): ?>
                    <?php /* alt stays empty: the site name beside it is the link's accessible name. */ ?>
                    <img class="brand-logo" src="<?= quaeriva_escape($logoUrl) ?>" alt="" width="40" height="40" decoding="async">
                <?php endif; ?>
                <span<?= $brandNameClass ?>><?= quaeriva_escape($applicationName) ?></span>
            </a>

            <?php /* On a phone the search occupied a full row of the header. It
                     now collapses behind this toggle, which is hidden on wider
                     screens where the field itself is shown. */ ?>
            <button type="button" class="header-search-toggle icon-button" id="header-search-toggle" aria-expanded="false" aria-controls="header-search" aria-label="<?= quaeriva_t($translator, 'common.search') ?>">⌕</button>
            <form class="header-search" id="header-search" method="get" action="<?= quaeriva_escape(quaeriva_url('search')) ?>" role="search">
                <label class="visually-hidden" for="header-search-input"><?= quaeriva_t($translator, 'common.search') ?></label>
                <input id="header-search-input" name="q" type="search" dir="<?= quaeriva_escape($htmlAttributes['dir']) ?>" placeholder="<?= quaeriva_t($translator, 'common.search_placeholder') ?>" value="<?= quaeriva_escape($searchQuery ?? '') ?>">
                <button class="icon-button" type="submit" aria-label="<?= quaeriva_t($translator, 'common.search_submit') ?>">⌕</button>
            </form>

            <button class="menu-toggle" type="button" data-menu-toggle data-open-label="<?= quaeriva_t($translator, 'common.open_menu') ?>" data-close-label="<?= quaeriva_t($translator, 'common.close_menu') ?>" aria-expanded="false" aria-controls="site-navigation" aria-label="<?= quaeriva_t($translator, 'common.open_menu') ?>">
                <span aria-hidden="true">☰</span>
            </button>

            <nav class="site-nav" id="site-navigation" data-menu aria-label="<?= quaeriva_t($translator, 'common.menu') ?>">
                <?php
                // Managed menu items replace the built-in links only once the
                // menu table actually has visible rows. The Create control is
                // anchored to the managed /ask row, so its saved position is
                // visible in the public header too.
                $navItems = (array) ($menuItems ?? []);
                $navHasAsk = false;
                if ($navItems !== []):
                    foreach ($navItems as $navItem):
                        $navLabel = trim((string) ($navItem['label'] ?? ''));
                        if ($navLabel === '' && ($navItem['translation_key'] ?? '') !== '') {
                            $navLabel = $translator->get((string) $navItem['translation_key']);
                        }
                        if ($navLabel === '') continue;
                        // The contact page can be switched off in settings; a
                        // menu item pointing at it must follow that.
                        if (($site['contact_enabled'] ?? true) !== true && str_contains((string) $navItem['url'], '/contact')) continue;
                        $navUrl = (string) $navItem['url'];
                        $navHref = str_starts_with($navUrl, '/') ? quaeriva_url(ltrim($navUrl, '/')) : $navUrl;
                        $navIsAsk = rtrim($navUrl, '/') === '/ask';
                        $navNewTab = !empty($navItem['opens_new_tab']);
                        ?>
                        <?php if ($navIsAsk): $navHasAsk = true; ?>
                            <details class="nav-create nav-menu"><summary class="button button-small button-secondary"><?= quaeriva_t($translator, 'common.create') ?></summary><div><a href="<?= quaeriva_escape(quaeriva_url('ask')) ?>"><?= quaeriva_t($translator, 'questions.ask') ?></a><a href="<?= quaeriva_escape(quaeriva_url('d/new')) ?>"><?= quaeriva_t($translator, 'topics.start') ?></a></div></details>
                            <?php continue; ?>
                        <?php endif; ?>
                        <a href="<?= quaeriva_escape($navHref) ?>"<?= $navNewTab ? ' target="_blank" rel="noopener noreferrer"' : '' ?>><?= quaeriva_escape($navLabel) ?></a>
                    <?php endforeach; ?>
                <?php else: ?>
                    <a href="<?= quaeriva_escape(quaeriva_url()) ?>"><?= quaeriva_t($translator, 'common.home') ?></a>
                    <a href="<?= quaeriva_escape(quaeriva_url() . '#latest-questions') ?>"><?= quaeriva_t($translator, 'common.browse_questions') ?></a>
                    <a href="<?= quaeriva_escape(quaeriva_url('d')) ?>"><?= quaeriva_t($translator, 'topics.nav') ?></a>
                    <?php if (($site['contact_enabled'] ?? true) === true): ?><a href="<?= quaeriva_escape(quaeriva_url('contact')) ?>"><?= quaeriva_t($translator, 'contact.nav') ?></a><?php endif; ?>
                <?php endif; ?>
                <?php if ($navItems === []): ?>
                    <details class="nav-create nav-menu"><summary class="button button-small button-secondary"><?= quaeriva_t($translator, 'common.create') ?></summary><div><a href="<?= quaeriva_escape(quaeriva_url('ask')) ?>"><?= quaeriva_t($translator, 'questions.ask') ?></a><a href="<?= quaeriva_escape(quaeriva_url('d/new')) ?>"><?= quaeriva_t($translator, 'topics.start') ?></a></div></details>
                <?php endif; ?>
                <?= $renderSection('nav_extra') ?>
                <?php if (($currentUser ?? null) !== null): ?>
                    <?php
                    // Four separate account controls pushed the bar past its width
                    // once topics arrived. They collapse into one menu.
                    ?>
                    <details class="nav-account nav-menu">
                        <summary class="button button-small button-secondary">
                            <?= quaeriva_t($translator, 'auth.account') ?>
                        </summary>
                        <div>
                            <?php
                            // Staff had no way into the panel from the site itself and
                            // had to know the URL. Absent from the markup entirely for
                            // everyone else, not hidden with CSS.
                            if (quaeriva_user_has_role($currentUser, 'admin', 'moderator')):
                            ?>
                                <a href="<?= quaeriva_escape(quaeriva_url(quaeriva_admin_path())) ?>"><?= quaeriva_t($translator, 'admin.title') ?></a>
                            <?php endif; ?>
                            <a href="<?= quaeriva_escape(quaeriva_url('notifications')) ?>"><?= quaeriva_t($translator, 'notifications.title') ?></a>
                            <a href="<?= quaeriva_escape(quaeriva_url('settings/profile')) ?>"><?= quaeriva_t($translator, 'auth.profile') ?></a>
                            <form class="nav-logout" method="post" action="<?= quaeriva_escape(quaeriva_url('logout')) ?>">
                                <input type="hidden" name="_csrf" value="<?= quaeriva_escape($csrfToken ?? '') ?>">
                                <button type="submit"><?= quaeriva_t($translator, 'auth.logout') ?></button>
                            </form>
                        </div>
                    </details>
                <?php else: ?>
                    <a href="<?= quaeriva_escape(quaeriva_url('login', ['redirect' => $currentPath ?? quaeriva_url()])) ?>"><?= quaeriva_t($translator, 'auth.login') ?></a>
                    <?php if (($site['registration_enabled'] ?? true) === true): ?><a href="<?= quaeriva_escape(quaeriva_url('register')) ?>"><?= quaeriva_t($translator, 'auth.register') ?></a><?php endif; ?>
                <?php endif; ?>
                <?php if (($site['language_switcher_enabled'] ?? true) === true && count($languages) > 1): ?>
                    <form class="language-switch-form" method="post" action="<?= quaeriva_escape(quaeriva_url('lang')) ?>" data-locale-switch-form>
                        <input type="hidden" name="_csrf" value="<?= quaeriva_escape($csrfToken ?? '') ?>">
                        <input type="hidden" name="next" value="<?= quaeriva_escape($currentPath ?? quaeriva_url()) ?>" data-locale-next>
                        <label class="visually-hidden" for="header-language-select"><?= quaeriva_t($translator, 'common.language') ?></label>
                        <select id="header-language-select" class="language-select" name="locale" data-locale-select>
                            <?php foreach ($languages as $language): $code = (string) ($language['code'] ?? ''); if ($code === '') continue; ?>
                                <option value="<?= quaeriva_escape($code) ?>"<?= $code === $currentLocale ? ' selected' : '' ?>><?= quaeriva_escape((string) ($language['native_name'] ?? $language['name'] ?? $code)) ?></option>
                            <?php endforeach; ?>
                        </select>
                        <button class="language-link" type="submit" data-locale-switch><?= quaeriva_t($translator, 'common.apply_language') ?></button>
                    </form>
                <?php endif; ?>
                <button class="theme-mode-toggle icon-button" type="button" id="quaerivaThemeToggle" aria-label="Toggle Dark/Light Mode" title="Toggle Dark/Light Mode" style="background:none; border:none; cursor:pointer; font-size:1.15rem; padding:0.25rem 0.5rem; display:inline-flex; align-items:center; justify-content:center;"><span class="theme-mode-icon" aria-hidden="true">🌙</span></button>
            </nav>
        </div>
        <?php if (isset($renderAd) && is_callable($renderAd)): ?><?= $renderAd('header') ?><?php endif; ?>
    </header>

    <main id="main-content" class="site-main">
        <?php if (is_array($breadcrumbItems ?? null) && $breadcrumbItems !== []): ?>
            <div class="container site-breadcrumbs-wrap">
                <nav class="site-breadcrumbs" aria-label="<?= quaeriva_t($translator, 'common.breadcrumb') ?>">
                    <ol>
                        <?php
                        $visibleBreadcrumbs = array_values(array_filter(
                            $breadcrumbItems,
                            static fn (mixed $item): bool => is_array($item) && trim((string) ($item['label'] ?? '')) !== ''
                        ));
                        foreach ($visibleBreadcrumbs as $index => $item):
                            $label = trim((string) ($item['label'] ?? ''));
                            $url = trim((string) ($item['url'] ?? ''));
                            $current = $index === count($visibleBreadcrumbs) - 1;
                        ?>
                            <li<?= $current ? ' aria-current="page"' : '' ?>>
                                <?php if (!$current): ?><a href="<?= quaeriva_escape($url) ?>"><?= quaeriva_escape($label) ?></a><?php else: ?><span><?= quaeriva_escape($label) ?></span><?php endif; ?>
                            </li>
                        <?php endforeach; ?>
                    </ol>
                </nav>
            </div>
        <?php endif; ?>
        <?= $content ?>
    </main>

    <footer class="site-footer">
        <?php if (isset($renderAd) && is_callable($renderAd)): ?><?= $renderAd('footer') ?><?php endif; ?>
        <?php
        // Widget-driven footer columns. Each is rendered only when it holds
        // widgets, so a site that has configured none keeps the original
        // two-column footer untouched.
        $footerColumns = '';
        foreach (['footer_col_1', 'footer_col_2', 'footer_col_3'] as $footerSection) {
            $footerColumnHtml = $renderSection($footerSection);
            if ($footerColumnHtml !== '') {
                $footerColumns .= '<div class="footer-widget-column">' . $footerColumnHtml . '</div>';
            }
        }
        ?>
        <?php if ($footerColumns !== ''): ?>
            <div class="container footer-widgets"><?= $footerColumns ?></div>
        <?php endif; ?>
        <div class="container footer-inner">
            <div>
                <strong><?= quaeriva_escape($applicationName) ?></strong>
                <p><?= quaeriva_t($translator, 'common.footer_note') ?></p>
            </div>
            <div>
                <?php if (($site['language_switcher_enabled'] ?? true) === true && count($languages) > 1): ?>
                    <form class="language-switch-form language-switch-form-footer" method="post" action="<?= quaeriva_escape(quaeriva_url('lang')) ?>" data-locale-switch-form>
                        <input type="hidden" name="_csrf" value="<?= quaeriva_escape($csrfToken ?? '') ?>">
                        <input type="hidden" name="next" value="<?= quaeriva_escape($currentPath ?? quaeriva_url()) ?>" data-locale-next>
                        <select class="language-select" name="locale" aria-label="<?= quaeriva_t($translator, 'common.language') ?>" data-locale-select>
                            <?php foreach ($languages as $language): $code = (string) ($language['code'] ?? ''); if ($code === '') continue; ?>
                                <option value="<?= quaeriva_escape($code) ?>"<?= $code === $currentLocale ? ' selected' : '' ?>><?= quaeriva_escape((string) ($language['native_name'] ?? $language['name'] ?? $code)) ?></option>
                            <?php endforeach; ?>
                        </select>
                        <button class="language-link" type="submit" data-locale-switch><?= quaeriva_t($translator, 'common.apply_language') ?></button>
                    </form>
                <?php endif; ?>
                <small class="site-version">v<?= quaeriva_escape((string) ($site['version'] ?? app_version())) ?></small>
            </div>
        </div>
        <?php $footerBottom = $renderSection('footer_bottom'); ?>
        <?php if ($footerBottom !== ''): ?><div class="container footer-bottom"><?= $footerBottom ?></div><?php endif; ?>
    </footer>

    <?php if (($site['turnstile_enabled'] ?? false) === true && trim((string) ($site['turnstile_site_key'] ?? '')) !== ''): ?><script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
    <?php endif; ?>
    <script src="<?= quaeriva_escape(quaeriva_url('assets/js/quaeriva.js', ['v' => quaeriva_asset_version('assets/js/quaeriva.js')])) ?>" defer></script>
    <?php foreach ($themeJsAssets as $asset): ?><script src="<?= quaeriva_escape($asset['url']) ?>" defer></script><?php endforeach; ?>
    <?php if ($mobileBottomNav): ?>
        <?php
        // One-handed reach on a phone. Shown only under a coarse pointer, and
        // only when the operator opted in, because a theme built around its own
        // header should not gain a second navigation bar from an upgrade.
        $bottomNavItems = [
            ['url' => quaeriva_url(), 'label' => $translator->get('common.home'), 'icon' => '⌂', 'route' => 'home'],
            ['url' => quaeriva_url('d'), 'label' => $translator->get('topics.title'), 'icon' => '💬', 'route' => 'topics'],
            ['url' => quaeriva_url('ask'), 'label' => $translator->get('questions.ask'), 'icon' => '＋', 'route' => 'ask'],
            $currentUser !== null
                ? ['url' => quaeriva_url('notifications'), 'label' => $translator->get('notifications.title'), 'icon' => '🔔', 'route' => 'notifications']
                : ['url' => quaeriva_url('login'), 'label' => $translator->get('auth.login'), 'icon' => '↪', 'route' => 'login'],
        ];
        ?>
        <nav class="mobile-bottom-nav" aria-label="<?= quaeriva_t($translator, 'common.primary_navigation') ?>">
            <?php foreach ($bottomNavItems as $item): ?>
                <a href="<?= quaeriva_escape($item['url']) ?>"<?= ($activeRoute ?? '') === $item['route'] ? ' aria-current="page"' : '' ?>>
                    <span class="mobile-bottom-nav-icon" aria-hidden="true"><?= $item['icon'] ?></span>
                    <span class="mobile-bottom-nav-label"><?= quaeriva_escape($item['label']) ?></span>
                </a>
            <?php endforeach; ?>
        </nav>
    <?php endif; ?>
    <button type="button" class="scroll-to-top" id="scroll-to-top" hidden aria-label="<?= quaeriva_t($translator, 'common.scroll_to_top') ?>">
        <span aria-hidden="true">&uarr;</span>
    </button>
    <?php if ($customCodeBodyEnd !== ''): ?><?= $customCodeBodyEnd ?><?php endif; ?>
</body>
</html>
