Commit Graph

245 Commits

Author SHA1 Message Date
sjg 723da3f7ed [fix](trx-frontend-http): make decode history lists fill remaining viewport
Replace the fixed max-height: 360px on FT8/FT4/FT2/WSPR message
containers with flex-based layout so they grow to fill the available
space. Make #content, .tab-panel, and .sub-tab-panel flex containers
that propagate height down the layout chain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 23:20:49 +01:00
sjg da799a1d1f [fix](trx-frontend): widen main panel on large screens
Allow the main frontend card to grow past the previous 1280px cap
on large screens while keeping side gutters for bookmark stacks.

Only widen the desktop layout at 1440px+ and cap it at 1600px so the
main content stays readable with room for side bookmarks.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 22:07:36 +01:00
sjg 49659a5ce7 [style](trx-frontend-http): increase spacing in scheduler entry form
Row gap 0.5→0.75rem and label-to-input gap 0.2→0.35rem, scoped
to #sch-entry-form so the bookmark form is unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 01:42:42 +01:00
sjg d6d7c7d1f0 [style](trx-frontend-http): make scheduler entry Edit/Remove buttons smaller
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 01:41:57 +01:00
sjg 8da4c49d1d [feat](trx-frontend-http): align scheduler entry form with bookmark modal
Replace the inline always-visible add-row with a modal overlay
(same fixed + blurred-backdrop pattern as the bookmark add/edit
form). The "+ Add Entry" button opens the modal; each row now has
Edit and Remove buttons. Edit pre-fills the modal and updates the
entry in-place on save. CSS reuses the existing bookmark modal
selectors rather than duplicating rules.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-17 01:40:37 +01:00
sjg 0f57fb8920 [fix](trx-frontend-http): fix axis bookmark chip positioning after name span addition
querySelectorAll("span") was picking up the inner .spectrum-bookmark-name
spans added in the previous commit, causing chips[i] to map to the wrong
element during left-position assignment.  Switch to :scope > span to
select only direct-child chip spans.

Also revert axis bar from height:auto (which breaks the CSS transition and
collapses the bar) to height:38px with overflow:visible to accommodate
two-line labels while keeping the open/close animation intact.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-16 23:37:11 +01:00
sjg 4a12d79f92 [feat](trx-frontend-http): disable path animations above threshold; wrap axis bookmark labels
Suppress stroke-dashoffset animation and drop-shadow filter on all
contact/radio paths when decodeContactPaths.size > 20 by toggling
.map-paths-static on #aprs-map, avoiding per-frame GPU compositing
with large decode histories.

Wrap non-sideStack bookmark chip labels in
<span class="spectrum-bookmark-name"> and allow word-break on axis
chips so long names split across two lines instead of being clipped.
Axis bar switches to min-height so it grows to fit taller chips.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-16 23:33:26 +01:00
sjg efa51443b6 [fix](trx-frontend-http): truncate long bookmark labels with ellipsis
Side-panel chips used white-space: normal + word-break: break-word,
causing names longer than ~16 characters to wrap onto a second line.
Switch to nowrap + overflow: hidden + text-overflow: ellipsis so long
names are clipped cleanly in a single line.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-16 23:20:29 +01:00
sjg b1f52bbfa5 [fix](trx-frontend-http): fix FT4/FT2/WSPR message container styling and cap DOM rows
Apply #ft8-messages container style (border, rounded corners, monospace
font, max-height with scroll) to #ft4-messages, #ft2-messages, and
#wspr-messages which were missing it.

Add #ft4-decode-toggle-btn and #ft2-decode-toggle-btn to the narrow-
screen white-space:nowrap media query rule alongside FT8/WSPR.

Cap DOM rows rendered per history view to 200 (FT8_MAX_DOM_ROWS,
FT4_MAX_DOM_ROWS, FT2_MAX_DOM_ROWS). Full history is retained in
memory; only the DOM representation is bounded. This prevents tab
switching from becoming sluggish after a long decode session where
thousands of rows accumulate in the DOM.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-15 08:46:14 +01:00
sjg b032473801 [feat](trx-frontend): simplify decoder history overlays
Move full-history clear actions into Settings > History.
Remove decoder pause controls and pause-only buffering paths.
Add close controls to live overlay bars and fix FT4/FT2 overlay naming.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
2026-03-14 20:13:55 +01:00
sjg e9cb2852be [fix](trx-frontend-http): restore longest qso card styling
Override the global button chrome on longest-QSO cards so they keep
the intended card layout instead of inheriting fixed control sizing.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 17:57:57 +01:00
sjg 4114e0b9fa [fix](trx-frontend-http): speed up decode history replay
Serve decode history as gzipped CBOR and decode it in the frontend.
Defer map materialization until replay completes to avoid replay-time stutter,
and include the pending longest-QSO style adjustment.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 17:47:49 +01:00
sjg 86768c8e7f [fix](trx-frontend-http): focus longest qso map paths
Let users click longest-QSO cards to isolate a single contact path on the map and click again to restore all visible contact paths. Also remove the extra inner panel styling from decode map tooltips so the popup renders as a single container.

Verification: node --check src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js
Verification: git diff --check -- src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 17:01:42 +01:00
sjg d5c3283b37 [fix](trx-frontend-http): restore map history window state
Keep map history data cached when the history window is reduced so older APRS, AIS, VDES, FT8, and WSPR items can be shown again when the user expands the window, and add a global decode-history replay overlay with progress updates across the UI. Also update the longest QSO summary to render bidirectional contacts with <-> labels.

Verification: node --check src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js
Verification: git diff --check -- src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 16:58:05 +01:00
sjg e2517ec184 [feat](trx-frontend-http): add longest map qso summary
Add a map summary section below the map that lists the five longest directed FT8 and WSPR contacts in the current view, including distance, band, age, and locator details.

Verification: node --check src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js
Verification: git diff --check -- src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 16:46:06 +01:00
sjg 3b52fdf232 [fix](trx-frontend-http): add map history limit filter
Add a map filter-panel history picker with 15 minute through 24 hour retention options and prune dynamic APRS, AIS, VDES, FT8, and WSPR overlays to the selected age window.

Verification: node --check src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 16:41:14 +01:00
sjg 5590ac5c7d [fix](trx-frontend-http): fix scheduler virtual channel selection
Apply scheduler-backed virtual channels as real manual selections so they take control, retune the rig, and restore bookmark decoder state including APRS/PKT. Also remove the inner border from the map decode locator tooltip.\n\nVerification: cargo test -p trx-frontend-http vchan\nVerification: node --check src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/vchan.js\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 13:44:51 +01:00
sjg badf7c0d0f [fix](trx-frontend-http): improve scheduler entry controls
Add previous/next scheduler entry controls for overlapping\ntime-span slots and fix interleave timing calculations so\nthe active slot and countdown align with the overlap window.\n\nVerification: cargo test -p trx-frontend-http scheduler\nVerification: node --check assets/web/plugins/scheduler.js\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 13:11:30 +01:00
sjg 28d5494c3b [fix](trx-frontend-http): correct map auth and overlay behavior
Treat the SPA entry routes as public so direct requests to /map,\n/decoders, /settings, and /about return the app shell and let\nthe frontend show the login screen instead of a 403.\n\nMove the map filter overlay to the bottom-right corner and color\ndecode contact paths by their decoded band so they match the band\nlegend and locator overlays.\n\nVerified with cargo test -p trx-frontend-http.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 12:46:08 +01:00
sjg b9744ef8fd [feat](trx-frontend-http): color radio paths by band or mode
Radio paths and decode contact paths now use the same color as the
marker they belong to, respecting the active filter mode:
- Band mode: color follows the band (golden-angle HSL hue)
- Mode/source mode: color follows the source type (FT8/WSPR/bookmark)

APRS, AIS, and VDES paths use their fixed source colors unchanged.
Decode contact paths sync color when the filter mode is switched.

CSS stroke/stroke-opacity removed from path classes so Leaflet's
color option takes effect; dasharray and flow animation are retained.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-14 12:31:56 +01:00
sjg fb83e3cade [feat](trx-frontend-http): default map filtering to band
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 16:31:40 +01:00
sjg cb824d20ec [fix](trx-frontend-http): separate map corner controls
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 15:48:28 +01:00
sjg e4487d9037 [feat](trx-frontend-http): add map filter panel toggle
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 14:29:29 +01:00
sjg a82a7ab668 [feat](trx-frontend-http): overlay map controls
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 14:18:18 +01:00
sjg b679ff0282 [feat](trx-frontend-http): refine map and scheduler controls
Add separate map path toggles, move scheduler handoff into the channels row, and show a live countdown to the next scheduler cycle.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 00:52:00 +01:00
sjg 4cca188d9f [feat](trx-frontend-http): improve scheduler and decode map controls
Remove settings rig pickers, restore the last scheduler cycle on release, fix FT8 locator role parsing, and add toggleable decode contact paths on the map.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 00:45:12 +01:00
sjg f7cbc0cb02 [fix](trx-frontend-http): move scheduler handoff out of channels row
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 00:28:25 +01:00
sjg 5c28ed1269 [feat](trx-frontend-http): add scheduler control handoff
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-13 00:22:18 +01:00
sjg f8fd4572c7 [feat](trx-frontend-http): paginate bookmarks tab
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 23:57:02 +01:00
sjg 95fccd3da6 [feat](trx-frontend-http): expand background decode selection
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 22:57:25 +01:00
sjg a91a1868d8 [fix](trx-frontend-http): refresh background decode settings UI
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 22:48:24 +01:00
sjg 2462f1dd47 [feat](trx-frontend-http): add background decode settings
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 22:42:50 +01:00
sjg fc24dc37ed [feat](trx-rs): add settings tab and virtual audio plan
Move Scheduler under a new Settings tab in the HTTP frontend.
Add the virtual-channel audio implementation plan document.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 21:55:54 +01:00
sjg add0a93424 [feat](trx-frontend-http): frequency-ordered z-index and hover-to-front for RDS overlay layers
Each RDS PS overlay item (position: absolute within the shared #rds-ps-overlay
container) now receives a z-index derived from its channel frequency: items are
sorted by freq_hz ascending so higher-frequency layers sit on top of
lower-frequency ones by default.

Hovering any layer temporarily assigns it the maximum z-index (entry count + 10)
to bring it to the front; mouseleave restores the frequency-derived default
stored in data-default-z.

Also reverts the incorrectly applied vchan picker layer changes from the
previous commit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 20:12:23 +01:00
sjg 1fe7dc88c6 [feat](trx-frontend-http): add frequency layers display for virtual channels
Render virtual channels as absolutely-positioned layer strips inside a
shared relative container (#vchan-freq-layers). Layers are sorted by
frequency ascending so higher-frequency channels receive a higher z-index
and sit on top by default. Hovering any layer temporarily assigns it the
maximum z-index to bring it to the front; leaving restores the original
stacking order. Each layer is offset by 11 px vertically so all channels
remain visible as a staggered card stack.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-12 20:04:27 +01:00
sjg 93ff35a824 Add per-channel RDS overlays for WFM vchans 2026-03-11 22:39:02 +01:00
sjg af45c32222 [feat](trx-frontend-http): vchan freq display sync, BW accent, scheduler multi-channel
Virtual channel display:
- vchan.js: wrap refreshFreqDisplay() so the main freq field always shows
  the active virtual channel's frequency instead of channel 0's; expose
  vchanSyncAccentUI() to add vchan-ch-active CSS class (colored border) to
  #freq and #spectrum-bw-input when on a non-primary channel
- style.css: --vchan-color (#38bdf8 sky-blue), .vchan-ch-active box-shadow,
  vchan-picker active button left-border accent

Scheduler multi-channel slots:
- scheduler.rs: add center_hz (Option<u64>) and bookmark_ids (Vec<String>)
  to ScheduleEntry; SchedulerStatus gains last_center_hz and
  last_bookmark_ids; background task sends SetCenterFreq before SetFreq
  when center_hz is set and records extra bookmark_ids in status
- scheduler.js: center-freq input and extra-channel bookmark picker (tag
  list with + / × buttons) in the add-entry form; extra channels shown in
  the entries table
- index.html: center freq field + extra bookmark picker widgets; table
  gains Center freq and Extra channels columns

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-11 07:22:36 +01:00
sjg e5aa74a1b6 [feat](trx-frontend-http): virtual channel manager and picker UI
Add client-side virtual channel support (Phase 1 — metadata only):

- vchan.rs: ClientChannelManager keyed by rig_id; tracks per-session
  channel subscriptions and broadcasts list changes via change_tx
- server.rs: instantiate Arc<ClientChannelManager> and expose as app_data
- api.rs: wire ClientChannelManager into /events SSE (session UUID,
  init_rig, update_primary, channel change stream, session cleanup on
  disconnect); add channel CRUD routes:
    GET/POST /channels/{rig_id}
    DELETE   /channels/{rig_id}/{channel_id}
    POST     /channels/{rig_id}/{channel_id}/subscribe
    PUT      /channels/{rig_id}/{channel_id}/freq|mode
- auth.rs: classify /channels/ prefix as Read access
- plugins/vchan.js: channel picker with +/× buttons, subscribe on click,
  SDR-only (shown when filter_controls capability is set)
- app.js: handle SSE `session` and `channels` events, call
  vchanApplyCapabilities from applyCapabilities
- index.html: #vchan-row div + <script src="/vchan.js">
- style.css: .vchan-picker pill styles

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-11 07:00:22 +01:00
sjg 998c6ad0e6 [style](trx-frontend-http): align scheduler buttons with site-wide button styles
Remove custom padding, border-radius, color, cursor, and hover rules from
.sch-save-btn, .sch-reset-btn, and .sch-remove-btn — the global button rule
already handles all of that consistently across every theme.

.sch-save-btn retains only the accent-green background/border-color to mark
it as the primary action; the global hover/active/disabled transitions still
apply.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-10 23:32:16 +01:00
sjg 6874055b1c [feat](trx-frontend-http): add Background Decoding Scheduler
Implements a scheduler that retunes the rig automatically when no SSE
clients are connected.  Two modes are supported:

- Grayline: tunes to per-period bookmarks (dawn/day/dusk/night) based on
  an inline NOAA solar algorithm given station lat/lon.
- Time Span: tunes to bookmarks within user-defined UTC windows; midnight-
  spanning intervals supported.

Backend:
- SchedulerStore (PickleDB, sch:{rig_id} keys) in scheduler.rs
- spawn_scheduler_task polls every 30 s, checks context.sse_clients == 0,
  sends SetFreq + SetMode via RigRequest with rig_id_override
- HTTP API: GET/PUT/DELETE /scheduler/{rig_id}, GET …/status
- sse_clients Arc<AtomicUsize> added to FrontendRuntimeContext and shared
  with the SSE counter in build_server (single source of truth)
- /scheduler/ added to Read auth routes (write requires Control)

Frontend:
- Scheduler tab (clock icon, 6th position) with Grayline/TimeSpan UI
- scheduler.js plugin: loads config + bookmarks, live status polling
  every 15 s, write controls hidden for Rx-role users
- CSS .sch-* component styles added to style.css
- SCHEDULER.md design document at repo root

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-10 23:20:42 +01:00
sjg 81515d921e [fix](trx-frontend-http): AIS map markers use scheme lead color (--accent-green)
Use --accent-green (the primary/lead accent color) for AIS vessel markers and
tracks instead of a hardcoded or red-based color, so they match the active
buttons and other prominent UI elements for every color scheme.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-10 19:37:15 +01:00
sjg 6a755ef2b4 [fix](trx-frontend-http): use dedicated --ais-accent color for map markers
Replace --accent-red with a new --ais-accent CSS variable (default #00aacc
cyan-blue) so AIS vessel markers and track lines are visually distinct from
other UI elements regardless of theme. Light theme uses a slightly darker
#0088aa for readability on the map.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-10 19:34:19 +01:00
sjg ce1ca48384 [fix](trx-frontend-http): remove animation from spectrum center-shift arrows
The global button transition and the :active scale(0.97) transform were
interfering with the translateY(-50%) centering, making the buttons jump
on press. Added transition:none and reduced :active to translateY(-50%)
only (no scale).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-10 19:07:05 +01:00
sjg 9a398f3754 [fix](trx-frontend-http): map fullscreen fallback for mobile Safari
Mobile Safari (iOS) blocks requestFullscreen() on non-video elements,
so the Fullscreen button silently did nothing.

Add a CSS-based fake fullscreen path:
- mapEnterFakeFullscreen() adds .map-fake-fullscreen to #map-stage
  (position:fixed; inset:0; z-index:9000; height:100dvh) and
  map-fake-fullscreen-active to <body> (overflow:hidden).
- toggleMapFullscreen() tries native fullscreen first; catches the
  thrown NotAllowedError (or any other error) and falls back to the
  CSS path. Also handles the case where requestFullscreen is absent.
- mapIsFullscreen() checks for the CSS class in addition to the
  native fullscreen element references.
- mapExitFakeFullscreen() removes both classes on exit.
- Escape key exits CSS fake fullscreen (native handles its own Escape).
- sizeAprsMapToViewport() uses window.innerHeight for the fake path
  since clientHeight may not reflect fixed layout synchronously.
- sizeAprsMapToViewport() is called via requestAnimationFrame after
  toggling so layout is settled before the Leaflet invalidateSize().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-10 19:01:48 +01:00
sjg 2e8f025b19 [fix](trx-frontend-http): fix spectrum center-shift arrow behavior
Two bugs fixed:

1. Wrong vertical position of shift buttons and bookmark side panels.
   top: calc((--spectrum-plot-height - --overview-plot-height) / 2)
   evaluates to 0 when both vars are equal (default 160 px), so
   translateY(-50%) placed the buttons at the top edge of .spectrum-wrap
   instead of mid-canvas. Changed to calc(--spectrum-plot-height / 2).

2. Rapid clicks on the arrows did not accumulate: each call read
   lastSpectrumData.center_hz which is only updated when the server
   sends a new spectrum frame. Added spectrumCenterPendingHz to track
   the optimistic center immediately on click; reset when the server
   confirms a frame near the expected position.

Also hide .spectrum-bookmark-side on ≤640px (no horizontal room on
narrow phones); previously visible but clipped off-screen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-10 18:57:59 +01:00
sjg 51df676e46 [feat](trx-frontend-http): mobile UI improvements
- Fix 5-tab bottom nav (grid was repeat(4) with 5 tabs; About overflowed)
- Add SVG icons to each tab; show icon+label on mobile bottom nav
- Swipe left/right to switch tabs (excludes jog wheel, spectrum canvas,
  map, scrollable containers and form inputs to avoid conflicts)
- Extract navigateToTab() helper used by both click and swipe handlers
- Collapse header subtitles at ≤640px to reclaim vertical space
- Bookmark table → 2-column card layout at ≤640px with ::before labels
- Audio volume labels switch to horizontal row layout at ≤520px;
  squelch slider now also spans full width
- Controls tray uses overflow-x: auto (not visible) at ≤760px so
  content wider than viewport scrolls rather than overflowing layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-10 18:46:44 +01:00
sjg 5a3c013db5 [style](trx-frontend-http): system font, button states, scrollbars, phosphor theme
System font stack: replace bare 'sans-serif' with system-ui / -apple-system
/ BlinkMacSystemFont / Segoe UI chain — sharper rendering on all platforms
at zero extra load cost.

Button hover/active: add transition (100ms) + color-mix hover brightening
+ active depression (translateY 1px) to all buttons. Previously buttons had
zero visual feedback on interaction.

Scrollbar styling: thin (6px) custom scrollbars via ::-webkit-scrollbar and
scrollbar-width/color for Firefox. Thumb uses border-color tinted with the
accent on hover — matches each theme automatically via CSS variables.

Phosphor theme: classic green-phosphor CRT aesthetic — near-black background,
#39ff14 neon-green accent, glow text-shadow on the freq display, matching
spectrum/waterfall canvas palette. Both dark and light variants included.
Registered in the style picker select, setStyle() valid list, and
CANVAS_PALETTE.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-10 18:23:15 +01:00
sjg 90d446c8f4 [fix](trx-frontend-http): add cw-bar-overlay to bar overlay CSS selector
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 22:31:22 +01:00
sjg 4e6a800391 [fix](trx-frontend-http): fix waterfall updates and bookmark top anchoring
Ensure overview waterfall incremental updates continue on HiDPI and anchor bookmark chips to the top of the full spectrum view (waterfall + waveform).\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 21:45:49 +01:00
sjg c4f0844137 [fix](trx-frontend-http): optimize WebGL rendering and pin bookmarks to top
Improve WebGL runtime performance by caching/downsampling overview waterfall texture updates and batching marker/dashed-line draws; keep bookmark chips anchored at the top of the waterfall area.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 21:41:49 +01:00