diff --git a/templates/components/card.html b/templates/components/card.html
new file mode 100644
index 0000000..c83088c
--- /dev/null
+++ b/templates/components/card.html
@@ -0,0 +1,24 @@
+{#
+ Card/Panel Component
+ Reusable container with optional header and footer
+
+ Variables:
+ - title: Optional card header title
+ - indicator: If true, shows status indicator dot in header
+ - indicator_active: If true, indicator is active/green
+ - no_padding: If true, removes body padding
+#}
+
+
+ {% if title %}
+
+ {% endif %}
+
+ {{ caller() }}
+
+
diff --git a/templates/components/empty_state.html b/templates/components/empty_state.html
new file mode 100644
index 0000000..8673707
--- /dev/null
+++ b/templates/components/empty_state.html
@@ -0,0 +1,38 @@
+{#
+ Empty State Component
+ Display when no data is available
+
+ Variables:
+ - icon: Optional SVG icon (default: generic empty icon)
+ - title: Main message (default: "No data")
+ - description: Optional helper text
+ - action_text: Optional button text
+ - action_onclick: Optional button onclick handler
+ - action_href: Optional button link
+#}
+
+
+
+ {% if icon %}
+ {{ icon|safe }}
+ {% else %}
+
+
+
+
+ {% endif %}
+
+
{{ title|default('No data') }}
+ {% if description %}
+
{{ description }}
+ {% endif %}
+ {% if action_text %}
+
+ {% if action_href %}
+
{{ action_text }}
+ {% elif action_onclick %}
+
{{ action_text }}
+ {% endif %}
+
+ {% endif %}
+
diff --git a/templates/components/loading.html b/templates/components/loading.html
new file mode 100644
index 0000000..c616b93
--- /dev/null
+++ b/templates/components/loading.html
@@ -0,0 +1,27 @@
+{#
+ Loading State Component
+ Display while data is being fetched
+
+ Variables:
+ - text: Optional loading text (default: "Loading...")
+ - size: 'sm', 'md', or 'lg' (default: 'md')
+ - overlay: If true, renders as full overlay
+#}
+
+{% if overlay %}
+
+
+
+ {% if text %}
+
{{ text }}
+ {% endif %}
+
+
+{% else %}
+
+
+ {% if text %}
+
{{ text }}
+ {% endif %}
+
+{% endif %}
diff --git a/templates/components/stats_strip.html b/templates/components/stats_strip.html
new file mode 100644
index 0000000..b70e2db
--- /dev/null
+++ b/templates/components/stats_strip.html
@@ -0,0 +1,47 @@
+{#
+ Stats Strip Component
+ Horizontal bar displaying key metrics
+
+ Variables:
+ - stats: List of stat objects with 'id', 'value', 'label', and optional 'title'
+ - show_divider: Show divider after stats (default: true)
+ - status_dot_id: Optional ID for status indicator dot
+ - status_text_id: Optional ID for status text
+ - time_id: Optional ID for time display
+#}
+
+
+
+ {% for stat in stats %}
+
+ {{ stat.value|default('0') }}
+ {{ stat.label }}
+
+ {% endfor %}
+
+ {% if show_divider|default(true) %}
+
+ {% endif %}
+
+ {# Additional content from caller #}
+ {% if caller is defined %}
+ {{ caller() }}
+ {% endif %}
+
+ {% if status_dot_id or status_text_id %}
+
+
+ {% if status_dot_id %}
+
+ {% endif %}
+ {% if status_text_id %}
+
STANDBY
+ {% endif %}
+
+ {% endif %}
+
+ {% if time_id %}
+
--:--:-- UTC
+ {% endif %}
+
+
diff --git a/templates/components/status_badge.html b/templates/components/status_badge.html
new file mode 100644
index 0000000..783aeeb
--- /dev/null
+++ b/templates/components/status_badge.html
@@ -0,0 +1,27 @@
+{#
+ Status Badge Component
+ Compact status indicator with dot and text
+
+ Variables:
+ - status: 'online', 'offline', 'warning', 'error' (default: 'offline')
+ - text: Status text to display
+ - id: Optional ID for the text element (for JS updates)
+ - dot_id: Optional ID for the dot element (for JS updates)
+ - pulse: If true, adds pulse animation to dot
+#}
+
+{% set status_class = {
+ 'online': 'online',
+ 'active': 'online',
+ 'offline': 'offline',
+ 'warning': 'warning',
+ 'error': 'error',
+ 'inactive': 'inactive'
+}.get(status|default('offline'), 'inactive') %}
+
+
+
+
{{ text|default('Unknown') }}
+
diff --git a/templates/layout/base.html b/templates/layout/base.html
new file mode 100644
index 0000000..09e97ee
--- /dev/null
+++ b/templates/layout/base.html
@@ -0,0 +1,169 @@
+
+
+
+
+
+
{% block title %}iNTERCEPT{% endblock %} // iNTERCEPT
+
+
+ {# Fonts - Conditional CDN/Local loading #}
+ {% if offline_settings and offline_settings.fonts_source == 'local' %}
+
+ {% else %}
+
+ {% endif %}
+
+ {# Core CSS (Design System) #}
+
+
+
+
+
+ {# Responsive styles #}
+
+
+ {# Page-specific CSS #}
+ {% block styles %}{% endblock %}
+
+ {# Page-specific head content #}
+ {% block head %}{% endblock %}
+
+
+
+ {# Global Header #}
+ {% block header %}
+
+ {% endblock %}
+
+ {# Global Navigation - opt-in for pages that need it #}
+ {# Override this block and include 'partials/nav.html' in child templates #}
+ {% block navigation %}{% endblock %}
+
+ {# Main Content Area #}
+
+ {% block main %}
+
+ {# Optional Sidebar #}
+ {% block sidebar %}{% endblock %}
+
+ {# Page Content #}
+
+ {% block content %}{% endblock %}
+
+
+ {% endblock %}
+
+
+ {# Toast/Notification Container #}
+
+
+
+ {# Core JavaScript #}
+
+
+ {# Page-specific JavaScript #}
+ {% block scripts %}{% endblock %}
+
+
diff --git a/templates/layout/base_dashboard.html b/templates/layout/base_dashboard.html
new file mode 100644
index 0000000..5714708
--- /dev/null
+++ b/templates/layout/base_dashboard.html
@@ -0,0 +1,228 @@
+{% 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() }}
+
+{% endblock %}
+
+{% block header %}
+
+{% endblock %}
+
+{% block navigation %}
+{# Include the unified nav partial with active_mode set #}
+{% include 'partials/nav.html' with context %}
+{% endblock %}
+
+{% block main %}
+{# Background effects #}
+
+ {% block dashboard_bg %}
+
+ {% endblock %}
+
+
+
+{# Stats strip #}
+{% block stats_strip %}{% endblock %}
+
+{# Dashboard content #}
+
+ {% block dashboard_content %}{% endblock %}
+
+{% endblock %}
+
+{% block scripts %}
+{{ super() }}
+
+{% endblock %}
diff --git a/templates/partials/nav.html b/templates/partials/nav.html
new file mode 100644
index 0000000..a88f02e
--- /dev/null
+++ b/templates/partials/nav.html
@@ -0,0 +1,304 @@
+{#
+ Global Navigation Partial
+ Single source of truth for app navigation
+
+ Compatible with:
+ - index.html (uses switchMode() for mode panels)
+ - Dashboard pages (uses navigation links)
+
+ Variables:
+ - active_mode: Current active mode (e.g., 'pager', 'adsb', 'wifi')
+ - show_mode_switcher: If true (default), shows mode switching nav for index.html
+ If false, shows simplified dashboard nav
+#}
+
+{% set show_mode_switcher = show_mode_switcher|default(true) %}
+
+{# Desktop Navigation - uses existing CSS class names for compatibility #}
+
+ {# SDR / RF Group #}
+
+
+ {# Wireless Group #}
+
+
+ {# Security Group #}
+
+
+ {# Space Group #}
+
+
+ {# Dynamic dashboard button (shown when in satellite mode) #}
+
+
+ {# Nav Utilities (clock, theme, tools) #}
+
+
+
+{# Mobile Navigation Bar #}
+
+
+
+ 433MHz
+
+
+ Meters
+
+
+ Aircraft
+
+
+ Vessels
+
+
+ APRS
+
+
+ WiFi
+
+
+ BT
+
+
+ TSCM
+
+
+ Sat
+
+
+ SSTV
+
+
+ Scanner
+
+
+ Spy
+
+
+ Mesh
+
+
+
+{# JavaScript stub for pages that don't have switchMode defined #}
+
diff --git a/templates/partials/page_header.html b/templates/partials/page_header.html
new file mode 100644
index 0000000..5d13ecd
--- /dev/null
+++ b/templates/partials/page_header.html
@@ -0,0 +1,37 @@
+{#
+ Page Header Partial
+ Consistent page title with optional description and actions
+
+ Variables:
+ - title: Page title (required)
+ - description: Optional description text
+ - back_url: Optional back link URL
+ - back_text: Optional back link text (default: "Back")
+#}
+
+
diff --git a/templates/satellite_dashboard.html b/templates/satellite_dashboard.html
index 74d56a9..36c67bf 100644
--- a/templates/satellite_dashboard.html
+++ b/templates/satellite_dashboard.html
@@ -1,9 +1,12 @@
-
+
-
SATELLITE COMMAND // iNTERCEPT - See the Invisible
+
SATELLITE COMMAND // iNTERCEPT
+
+
+
{% if offline_settings.fonts_source == 'local' %}
@@ -27,8 +30,10 @@
+
+ {% set active_mode = 'satellite' %}
+ {% include 'partials/nav.html' %}
+