mirror of
https://github.com/smittix/intercept.git
synced 2026-04-25 07:10:00 -07:00
The CSS ::after dot positioning was unreliable across fonts and sizes. Switch to an inline SVG of the "i" glyph (green dot + cyan stem/bars) extracted from the logo — renders pixel-perfect at any size. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
229 lines
7.6 KiB
HTML
229 lines
7.6 KiB
HTML
{% extends 'layout/base.html' %}
|
|
|
|
{#
|
|
Dashboard Base Template
|
|
Extended layout for full-screen dashboard pages (ADSB, AIS, Satellite, etc.)
|
|
Features: Full-height layout, stats strip, sidebar overlay on mobile
|
|
|
|
Variables:
|
|
- active_mode: The current mode for nav highlighting (e.g., 'adsb', 'ais', 'satellite')
|
|
#}
|
|
|
|
{% block styles %}
|
|
{{ super() }}
|
|
<style>
|
|
/* Dashboard-specific overrides */
|
|
html, body {
|
|
height: 100%;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.app-shell {
|
|
height: 100vh;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.app-main {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* Radar/Grid background effect */
|
|
.dashboard-bg {
|
|
position: fixed;
|
|
inset: 0;
|
|
pointer-events: none;
|
|
z-index: -1;
|
|
}
|
|
|
|
.radar-bg {
|
|
position: absolute;
|
|
inset: 0;
|
|
background-image:
|
|
radial-gradient(circle at center, transparent 0%, var(--bg-primary) 70%),
|
|
repeating-linear-gradient(0deg, transparent, transparent 50px, var(--border-color) 50px, var(--border-color) 51px),
|
|
repeating-linear-gradient(90deg, transparent, transparent 50px, var(--border-color) 50px, var(--border-color) 51px);
|
|
opacity: 0.3;
|
|
}
|
|
|
|
.grid-bg {
|
|
position: absolute;
|
|
inset: 0;
|
|
background-image:
|
|
linear-gradient(var(--border-color) 1px, transparent 1px),
|
|
linear-gradient(90deg, var(--border-color) 1px, transparent 1px);
|
|
background-size: 40px 40px;
|
|
opacity: 0.15;
|
|
}
|
|
|
|
.scanline {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 2px;
|
|
background: linear-gradient(90deg, transparent, var(--accent-cyan), transparent);
|
|
opacity: 0.5;
|
|
animation: scanline 8s linear infinite;
|
|
}
|
|
|
|
@keyframes scanline {
|
|
0% { top: 0; }
|
|
100% { top: 100%; }
|
|
}
|
|
|
|
/* Animations toggle */
|
|
[data-animations="off"] .scanline,
|
|
[data-animations="off"] .radar-bg,
|
|
[data-animations="off"] .grid-bg {
|
|
display: none;
|
|
}
|
|
|
|
/* Dashboard main content */
|
|
.dashboard-content {
|
|
flex: 1;
|
|
display: flex;
|
|
overflow: hidden;
|
|
position: relative;
|
|
}
|
|
|
|
.dashboard-map-container {
|
|
flex: 1;
|
|
position: relative;
|
|
}
|
|
|
|
.dashboard-sidebar {
|
|
width: 320px;
|
|
background: var(--bg-secondary);
|
|
border-left: 1px solid var(--border-color);
|
|
overflow-y: auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-3);
|
|
padding: var(--space-3);
|
|
}
|
|
|
|
@media (max-width: 1024px) {
|
|
.dashboard-sidebar {
|
|
width: 280px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.dashboard-sidebar {
|
|
position: fixed;
|
|
right: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
z-index: var(--z-fixed);
|
|
transform: translateX(100%);
|
|
transition: transform var(--transition-base);
|
|
}
|
|
|
|
.dashboard-sidebar.open {
|
|
transform: translateX(0);
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block header %}
|
|
<header class="app-header" style="padding: 0 var(--space-3); height: 48px;">
|
|
<div class="app-header-left" style="gap: var(--space-3);">
|
|
<a href="/" class="app-logo" style="gap: var(--space-2);">
|
|
<svg class="app-logo-icon" width="28" height="28" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M15 30 Q5 50, 15 70" stroke="var(--accent-cyan)" stroke-width="3" fill="none" stroke-linecap="round" opacity="0.5"/>
|
|
<path d="M22 35 Q14 50, 22 65" stroke="var(--accent-cyan)" stroke-width="2.5" fill="none" stroke-linecap="round" opacity="0.7"/>
|
|
<path d="M29 40 Q23 50, 29 60" stroke="var(--accent-cyan)" stroke-width="2" fill="none" stroke-linecap="round"/>
|
|
<path d="M85 30 Q95 50, 85 70" stroke="var(--accent-cyan)" stroke-width="3" fill="none" stroke-linecap="round" opacity="0.5"/>
|
|
<path d="M78 35 Q86 50, 78 65" stroke="var(--accent-cyan)" stroke-width="2.5" fill="none" stroke-linecap="round" opacity="0.7"/>
|
|
<path d="M71 40 Q77 50, 71 60" stroke="var(--accent-cyan)" stroke-width="2" fill="none" stroke-linecap="round"/>
|
|
<circle cx="50" cy="22" r="6" fill="var(--accent-green)"/>
|
|
<rect x="44" y="35" width="12" height="45" rx="2" fill="var(--accent-cyan)"/>
|
|
<rect x="38" y="35" width="24" height="4" rx="1" fill="var(--accent-cyan)"/>
|
|
<rect x="38" y="76" width="24" height="4" rx="1" fill="var(--accent-cyan)"/>
|
|
</svg>
|
|
</a>
|
|
<div class="dashboard-header-title">
|
|
<span style="font-size: var(--text-lg); font-weight: var(--font-bold); color: var(--text-primary);">
|
|
{% block dashboard_title %}DASHBOARD{% endblock %}
|
|
</span>
|
|
<span style="font-size: var(--text-sm); color: var(--text-dim); margin-left: var(--space-2);">
|
|
// <span class="brand-i"><svg viewBox="36 14 28 68" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="20" r="6" fill="#00ff88"/><rect x="44" y="33" width="12" height="45" rx="2" fill="#00d4ff"/><rect x="38" y="33" width="24" height="4" rx="1" fill="#00d4ff"/><rect x="38" y="74" width="24" height="4" rx="1" fill="#00d4ff"/></svg></span>NTERCEPT
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="app-header-right">
|
|
{% block dashboard_header_center %}{% endblock %}
|
|
<div class="header-utilities" style="gap: var(--space-2);">
|
|
{% block agent_selector %}{% endblock %}
|
|
</div>
|
|
</div>
|
|
</header>
|
|
{% endblock %}
|
|
|
|
{% block navigation %}
|
|
{# Include the unified nav partial with active_mode set #}
|
|
{% if not embedded %}
|
|
{% include 'partials/nav.html' with context %}
|
|
{% endif %}
|
|
{% endblock %}
|
|
|
|
{% block main %}
|
|
{# Background effects #}
|
|
<div class="dashboard-bg">
|
|
{% block dashboard_bg %}
|
|
<div class="radar-bg"></div>
|
|
{% endblock %}
|
|
<div class="scanline"></div>
|
|
</div>
|
|
|
|
{# Stats strip #}
|
|
{% block stats_strip %}{% endblock %}
|
|
|
|
{# Dashboard content #}
|
|
<div class="dashboard-content">
|
|
{% block dashboard_content %}{% endblock %}
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
{{ super() }}
|
|
<script>
|
|
// Dashboard-specific scripts
|
|
(function() {
|
|
// Mobile sidebar toggle
|
|
const sidebarToggle = document.getElementById('sidebarToggle');
|
|
const sidebar = document.querySelector('.dashboard-sidebar');
|
|
const overlay = document.getElementById('drawerOverlay');
|
|
|
|
if (sidebarToggle && sidebar) {
|
|
sidebarToggle.addEventListener('click', function() {
|
|
sidebar.classList.toggle('open');
|
|
if (overlay) overlay.classList.toggle('visible');
|
|
});
|
|
}
|
|
|
|
if (overlay) {
|
|
overlay.addEventListener('click', function() {
|
|
sidebar?.classList.remove('open');
|
|
this.classList.remove('visible');
|
|
});
|
|
}
|
|
|
|
// UTC Clock update
|
|
function updateUtcClock() {
|
|
const now = new Date();
|
|
const utc = now.toISOString().slice(11, 19) + ' UTC';
|
|
document.querySelectorAll('[id$="utcTime"], [id$="UtcTime"]').forEach(el => {
|
|
el.textContent = utc;
|
|
});
|
|
}
|
|
setInterval(updateUtcClock, 1000);
|
|
updateUtcClock();
|
|
})();
|
|
</script>
|
|
{% endblock %}
|