a11y: WCAG AA contrast + ARIA roles + focus management across all pages

- css/ls.css: --text-3 #8898AA → #56687A (5.1:1 contrast), min-height 44px on .btn-primary/.btn-ghost/.sb-link, new .icon-btn utility (44×44px)
- js/api.js: lsConfirm — role=dialog, aria-modal, aria-labelledby, Tab focus trap, restore focus on close; lsToast — aria-live=polite on container, role=alert on errors; live quiz — role=dialog, role=radiogroup, role=radio, aria-checked, keyboard support
- test-run.html: q-opt divs — role=radio/checkbox, aria-checked, tabindex, keyboard enter/space; confirm modal — role=dialog, aria-modal; btn-flag — aria-pressed; dots — aria-label, aria-current; touch targets 44px
- board.html: btn-del-ann — aria-label; reaction buttons — aria-label, aria-pressed
- All 18 HTML files: replace hardcoded color:#8898AA with color:var(--text-3)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-04-16 11:42:38 +03:00
parent 3a4623a60a
commit 26ba289019
22 changed files with 362 additions and 299 deletions
+23 -6
View File
@@ -13,7 +13,7 @@
--border-h: rgba(15,23,42,0.20);
--text: #0F172A;
--text-2: #3D4F6B;
--text-3: #8898AA;
--text-3: #56687A; /* WCAG AA: ~5.1:1 on white, ~4.6:1 on --bg */
--violet: #9B5DE5;
--cyan: #06D6E0;
@@ -53,6 +53,20 @@ body {
/* ── Focus ring ── */
:focus-visible { outline: 2px solid var(--violet); outline-offset: 3px; }
/* ── Icon-only button (WCAG 2.5.5: 44×44 tap area) ── */
.icon-btn {
display: inline-flex; align-items: center; justify-content: center;
min-width: 44px; min-height: 44px;
border: none; border-radius: 10px;
background: transparent;
cursor: pointer;
transition: background var(--tr), color var(--tr);
color: var(--text-2);
flex-shrink: 0;
}
.icon-btn:hover { background: rgba(155,93,229,0.08); color: var(--violet); }
.icon-btn svg { width: 20px; height: 20px; }
/* ── Navbar ── */
.nav {
position: sticky; top: 0; z-index: 100;
@@ -122,6 +136,7 @@ body {
.btn-primary {
position: relative; overflow: hidden;
padding: 10px 26px;
min-height: 44px; /* WCAG 2.5.5 touch target */
border: none; border-radius: var(--r-pill);
background: var(--grad-1);
color: #fff;
@@ -145,6 +160,7 @@ body {
/* ── Ghost & danger buttons ── */
.btn-ghost {
padding: 8px 18px;
min-height: 44px; /* WCAG 2.5.5 touch target */
border: 1.5px solid var(--border-h); border-radius: var(--r-pill);
background: transparent;
font-family: 'Manrope', sans-serif; font-size: 0.82rem; font-weight: 600;
@@ -306,6 +322,7 @@ body {
align-items: center;
gap: 10px;
padding: 9px 12px;
min-height: 44px; /* WCAG 2.5.5 touch target */
border-radius: 12px;
text-decoration: none;
font-size: 0.875rem;
@@ -745,25 +762,25 @@ body {
display: flex; align-items: center; gap: 10px;
padding: 16px 20px; border-bottom: 1px solid rgba(15,23,42,0.08);
}
.gs-input-wrap svg { flex-shrink: 0; color: #8898AA; }
.gs-input-wrap svg { flex-shrink: 0; color: var(--text-3); }
.gs-input {
flex: 1; border: none; outline: none; font-family: 'Manrope', sans-serif;
font-size: 0.95rem; font-weight: 500; color: #0F172A; background: transparent;
}
.gs-input::placeholder { color: #B0BEC5; }
.gs-kbd {
font-size: 0.65rem; font-weight: 700; color: #8898AA; background: rgba(15,23,42,0.06);
font-size: 0.65rem; font-weight: 700; color: var(--text-3); background: rgba(15,23,42,0.06);
padding: 3px 7px; border-radius: 5px; line-height: 1;
}
.gs-results {
max-height: 380px; overflow-y: auto; padding: 8px;
}
.gs-empty {
text-align: center; padding: 40px 20px; color: #8898AA; font-size: 0.85rem;
text-align: center; padding: 40px 20px; color: var(--text-3); font-size: 0.85rem;
}
.gs-group-label {
font-size: 0.65rem; font-weight: 700; text-transform: uppercase;
letter-spacing: 0.06em; color: #8898AA; padding: 10px 12px 4px;
letter-spacing: 0.06em; color: var(--text-3); padding: 10px 12px 4px;
}
.gs-item {
display: flex; align-items: center; gap: 12px;
@@ -786,7 +803,7 @@ body {
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gs-item-sub {
font-size: 0.7rem; color: #8898AA; margin-top: 1px;
font-size: 0.7rem; color: var(--text-3); margin-top: 1px;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gs-item-arrow { color: #ccc; flex-shrink: 0; }