{% load compress %}
{% load static %}


<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="author" content="Disco DeDisco">
        <meta name="robots" content="noindex, nofollow">
        <title>Earthman RPG | {% block title_text %}{% endblock title_text %}</title>
        {% compress css %}
             <link type="text/x-scss" rel="stylesheet" href="{% static 'scss/core.scss' %}">
        {% endcompress %}
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css">
    </head>

    <body class="{{ user_palette }} {{ page_class|default:'' }}">
        <div class="container">
            {% include "core/_partials/_navbar.html" %}

            <div class="row">
                <div class="col-lg-6">
                    <h2 >{% block header_text %}{% endblock header_text %}</h2>
                    {% block extra_header %}
                    {% endblock extra_header %}
                </div>
            </div>

            {% if messages %}
                {% for message in messages %}
                    {# Transient Brief-styled banner — no DB row, no FYI/square. #}
                    {# Slides in under the navbar h2 w. the same Gaussian-glass    #}
                    {# look as the Brief notification banner; NVM dismisses.       #}
                    <div class="note-banner note-banner--message note-banner--{{ message.level_tag }}">
                        <div class="note-banner__body">
                            <p class="note-banner__description">{{ message }}</p>
                        </div>
                        <button type="button" class="btn btn-cancel note-banner__nvm"
                                onclick="this.parentElement.remove()">NVM</button>
                    </div>
                {% endfor %}
            {% endif %}

            {# Anchor for Brief.showBanner — banner inserts as nextSibling so #}
            {# it lands at the top of page content on every base.html-extending #}
            {# page, regardless of where (or whether) <h2> is positioned. #}
            <div id="id_brief_banner_anchor"></div>

            {% block content %}
            {% endblock content %}

        </div>
        
        {% include "core/_partials/_footer.html" %}

        {% if user.is_authenticated %}
        <button id="id_kit_btn" data-kit-url="{% url 'kit_bag' %}" aria-label="Open Kit Bag">
            <i class="fa-solid fa-briefcase"></i>
        </button>
        {% endif %}
        <dialog id="id_kit_bag_dialog"></dialog>

        <div id="id_guard_portal">
            <span class="guard-message"></span>
            <div class="guard-actions">
                <button class="btn btn-confirm guard-yes" type="button">OK</button>
                <button class="btn btn-cancel guard-no" type="button">NVM</button>
            </div>
        </div>

        {% block scripts %}
        {% endblock scripts %}
        <script>
        // h2 letter splitter — wrap each character of every .row .col-lg-6 h2
        // word-span in its own <span> so .scss can use justify-content:
        // space-between to fill the 45/55 slot. text-justify: inter-character
        // would do this in pure CSS but iOS Safari + Firefox silently fall
        // back to inter-word for Latin text, leaving letters clustered at the
        // slot's start.
        (function () {
            var spans = document.querySelectorAll('.row .col-lg-6 h2 > span');
            for (var i = 0; i < spans.length; i++) {
                var span = spans[i];
                if (span.dataset.lettersSplit === '1') continue;
                var text = (span.textContent || '').trim();
                if (!text) continue;
                span.dataset.lettersSplit = '1';
                span.setAttribute('aria-label', text);
                span.textContent = '';
                for (var j = 0; j < text.length; j++) {
                    var letter = document.createElement('span');
                    letter.setAttribute('aria-hidden', 'true');
                    letter.textContent = text[j];
                    span.appendChild(letter);
                }
            }
        }());

        // iOS Safari auto-zooms when focusing an <input>/<textarea>/<select>
        // whose font-size is < 16px, and does NOT auto-zoom back out on blur.
        // Belt-and-suspenders: primary prevention is the global `font-size:
        // max(16px, 1em)` rule in core.scss; this JS is a fallback for inputs
        // that slip through (custom controls, shadow DOM, etc.). Modern iOS
        // doesn't reliably react to a simple `setAttribute('content', ...)`
        // tweak on the existing meta — removing and re-appending the meta
        // element entirely is more dependable.
        (function () {
            var origMeta = document.querySelector('meta[name="viewport"]');
            if (!origMeta) return;
            var baseContent = origMeta.getAttribute('content');
            document.addEventListener('focusout', function (e) {
                if (!e.target.matches || !e.target.matches('input, textarea, select')) return;
                var oldMeta = document.querySelector('meta[name="viewport"]');
                if (oldMeta) oldMeta.remove();
                var snapMeta = document.createElement('meta');
                snapMeta.setAttribute('name', 'viewport');
                snapMeta.setAttribute('content', baseContent + ', maximum-scale=1.0, user-scalable=no');
                document.head.appendChild(snapMeta);
                setTimeout(function () {
                    snapMeta.remove();
                    var revertMeta = document.createElement('meta');
                    revertMeta.setAttribute('name', 'viewport');
                    revertMeta.setAttribute('content', baseContent);
                    document.head.appendChild(revertMeta);
                }, 300);
            });
        }());
        </script>
        <script>
        (function () {
            var portal = null;
            var _cb = null;
            var _onDismiss = null;

            function show(anchor, message, callback, onDismiss, options) {
                if (!portal) return;
                options = options || {};
                _cb = callback;
                _onDismiss = onDismiss || null;
                portal.querySelector('.guard-message').innerHTML = message;
                // Optional override for the YES-button label (e.g., "DEL" for
                // a destructive-named action). Resets to "OK" inside dismiss/
                // doConfirm so the next show() starts from the default.
                portal.querySelector('.guard-yes').textContent = options.yesLabel || 'OK';
                portal.classList.add('active');
                var rect = anchor.getBoundingClientRect();
                var pw = portal.offsetWidth;
                var rawLeft = rect.left + rect.width / 2;
                var cleft = Math.max(pw / 2 + 8, Math.min(rawLeft, window.innerWidth - pw / 2 - 8));
                portal.style.left = Math.round(cleft) + 'px';
                var cardCenterY = rect.top + rect.height / 2;
                // Default: upper half → below (avoids viewport top edge for navbar/fixed buttons).
                // invertY: upper half → above (for modal grids where tooltip should fly away from centre).
                var showBelow = (cardCenterY < window.innerHeight / 2);
                if (options.invertY) showBelow = !showBelow;
                if (showBelow) {
                    portal.style.top = Math.round(rect.bottom) + 'px';
                    portal.style.transform = 'translate(-50%, 0.5rem)';
                } else {
                    portal.style.top = Math.round(rect.top) + 'px';
                    portal.style.transform = 'translate(-50%, calc(-100% - 0.5rem))';
                }
            }

            function dismiss() {
                if (!portal) return;
                var od = _onDismiss;
                portal.classList.remove('active');
                portal.querySelector('.guard-yes').textContent = 'OK';
                _cb = null;
                _onDismiss = null;
                if (od) od();
            }

            function doConfirm() {
                var cb = _cb;
                portal.classList.remove('active');
                portal.querySelector('.guard-yes').textContent = 'OK';
                _cb = null;
                _onDismiss = null;
                if (cb) cb();
            }

            document.addEventListener('DOMContentLoaded', function () {
                portal = document.getElementById('id_guard_portal');
                if (!portal) return;
                portal.querySelector('.guard-yes').addEventListener('click', doConfirm);
                portal.querySelector('.guard-no').addEventListener('click', dismiss);
                document.addEventListener('keydown', function (e) {
                    if (e.key === 'Escape') dismiss();
                });
                // Outside-click to dismiss — capture phase + stopPropagation
                // prevents the click from cascading to backdrop listeners (e.g. closeFan)
                document.addEventListener('click', function (e) {
                    if (!portal.classList.contains('active')) return;
                    if (portal.contains(e.target)) return;
                    // If clicking a card, let the event through so the card's
                    // own handler immediately opens the guard on the new target.
                    // For any other outside click, stop propagation to prevent
                    // the backdrop from also closing the fan.
                    if (!e.target.closest('.card')) e.stopPropagation();
                    dismiss();
                }, true);
                // Intercept [data-confirm] buttons (capture phase, before form submits)
                document.addEventListener('click', function (e) {
                    var btn = e.target.closest('[data-confirm]');
                    if (!btn) return;
                    e.preventDefault();
                    e.stopImmediatePropagation();
                    var form = btn.closest('form');
                    show(btn, btn.dataset.confirm, function () {
                        if (form) form.submit();
                        else if (btn.dataset.href) window.location.href = btn.dataset.href;
                    });
                }, true);
            });

            window.showGuard = show;
        }());
        </script>
        <script src="{% static "vendor/htmx.min.js" %}"></script>
        <script src="{% static "apps/applets/applets.js" %}"></script>
        <script src="{% static "apps/applets/row-lock.js" %}"></script>
        <script src="{% static "apps/dashboard/game-kit.js" %}"></script>
        <script>
            document.cookie = 'user_tz=' + Intl.DateTimeFormat().resolvedOptions().timeZone + '; path=/; SameSite=Lax';
            document.body.addEventListener('htmx:configRequest', function(evt) {
                evt.detail.headers['X-CSRFToken'] = getCookie('csrftoken');
            });
            function getCookie(name) {
                let val = null;
                if (document.cookie) {
                    for (let c of document.cookie.split(';')) {
                        c = c.trim();
                        if (c.startsWith(name + '=')) {
                            val = decodeURIComponent(c.substring(name.length + 1));
                            break;
                        }
                    }
                }
                return val;
            }
        </script>
    </body>
</html>