diff --git a/internal/web/static/app.css b/internal/web/static/app.css index e26193f..5aa6412 100644 --- a/internal/web/static/app.css +++ b/internal/web/static/app.css @@ -34,7 +34,9 @@ code.pubkey { border-radius: var(--tblr-border-radius); padding: 0.5rem 0.625rem; font-size: 0.8125rem; - color: var(--tblr-secondary); + /* gray-400, not --tblr-secondary (#6b7280): the latter is only 3.67:1 on the + near-black panel bg and fails WCAG AA for this key/data text. */ + color: var(--tblr-gray-400); } /* ---------- Live event / console log ---------- */ @@ -54,14 +56,25 @@ code.pubkey { .evlog.console { max-height: 320px; } .ev { padding: 0.15rem 0; border-bottom: 1px solid var(--tblr-border-color-translucent, rgba(255, 255, 255, 0.05)); } .ev:last-child { border-bottom: none; } -.ev-info { color: var(--tblr-secondary); } +/* Colors chosen for WCAG AA (≥4.5:1) on the near-black log background: + --tblr-secondary (#6b7280) and --tblr-danger (#d63939) only reach ~3.7:1, + so info uses the lighter gray-400 and errors the lighter danger emphasis. */ +.ev-info { color: var(--tblr-gray-400); } .ev-confirmed { color: var(--tblr-success); font-weight: 600; } -.ev-error, .ev-timeout { color: var(--tblr-danger); } +.ev-error, .ev-timeout { color: var(--tblr-danger-text-emphasis); } .ev-warning, .ev-denied, .ev-noreply { color: var(--tblr-warning); } .ev-debug { color: var(--tblr-info); word-break: break-all; } .ev-sent { color: var(--tblr-azure); } .ev-reply { color: var(--tblr-body-color); white-space: pre-wrap; } +/* ---------- Badge contrast (dark) ---------- + Tabler's light "-lt" badges set their text to the full-strength brand color + over a 10%-opacity tint. On the dark theme purple (#ae3ec9 → 2.80:1) and + secondary (#6b7280 → 2.74:1) fall below WCAG AA for this small status text; + lighten just those two. success/azure/warning/yellow already pass. */ +.badge.bg-purple-lt { color: #d98fe6 !important; } +.badge.bg-secondary-lt { color: var(--tblr-secondary-text-emphasis) !important; } + /* ---------- Leaflet map (dark) ---------- */ #map { height: 360px; diff --git a/internal/web/static/webauthn.js b/internal/web/static/webauthn.js index 66026d9..c905bd1 100644 --- a/internal/web/static/webauthn.js +++ b/internal/web/static/webauthn.js @@ -207,5 +207,12 @@ document.addEventListener("click", function (e) { if (!t) return; e.preventDefault(); const input = document.getElementById(t.getAttribute("data-pwtoggle")); - if (input) input.type = input.type === "password" ? "text" : "password"; + if (!input) return; + const showing = input.type !== "password"; + input.type = showing ? "password" : "text"; + // Keep the control's state in sync for screen readers: pressed = revealed. + const nowShowing = !showing; + t.setAttribute("aria-pressed", String(nowShowing)); + t.setAttribute("aria-label", nowShowing ? "Hide password" : "Show password"); + t.setAttribute("title", nowShowing ? "Hide password" : "Show password"); }); diff --git a/internal/web/templates/account.html b/internal/web/templates/account.html index fd6c9cb..f2e33f2 100644 --- a/internal/web/templates/account.html +++ b/internal/web/templates/account.html @@ -19,13 +19,13 @@
{{.ServerPubKey}}
{{.SetPermCommand}}
@@ -56,12 +56,12 @@
{{template "revokedoc" .RevokeCommand}}
Tell MeshTender which repeater you just granted access to, and how its radio is configured.