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
+16 -16
View File
@@ -55,7 +55,7 @@
.an-chip-val {
font-family: 'Unbounded', sans-serif; font-size: 1.5rem; font-weight: 800;
}
.an-chip-label { font-size: 0.72rem; color: #8898AA; font-weight: 600; margin-top: 4px; }
.an-chip-label { font-size: 0.72rem; color: var(--text-3); font-weight: 600; margin-top: 4px; }
/* ── content container ── */
.an-container { max-width: 1200px; margin: 0 auto; padding: 28px 28px 80px; }
@@ -82,7 +82,7 @@
.hq-table thead th {
padding: 10px 14px; text-align: left;
background: #f8f9fc; border-bottom: 1.5px solid rgba(15,23,42,0.08);
font-size: 0.7rem; font-weight: 700; color: #8898AA;
font-size: 0.7rem; font-weight: 700; color: var(--text-3);
text-transform: uppercase; letter-spacing: 0.04em;
}
.hq-table tbody td {
@@ -100,7 +100,7 @@
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
overflow: hidden; font-weight: 600; color: #0F172A;
}
.hq-topic { font-size: 0.72rem; color: #8898AA; margin-top: 2px; }
.hq-topic { font-size: 0.72rem; color: var(--text-3); margin-top: 2px; }
.diff-badge {
display: inline-flex; align-items: center;
padding: 3px 10px; border-radius: 999px;
@@ -137,20 +137,20 @@
.hm-4 { background: rgba(155,93,229,0.80); }
.heatmap-legend {
display: flex; align-items: center; gap: 6px;
margin-top: 10px; font-size: 0.7rem; color: #8898AA; font-weight: 600;
margin-top: 10px; font-size: 0.7rem; color: var(--text-3); font-weight: 600;
}
.hm-legend-cell {
width: 12px; height: 12px; border-radius: 2px;
}
.heatmap-days {
display: grid; grid-template-rows: repeat(7, 14px); gap: 3px;
font-size: 0.62rem; color: #8898AA; font-weight: 700;
font-size: 0.62rem; color: var(--text-3); font-weight: 700;
margin-right: 8px; flex-shrink: 0;
}
.heatmap-row { display: flex; align-items: flex-start; }
.heatmap-months {
display: flex; margin-left: 30px; margin-bottom: 4px;
font-size: 0.65rem; color: #8898AA; font-weight: 700;
font-size: 0.65rem; color: var(--text-3); font-weight: 700;
}
.hm-month { flex-shrink: 0; }
@@ -177,12 +177,12 @@
color: var(--violet);
}
.asgn-deadline {
font-size: 0.7rem; color: #8898AA; flex-shrink: 0; min-width: 80px;
font-size: 0.7rem; color: var(--text-3); flex-shrink: 0; min-width: 80px;
}
/* ── empty state ── */
.an-empty {
text-align: center; padding: 80px 20px; color: #8898AA; font-size: 0.9rem;
text-align: center; padding: 80px 20px; color: var(--text-3); font-size: 0.9rem;
}
.an-empty-icon { margin-bottom: 14px; opacity: 0.25; }
@@ -449,7 +449,7 @@
<td class="hq-text">
<div class="hq-text-inner">${esc(q.text)}</div>
</td>
<td><span style="font-size:0.75rem;color:#8898AA;font-weight:600">${esc(q.topic || '—')}</span></td>
<td><span style="font-size:0.75rem;color:var(--text-3);font-weight:600">${esc(q.topic || '—')}</span></td>
<td><span class="diff-badge ${diffCls}">${diffLabel}</span></td>
<td><span class="hq-pct ${errCls}">${errPct}%</span></td>
<td style="font-weight:600">${q.attempts || 0}</td>
@@ -457,7 +457,7 @@
});
html += '</tbody></table></div>';
} else {
html += '<div style="padding:40px;text-align:center;color:#8898AA;font-size:0.88rem">Нет данных о сложных вопросах</div>';
html += '<div style="padding:40px;text-align:center;color:var(--text-3);font-size:0.88rem">Нет данных о сложных вопросах</div>';
}
html += '</div>';
@@ -492,7 +492,7 @@
});
html += '</div>';
} else {
html += '<div style="text-align:center;color:#8898AA;padding:30px;font-size:0.88rem">Нет заданий</div>';
html += '<div style="text-align:center;color:var(--text-3);padding:30px;font-size:0.88rem">Нет заданий</div>';
}
html += '</div>';
@@ -544,26 +544,26 @@
scales: {
x: {
grid: { color: 'rgba(15,23,42,0.05)' },
ticks: { font: { family: 'Manrope', size: 11 }, color: '#8898AA' },
ticks: { font: { family: 'Manrope', size: 11 }, color: '#56687A' },
},
y: {
min: 0, max: 100,
grid: { color: 'rgba(15,23,42,0.05)' },
ticks: {
font: { family: 'Manrope', size: 11 }, color: '#8898AA',
font: { family: 'Manrope', size: 11 }, color: '#56687A',
callback: v => v + '%',
},
},
y2: {
position: 'right',
grid: { display: false },
ticks: { font: { family: 'Manrope', size: 11 }, color: '#8898AA' },
ticks: { font: { family: 'Manrope', size: 11 }, color: '#56687A' },
},
},
},
});
} else if (canvas) {
canvas.parentElement.innerHTML = '<div style="display:flex;align-items:center;justify-content:center;height:100%;color:#8898AA;font-size:0.88rem">Нет данных за последние недели</div>';
canvas.parentElement.innerHTML = '<div style="display:flex;align-items:center;justify-content:center;height:100%;color:var(--text-3);font-size:0.88rem">Нет данных за последние недели</div>';
}
// render heatmap
@@ -644,7 +644,7 @@
area.innerHTML = `
<div style="display:flex;gap:0">
<div class="heatmap-days">
${days.map((d, i) => `<div style="display:flex;align-items:center;font-size:0.62rem;color:#8898AA;font-weight:700">${i % 2 === 1 ? d : ''}</div>`).join('')}
${days.map((d, i) => `<div style="display:flex;align-items:center;font-size:0.62rem;color:var(--text-3);font-weight:700">${i % 2 === 1 ? d : ''}</div>`).join('')}
</div>
<div>
<div class="heatmap-months" style="margin-left:0">${monthHtml}</div>