[style](trx-frontend-http): refine web UI design system and a11y
Introduce a shared design-token layer and apply it to the web frontend for a more consistent, readable, and accessible feel. Pure CSS plus one HTML block; no app.js behaviour changes, and the existing multi-theme (style x light/dark) system is preserved. - Add spacing, type, radius and motion tokens to :root. - Fix undefined --surface consumed by .controls-tray, which dropped the panel background entirely; it now resolves per theme. - Set body line-height and font smoothing; collapse near-duplicate font sizes onto canonical scale steps. - Rebuild the auth gate with classes and replace hardcoded colours (#ff6b6b, #9aa4b5) with theme variables so it renders correctly in every theme. - Add an opacity fade on tab switches, gated by prefers-reduced-motion. - Extend focus-visible rings to the spectrum canvas, tabindex controls and links. - Add a self-theming --accent-text token to lift accent-coloured text (links, active tab) to WCAG AA without altering brand fills. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NFpGtGTWUEYXLwZeZs2RAV Signed-off-by: Stan Grams <sjg@haxx.space>
This commit was merged in pull request #1.
This commit is contained in:
@@ -104,24 +104,24 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Auth gate (hidden by default, shown if auth is required) -->
|
<!-- Auth gate (hidden by default, shown if auth is required) -->
|
||||||
<div id="auth-gate" style="display:none; max-width: 30rem; margin: 0 auto 0.9rem; padding: 1.25rem 0 1.5rem; text-align: center;">
|
<div id="auth-gate" class="auth-gate" style="display:none;">
|
||||||
<div style="margin-bottom: 1.5rem;">
|
<div class="auth-gate-head">
|
||||||
<div style="font-size: 1.1rem; font-weight: 600; margin-bottom: 0.5rem;">Access Required</div>
|
<div class="auth-gate-title">Access Required</div>
|
||||||
<div style="color: var(--text-muted);">Enter passphrase to continue</div>
|
<div class="auth-gate-sub">Enter passphrase to continue</div>
|
||||||
</div>
|
</div>
|
||||||
<form id="auth-form" style="margin: 1rem 0 0.35rem;">
|
<form id="auth-form" class="auth-form">
|
||||||
<input type="password" id="auth-passphrase" placeholder="Passphrase" autocomplete="off" style="width: 100%; padding: 0.65rem 0.75rem; margin-bottom: 1rem; border: 1px solid var(--border-light); border-radius: 0.45rem; background: var(--input-bg); color: var(--text); font-size: 1rem; box-sizing: border-box;" />
|
<input type="password" id="auth-passphrase" class="auth-input" placeholder="Passphrase" autocomplete="off" />
|
||||||
<button type="submit" style="width: 100%; padding: 0.65rem 0.75rem; background: var(--accent-green); color: #fff; border: none; border-radius: 0.45rem; font-weight: 700; cursor: pointer; font-size: 1rem; box-sizing: border-box;">Login</button>
|
<button type="submit" class="auth-submit">Login</button>
|
||||||
</form>
|
</form>
|
||||||
<button id="auth-guest-btn" type="button" style="width: 100%; padding: 0.65rem 0.75rem; background: var(--btn-bg); color: var(--text); border: 1px solid var(--border-light); border-radius: 0.45rem; font-weight: 600; cursor: pointer; font-size: 1rem; box-sizing: border-box; margin-top: 0; display: none;">Continue as Guest</button>
|
<button id="auth-guest-btn" type="button" class="auth-guest" style="display: none;">Continue as Guest</button>
|
||||||
<div id="auth-error" style="color: #ff6b6b; font-size: 0.9rem; margin-top: 1rem; display: none;"></div>
|
<div id="auth-error" class="auth-error" style="display: none;"></div>
|
||||||
<div id="auth-role" style="margin-top: 1rem; color: var(--text-muted); font-size: 0.85rem; display: none;"></div>
|
<div id="auth-role" class="auth-role" style="display: none;"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="tab-main" class="tab-panel">
|
<div id="tab-main" class="tab-panel">
|
||||||
<div id="server-lost-banner" aria-live="assertive"><span class="banner-dot"></span>trx-server connection lost — waiting for reconnect</div>
|
<div id="server-lost-banner" aria-live="assertive"><span class="banner-dot"></span>trx-server connection lost — waiting for reconnect</div>
|
||||||
<div id="loading" role="status" aria-live="polite" style="text-align:center; padding:2rem 0;">
|
<div id="loading" role="status" aria-live="polite" style="text-align:center; padding:2rem 0;">
|
||||||
<div id="loading-title" style="margin-bottom:0.4rem; font-size:1.1rem; font-weight:600;">Initializing (rig)…</div>
|
<div id="loading-title" style="margin-bottom:0.4rem; font-size:1.1rem; font-weight:600;">Initializing (rig)…</div>
|
||||||
<div id="loading-sub" style="color:#9aa4b5;"></div>
|
<div id="loading-sub" style="color:var(--text-muted);"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="content" style="display:none;">
|
<div id="content" style="display:none;">
|
||||||
<div class="signal-visual-block">
|
<div class="signal-visual-block">
|
||||||
|
|||||||
@@ -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%);
|
--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-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-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"] {
|
[data-theme="light"] {
|
||||||
@@ -89,6 +133,10 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
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;
|
margin: 0;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
min-height: 100dvh;
|
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; }
|
.label { color: var(--text-muted); font-size: 0.9rem; margin-bottom: 6px; display: block; }
|
||||||
#tab-main .label > span {
|
#tab-main .label > span {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -220,7 +319,7 @@ input.status-input, select.status-input { width: 100%; padding: 0.45rem 0.5rem;
|
|||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
gap: 0.22rem;
|
gap: 0.22rem;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 0.72rem;
|
font-size: 0.75rem;
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
@@ -408,7 +507,7 @@ input.status-input, select.status-input { width: 100%; padding: 0.45rem 0.5rem;
|
|||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 0 0.65rem;
|
padding: 0 0.65rem;
|
||||||
font-size: 0.92rem;
|
font-size: 0.9rem;
|
||||||
background: var(--input-bg);
|
background: var(--input-bg);
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -486,7 +585,7 @@ input.status-input, select.status-input { width: 100%; padding: 0.45rem 0.5rem;
|
|||||||
}
|
}
|
||||||
.scheduler-cycle-status {
|
.scheduler-cycle-status {
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 0.74rem;
|
font-size: 0.75rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
opacity: 0.88;
|
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)); }
|
.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 { 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; }
|
.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; }
|
.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; }
|
.signal { display: flex; gap: 0.6rem; align-items: center; }
|
||||||
@@ -1433,7 +1532,7 @@ small { color: var(--text-muted); }
|
|||||||
font-size: 0.95rem;
|
font-size: 0.95rem;
|
||||||
height: auto;
|
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:hover:not(.active) { color: var(--text); }
|
||||||
/* Tab icons — hidden on desktop, shown on mobile bottom nav */
|
/* Tab icons — hidden on desktop, shown on mobile bottom nav */
|
||||||
.tab-icon {
|
.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; }
|
.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; }
|
.full-row { grid-column: 1 / -1; }
|
||||||
.copyright { color: var(--text-muted); font-size: 0.75rem; opacity: 0.7; }
|
.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; }
|
.copyright a:hover { text-decoration: underline; }
|
||||||
.gh-link-wrap {
|
.gh-link-wrap {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@@ -1499,7 +1598,7 @@ small { color: var(--text-muted); }
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.vol-pct {
|
.vol-pct {
|
||||||
font-size: 0.72rem;
|
font-size: 0.75rem;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
@@ -1602,7 +1701,7 @@ small { color: var(--text-muted); }
|
|||||||
}
|
}
|
||||||
.shortcut-table td {
|
.shortcut-table td {
|
||||||
padding: 0.32rem 0.4rem;
|
padding: 0.32rem 0.4rem;
|
||||||
font-size: 0.88rem;
|
font-size: 0.85rem;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
border-bottom: 1px solid color-mix(in srgb, var(--border-light) 40%, transparent);
|
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 {
|
.shortcut-overlay-hint {
|
||||||
margin-top: 0.7rem;
|
margin-top: 0.7rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 0.76rem;
|
font-size: 0.75rem;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1706,7 +1805,7 @@ small { color: var(--text-muted); }
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.decode-history-overlay-title {
|
.decode-history-overlay-title {
|
||||||
font-size: 0.98rem;
|
font-size: 1rem;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
color: var(--text-heading);
|
color: var(--text-heading);
|
||||||
}
|
}
|
||||||
@@ -1756,7 +1855,7 @@ small { color: var(--text-muted); }
|
|||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
}
|
}
|
||||||
.map-qso-summary-title {
|
.map-qso-summary-title {
|
||||||
font-size: 0.88rem;
|
font-size: 0.85rem;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
letter-spacing: 0.08em;
|
letter-spacing: 0.08em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
@@ -1841,7 +1940,7 @@ button.map-qso-card:focus-visible {
|
|||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: color-mix(in srgb, var(--accent-green) 16%, transparent);
|
background: color-mix(in srgb, var(--accent-green) 16%, transparent);
|
||||||
color: var(--accent-green);
|
color: var(--accent-green);
|
||||||
font-size: 0.76rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
.map-qso-card-distance {
|
.map-qso-card-distance {
|
||||||
@@ -1858,7 +1957,7 @@ button.map-qso-card:focus-visible {
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
.map-qso-card-pair {
|
.map-qso-card-pair {
|
||||||
font-size: 0.92rem;
|
font-size: 0.9rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
white-space: nowrap;
|
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);
|
border: 1px solid color-mix(in srgb, var(--border-light) 74%, transparent);
|
||||||
background: color-mix(in srgb, var(--card-bg) 82%, transparent);
|
background: color-mix(in srgb, var(--card-bg) 82%, transparent);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
font-size: 0.76rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.02em;
|
letter-spacing: 0.02em;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -1967,7 +2066,7 @@ button.map-qso-card:focus-visible {
|
|||||||
border: 1px solid color-mix(in srgb, var(--border-light) 74%, transparent);
|
border: 1px solid color-mix(in srgb, var(--border-light) 74%, transparent);
|
||||||
background: color-mix(in srgb, var(--card-bg) 82%, transparent);
|
background: color-mix(in srgb, var(--card-bg) 82%, transparent);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
font-size: 0.76rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.02em;
|
letter-spacing: 0.02em;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -2000,7 +2099,7 @@ button.map-qso-card:focus-visible {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.map-band-legend-title {
|
.map-band-legend-title {
|
||||||
font-size: 0.72rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
letter-spacing: 0.1em;
|
letter-spacing: 0.1em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
@@ -2027,7 +2126,7 @@ button.map-qso-card:focus-visible {
|
|||||||
}
|
}
|
||||||
.map-band-legend-text {
|
.map-band-legend-text {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
font-size: 0.76rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@@ -2084,7 +2183,7 @@ body.map-fake-fullscreen-active {
|
|||||||
}
|
}
|
||||||
.aprs-summary-label {
|
.aprs-summary-label {
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 0.72rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.06em;
|
letter-spacing: 0.06em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
@@ -2142,7 +2241,7 @@ body.map-fake-fullscreen-active {
|
|||||||
}
|
}
|
||||||
.ais-summary-label {
|
.ais-summary-label {
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 0.72rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.06em;
|
letter-spacing: 0.06em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
@@ -2260,7 +2359,7 @@ body.map-fake-fullscreen-active {
|
|||||||
}
|
}
|
||||||
.aprs-meta-text {
|
.aprs-meta-text {
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 0.76rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
.aprs-inline-btn {
|
.aprs-inline-btn {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@@ -2273,7 +2372,7 @@ body.map-fake-fullscreen-active {
|
|||||||
background: var(--filter-bg);
|
background: var(--filter-bg);
|
||||||
color: var(--filter-fg);
|
color: var(--filter-fg);
|
||||||
font: inherit;
|
font: inherit;
|
||||||
font-size: 0.74rem;
|
font-size: 0.75rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.aprs-inline-btn:hover {
|
.aprs-inline-btn:hover {
|
||||||
@@ -2286,7 +2385,7 @@ body.map-fake-fullscreen-active {
|
|||||||
.aprs-details summary {
|
.aprs-details summary {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: var(--accent-green);
|
color: var(--accent-green);
|
||||||
font-size: 0.76rem;
|
font-size: 0.75rem;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
.aprs-details[open] summary {
|
.aprs-details[open] summary {
|
||||||
@@ -2364,7 +2463,7 @@ body.map-fake-fullscreen-active {
|
|||||||
}
|
}
|
||||||
.ais-meta-text {
|
.ais-meta-text {
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 0.76rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
.ais-pos-link {
|
.ais-pos-link {
|
||||||
color: var(--accent-red);
|
color: var(--accent-red);
|
||||||
@@ -2406,7 +2505,7 @@ body.map-fake-fullscreen-active {
|
|||||||
}
|
}
|
||||||
.vdes-raw {
|
.vdes-raw {
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 0.76rem;
|
font-size: 0.75rem;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
.aprs-symbol { display: inline-block; width: 24px; height: 24px; background-size: 384px 192px; vertical-align: middle; margin-right: 0.3rem; }
|
.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 {
|
.decode-locator-tip-meta {
|
||||||
margin-top: 0.12rem;
|
margin-top: 0.12rem;
|
||||||
font-size: 0.74rem;
|
font-size: 0.75rem;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
}
|
}
|
||||||
.decode-locator-tip-rx {
|
.decode-locator-tip-rx {
|
||||||
margin-top: 0.12rem;
|
margin-top: 0.12rem;
|
||||||
font-size: 0.72rem;
|
font-size: 0.75rem;
|
||||||
color: var(--accent-yellow);
|
color: var(--accent-yellow);
|
||||||
opacity: 0.85;
|
opacity: 0.85;
|
||||||
}
|
}
|
||||||
.decode-locator-tip-note {
|
.decode-locator-tip-note {
|
||||||
margin-top: 0.2rem;
|
margin-top: 0.2rem;
|
||||||
font-size: 0.76rem;
|
font-size: 0.75rem;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
@@ -2503,7 +2602,7 @@ body.map-fake-fullscreen-active {
|
|||||||
background: color-mix(in srgb, var(--card-bg) 88%, transparent);
|
background: color-mix(in srgb, var(--card-bg) 88%, transparent);
|
||||||
color: color-mix(in srgb, var(--accent-green) 72%, var(--accent-yellow));
|
color: color-mix(in srgb, var(--accent-green) 72%, var(--accent-yellow));
|
||||||
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.22);
|
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.22);
|
||||||
font-size: 0.72rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.03em;
|
letter-spacing: 0.03em;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@@ -2576,7 +2675,7 @@ body.map-fake-fullscreen-active {
|
|||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
min-width: 4.4rem;
|
min-width: 4.4rem;
|
||||||
padding-top: 0.35rem;
|
padding-top: 0.35rem;
|
||||||
font-size: 0.72rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.03em;
|
letter-spacing: 0.03em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
@@ -2604,7 +2703,7 @@ body.map-fake-fullscreen-active {
|
|||||||
border: 1px solid color-mix(in srgb, var(--border-light) 82%, transparent);
|
border: 1px solid color-mix(in srgb, var(--border-light) 82%, transparent);
|
||||||
background: color-mix(in srgb, var(--input-bg) 92%, transparent);
|
background: color-mix(in srgb, var(--input-bg) 92%, transparent);
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 0.76rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.02em;
|
letter-spacing: 0.02em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
@@ -2621,7 +2720,7 @@ body.map-fake-fullscreen-active {
|
|||||||
color: var(--accent-green);
|
color: var(--accent-green);
|
||||||
}
|
}
|
||||||
.map-locator-empty {
|
.map-locator-empty {
|
||||||
font-size: 0.74rem;
|
font-size: 0.75rem;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
@@ -2655,7 +2754,7 @@ body.map-fake-fullscreen-active {
|
|||||||
background: color-mix(in srgb, var(--input-bg) 96%, transparent);
|
background: color-mix(in srgb, var(--input-bg) 96%, transparent);
|
||||||
}
|
}
|
||||||
.map-locator-chip-text {
|
.map-locator-chip-text {
|
||||||
font-size: 0.77rem;
|
font-size: 0.78rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
.map-search-input {
|
.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-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-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-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; }
|
.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; }
|
.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"][readonly] { opacity: 0.6; }
|
||||||
.cw-config input[type="number"]:disabled { opacity: 0.58; }
|
.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: 2px solid var(--accent-green);
|
||||||
outline-offset: 2px;
|
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 */
|
/* Collapse verbose subtitles — the About tab has this info */
|
||||||
.tab-bar .subtitle { display: none; }
|
.tab-bar .subtitle { display: none; }
|
||||||
.tab-bar .title { font-size: 0.92rem; }
|
.tab-bar .title { font-size: 0.9rem; }
|
||||||
.tab-bar-nav {
|
.tab-bar-nav {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: calc(0.6rem + env(safe-area-inset-left));
|
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;
|
will-change: transform;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 0.66rem;
|
font-size: 0.65rem;
|
||||||
background: var(--bm-cat-bg, var(--accent-yellow));
|
background: var(--bm-cat-bg, var(--accent-yellow));
|
||||||
color: var(--bm-cat-fg, #1a202c);
|
color: var(--bm-cat-fg, #1a202c);
|
||||||
border: 1px solid var(--bm-cat-bg, var(--accent-yellow));
|
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 {
|
.spectrum-bookmark-chip-side .spectrum-bookmark-name {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 0.64rem;
|
font-size: 0.65rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -3662,7 +3763,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
font-size: 0.73rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
#spectrum-level-row {
|
#spectrum-level-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -3709,7 +3810,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
font-size: 0.73rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
#spectrum-gamma-label {
|
#spectrum-gamma-label {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -3724,7 +3825,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
#spectrum-gamma-value {
|
#spectrum-gamma-value {
|
||||||
font-size: 0.72rem;
|
font-size: 0.75rem;
|
||||||
min-width: 1.6rem;
|
min-width: 1.6rem;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
@@ -3882,7 +3983,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
|
|
||||||
.bm-label input,
|
.bm-label input,
|
||||||
.bm-label select {
|
.bm-label select {
|
||||||
font-size: 0.88rem;
|
font-size: 0.85rem;
|
||||||
padding: 0.35rem 0.5rem;
|
padding: 0.35rem 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3938,7 +4039,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.35rem;
|
gap: 0.35rem;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
font-size: 0.84rem;
|
font-size: 0.85rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bm-decoder-check input {
|
.bm-decoder-check input {
|
||||||
@@ -4048,7 +4149,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
.bm-page-summary,
|
.bm-page-summary,
|
||||||
.bm-page-indicator {
|
.bm-page-indicator {
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 0.88rem;
|
font-size: 0.85rem;
|
||||||
}
|
}
|
||||||
.bm-page-controls {
|
.bm-page-controls {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -4266,7 +4367,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
color: var(--text);
|
color: var(--text);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
padding: 0.55rem 1rem;
|
padding: 0.55rem 1rem;
|
||||||
font-size: 0.88rem;
|
font-size: 0.85rem;
|
||||||
}
|
}
|
||||||
#sch-sat-form-cancel:hover {
|
#sch-sat-form-cancel:hover {
|
||||||
background: var(--border);
|
background: var(--border);
|
||||||
@@ -4478,7 +4579,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
.sch-log-action {
|
.sch-log-action {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: 0.72rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
.sch-log-bm {
|
.sch-log-bm {
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
@@ -4687,7 +4788,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
}
|
}
|
||||||
.bgd-checklist-meta {
|
.bgd-checklist-meta {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
font-size: 0.72rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* ── SAT panel ──────────────────────────────────────────────────────── */
|
/* ── SAT panel ──────────────────────────────────────────────────────── */
|
||||||
@@ -4756,7 +4857,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
}
|
}
|
||||||
.stats-control-label {
|
.stats-control-label {
|
||||||
font-size: 0.72rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.06em;
|
letter-spacing: 0.06em;
|
||||||
@@ -4796,7 +4897,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
}
|
}
|
||||||
.stats-counter-label {
|
.stats-counter-label {
|
||||||
font-size: 0.74rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.06em;
|
letter-spacing: 0.06em;
|
||||||
@@ -4819,7 +4920,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
gap: 0.18rem;
|
gap: 0.18rem;
|
||||||
}
|
}
|
||||||
.stats-section-title {
|
.stats-section-title {
|
||||||
font-size: 0.88rem;
|
font-size: 0.85rem;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
letter-spacing: 0.08em;
|
letter-spacing: 0.08em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
@@ -4884,7 +4985,7 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
#tab-statistics { padding: 0.75rem; }
|
#tab-statistics { padding: 0.75rem; }
|
||||||
.stats-counters { grid-template-columns: repeat(2, 1fr); }
|
.stats-counters { grid-template-columns: repeat(2, 1fr); }
|
||||||
.stats-counter-value { font-size: 1.3rem; }
|
.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; }
|
.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);
|
-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; }
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user