diff --git a/design-mockups/field-station-list.html b/design-mockups/field-station-list.html
new file mode 100644
index 0000000..9d0fe72
--- /dev/null
+++ b/design-mockups/field-station-list.html
@@ -0,0 +1,87 @@
+
+
+
+
+
+Field Station — Advertisements
+
+
+
+
+
+
+
+ IPNET
+
+
+ ◐
+ ≡
+
+
+
+
+
Advertisements
+
UTC+1
+
1,284 total
+
+
⏸
+
+
+
+
+
+
Sort by Newest first Oldest first Node name
+
+
+
+
+
+
+
+
+
+Field Station · List view · ◐ toggle theme · resize narrow for mobile cards
+
+
+
diff --git a/design-mockups/field-station-map.html b/design-mockups/field-station-map.html
new file mode 100644
index 0000000..30fff4f
--- /dev/null
+++ b/design-mockups/field-station-map.html
@@ -0,0 +1,78 @@
+
+
+
+
+
+Field Station — Map
+
+
+
+
+
+
+
+ IPNET
+
+
+ ◐
+ ≡
+
+
+
+
+
Map
+ 42 nodes
+ 18 shown
+ UTC+1
+
+
+
+
+
+
+
+
+
+
+
Holbeck-Relay · 2m
+
kestrel · 6m
+
Briggate-Room · 11m
+
Armley-Hill · 18m
+
g7xyz · 24m
+
+
+
+
+
Infrastructure
+
Public node
+
+
+
+
+
+
+Field Station · Map view · ◐ toggle theme · resize narrow to stack filters
+
+
+
diff --git a/design-mockups/field-station.css b/design-mockups/field-station.css
new file mode 100644
index 0000000..3ce0ceb
--- /dev/null
+++ b/design-mockups/field-station.css
@@ -0,0 +1,145 @@
+/* ===== Field Station — shared theme stylesheet (mockup) ===== */
+:root{
+ --display:"Chakra Petch",system-ui,sans-serif;
+ --body:"IBM Plex Sans",system-ui,sans-serif;
+ --mono:"IBM Plex Mono",ui-monospace,monospace;
+ --radius:10px;
+}
+[data-theme="dark"]{
+ --bg:#0B0F14; --panel:#11171F; --panel-2:#161E29; --line:#1B2430;
+ --text:#E6EDF3; --muted:#8B9AAB;
+ --tx:#E8932A; --tx-soft:#E8932A26;
+ --rx:#2BB8AD; --rx-soft:#2BB8AD22;
+ --good:#5BD17F; --warn:#E8C44A;
+ --infra:#7AA7FF; --public:#5BD17F;
+ --map-bg:#0C1219;
+}
+[data-theme="light"]{
+ --bg:#F3F5F7; --panel:#FFFFFF; --panel-2:#F7F9FB; --line:#DCE2E8;
+ --text:#10171F; --muted:#5A6B7B;
+ --tx:#B86A12; --tx-soft:#B86A1218;
+ --rx:#0E857C; --rx-soft:#0E857C14;
+ --good:#1E9E4A; --warn:#9A7710;
+ --infra:#2563EB; --public:#1E9E4A;
+ --map-bg:#E9EEF2;
+}
+*{box-sizing:border-box}
+body{margin:0;font-family:var(--body);background:var(--bg);color:var(--text);
+ -webkit-font-smoothing:antialiased;line-height:1.5}
+a{color:inherit;text-decoration:none}
+.mono{font-family:var(--mono)}
+.wrap{max-width:1080px;margin:0 auto;padding:1.25rem 1rem 3rem}
+
+/* NAV */
+.nav{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:.5rem;
+ padding:.6rem 1rem;background:color-mix(in oklab,var(--panel) 88%,transparent);
+ backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
+.brand{display:flex;align-items:center;gap:.6rem;font-family:var(--display);
+ font-weight:700;letter-spacing:.04em;font-size:1.05rem}
+.brand .logo{height:22px;width:auto;color:var(--text)}
+.brand .logo .arcs{stroke:var(--tx)}
+.navlinks{display:none;margin-left:1rem;gap:.15rem}
+.navlinks a{font-size:.85rem;padding:.35rem .6rem;border-radius:7px;color:var(--muted);
+ display:flex;align-items:center;gap:.35rem}
+.navlinks a:hover{background:var(--tx-soft);color:var(--text)}
+.navlinks a.active{color:var(--text);background:var(--tx-soft)}
+.navlinks a .i{width:6px;height:6px;border-radius:50%;background:currentColor;opacity:.7}
+.spacer{flex:1}
+.iconbtn{width:34px;height:34px;border-radius:8px;border:1px solid var(--line);
+ background:var(--panel-2);color:var(--text);display:grid;place-items:center;cursor:pointer}
+@media(min-width:1000px){.navlinks{display:flex}.burger{display:none}}
+
+/* PANEL + buttons + badges */
+.panel{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);overflow:hidden}
+.panel-h{display:flex;align-items:center;justify-content:space-between;padding:.85rem 1rem;border-bottom:1px solid var(--line)}
+.panel-h h2{font-family:var(--display);font-weight:600;font-size:1rem;margin:0;letter-spacing:.02em}
+.btn{font-family:var(--body);font-weight:600;font-size:.82rem;padding:.45rem .8rem;border-radius:8px;
+ background:var(--tx);color:#0B0F14;border:none;cursor:pointer}
+[data-theme="light"] .btn{color:#fff}
+.btn-ghost{background:transparent;color:var(--muted);border:1px solid var(--line)}
+.badge{font-family:var(--mono);font-size:.66rem;letter-spacing:.04em;padding:.12rem .5rem;border-radius:99px;border:1px solid var(--line)}
+.b-tx{color:var(--tx);background:var(--tx-soft);border-color:transparent}
+.b-rx{color:var(--rx);background:var(--rx-soft);border-color:transparent}
+.chip{display:inline-flex;align-items:center;gap:.35rem;font-family:var(--mono);font-size:.68rem;
+ color:var(--muted);border:1px solid var(--line);border-radius:99px;padding:.18rem .55rem;background:var(--panel-2)}
+.chip b{color:var(--text);font-weight:600}
+
+/* PAGE HEAD */
+.page-head{display:flex;align-items:center;flex-wrap:wrap;gap:.6rem;margin-bottom:1rem}
+.page-title{font-family:var(--display);font-weight:700;font-size:1.5rem;letter-spacing:.02em;margin:0}
+.page-head .spacer{flex:1}
+
+/* FORMS / FILTERS */
+.filters{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);
+ padding:.9rem 1rem;margin-bottom:1rem;display:grid;gap:.7rem;
+ grid-template-columns:1fr;align-items:end}
+@media(min-width:760px){.filters{grid-template-columns:2fr 1fr 1fr auto auto}}
+.field{display:flex;flex-direction:column;gap:.25rem}
+.field label{font-family:var(--mono);font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
+input,select{font-family:var(--body);font-size:.85rem;background:var(--panel-2);color:var(--text);
+ border:1px solid var(--line);border-radius:8px;padding:.5rem .6rem;width:100%}
+input:focus,select:focus{outline:2px solid var(--tx);outline-offset:1px}
+
+/* TABLE */
+.tbl-mobile-sort{display:block;margin-bottom:.75rem}
+@media(min-width:760px){.tbl-mobile-sort{display:none}}
+table{width:100%;border-collapse:collapse;font-size:.85rem}
+th{text-align:left;font-family:var(--mono);font-size:.66rem;letter-spacing:.1em;text-transform:uppercase;
+ color:var(--muted);font-weight:500;padding:.55rem 1rem;white-space:nowrap}
+th.sort{cursor:pointer}
+th.sort .caret{opacity:.55;margin-left:.25rem}
+th.sort.asc .caret::after{content:"▲"} th.sort.desc .caret::after{content:"▼"}
+td{padding:.6rem 1rem;border-top:1px solid var(--line)}
+tbody tr:hover td{background:var(--panel-2)}
+.key{font-family:var(--mono);font-size:.78rem;color:var(--muted)}
+.node{display:flex;align-items:center;gap:.6rem}.node .em{font-size:1.1rem}.node .nm{font-weight:600}
+.time{font-family:var(--mono);color:var(--muted);font-size:.8rem}
+.observers{display:inline-flex;align-items:center;gap:.3rem;font-family:var(--mono);font-size:.72rem;color:var(--muted)}
+.table-scroll{overflow-x:auto}
+.desktop-only{display:none}
+@media(min-width:760px){.desktop-only{display:block}.mobile-only{display:none}}
+
+/* MOBILE CARDS */
+.cards{display:flex;flex-direction:column;gap:.55rem}
+.ncard{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);padding:.75rem .85rem;
+ display:flex;align-items:center;gap:.7rem}
+.ncard .meta{flex:1;min-width:0}
+.ncard .nm{font-weight:600}
+.ncard .sub{font-family:var(--mono);font-size:.72rem;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
+
+/* PAGINATION */
+.pager{display:flex;justify-content:center;gap:.25rem;padding:1rem;flex-wrap:wrap}
+.pager a{min-width:34px;text-align:center;padding:.35rem .6rem;border:1px solid var(--line);border-radius:8px;
+ font-family:var(--mono);font-size:.8rem;color:var(--muted)}
+.pager a.cur{background:var(--tx-soft);color:var(--text);border-color:transparent}
+
+/* MAP */
+.map-layout{display:grid;gap:1rem;grid-template-columns:1fr}
+@media(min-width:900px){.map-layout{grid-template-columns:260px 1fr}}
+.mapwrap{position:relative;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;
+ min-height:460px;background:var(--map-bg);
+ background-image:
+ linear-gradient(color-mix(in oklab,var(--line) 60%,transparent) 1px,transparent 1px),
+ linear-gradient(90deg,color-mix(in oklab,var(--line) 60%,transparent) 1px,transparent 1px);
+ background-size:42px 42px}
+.mapwrap .ring{position:absolute;border:1px solid var(--tx);border-radius:50%;opacity:.18;pointer-events:none}
+.pin{position:absolute;width:16px;height:16px;border-radius:50%;transform:translate(-50%,-50%);
+ border:2px solid var(--bg);box-shadow:0 0 0 2px currentColor}
+.pin.infra{background:var(--infra);color:var(--infra)}
+.pin.public{background:var(--public);color:var(--public)}
+.pin .plabel{position:absolute;left:14px;top:-2px;white-space:nowrap;font-family:var(--mono);font-size:.66rem;
+ color:var(--text);background:color-mix(in oklab,var(--panel) 85%,transparent);padding:.05rem .35rem;border-radius:4px;border:1px solid var(--line)}
+.popup{position:absolute;width:210px;border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);
+ box-shadow:0 8px 24px #0006;padding:.7rem .8rem;font-size:.8rem}
+.popup h3{font-family:var(--display);font-size:.95rem;margin:0 0 .3rem;display:flex;align-items:center;gap:.4rem}
+.popup .row{display:flex;justify-content:space-between;color:var(--muted);font-family:var(--mono);font-size:.72rem;margin:.12rem 0}
+.popup a{color:var(--tx);font-weight:600;font-size:.78rem}
+.legend{position:absolute;left:12px;bottom:12px;background:color-mix(in oklab,var(--panel) 90%,transparent);
+ border:1px solid var(--line);border-radius:8px;padding:.5rem .7rem;font-size:.74rem}
+.legend .li{display:flex;align-items:center;gap:.45rem;margin:.15rem 0;color:var(--muted)}
+.legend .sw{width:11px;height:11px;border-radius:50%}
+
+.foot{max-width:1080px;margin:2rem auto 0;padding:1.5rem 1rem;color:var(--muted);font-size:.78rem;
+ border-top:1px solid var(--line);text-align:center}
+.note{position:fixed;left:50%;transform:translateX(-50%);bottom:14px;font-family:var(--mono);font-size:.68rem;
+ color:var(--muted);background:var(--panel);border:1px solid var(--line);padding:.3rem .7rem;border-radius:99px;z-index:30}
diff --git a/design-mockups/field-station.html b/design-mockups/field-station.html
new file mode 100644
index 0000000..3d394ba
--- /dev/null
+++ b/design-mockups/field-station.html
@@ -0,0 +1,175 @@
+
+
+
+
+
+Field Station — MeshCore Hub mockup
+
+
+
+
+
+
+
+
+
+
+ ◐
+ ≡
+
+
+
+
+
+
+
+ ON AIR · 42 NODES
+ IPNET
+ Off-grid encrypted LoRa mesh. Tracking who's transmitting, how packets propagate, and where the network reaches.
+
+
+
+
+
Adverts · 7d
1,284
flood & direct
+
Messages · 7d
318
6 channels
+
+
+
+
+
Recent nodes View all
+
+ Node Public key Route Last heard
+
+ 📡 Holbeck-Relay
a1f3…9c2e DIRECT 2m ago
+ 💬 kestrel
7b02…4d1a FLOOD 11m ago
+ 🪧 Briggate-Room
e5c9…aa70 FLOOD 38m ago
+ 📡 Armley-Hill
3d8e…1f55 DIRECT 1h ago
+
+
+
+
+
+
+Field Station · click ◐ to toggle light/dark · resize to portrait to test mobile
+
+
+
diff --git a/design-mockups/index.html b/design-mockups/index.html
new file mode 100644
index 0000000..71d7fe6
--- /dev/null
+++ b/design-mockups/index.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+IPNet — design mockups
+
+
+
+
+
IPNet — theme mockups
+
Each theme has three pages. Click ◐ (top-right of any page) to toggle light/dark. Resize the window narrow to test mobile portrait. Nav links move between that theme's pages. All keep the existing navigation and functionality — only palette, type, and a signature element change.
+
+
+
1 · Field Station
+
Radio instrument console. Amber transmit + cyan receive. Chakra Petch + IBM Plex. RF range-rings signature.
+
+
+
+
+
2 · Topographic
+
Cartographic survey. Rust + topo green. Archivo Narrow + Inter. Faint contour-line signature.
+
+
+
+
+
3 · Packet Monitor
+
Live ops console. Monospace-forward, dense, square corners. JetBrains Mono + IBM Plex Sans.
+
+
+
+
Maps are stylised placeholders (CSS-drawn) to show the themed chrome — filters, markers, popups, legend — not real Leaflet tiles. The production build keeps the real Leaflet map and just restyles its container, popups, and markers.
+
+
+
diff --git a/design-mockups/packet-monitor-list.html b/design-mockups/packet-monitor-list.html
new file mode 100644
index 0000000..d03f115
--- /dev/null
+++ b/design-mockups/packet-monitor-list.html
@@ -0,0 +1,78 @@
+
+
+
+
+
+Packet Monitor — Advertisements
+
+
+
+
+
+
+
+ IPNET
+
+
+ ◐
+ ≡
+
+
+
+
+
advertisements
+
UTC+1
+
1284 total
+
+
⏸
+
+
+
+
+
sort_by newest first oldest first node name
+
+
+
+
+
+
+
+Packet Monitor · List view · ◐ toggle theme · resize narrow for mobile cards
+
+
+
diff --git a/design-mockups/packet-monitor-map.html b/design-mockups/packet-monitor-map.html
new file mode 100644
index 0000000..fdc4733
--- /dev/null
+++ b/design-mockups/packet-monitor-map.html
@@ -0,0 +1,68 @@
+
+
+
+
+
+Packet Monitor — Map
+
+
+
+
+
+
+
+ IPNET
+
+
+ ◐
+ ≡
+
+
+
+
+
map
+ 42 nodes
+ 18 shown
+ UTC+1
+
+
+
+
+
+
+
Holbeck-Relay · 2m
+
kestrel · 6m
+
Briggate-Room · 11m
+
Armley-Hill · 18m
+
g7xyz · 24m
+
+
+
+
+
infrastructure
+
public node
+
+
+
+
+
+
+Packet Monitor · Map view · ◐ toggle theme · resize narrow to stack filters
+
+
+
diff --git a/design-mockups/packet-monitor.css b/design-mockups/packet-monitor.css
new file mode 100644
index 0000000..b3ea89a
--- /dev/null
+++ b/design-mockups/packet-monitor.css
@@ -0,0 +1,121 @@
+/* ===== Packet Monitor — shared theme stylesheet (mockup) ===== */
+:root{
+ --display:"JetBrains Mono",ui-monospace,monospace;
+ --body:"IBM Plex Sans",system-ui,sans-serif;
+ --mono:"JetBrains Mono",ui-monospace,monospace;
+ --radius:3px;
+}
+[data-theme="dark"]{
+ --bg:#07090B; --panel:#0E1316; --panel-2:#141B1F; --line:#1A2129;
+ --text:#D7E0E2; --muted:#6F8088;
+ --accent:#5FB874; --accent-soft:#5FB87422;
+ --amber:#D39E2A; --amber-soft:#D39E2A1c;
+ --infra:#5FB874; --public:#D39E2A;
+ --map-bg:#080B0D;
+}
+[data-theme="light"]{
+ --bg:#F6F8F8; --panel:#FFFFFF; --panel-2:#F0F3F3; --line:#D7DEDE;
+ --text:#0C1416; --muted:#5A696D;
+ --accent:#2F8F4E; --accent-soft:#2F8F4E14;
+ --amber:#9A7415; --amber-soft:#9A741514;
+ --infra:#2F8F4E; --public:#9A7415;
+ --map-bg:#EAEFEF;
+}
+*{box-sizing:border-box}
+body{margin:0;font-family:var(--body);background:var(--bg);color:var(--text);-webkit-font-smoothing:antialiased;line-height:1.5}
+a{color:inherit;text-decoration:none}
+.mono{font-family:var(--mono)}
+.wrap{max-width:1100px;margin:0 auto;padding:1.1rem 1rem 3rem}
+
+/* NAV */
+.nav{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:.5rem;padding:.55rem 1rem;background:var(--panel);border-bottom:1px solid var(--line)}
+.brand{display:flex;align-items:center;gap:.5rem;font-family:var(--display);font-weight:800;font-size:.95rem;letter-spacing:.02em}
+.brand .logo{height:20px;width:auto;color:var(--text)}
+.brand .logo .arcs{stroke:var(--accent)}
+.navlinks{display:none;margin-left:1rem;gap:0}
+.navlinks a{font-family:var(--mono);font-size:.8rem;padding:.3rem .55rem;color:var(--muted)}
+.navlinks a::before{content:"/";opacity:.4;margin-right:1px}
+.navlinks a:hover{color:var(--text);background:var(--accent-soft)}
+.navlinks a.active{color:var(--accent)}
+.spacer{flex:1}
+.iconbtn{width:32px;height:32px;border-radius:3px;border:1px solid var(--line);background:var(--panel-2);color:var(--text);display:grid;place-items:center;cursor:pointer}
+@media(min-width:1000px){.navlinks{display:flex}.burger{display:none}}
+
+/* PANEL + buttons + badges */
+.panel{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);overflow:hidden}
+.panel-h{display:flex;align-items:center;justify-content:space-between;padding:.65rem 1rem;border-bottom:1px solid var(--line)}
+.panel-h h2{font-family:var(--display);font-weight:700;font-size:.85rem;margin:0;letter-spacing:.02em;text-transform:uppercase}
+.btn{font-family:var(--mono);font-weight:700;font-size:.78rem;padding:.4rem .8rem;border-radius:3px;background:transparent;color:var(--accent);border:1px solid var(--accent);cursor:pointer}
+.btn-ghost{color:var(--muted);border-color:var(--line)}
+.badge{font-family:var(--mono);font-size:.64rem;padding:.08rem .4rem;border-radius:2px}
+.b-tx,.b-amb{color:var(--amber);background:var(--amber-soft)}
+.b-rx,.b-acc{color:var(--accent);background:var(--accent-soft)}
+.chip{display:inline-flex;align-items:center;gap:.35rem;font-family:var(--mono);font-size:.68rem;color:var(--muted);border:1px solid var(--line);border-radius:3px;padding:.16rem .5rem;background:var(--panel-2)}
+.chip b{color:var(--accent);font-weight:700}
+
+/* PAGE HEAD */
+.page-head{display:flex;align-items:center;flex-wrap:wrap;gap:.6rem;margin-bottom:.9rem}
+.page-title{font-family:var(--display);font-weight:800;font-size:1.3rem;letter-spacing:.02em;margin:0;text-transform:lowercase}
+.page-title::before{content:"/";color:var(--muted);opacity:.5}
+.page-head .spacer{flex:1}
+
+/* FORMS / FILTERS */
+.filters{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);padding:.8rem 1rem;margin-bottom:.9rem;display:grid;gap:.6rem;grid-template-columns:1fr;align-items:end}
+@media(min-width:760px){.filters{grid-template-columns:2fr 1fr 1fr auto auto}}
+.field{display:flex;flex-direction:column;gap:.25rem}
+.field label{font-family:var(--mono);font-size:.62rem;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
+input,select{font-family:var(--mono);font-size:.82rem;background:var(--panel-2);color:var(--text);border:1px solid var(--line);border-radius:3px;padding:.45rem .6rem;width:100%}
+input:focus,select:focus{outline:2px solid var(--accent);outline-offset:1px}
+
+/* TABLE (log style) */
+.tbl-mobile-sort{display:block;margin-bottom:.7rem}
+@media(min-width:760px){.tbl-mobile-sort{display:none}}
+table{width:100%;border-collapse:collapse;font-size:.82rem;font-family:var(--mono)}
+th{text-align:left;font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);font-weight:500;padding:.45rem 1rem;white-space:nowrap}
+th.sort{cursor:pointer}
+th.sort .caret{opacity:.55;margin-left:.25rem}
+th.sort.asc .caret::after{content:"▲"} th.sort.desc .caret::after{content:"▼"}
+td{padding:.42rem 1rem;border-top:1px solid var(--line)}
+tbody tr:hover td{background:var(--panel-2)}
+.key{color:var(--muted)}
+.node{display:flex;align-items:center;gap:.5rem}.node .em{font-size:1rem}.node .nm{font-family:var(--body);font-weight:600}
+.time{color:var(--muted);font-size:.8rem}
+.observers{display:inline-flex;align-items:center;gap:.3rem;font-size:.72rem;color:var(--muted)}
+.table-scroll{overflow-x:auto}
+.desktop-only{display:none}
+@media(min-width:760px){.desktop-only{display:block}.mobile-only{display:none}}
+
+/* MOBILE CARDS */
+.cards{display:flex;flex-direction:column;gap:.45rem}
+.ncard{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);padding:.65rem .8rem;display:flex;align-items:center;gap:.6rem}
+.ncard .meta{flex:1;min-width:0}.ncard .nm{font-weight:600}
+.ncard .sub{font-family:var(--mono);font-size:.72rem;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
+
+/* PAGINATION */
+.pager{display:flex;justify-content:center;gap:.25rem;padding:.9rem;flex-wrap:wrap}
+.pager a{min-width:32px;text-align:center;padding:.3rem .55rem;border:1px solid var(--line);border-radius:3px;font-family:var(--mono);font-size:.8rem;color:var(--muted)}
+.pager a.cur{background:var(--accent-soft);color:var(--accent);border-color:transparent}
+
+/* MAP — fine grid */
+.map-layout{display:grid;gap:.9rem;grid-template-columns:1fr}
+@media(min-width:900px){.map-layout{grid-template-columns:250px 1fr}}
+.mapwrap{position:relative;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;min-height:460px;background:var(--map-bg);
+ background-image:
+ linear-gradient(color-mix(in oklab,var(--line) 55%,transparent) 1px,transparent 1px),
+ linear-gradient(90deg,color-mix(in oklab,var(--line) 55%,transparent) 1px,transparent 1px);
+ background-size:28px 28px}
+.pin{position:absolute;width:14px;height:14px;border-radius:2px;transform:translate(-50%,-50%);border:2px solid var(--bg);box-shadow:0 0 0 2px currentColor,0 0 8px currentColor}
+.pin.infra{background:var(--infra);color:var(--infra)}
+.pin.public{background:var(--public);color:var(--public)}
+.pin .plabel{position:absolute;left:12px;top:-3px;white-space:nowrap;font-family:var(--mono);font-size:.66rem;
+ color:var(--text);background:color-mix(in oklab,var(--panel) 88%,transparent);padding:.05rem .35rem;border-radius:2px;border:1px solid var(--line)}
+.popup{position:absolute;width:210px;border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);box-shadow:0 8px 24px #000a;padding:.6rem .7rem;font-size:.78rem;font-family:var(--mono)}
+.popup h3{font-family:var(--display);font-size:.85rem;margin:0 0 .3rem;display:flex;align-items:center;gap:.4rem;text-transform:uppercase}
+.popup .row{display:flex;justify-content:space-between;color:var(--muted);font-size:.72rem;margin:.12rem 0}
+.popup a{color:var(--accent);font-weight:700;font-size:.76rem}
+.legend{position:absolute;left:12px;bottom:12px;background:color-mix(in oklab,var(--panel) 92%,transparent);border:1px solid var(--line);border-radius:3px;padding:.5rem .7rem;font-size:.72rem;font-family:var(--mono)}
+.legend .li{display:flex;align-items:center;gap:.45rem;margin:.15rem 0;color:var(--muted)}
+.legend .sw{width:10px;height:10px;border-radius:2px}
+
+.foot{max-width:1100px;margin:1.8rem auto 0;padding:1.4rem 1rem;color:var(--muted);font-family:var(--mono);font-size:.74rem;border-top:1px solid var(--line);text-align:center}
+.note{position:fixed;left:50%;transform:translateX(-50%);bottom:14px;font-family:var(--mono);font-size:.68rem;color:var(--muted);background:var(--panel);border:1px solid var(--line);padding:.3rem .7rem;border-radius:99px;z-index:30}
diff --git a/design-mockups/packet-monitor.html b/design-mockups/packet-monitor.html
new file mode 100644
index 0000000..0b5978d
--- /dev/null
+++ b/design-mockups/packet-monitor.html
@@ -0,0 +1,140 @@
+
+
+
+
+
+Packet Monitor — MeshCore Hub mockup
+
+
+
+
+
+
+
+
+
+
+ ◐
+ ≡
+
+
+
+
+
+ // network
+ IPNET ● ONLINE
+ nodes 42 adv/7d 1284 msg/7d 318 channels 6 reach 31km
+
+
+
+
+
+
recent_nodes view_all
+
+ node pubkey route last_heard
+
+ 📡 Holbeck-Relay
a1f3…9c2e DIRECT 2m
+ 💬 kestrel
7b02…4d1a FLOOD 11m
+ 🪧 Briggate-Room
e5c9…aa70 FLOOD 38m
+ 📡 Armley-Hill
3d8e…1f55 DIRECT 1h
+
+
+
+
+
+
+Packet Monitor · click ◐ to toggle light/dark · resize to portrait to test mobile
+
+
+
diff --git a/design-mockups/topographic-list.html b/design-mockups/topographic-list.html
new file mode 100644
index 0000000..7e9e8c6
--- /dev/null
+++ b/design-mockups/topographic-list.html
@@ -0,0 +1,78 @@
+
+
+
+
+
+Topographic — Advertisements
+
+
+
+
+
+
+
+ IPNet
+
+
+ ◐
+ ≡
+
+
+
+
+
Advertisements
+
UTC+1
+
1,284 total
+
+
⏸
+
+
+
+
+
Sort by Newest first Oldest first Node name
+
+
+
+
+
+
+
+Topographic · List view · ◐ toggle theme · resize narrow for mobile cards
+
+
+
diff --git a/design-mockups/topographic-map.html b/design-mockups/topographic-map.html
new file mode 100644
index 0000000..407a597
--- /dev/null
+++ b/design-mockups/topographic-map.html
@@ -0,0 +1,68 @@
+
+
+
+
+
+Topographic — Map
+
+
+
+
+
+
+
+ IPNet
+
+
+ ◐
+ ≡
+
+
+
+
+
Map
+ 42 nodes
+ 18 shown
+ UTC+1
+
+
+
+
+
+
+
Holbeck-Relay · 2m
+
kestrel · 6m
+
Briggate-Room · 11m
+
Armley-Hill · 18m
+
g7xyz · 24m
+
+
+
+
+
Infrastructure
+
Public node
+
+
+
+
+
+
+Topographic · Map view · ◐ toggle theme · resize narrow to stack filters
+
+
+
diff --git a/design-mockups/topographic.css b/design-mockups/topographic.css
new file mode 100644
index 0000000..0c010f8
--- /dev/null
+++ b/design-mockups/topographic.css
@@ -0,0 +1,117 @@
+/* ===== Topographic — shared theme stylesheet (mockup) ===== */
+:root{
+ --display:"Archivo Narrow","Archivo",system-ui,sans-serif;
+ --body:"Inter",system-ui,sans-serif;
+ --mono:"IBM Plex Mono",ui-monospace,monospace;
+ --radius:8px;
+}
+[data-theme="dark"]{
+ --bg:#14180F; --panel:#1C2116; --panel-2:#232A1C; --line:#2E3722;
+ --text:#ECE8DA; --muted:#9AA284;
+ --accent:#D8642A; --accent-soft:#D8642A24;
+ --green:#92AE5E; --green-soft:#92AE5E22;
+ --infra:#D8642A; --public:#92AE5E;
+ --map-bg:#171C11;
+}
+[data-theme="light"]{
+ --bg:#F5F1E6; --panel:#FFFDF7; --panel-2:#F0EAD8; --line:#DED7C3;
+ --text:#23271A; --muted:#6E7257;
+ --accent:#B14A1B; --accent-soft:#B14A1B16;
+ --green:#5F7741; --green-soft:#5F774114;
+ --infra:#B14A1B; --public:#5F7741;
+ --map-bg:#EFE9D8;
+}
+*{box-sizing:border-box}
+body{margin:0;font-family:var(--body);background:var(--bg);color:var(--text);-webkit-font-smoothing:antialiased;line-height:1.5}
+a{color:inherit;text-decoration:none}
+.mono{font-family:var(--mono)}
+.wrap{max-width:1080px;margin:0 auto;padding:1.25rem 1rem 3rem}
+
+/* NAV */
+.nav{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:.5rem;padding:.6rem 1rem;
+ background:color-mix(in oklab,var(--panel) 90%,transparent);backdrop-filter:blur(8px);border-bottom:1px solid var(--line)}
+.brand{display:flex;align-items:center;gap:.55rem;font-family:var(--display);font-weight:700;letter-spacing:.02em;font-size:1.15rem;text-transform:uppercase}
+.brand .logo{height:22px;width:auto;color:var(--text)}
+.brand .logo .arcs{stroke:var(--accent)}
+.navlinks{display:none;margin-left:1rem;gap:.1rem}
+.navlinks a{font-family:var(--display);font-size:.95rem;padding:.3rem .55rem;border-radius:6px;color:var(--muted);text-transform:uppercase;letter-spacing:.02em}
+.navlinks a:hover{background:var(--accent-soft);color:var(--text)}
+.navlinks a.active{color:var(--text);background:var(--accent-soft)}
+.spacer{flex:1}
+.iconbtn{width:34px;height:34px;border-radius:7px;border:1px solid var(--line);background:var(--panel-2);color:var(--text);display:grid;place-items:center;cursor:pointer}
+@media(min-width:1000px){.navlinks{display:flex}.burger{display:none}}
+
+/* PANEL + buttons + badges */
+.panel{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);overflow:hidden}
+.panel-h{display:flex;align-items:center;justify-content:space-between;padding:.8rem 1rem;border-bottom:1px solid var(--line)}
+.panel-h h2{font-family:var(--display);font-weight:700;text-transform:uppercase;font-size:1.05rem;margin:0;letter-spacing:.02em}
+.btn{font-family:var(--display);text-transform:uppercase;font-weight:700;letter-spacing:.03em;font-size:.82rem;padding:.45rem .9rem;border-radius:6px;background:var(--accent);color:#fff;border:none;cursor:pointer}
+.btn-ghost{background:transparent;color:var(--muted);border:1px solid var(--line)}
+.badge{font-family:var(--mono);font-size:.64rem;letter-spacing:.04em;padding:.12rem .5rem;border-radius:4px}
+.b-tx,.b-acc{color:var(--accent);background:var(--accent-soft)}
+.b-rx,.b-grn{color:var(--green);background:var(--green-soft)}
+.chip{display:inline-flex;align-items:center;gap:.35rem;font-family:var(--mono);font-size:.68rem;color:var(--muted);border:1px solid var(--line);border-radius:99px;padding:.18rem .55rem;background:var(--panel-2)}
+.chip b{color:var(--text);font-weight:600}
+
+/* PAGE HEAD */
+.page-head{display:flex;align-items:center;flex-wrap:wrap;gap:.6rem;margin-bottom:1rem}
+.page-title{font-family:var(--display);font-weight:700;text-transform:uppercase;font-size:1.7rem;letter-spacing:.02em;margin:0}
+.page-head .spacer{flex:1}
+
+/* FORMS / FILTERS */
+.filters{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);padding:.9rem 1rem;margin-bottom:1rem;display:grid;gap:.7rem;grid-template-columns:1fr;align-items:end}
+@media(min-width:760px){.filters{grid-template-columns:2fr 1fr 1fr auto auto}}
+.field{display:flex;flex-direction:column;gap:.25rem}
+.field label{font-family:var(--mono);font-size:.62rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
+input,select{font-family:var(--body);font-size:.85rem;background:var(--panel-2);color:var(--text);border:1px solid var(--line);border-radius:6px;padding:.5rem .6rem;width:100%}
+input:focus,select:focus{outline:2px solid var(--accent);outline-offset:1px}
+
+/* TABLE */
+.tbl-mobile-sort{display:block;margin-bottom:.75rem}
+@media(min-width:760px){.tbl-mobile-sort{display:none}}
+table{width:100%;border-collapse:collapse;font-size:.85rem}
+th{text-align:left;font-family:var(--mono);font-size:.64rem;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);font-weight:500;padding:.55rem 1rem;white-space:nowrap}
+th.sort{cursor:pointer}
+th.sort .caret{opacity:.55;margin-left:.25rem}
+th.sort.asc .caret::after{content:"▲"} th.sort.desc .caret::after{content:"▼"}
+td{padding:.6rem 1rem;border-top:1px solid var(--line)}
+tbody tr:hover td{background:var(--panel-2)}
+.key{font-family:var(--mono);font-size:.78rem;color:var(--muted)}
+.node{display:flex;align-items:center;gap:.6rem}.node .em{font-size:1.1rem}.node .nm{font-weight:600}
+.time{font-family:var(--mono);color:var(--muted);font-size:.8rem}
+.observers{display:inline-flex;align-items:center;gap:.3rem;font-family:var(--mono);font-size:.72rem;color:var(--muted)}
+.table-scroll{overflow-x:auto}
+.desktop-only{display:none}
+@media(min-width:760px){.desktop-only{display:block}.mobile-only{display:none}}
+
+/* MOBILE CARDS */
+.cards{display:flex;flex-direction:column;gap:.55rem}
+.ncard{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);padding:.75rem .85rem;display:flex;align-items:center;gap:.7rem}
+.ncard .meta{flex:1;min-width:0}.ncard .nm{font-weight:600}
+.ncard .sub{font-family:var(--mono);font-size:.72rem;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
+
+/* PAGINATION */
+.pager{display:flex;justify-content:center;gap:.25rem;padding:1rem;flex-wrap:wrap}
+.pager a{min-width:34px;text-align:center;padding:.35rem .6rem;border:1px solid var(--line);border-radius:6px;font-family:var(--mono);font-size:.8rem;color:var(--muted)}
+.pager a.cur{background:var(--accent-soft);color:var(--text);border-color:transparent}
+
+/* MAP — concentric contour background */
+.map-layout{display:grid;gap:1rem;grid-template-columns:1fr}
+@media(min-width:900px){.map-layout{grid-template-columns:260px 1fr}}
+.mapwrap{position:relative;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;min-height:460px;background:var(--map-bg);
+ background-image:repeating-radial-gradient(circle at 32% 44%,transparent 0 32px,color-mix(in oklab,var(--line) 70%,transparent) 32px 33px);}
+.pin{position:absolute;width:14px;height:14px;border-radius:50% 50% 50% 0;transform:translate(-50%,-100%) rotate(-45deg);border:2px solid var(--bg);box-shadow:0 0 0 2px currentColor}
+.pin.infra{background:var(--infra);color:var(--infra)}
+.pin.public{background:var(--public);color:var(--public)}
+.pin .plabel{position:absolute;left:10px;top:-8px;white-space:nowrap;font-family:var(--mono);font-size:.66rem;transform:rotate(45deg);transform-origin:left;
+ color:var(--text);background:color-mix(in oklab,var(--panel) 88%,transparent);padding:.05rem .35rem;border-radius:4px;border:1px solid var(--line)}
+.popup{position:absolute;width:210px;border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);box-shadow:0 8px 24px #0006;padding:.7rem .8rem;font-size:.8rem}
+.popup h3{font-family:var(--display);text-transform:uppercase;font-size:1rem;margin:0 0 .3rem;display:flex;align-items:center;gap:.4rem}
+.popup .row{display:flex;justify-content:space-between;color:var(--muted);font-family:var(--mono);font-size:.72rem;margin:.12rem 0}
+.popup a{color:var(--accent);font-weight:600;font-size:.78rem}
+.legend{position:absolute;left:12px;bottom:12px;background:color-mix(in oklab,var(--panel) 90%,transparent);border:1px solid var(--line);border-radius:8px;padding:.5rem .7rem;font-size:.74rem}
+.legend .li{display:flex;align-items:center;gap:.45rem;margin:.15rem 0;color:var(--muted)}
+.legend .sw{width:11px;height:11px;border-radius:50%}
+
+.foot{max-width:1080px;margin:2rem auto 0;padding:1.5rem 1rem;color:var(--muted);font-size:.78rem;border-top:1px solid var(--line);text-align:center}
+.note{position:fixed;left:50%;transform:translateX(-50%);bottom:14px;font-family:var(--mono);font-size:.68rem;color:var(--muted);background:var(--panel);border:1px solid var(--line);padding:.3rem .7rem;border-radius:99px;z-index:30}
diff --git a/design-mockups/topographic.html b/design-mockups/topographic.html
new file mode 100644
index 0000000..1b35b41
--- /dev/null
+++ b/design-mockups/topographic.html
@@ -0,0 +1,156 @@
+
+
+
+
+
+Topographic — MeshCore Hub mockup
+
+
+
+
+
+
+
+
+
+
+ ◐
+ ≡
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 53.80°N · 1.55°W
+ IPNet
+ Off-grid encrypted LoRa mesh — a survey of the territory: who's on air, how packets cross the hops, and where the network reaches.
+ ● 42 NODES ON AIR
+
+
+
+
+
Adverts · 7d
1,284
flood & direct
+
Messages · 7d
318
6 channels
+
+
+
+
+
Recent nodes View all
+
+ Node Public key Route Last heard
+
+ 📡 Holbeck-Relay
a1f3…9c2e DIRECT 2m ago
+ 💬 kestrel
7b02…4d1a FLOOD 11m ago
+ 🪧 Briggate-Room
e5c9…aa70 FLOOD 38m ago
+ 📡 Armley-Hill
3d8e…1f55 DIRECT 1h ago
+
+
+
+
+
+
+Topographic · click ◐ to toggle light/dark · resize to portrait to test mobile
+
+
+