193 lines
10 KiB
HTML
193 lines
10 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
{% set page_title %}{% block title %}myboker.org{% endblock %}{% endset %}
|
|
{% set page_description %}{% block meta_description %}{{ seo_default_description }}{% endblock %}{% endset %}
|
|
{% set page_keywords %}{% block meta_keywords %}{{ seo_default_keywords }}{% endblock %}{% endset %}
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>{{ page_title | trim }}</title>
|
|
<meta name="description" content="{{ page_description | striptags | trim }}">
|
|
<meta name="keywords" content="{{ page_keywords | striptags | trim }}">
|
|
<meta name="application-name" content="myboker.org">
|
|
<meta name="theme-color" content="#09090d">
|
|
<meta name="apple-mobile-web-app-title" content="myboker">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
<meta name="robots" content="{% block robots %}index,follow,max-image-preview:large{% endblock %}">
|
|
<link rel="canonical" href="{{ seo_canonical_url }}">
|
|
<meta property="og:site_name" content="myboker.org">
|
|
<meta property="og:title" content="{{ page_title | trim }}">
|
|
<meta property="og:description" content="{{ page_description | striptags | trim }}">
|
|
<meta property="og:type" content="{% block og_type %}website{% endblock %}">
|
|
<meta property="og:url" content="{{ seo_canonical_url }}">
|
|
<meta name="twitter:card" content="summary">
|
|
<meta name="twitter:title" content="{{ page_title | trim }}">
|
|
<meta name="twitter:description" content="{{ page_description | striptags | trim }}">
|
|
<link rel="icon" href="{{ url_for('static', filename='favicon.svg') }}" type="image/svg+xml">
|
|
<link rel="icon" href="{{ url_for('static', filename='favicon.png') }}" type="image/png" sizes="32x32">
|
|
<link rel="apple-touch-icon" href="{{ url_for('static', filename='icons/apple-touch-icon.png') }}" sizes="180x180">
|
|
<link rel="manifest" href="{{ url_for('static', filename='site.webmanifest') }}">
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/tokens.css') }}">
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
{% block structured_data %}{% endblock %}
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
</head>
|
|
<body>
|
|
<div class="l-bg" aria-hidden="true"></div>
|
|
<header class="topbar">
|
|
<div class="topbar__inner">
|
|
<a class="brand" href="{{ url_for('public.home') }}">
|
|
<span class="brand__mark"></span>
|
|
<span class="brand__name">myboker<span class="brand__tld">.org</span></span>
|
|
</a>
|
|
<button class="nav-toggle" type="button" aria-controls="mainnav" aria-expanded="false" aria-label="Open navigation">
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</button>
|
|
<nav class="mainnav" id="mainnav">
|
|
{% if is_logged_in %}
|
|
<a class="navlink {{ 'is-active' if request.endpoint and request.endpoint.startswith('leagues.') }}" href="{{ url_for('leagues.index') }}">Leagues</a>
|
|
<a class="navlink {{ 'is-active' if request.endpoint == 'public.explore' }}" href="{{ url_for('public.explore') }}">Explore</a>
|
|
<a class="navlink {{ 'is-active' if request.endpoint and request.endpoint.startswith('account.') and request.endpoint not in ('account.login', 'account.register') }}" href="{{ url_for('account.settings') }}">Account</a>
|
|
<a class="navlink {{ 'is-active' if request.endpoint == 'public.help' }}" href="{{ url_for('public.help') }}">Help</a>
|
|
{% else %}
|
|
<a class="navlink {{ 'is-active' if request.endpoint == 'public.explore' }}" href="{{ url_for('public.explore') }}">Explore</a>
|
|
<a class="navlink {{ 'is-active' if request.endpoint == 'public.help' }}" href="{{ url_for('public.help') }}">Help</a>
|
|
<a class="navlink navlink--mobile-auth {{ 'is-active' if request.endpoint == 'account.login' }}" href="{{ url_for('account.login') }}">Login</a>
|
|
<a class="navlink navlink--mobile-auth {{ 'is-active' if request.endpoint == 'account.register' }}" href="{{ url_for('account.register') }}">Register</a>
|
|
{% endif %}
|
|
</nav>
|
|
<span class="topbar__spacer"></span>
|
|
{% if is_logged_in %}
|
|
<div class="topbar__admin-actions">
|
|
<form method="post" action="{{ url_for('account.logout') }}" style="margin:0">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
<button class="btn btn--ghost btn--sm" type="submit">Logout</button>
|
|
</form>
|
|
</div>
|
|
{% else %}
|
|
<div class="topbar__admin-actions topbar__account-actions">
|
|
<a class="btn btn--ghost btn--sm" href="{{ url_for('account.login') }}">Login</a>
|
|
<a class="btn btn--outline btn--sm" href="{{ url_for('account.register') }}">Register</a>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</header>
|
|
<div class="app-shell">
|
|
{% block sidebar %}{% endblock %}
|
|
<main class="page {% block page_class %}page--public{% endblock %}">
|
|
{% block subnav %}{% endblock %}
|
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
|
{% if messages %}
|
|
<div class="flash-stack">
|
|
{% for category, message in messages %}
|
|
<div class="flash {{ category }}" role="{{ 'alert' if category == 'error' else 'status' }}">
|
|
<span class="flash__message">{{ message }}</span>
|
|
<button class="flash__dismiss" type="button" aria-label="Dismiss message" data-dismiss-flash>×</button>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
{% endwith %}
|
|
|
|
{% block content %}{% endblock %}
|
|
|
|
<footer class="site-footer" aria-label="Site footer">
|
|
<div class="site-footer__copy">
|
|
<span>© 2026 <strong>myboker.org</strong></span>
|
|
<span class="site-footer__version">v{{ app_version }}</span>
|
|
</div>
|
|
<nav class="site-footer__links" aria-label="Footer links">
|
|
<a href="{{ url_for('public.help') }}">Help</a>
|
|
<a href="{{ url_for('public.help') }}#contact">Contact</a>
|
|
<a href="{{ url_for('public.privacy') }}">Privacy</a>
|
|
<a href="{{ url_for('public.terms') }}">Terms</a>
|
|
</nav>
|
|
<div class="site-footer__brand">
|
|
<a href="https://cedarline.digital" target="_blank" rel="noopener">cedarline.digital</a>
|
|
</div>
|
|
</footer>
|
|
</main>
|
|
</div><!-- /.app-shell -->
|
|
<script>
|
|
(() => {
|
|
const toggle = document.querySelector('.nav-toggle');
|
|
const nav = document.getElementById('mainnav');
|
|
if (!toggle || !nav) return;
|
|
|
|
const setOpen = (open) => {
|
|
document.body.classList.toggle('nav-is-open', open);
|
|
toggle.setAttribute('aria-expanded', String(open));
|
|
toggle.setAttribute('aria-label', open ? 'Close navigation' : 'Open navigation');
|
|
};
|
|
|
|
toggle.addEventListener('click', () => {
|
|
setOpen(!document.body.classList.contains('nav-is-open'));
|
|
});
|
|
nav.addEventListener('click', (event) => {
|
|
if (event.target.closest('a')) setOpen(false);
|
|
});
|
|
document.addEventListener('keydown', (event) => {
|
|
if (event.key === 'Escape') setOpen(false);
|
|
});
|
|
document.addEventListener('click', (event) => {
|
|
if (!document.body.classList.contains('nav-is-open')) return;
|
|
if (event.target.closest('.topbar')) return;
|
|
setOpen(false);
|
|
});
|
|
window.addEventListener('resize', () => {
|
|
if (window.matchMedia('(min-width: 701px)').matches) setOpen(false);
|
|
});
|
|
})();
|
|
</script>
|
|
<script>
|
|
(() => {
|
|
document.addEventListener('click', (event) => {
|
|
const button = event.target.closest('[data-dismiss-flash]');
|
|
if (!button) return;
|
|
const flash = button.closest('.flash');
|
|
const stack = button.closest('.flash-stack');
|
|
if (flash) flash.remove();
|
|
if (stack && !stack.querySelector('.flash')) stack.remove();
|
|
});
|
|
})();
|
|
</script>
|
|
<script>
|
|
(() => {
|
|
function positionBubble(tip) {
|
|
const bubble = tip.querySelector('.info-tip__bubble');
|
|
if (!bubble) return;
|
|
const rect = tip.getBoundingClientRect();
|
|
const bw = bubble.offsetWidth || 220;
|
|
const bh = bubble.offsetHeight || 60;
|
|
let left = rect.left + rect.width / 2 - bw / 2;
|
|
let top = rect.top - bh - 8;
|
|
left = Math.max(8, Math.min(left, window.innerWidth - bw - 8));
|
|
if (top < 8) top = rect.bottom + 8;
|
|
bubble.style.left = left + 'px';
|
|
bubble.style.top = top + 'px';
|
|
}
|
|
document.querySelectorAll('.info-tip').forEach(tip => {
|
|
tip.addEventListener('mouseenter', () => { positionBubble(tip); tip.classList.add('is-open'); });
|
|
tip.addEventListener('mouseleave', () => tip.classList.remove('is-open'));
|
|
tip.addEventListener('click', e => {
|
|
e.stopPropagation();
|
|
const wasOpen = tip.classList.contains('is-open');
|
|
document.querySelectorAll('.info-tip.is-open').forEach(t => t.classList.remove('is-open'));
|
|
if (!wasOpen) { positionBubble(tip); tip.classList.add('is-open'); }
|
|
});
|
|
tip.addEventListener('keydown', e => {
|
|
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); tip.click(); }
|
|
if (e.key === 'Escape') tip.classList.remove('is-open');
|
|
});
|
|
});
|
|
document.addEventListener('click', () => {
|
|
document.querySelectorAll('.info-tip.is-open').forEach(t => t.classList.remove('is-open'));
|
|
});
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|