diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css
index cacaabad..765f4411 100644
--- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css
+++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css
@@ -47,6 +47,50 @@ SPDX-License-Identifier: GPL-2.0-or-later
--border-hover: color-mix(in srgb, var(--border-light) 80%, var(--text) 20%);
--accent-green-hover: color-mix(in srgb, var(--accent-green) 85%, #fff 15%);
--accent-green-active: color-mix(in srgb, var(--accent-green) 75%, #fff 25%);
+ /* Accent tuned for text/links: mixes toward the theme's text colour,
+ which is always the higher-contrast direction (lighter on dark
+ themes, darker on light). Use for accent-coloured text; keep
+ --accent-green for fills, indicators and meters. */
+ --accent-text: color-mix(in srgb, var(--accent-green) 82%, var(--text) 18%);
+
+ /* ── Design tokens ──────────────────────────────────────────────────
+ Derived tokens use color-mix over themed variables, so they
+ re-resolve per active [data-style]/[data-theme] automatically. */
+
+ /* Elevated surface, one step lighter than --card-bg. Consumed by
+ .controls-tray and other raised panels. */
+ --surface: color-mix(in srgb, var(--card-bg) 90%, var(--text) 7%);
+
+ /* Type scale */
+ --fs-xs: 0.75rem;
+ --fs-sm: 0.85rem;
+ --fs-base: 1rem;
+ --fs-md: 1.125rem;
+ --fs-lg: 1.25rem;
+ --fs-xl: 1.5rem;
+ --fs-2xl: 2rem;
+
+ /* Spacing scale (4px grid) */
+ --space-1: 0.25rem;
+ --space-2: 0.5rem;
+ --space-3: 0.75rem;
+ --space-4: 1rem;
+ --space-5: 1.25rem;
+ --space-6: 1.5rem;
+ --space-8: 2rem;
+
+ /* Corner radii */
+ --radius-sm: 6px;
+ --radius-md: 0.5rem;
+ --radius-lg: 1rem;
+ --radius-pill: 999px;
+
+ /* Motion */
+ --dur-fast: 100ms;
+ --dur-base: 180ms;
+ --dur-slow: 300ms;
+ --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
+ --ease-out: cubic-bezier(0, 0, 0.2, 1);
}
[data-theme="light"] {
@@ -89,6 +133,10 @@ SPDX-License-Identifier: GPL-2.0-or-later
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+ font-size: var(--fs-base);
+ line-height: 1.5;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
margin: 0;
min-height: 100vh;
min-height: 100dvh;
@@ -120,6 +168,57 @@ body {
);
}
}
+/* ── Auth gate ────────────────────────────────────────────────────────
+ Class-based; #display toggling stays inline (driven by app.js). */
+.auth-gate {
+ max-width: 30rem;
+ margin: 0 auto 0.9rem;
+ padding: var(--space-5) 0 var(--space-6);
+ text-align: center;
+}
+.auth-gate-head { margin-bottom: var(--space-6); }
+.auth-gate-title { font-size: var(--fs-md); font-weight: 600; margin-bottom: var(--space-2); }
+.auth-gate-sub { color: var(--text-muted); }
+.auth-form { margin: var(--space-4) 0 0.35rem; }
+.auth-input {
+ width: 100%;
+ padding: 0.65rem 0.75rem;
+ margin-bottom: var(--space-4);
+ border: 1px solid var(--border-light);
+ border-radius: var(--radius-md);
+ background: var(--input-bg);
+ color: var(--text);
+ font-size: var(--fs-base);
+ box-sizing: border-box;
+}
+.auth-submit,
+.auth-guest {
+ width: 100%;
+ padding: 0.65rem 0.75rem;
+ border-radius: var(--radius-md);
+ font-size: var(--fs-base);
+ cursor: pointer;
+ box-sizing: border-box;
+ transition: background-color var(--dur-fast) var(--ease-standard);
+}
+.auth-submit {
+ background: var(--accent-green);
+ color: #fff;
+ border: none;
+ font-weight: 700;
+}
+.auth-submit:hover:not(:disabled) { background: var(--accent-green-hover); }
+.auth-guest {
+ background: var(--btn-bg);
+ color: var(--text);
+ border: 1px solid var(--border-light);
+ font-weight: 600;
+ margin-top: var(--space-4);
+}
+.auth-guest:hover:not(:disabled) { background: var(--btn-hover-bg); }
+.auth-error { color: var(--accent-red); font-size: var(--fs-sm); margin-top: var(--space-4); }
+.auth-role { margin-top: var(--space-4); color: var(--text-muted); font-size: var(--fs-sm); }
+
.label { color: var(--text-muted); font-size: 0.9rem; margin-bottom: 6px; display: block; }
#tab-main .label > span {
display: inline-block;
@@ -220,7 +319,7 @@ input.status-input, select.status-input { width: 100%; padding: 0.45rem 0.5rem;
align-items: stretch;
gap: 0.22rem;
color: var(--text-muted);
- font-size: 0.72rem;
+ font-size: 0.75rem;
line-height: 1.1;
white-space: nowrap;
}
@@ -408,7 +507,7 @@ input.status-input, select.status-input { width: 100%; padding: 0.45rem 0.5rem;
border-radius: 0;
height: 100%;
padding: 0 0.65rem;
- font-size: 0.92rem;
+ font-size: 0.9rem;
background: var(--input-bg);
color: var(--text-muted);
cursor: pointer;
@@ -486,7 +585,7 @@ input.status-input, select.status-input { width: 100%; padding: 0.45rem 0.5rem;
}
.scheduler-cycle-status {
color: var(--text-muted);
- font-size: 0.74rem;
+ font-size: 0.75rem;
text-align: left;
opacity: 0.88;
}
@@ -1357,7 +1456,7 @@ small { color: var(--text-muted); }
}
.header-logo { height: 4.6em; width: auto; flex-shrink: 0; filter: drop-shadow(0 4px 12px rgba(0,0,0,0.35)); }
.subtitle { color: var(--text-muted); font-size: 0.95rem; }
-.subtitle a { color: var(--accent-green); text-decoration: none; }
+.subtitle a { color: var(--accent-text); text-decoration: none; }
.subtitle a:hover { text-decoration: underline; }
.band-tag { display: inline-block; padding: 2px 6px; border-radius: 6px; background: var(--btn-bg); color: var(--text); font-size: 0.82rem; border: 1px solid var(--border-light); margin-left: 6px; }
.signal { display: flex; gap: 0.6rem; align-items: center; }
@@ -1433,7 +1532,7 @@ small { color: var(--text-muted); }
font-size: 0.95rem;
height: auto;
}
-.tab.active { border-bottom-color: var(--accent-green); color: var(--accent-green); font-weight: 600; }
+.tab.active { border-bottom-color: var(--accent-green); color: var(--accent-text); font-weight: 600; }
.tab:hover:not(.active) { color: var(--text); }
/* Tab icons — hidden on desktop, shown on mobile bottom nav */
.tab-icon {
@@ -1458,7 +1557,7 @@ small { color: var(--text-muted); }
.footer { display: flex; justify-content: space-between; align-items: baseline; margin-top: auto; padding-top: 1rem; flex-shrink: 0; }
.full-row { grid-column: 1 / -1; }
.copyright { color: var(--text-muted); font-size: 0.75rem; opacity: 0.7; }
-.copyright a { color: var(--accent-green); text-decoration: none; }
+.copyright a { color: var(--accent-text); text-decoration: none; }
.copyright a:hover { text-decoration: underline; }
.gh-link-wrap {
display: inline-flex;
@@ -1499,7 +1598,7 @@ small { color: var(--text-muted); }
white-space: nowrap;
}
.vol-pct {
- font-size: 0.72rem;
+ font-size: 0.75rem;
color: var(--text-muted);
line-height: 1;
}
@@ -1602,7 +1701,7 @@ small { color: var(--text-muted); }
}
.shortcut-table td {
padding: 0.32rem 0.4rem;
- font-size: 0.88rem;
+ font-size: 0.85rem;
color: var(--text);
border-bottom: 1px solid color-mix(in srgb, var(--border-light) 40%, transparent);
}
@@ -1632,7 +1731,7 @@ small { color: var(--text-muted); }
.shortcut-overlay-hint {
margin-top: 0.7rem;
text-align: center;
- font-size: 0.76rem;
+ font-size: 0.75rem;
color: var(--text-muted);
}
@@ -1706,7 +1805,7 @@ small { color: var(--text-muted); }
text-align: center;
}
.decode-history-overlay-title {
- font-size: 0.98rem;
+ font-size: 1rem;
font-weight: 800;
color: var(--text-heading);
}
@@ -1756,7 +1855,7 @@ small { color: var(--text-muted); }
gap: 0.75rem;
}
.map-qso-summary-title {
- font-size: 0.88rem;
+ font-size: 0.85rem;
font-weight: 800;
letter-spacing: 0.08em;
text-transform: uppercase;
@@ -1841,7 +1940,7 @@ button.map-qso-card:focus-visible {
border-radius: 999px;
background: color-mix(in srgb, var(--accent-green) 16%, transparent);
color: var(--accent-green);
- font-size: 0.76rem;
+ font-size: 0.75rem;
font-weight: 800;
}
.map-qso-card-distance {
@@ -1858,7 +1957,7 @@ button.map-qso-card:focus-visible {
min-width: 0;
}
.map-qso-card-pair {
- font-size: 0.92rem;
+ font-size: 0.9rem;
font-weight: 700;
color: var(--text);
white-space: nowrap;
@@ -1948,7 +2047,7 @@ button.map-qso-card:focus-visible {
border: 1px solid color-mix(in srgb, var(--border-light) 74%, transparent);
background: color-mix(in srgb, var(--card-bg) 82%, transparent);
color: var(--text);
- font-size: 0.76rem;
+ font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.02em;
cursor: pointer;
@@ -1967,7 +2066,7 @@ button.map-qso-card:focus-visible {
border: 1px solid color-mix(in srgb, var(--border-light) 74%, transparent);
background: color-mix(in srgb, var(--card-bg) 82%, transparent);
color: var(--text);
- font-size: 0.76rem;
+ font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.02em;
cursor: pointer;
@@ -2000,7 +2099,7 @@ button.map-qso-card:focus-visible {
display: none;
}
.map-band-legend-title {
- font-size: 0.72rem;
+ font-size: 0.75rem;
font-weight: 800;
letter-spacing: 0.1em;
text-transform: uppercase;
@@ -2027,7 +2126,7 @@ button.map-qso-card:focus-visible {
}
.map-band-legend-text {
min-width: 0;
- font-size: 0.76rem;
+ font-size: 0.75rem;
font-weight: 700;
color: var(--text);
white-space: nowrap;
@@ -2084,7 +2183,7 @@ body.map-fake-fullscreen-active {
}
.aprs-summary-label {
color: var(--text-muted);
- font-size: 0.72rem;
+ font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
@@ -2142,7 +2241,7 @@ body.map-fake-fullscreen-active {
}
.ais-summary-label {
color: var(--text-muted);
- font-size: 0.72rem;
+ font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
@@ -2260,7 +2359,7 @@ body.map-fake-fullscreen-active {
}
.aprs-meta-text {
color: var(--text-muted);
- font-size: 0.76rem;
+ font-size: 0.75rem;
}
.aprs-inline-btn {
display: inline-flex;
@@ -2273,7 +2372,7 @@ body.map-fake-fullscreen-active {
background: var(--filter-bg);
color: var(--filter-fg);
font: inherit;
- font-size: 0.74rem;
+ font-size: 0.75rem;
cursor: pointer;
}
.aprs-inline-btn:hover {
@@ -2286,7 +2385,7 @@ body.map-fake-fullscreen-active {
.aprs-details summary {
cursor: pointer;
color: var(--accent-green);
- font-size: 0.76rem;
+ font-size: 0.75rem;
user-select: none;
}
.aprs-details[open] summary {
@@ -2364,7 +2463,7 @@ body.map-fake-fullscreen-active {
}
.ais-meta-text {
color: var(--text-muted);
- font-size: 0.76rem;
+ font-size: 0.75rem;
}
.ais-pos-link {
color: var(--accent-red);
@@ -2406,7 +2505,7 @@ body.map-fake-fullscreen-active {
}
.vdes-raw {
color: var(--text-muted);
- font-size: 0.76rem;
+ font-size: 0.75rem;
word-break: break-all;
}
.aprs-symbol { display: inline-block; width: 24px; height: 24px; background-size: 384px 192px; vertical-align: middle; margin-right: 0.3rem; }
@@ -2465,18 +2564,18 @@ body.map-fake-fullscreen-active {
}
.decode-locator-tip-meta {
margin-top: 0.12rem;
- font-size: 0.74rem;
+ font-size: 0.75rem;
color: var(--text-muted);
}
.decode-locator-tip-rx {
margin-top: 0.12rem;
- font-size: 0.72rem;
+ font-size: 0.75rem;
color: var(--accent-yellow);
opacity: 0.85;
}
.decode-locator-tip-note {
margin-top: 0.2rem;
- font-size: 0.76rem;
+ font-size: 0.75rem;
line-height: 1.3;
color: var(--text);
word-break: break-word;
@@ -2503,7 +2602,7 @@ body.map-fake-fullscreen-active {
background: color-mix(in srgb, var(--card-bg) 88%, transparent);
color: color-mix(in srgb, var(--accent-green) 72%, var(--accent-yellow));
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.22);
- font-size: 0.72rem;
+ font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.03em;
white-space: nowrap;
@@ -2576,7 +2675,7 @@ body.map-fake-fullscreen-active {
flex: 0 0 auto;
min-width: 4.4rem;
padding-top: 0.35rem;
- font-size: 0.72rem;
+ font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.03em;
text-transform: uppercase;
@@ -2604,7 +2703,7 @@ body.map-fake-fullscreen-active {
border: 1px solid color-mix(in srgb, var(--border-light) 82%, transparent);
background: color-mix(in srgb, var(--input-bg) 92%, transparent);
color: var(--text-muted);
- font-size: 0.76rem;
+ font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.02em;
text-transform: uppercase;
@@ -2621,7 +2720,7 @@ body.map-fake-fullscreen-active {
color: var(--accent-green);
}
.map-locator-empty {
- font-size: 0.74rem;
+ font-size: 0.75rem;
color: var(--text-muted);
opacity: 0.8;
align-self: flex-start;
@@ -2655,7 +2754,7 @@ body.map-fake-fullscreen-active {
background: color-mix(in srgb, var(--input-bg) 96%, transparent);
}
.map-locator-chip-text {
- font-size: 0.77rem;
+ font-size: 0.78rem;
font-weight: 600;
}
.map-search-input {
@@ -2712,7 +2811,7 @@ body.map-fake-fullscreen-active {
.rds-raw-header { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; margin-bottom: 0.3rem; }
.rds-raw-label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); margin-bottom: 0.3rem; }
.rds-raw-header .rds-raw-label { margin-bottom: 0; }
-#rds-raw-copy-btn { height: 1.65rem; padding: 0 0.55rem; font-size: 0.72rem; }
+#rds-raw-copy-btn { height: 1.65rem; padding: 0 0.55rem; font-size: 0.75rem; }
.rds-raw { background: var(--input-bg); border: 1px solid var(--border-light); border-radius: 6px; padding: 0.5rem 0.6rem; font-size: 0.8rem; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; color: var(--text); white-space: pre; overflow-x: auto; margin: 0; }
.cw-controls { display: flex; gap: 0.6rem; align-items: center; margin-bottom: 0.75rem; }
@@ -2733,7 +2832,9 @@ body.map-fake-fullscreen-active {
.cw-config input[type="number"][readonly] { opacity: 0.6; }
.cw-config input[type="number"]:disabled { opacity: 0.58; }
-button:focus-visible, input:focus-visible, select:focus-visible {
+button:focus-visible, input:focus-visible, select:focus-visible,
+textarea:focus-visible, a:focus-visible,
+canvas:focus-visible, [tabindex]:focus-visible {
outline: 2px solid var(--accent-green);
outline-offset: 2px;
}
@@ -2844,7 +2945,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
}
/* Collapse verbose subtitles — the About tab has this info */
.tab-bar .subtitle { display: none; }
- .tab-bar .title { font-size: 0.92rem; }
+ .tab-bar .title { font-size: 0.9rem; }
.tab-bar-nav {
position: fixed;
left: calc(0.6rem + env(safe-area-inset-left));
@@ -3506,7 +3607,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
will-change: transform;
cursor: pointer;
font-weight: 600;
- font-size: 0.66rem;
+ font-size: 0.65rem;
background: var(--bm-cat-bg, var(--accent-yellow));
color: var(--bm-cat-fg, #1a202c);
border: 1px solid var(--bm-cat-bg, var(--accent-yellow));
@@ -3598,7 +3699,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
}
.spectrum-bookmark-chip-side .spectrum-bookmark-name {
width: 100%;
- font-size: 0.64rem;
+ font-size: 0.65rem;
font-weight: 600;
white-space: nowrap;
overflow: hidden;
@@ -3662,7 +3763,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
height: 1.5rem;
min-height: 0;
padding: 0 8px;
- font-size: 0.73rem;
+ font-size: 0.75rem;
}
#spectrum-level-row {
display: flex;
@@ -3709,7 +3810,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
height: 1.5rem;
min-height: 0;
padding: 0 8px;
- font-size: 0.73rem;
+ font-size: 0.75rem;
}
#spectrum-gamma-label {
display: flex;
@@ -3724,7 +3825,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
cursor: pointer;
}
#spectrum-gamma-value {
- font-size: 0.72rem;
+ font-size: 0.75rem;
min-width: 1.6rem;
text-align: right;
}
@@ -3882,7 +3983,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
.bm-label input,
.bm-label select {
- font-size: 0.88rem;
+ font-size: 0.85rem;
padding: 0.35rem 0.5rem;
}
@@ -3938,7 +4039,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
align-items: center;
gap: 0.35rem;
color: var(--text);
- font-size: 0.84rem;
+ font-size: 0.85rem;
}
.bm-decoder-check input {
@@ -4048,7 +4149,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
.bm-page-summary,
.bm-page-indicator {
color: var(--text-muted);
- font-size: 0.88rem;
+ font-size: 0.85rem;
}
.bm-page-controls {
display: flex;
@@ -4266,7 +4367,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
color: var(--text);
border-radius: var(--radius);
padding: 0.55rem 1rem;
- font-size: 0.88rem;
+ font-size: 0.85rem;
}
#sch-sat-form-cancel:hover {
background: var(--border);
@@ -4478,7 +4579,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
.sch-log-action {
font-weight: 600;
text-transform: uppercase;
- font-size: 0.72rem;
+ font-size: 0.75rem;
}
.sch-log-bm {
color: var(--accent);
@@ -4687,7 +4788,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
}
.bgd-checklist-meta {
margin-left: 0;
- font-size: 0.72rem;
+ font-size: 0.75rem;
}
}
/* ── SAT panel ──────────────────────────────────────────────────────── */
@@ -4756,7 +4857,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
gap: 0.25rem;
}
.stats-control-label {
- font-size: 0.72rem;
+ font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
@@ -4796,7 +4897,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
line-height: 1.1;
}
.stats-counter-label {
- font-size: 0.74rem;
+ font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
@@ -4819,7 +4920,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
gap: 0.18rem;
}
.stats-section-title {
- font-size: 0.88rem;
+ font-size: 0.85rem;
font-weight: 800;
letter-spacing: 0.08em;
text-transform: uppercase;
@@ -4884,7 +4985,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
#tab-statistics { padding: 0.75rem; }
.stats-counters { grid-template-columns: repeat(2, 1fr); }
.stats-counter-value { font-size: 1.3rem; }
- .stats-bar-label { min-width: 4rem; font-size: 0.72rem; }
+ .stats-bar-label { min-width: 4rem; font-size: 0.75rem; }
.stats-section { padding: 0.8rem 0.85rem 0.9rem; }
}
@@ -4945,3 +5046,18 @@ button:focus-visible, input:focus-visible, select:focus-visible {
-webkit-backdrop-filter: blur(12px);
}
}
+
+/* ── Panel-switch fade ────────────────────────────────────────────────
+ Panels are shown by clearing inline display (app.js), so this fires on
+ every tab/sub-tab change. Opacity-only to avoid transforming canvases
+ and the Leaflet map. Gated so reduced-motion users get instant switches. */
+@media (prefers-reduced-motion: no-preference) {
+ .tab-panel,
+ .sub-tab-panel {
+ animation: trx-fade-in var(--dur-base) var(--ease-out);
+ }
+}
+@keyframes trx-fade-in {
+ from { opacity: 0; }
+ to { opacity: 1; }
+}