- Replaced sepia+hue-rotate chain with grayscale+brightness+contrast
- Green tint via ::before (multiply) + ::after (screen) overlays
- Much brighter base map — roads/coastlines/land clearly visible
- Markers dimmed to #005f15 at 40% opacity
- DivIcon markers at 35% brightness
- Map tiles desaturated + darkened to near-black with green tint
- CRT scanline overlay with subtle flicker animation
- All node markers re-tinted to Matrix green (#00ff41)
- Feed panel: dark green background, monospace font, green text
- Controls/VCR bar: green-on-black theme
- Node detail panel: green themed
- Zoom controls, attribution: themed
- Node labels glow green
- Markers get hue-rotate filter (except matrix hex chars)
- Restores all original colors when toggled off
New toggle in live map controls: 'Matrix' - animates packet hex bytes
flowing along paths in green Matrix-style rain effect.
- Hex bytes from actual packet raw_hex data flow along each hop
- Green (#00ff41) monospace characters with neon glow/text-shadow
- Trail of 8 characters with progressive fade
- Dim green trail line underneath
- Falls back to random hex if no raw data available
- Persists toggle state to localStorage
- Works alongside existing Realistic mode
getElementById('pktPauseBtn') was null because button is rendered by
loadPackets() which runs async. Crash at line 218 prevented wsHandler
from being registered at line 260. Moved to data-action event delegation
which works regardless of render timing.
getById() returns null for deduped observations (not stored in byId).
Client filters on m.data.packet being truthy, so all deduped packets
were silently dropped from WS. Fallback to transmission or raw pktData.
- Add time window dropdown (15min default, up to 24h or All)
- Use 'since' param instead of fixed limit=10000
- Persist selection to localStorage
- Keep limit=50000 as safety net
Migration runs automatically on next startup — drops paths first (FK to
packets), then packets. Removes insertPacket(), insertPath(), all
prepared statements and references to both tables. Server-side type/
observer filtering also removed (client does it in-memory).
Saves ~2M rows (paths) + full packets table worth of disk.
- Server: support comma-separated type filter values (OR logic)
- Server: add observer_id filtering to /api/packets endpoint
- Client: fix type and observer filters to use OR logic for multi-select
- Client: persist observer and type filter selections to localStorage
- Keys: meshcore-observer-filter, meshcore-type-filter
CSS content:attr() doesn't support newlines in any browser. Replaced
with a real <span> child element with white-space:pre-line, shown on
hover via .sort-help:hover .sort-help-tip { display: block }.
Native title tooltips are unreliable (delayed, sometimes not shown).
Replaced with CSS ::after pseudo-element tooltip using data-tip attr.
Shows immediately on hover with proper formatting.
HTML entities like don't work inside JS template literals
(inserted as literal text). Setting .title via JS with actual \n
newlines works correctly in browser tooltips.
When Group by Hash is off, fetches all observations for multi-obs
packets and flattens them into individual rows showing each observer's
view. Previously just showed grouped transmissions without expand arrows.
- Region filter container: remove margin-bottom, use inline-flex align
- Column dropdown checkboxes: 14x14px to match region dropdown
- Sort help ⓘ: use for newlines in title (\n doesn't render)
- Dark mode: .filter-bar .btn.active now retains accent background
(dark theme override was clobbering the active state)
- All filter-bar controls now exactly 34px tall with line-height:1 and border-radius:6px
- col-toggle-btn matched to same height/font-size as other controls
- Controls grouped into 4 logical sections (Filters, Display, Sort, Columns) with vertical separators
- Added title attributes with helpful descriptions to all controls
- Added sort help icon (ⓘ) with detailed tooltip explaining each sort mode
- Mobile responsive: separators hidden on small screens
All filter bar controls now share: height 34px, font-size 13px,
border-radius 6px, same padding. Region dropdown trigger matches
other controls, menu widened to 220px with white-space:nowrap to
prevent text wrapping.
When switching to a non-Observer sort, batch-fetches observations for
all visible multi-observation groups that haven't been expanded yet.
Header rows update immediately without needing manual expand.