From 26ba2890196301b4b4b5c99908d91bc3a433928e Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Thu, 16 Apr 2026 11:42:38 +0300 Subject: [PATCH] a11y: WCAG AA contrast + ARIA roles + focus management across all pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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) --- frontend/admin.html | 28 ++++----- frontend/analytics.html | 32 +++++----- frontend/board.html | 8 ++- frontend/classes.html | 20 +++--- frontend/classroom.html | 38 +++++------ frontend/course.html | 30 ++++----- frontend/css/ls.css | 29 +++++++-- frontend/dashboard.html | 122 ++++++++++++++++++------------------ frontend/gradebook.html | 10 +-- frontend/homework.html | 16 ++--- frontend/knowledge-map.html | 10 +-- frontend/lab.html | 4 +- frontend/lesson-editor.html | 62 +++++++++--------- frontend/lesson.html | 48 +++++++------- frontend/live-quiz.html | 36 +++++------ frontend/parent.html | 2 +- frontend/profile.html | 8 +-- frontend/question-bank.html | 12 ++-- frontend/teacher-guide.html | 24 +++---- frontend/test-run.html | 41 ++++++++---- frontend/theory.html | 18 +++--- js/api.js | 63 +++++++++++++------ 22 files changed, 362 insertions(+), 299 deletions(-) diff --git a/frontend/admin.html b/frontend/admin.html index c74aa0f..c058c64 100644 --- a/frontend/admin.html +++ b/frontend/admin.html @@ -60,7 +60,7 @@ background: rgba(15,23,42,0.05); color: #64748B; } .sc-tag-mode { background: rgba(155,93,229,0.08); color: var(--violet); } - .sc-qcount { font-size: 0.72rem; color: #8898AA; font-weight: 600; } + .sc-qcount { font-size: 0.72rem; color: var(--text-3); font-weight: 600; } .sc-chevron { width: 20px; height: 20px; color: #cbd5e1; transition: transform 0.2s; flex-shrink: 0; } @@ -89,7 +89,7 @@ .sc-fields { display: flex; flex-direction: column; gap: 12px; } .sc-field { display: flex; align-items: center; gap: 10px; } .sc-label { - font-size: 0.72rem; color: #8898AA; font-weight: 700; white-space: nowrap; + font-size: 0.72rem; color: var(--text-3); font-weight: 700; white-space: nowrap; text-transform: uppercase; letter-spacing: 0.04em; min-width: 68px; } .sc-select { @@ -110,7 +110,7 @@ .sc-src-btn { flex: 1; padding: 6px 12px; border: none; border-radius: 8px; background: transparent; font-family: 'Manrope', sans-serif; font-size: 0.76rem; font-weight: 600; - color: #8898AA; cursor: pointer; transition: all 0.15s; text-align: center; + color: var(--text-3); cursor: pointer; transition: all 0.15s; text-align: center; } .sc-src-btn.active { background: #fff; color: var(--violet); box-shadow: 0 1px 4px rgba(15,23,42,0.08); } .sc-test-pick { display: none; flex-direction: column; gap: 10px; } @@ -661,7 +661,7 @@ font-size: 0.78rem; color: #64748B; font-family: monospace; } .sl-assignment { font-weight: 600; color: #3D4F6B; } - .sl-class { font-size: 0.78rem; color: #8898AA; } + .sl-class { font-size: 0.78rem; color: var(--text-3); } .sl-status { display: inline-flex; align-items: center; gap: 4px; @@ -696,7 +696,7 @@ .sl-role-student { background: rgba(6,214,224,0.1); color: #06aab3; } .sl-empty { - padding: 48px 24px; text-align: center; color: #8898AA; font-size: 0.88rem; + padding: 48px 24px; text-align: center; color: var(--text-3); font-size: 0.88rem; } .sl-empty-icon { margin-bottom: 12px; opacity: 0.3; } @@ -708,7 +708,7 @@ transition: border-color 0.15s; } .sl-filter-select:focus { border-color: var(--violet); outline: none; } - .sl-count { font-size: 0.78rem; color: #8898AA; font-weight: 600; } + .sl-count { font-size: 0.78rem; color: var(--text-3); font-weight: 600; } /* ══════════ CLASSROOM ADMIN TAB ══════════ */ .cr-admin-section { margin-bottom: 40px; } @@ -3454,17 +3454,17 @@ function renderAcFiles(q) { const el = document.getElementById('acf-file-list'); - if (!_acAllFiles) { el.innerHTML = '
Загрузка…
'; return; } + if (!_acAllFiles) { el.innerHTML = '
Загрузка…
'; return; } const lq = q.toLowerCase(); const items = q ? _acAllFiles.filter(f => (f.title||'').toLowerCase().includes(lq)) : _acAllFiles; const SUBJ = { bio:'Биология', chem:'Химия', math:'Математика', phys:'Физика' }; - if (!items.length) { el.innerHTML = '
Нет файлов
'; return; } + if (!items.length) { el.innerHTML = '
Нет файлов
'; return; } el.innerHTML = items.map(f => `
${esc(f.title||'Файл')}
-
${SUBJ[f.subject_slug]||f.subject_slug||''}
+
${SUBJ[f.subject_slug]||f.subject_slug||''}
${_acFileId===f.id ? '' : ''}
`).join(''); @@ -4819,7 +4819,7 @@ try { const rows = await LS.api(`/api/admin/topics?subject_id=${subjId}`); document.getElementById('topics-count').textContent = rows.length + ' тем'; - if (!rows.length) { el.innerHTML = '
Тем нет
'; return; } + if (!rows.length) { el.innerHTML = '
Тем нет
'; return; } el.innerHTML = '
' + rows.map(t => `
#${t.order_index} @@ -4887,7 +4887,7 @@ el.innerHTML = LS.skeleton(5, 'row'); try { const rows = await LS.api('/api/admin/audit-log?limit=200'); - if (!rows.length) { el.innerHTML = '
Журнал пуст
'; return; } + if (!rows.length) { el.innerHTML = '
Журнал пуст
'; return; } const ACTION_LABELS = { 'user.role_change': 'Смена роли', 'user.edit': 'Редактирование', 'user.ban': 'Блокировка', 'user.unban': 'Разблокировка', 'user.delete': 'Удаление', 'user.clear_sessions': 'Очистка истории', @@ -4918,7 +4918,7 @@ if (!await LS.confirm('Очистить весь аудит-лог?', { danger: true })) return; try { await LS.api('/api/admin/audit-log', { method:'DELETE' }); - document.getElementById('audit-list').innerHTML = '
Журнал очищен
'; + document.getElementById('audit-list').innerHTML = '
Журнал очищен
'; LS.toast('Журнал очищен', 'success'); } catch (e) { LS.toast(e.message, 'error'); } } @@ -4929,7 +4929,7 @@ el.innerHTML = LS.skeleton(3, 'row'); try { const rows = await LS.api('/api/admin/error-log?limit=200'); - if (!rows.length) { el.innerHTML = '
Ошибок нет
'; return; } + if (!rows.length) { el.innerHTML = '
Ошибок нет
'; return; } el.innerHTML = rows.map(r => { const dt = new Date(r.created_at); const ds = dt.toLocaleDateString('ru',{day:'numeric',month:'short'}) + ' ' + dt.toLocaleTimeString('ru',{hour:'2-digit',minute:'2-digit'}); @@ -4949,7 +4949,7 @@ if (!await LS.confirm('Очистить журнал ошибок?', { danger: true })) return; try { await LS.api('/api/admin/error-log', { method:'DELETE' }); - document.getElementById('errors-list').innerHTML = '
Журнал очищен
'; + document.getElementById('errors-list').innerHTML = '
Журнал очищен
'; LS.toast('Журнал очищен', 'success'); } catch (e) { LS.toast(e.message, 'error'); } } diff --git a/frontend/analytics.html b/frontend/analytics.html index e0ea7eb..cfd255b 100644 --- a/frontend/analytics.html +++ b/frontend/analytics.html @@ -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 @@
${esc(q.text)}
- ${esc(q.topic || '—')} + ${esc(q.topic || '—')} ${diffLabel} ${errPct}% ${q.attempts || 0} @@ -457,7 +457,7 @@ }); html += '
'; } else { - html += '
Нет данных о сложных вопросах
'; + html += '
Нет данных о сложных вопросах
'; } html += '
'; @@ -492,7 +492,7 @@ }); html += ''; } else { - html += '
Нет заданий
'; + html += '
Нет заданий
'; } html += ''; @@ -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 = '
Нет данных за последние недели
'; + canvas.parentElement.innerHTML = '
Нет данных за последние недели
'; } // render heatmap @@ -644,7 +644,7 @@ area.innerHTML = `
- ${days.map((d, i) => `
${i % 2 === 1 ? d : ''}
`).join('')} + ${days.map((d, i) => `
${i % 2 === 1 ? d : ''}
`).join('')}
${monthHtml}
diff --git a/frontend/board.html b/frontend/board.html index e3eaee2..9cce100 100644 --- a/frontend/board.html +++ b/frontend/board.html @@ -714,7 +714,8 @@ /* ════════════════════════════════════════ ANNOUNCEMENT CARD ════════════════════════════════════════ */ - const EMOJIS = ['', '️', '']; + const EMOJIS = ['', '️', '']; + const REACTION_LABELS = ['Нравится', 'Обожаю', 'Огонь']; function renderAnnouncement(a, delay, fresh) { const key = `ann_${a.id}`; @@ -725,11 +726,12 @@ const rxHtml = EMOJIS.map((em, idx) => { const count = rxState[idx] ? 1 : 0; - return ``; + const lbl = rxState[idx] ? `Убрать «${REACTION_LABELS[idx]}»` : `${REACTION_LABELS[idx]}`; + return ``; }).join(''); const delBtn = isTeacher - ? `` : ''; + ? `` : ''; return `
diff --git a/frontend/classes.html b/frontend/classes.html index 4d452b7..762c9e0 100644 --- a/frontend/classes.html +++ b/frontend/classes.html @@ -27,12 +27,12 @@ .cl-avatar { width: 44px; height: 44px; border-radius: 13px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; font-family: 'Unbounded', sans-serif; font-size: 0.82rem; font-weight: 800; color: #fff; } .cl-info { flex: 1; min-width: 0; } .cl-name { font-size: 0.88rem; font-weight: 700; color: #0F172A; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.25; } - .cl-meta { font-size: 0.73rem; color: #8898AA; margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + .cl-meta { font-size: 0.73rem; color: var(--text-3); margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .cl-chevron { color: #cbd5e1; flex-shrink: 0; transition: color 0.15s; } .cl-item.active .cl-chevron { color: var(--violet); } .cl-item:hover .cl-chevron { color: #94a3b8; } .cl-works-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pink); flex-shrink: 0; } - .cl-empty-side { padding: 40px 16px; text-align: center; color: #8898AA; font-size: 0.8rem; line-height: 1.6; } + .cl-empty-side { padding: 40px 16px; text-align: center; color: var(--text-3); font-size: 0.8rem; line-height: 1.6; } /* Right: class detail */ .cl-main { flex: 1; overflow-y: auto; display: flex; flex-direction: column; min-width: 0; } @@ -47,7 +47,7 @@ .cl-placeholder-icon { width: 72px; height: 72px; border-radius: 22px; background: linear-gradient(135deg, rgba(155,93,229,0.12), rgba(6,214,224,0.08)); display: flex; align-items: center; justify-content: center; margin-bottom: 4px; } .cl-placeholder-icon svg { width: 32px; height: 32px; stroke: var(--violet); stroke-width: 1.6; } .cl-placeholder-title { font-family: 'Unbounded', sans-serif; font-size: 0.95rem; font-weight: 800; color: #0F172A; } - .cl-placeholder-sub { font-size: 0.82rem; color: #8898AA; max-width: 220px; line-height: 1.6; } + .cl-placeholder-sub { font-size: 0.82rem; color: var(--text-3); max-width: 220px; line-height: 1.6; } .cl-detail-wrap { padding: 28px 32px 60px; flex: 1; } .btn-primary { padding: 10px 24px; border: none; border-radius: var(--r-pill); background: var(--grad-1); color: #fff; font-family: 'Manrope', sans-serif; font-size: 0.88rem; font-weight: 700; cursor: pointer; transition: transform var(--tr); } @@ -392,7 +392,7 @@ .works-filters { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 18px; align-items: center; } .works-chip { padding: 4px 14px; border-radius: 99px; border: 1.5px solid rgba(15,23,42,0.1); - background: #fff; color: #8898AA; + background: #fff; color: var(--text-3); font-family: 'Manrope', sans-serif; font-size: 0.74rem; font-weight: 700; cursor: pointer; transition: all 0.15s; } @@ -420,10 +420,10 @@ .work-body { flex: 1; min-width: 0; } .work-student { font-size: 0.88rem; font-weight: 700; color: #0F172A; margin-bottom: 2px; } .work-assign { font-size: 0.76rem; color: var(--violet); font-weight: 600; margin-bottom: 3px; } - .work-file { font-size: 0.74rem; color: #8898AA; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + .work-file { font-size: 0.74rem; color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .work-msg { font-size: 0.76rem; color: #3D4F6B; margin-top: 5px; line-height: 1.4; font-style: italic; } .work-note { font-size: 0.74rem; color: #059652; margin-top: 4px; font-style: italic; } - .work-meta { font-size: 0.70rem; color: #8898AA; white-space: nowrap; flex-shrink: 0; text-align: right; } + .work-meta { font-size: 0.70rem; color: var(--text-3); white-space: nowrap; flex-shrink: 0; text-align: right; } .work-status { display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; border-radius: 99px; font-size: 0.70rem; font-weight: 700; @@ -2359,7 +2359,7 @@ let html = `
- Курсы класса (${(courses||[]).length}) + Курсы класса (${(courses||[]).length})
${available.length ? `
`; if (!(courses||[]).length) { - html += `
+ html += `
Нет назначенных курсов. Нажмите «Добавить курс», чтобы назначить курс классу.
`; } else { @@ -2380,7 +2380,7 @@ ${c.coverEmoji || LS.icon('book-open',20)}
${esc(c.title)}
-
${esc(SUBJ_LABEL[c.subjectSlug] || c.subjectSlug || '')} · ${c.lessonCount} уроков
+
${esc(SUBJ_LABEL[c.subjectSlug] || c.subjectSlug || '')} · ${c.lessonCount} уроков
@@ -2438,7 +2438,7 @@
Назначить курс классу
- +
`; diff --git a/frontend/classroom.html b/frontend/classroom.html index b5d2ca8..a6cab77 100644 --- a/frontend/classroom.html +++ b/frontend/classroom.html @@ -78,7 +78,7 @@ font-family: 'Unbounded',sans-serif; font-size: 1.1rem; font-weight: 800; color: #fff; margin: 0; } - .cr-idle p { color: #8898AA; font-size: 0.85rem; margin: 0; max-width: 340px; line-height: 1.6; } + .cr-idle p { color: var(--text-3); font-size: 0.85rem; margin: 0; max-width: 340px; line-height: 1.6; } .cr-start-btn { display: flex; align-items: center; gap: 8px; padding: 12px 28px; border-radius: 99px; @@ -672,7 +672,7 @@ .mic-off { color: rgba(255,255,255,0.18); } .cr-p-mute-btn { background: none; border: none; cursor: pointer; padding: 2px; border-radius: 4px; - color: #8898AA; display: flex; align-items: center; opacity: 0; transition: opacity .15s, color .15s; + color: var(--text-3); display: flex; align-items: center; opacity: 0; transition: opacity .15s, color .15s; } .cr-participant:hover .cr-p-mute-btn { opacity: 1; } @@ -733,7 +733,7 @@ display: flex; align-items: center; gap: 4px; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; padding: 2px 7px 2px 5px; - cursor: pointer; font-size: 0.67rem; font-weight: 600; color: #8898AA; + cursor: pointer; font-size: 0.67rem; font-weight: 600; color: var(--text-3); transition: background .15s, border-color .15s, color .15s; white-space: nowrap; } @@ -792,7 +792,7 @@ .cr-msg-row.mine .cr-msg-time { text-align: right; } .cr-msg-pin-badge { color: #9B5DE5; opacity: 0.8; display: flex; align-items: center; } .cr-msg-pin-btn { - background: none; border: none; cursor: pointer; color: #8898AA; + background: none; border: none; cursor: pointer; color: var(--text-3); padding: 1px; border-radius: 4px; display: flex; align-items: center; opacity: 0; transition: opacity .15s, color .15s; } @@ -1030,7 +1030,7 @@ padding: 20px; text-align: center; } .cr-no-session svg { width: 32px; height: 32px; stroke: #8898AA; } - .cr-no-session p { font-size: 0.78rem; color: #8898AA; line-height: 1.5; margin: 0; } + .cr-no-session p { font-size: 0.78rem; color: var(--text-3); line-height: 1.5; margin: 0; } /* ── Modal: start session ── */ .cr-modal-overlay { @@ -1050,13 +1050,13 @@ font-family: 'Unbounded',sans-serif; font-size: 1rem; font-weight: 800; color: #fff; margin-bottom: 6px; } - .cr-modal-sub { font-size: 0.8rem; color: #8898AA; margin-bottom: 20px; } + .cr-modal-sub { font-size: 0.8rem; color: var(--text-3); margin-bottom: 20px; } .cr-mode-tabs { display: flex; gap: 8px; margin-bottom: 16px; } .cr-mode-tab { flex: 1; padding: 9px; border-radius: 10px; border: 1.5px solid rgba(255,255,255,0.1); background: transparent; - color: #8898AA; font-family: 'Manrope',sans-serif; font-size: 0.78rem; + color: var(--text-3); font-family: 'Manrope',sans-serif; font-size: 0.78rem; font-weight: 700; cursor: pointer; transition: all .15s; } .cr-mode-tab.active { @@ -1064,7 +1064,7 @@ } .cr-field { margin-bottom: 14px; } - .cr-label { font-size: 0.75rem; font-weight: 700; color: #8898AA; margin-bottom: 6px; display: block; } + .cr-label { font-size: 0.75rem; font-weight: 700; color: var(--text-3); margin-bottom: 6px; display: block; } .cr-input { width: 100%; background: rgba(255,255,255,0.06); border: 1.5px solid rgba(255,255,255,0.1); border-radius: 10px; @@ -1113,7 +1113,7 @@ .cr-online-empty { padding: 16px 12px; text-align: center; font-size: .8rem; color: #475569; } .cr-online-refresh { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; - font-size: .72rem; font-weight: 700; color: #8898AA; cursor: pointer; + font-size: .72rem; font-weight: 700; color: var(--text-3); cursor: pointer; background: none; border: none; padding: 0; font-family: 'Manrope',sans-serif; } .cr-online-refresh:hover { color: #c4b5fd; } @@ -1135,7 +1135,7 @@ .cr-modal-cancel { flex: 1; padding: 11px; border-radius: 10px; border: 1.5px solid rgba(255,255,255,0.1); background: transparent; - color: #8898AA; font-family: 'Manrope',sans-serif; font-size: 0.85rem; + color: var(--text-3); font-family: 'Manrope',sans-serif; font-size: 0.85rem; font-weight: 700; cursor: pointer; transition: all .15s; } .cr-modal-cancel:hover { border-color: rgba(255,255,255,0.25); color: #fff; } @@ -1199,7 +1199,7 @@ font-family: 'Unbounded',sans-serif; font-size: 1rem; font-weight: 800; color: #fff; margin: 0; } - .cr-join-banner p { font-size: 0.82rem; color: #8898AA; margin: 0; line-height: 1.6; } + .cr-join-banner p { font-size: 0.82rem; color: var(--text-3); margin: 0; line-height: 1.6; } .cr-join-btn { padding: 11px 32px; border-radius: 99px; background: linear-gradient(135deg, #9B5DE5, #7B3FC5); @@ -1835,13 +1835,13 @@ color: #fff; margin: 0 0 8px; } .cr-dlg-msg { - font-size: 0.83rem; color: #8898AA; margin: 0 0 24px; line-height: 1.65; + font-size: 0.83rem; color: var(--text-3); margin: 0 0 24px; line-height: 1.65; } .cr-dlg-actions { display: flex; gap: 10px; } .cr-dlg-cancel { flex: 1; padding: 10px; border-radius: 10px; border: 1.5px solid rgba(255,255,255,0.1); background: transparent; - color: #8898AA; font-family: 'Manrope',sans-serif; font-size: 0.85rem; + color: var(--text-3); font-family: 'Manrope',sans-serif; font-size: 0.85rem; font-weight: 700; cursor: pointer; transition: all .15s; } .cr-dlg-cancel:hover { border-color: rgba(255,255,255,0.28); color: #fff; } @@ -1885,7 +1885,7 @@ } .cr-sp-close { background: none; border: none; cursor: pointer; padding: 6px; - border-radius: 8px; color: #8898AA; transition: color .15s, background .15s; + border-radius: 8px; color: var(--text-3); transition: color .15s, background .15s; display: flex; align-items: center; } .cr-sp-close:hover { background: rgba(255,255,255,0.07); color: #fff; } @@ -1894,7 +1894,7 @@ } .cr-sp-tab { flex: 1; padding: 10px 6px; font-family: 'Manrope',sans-serif; - font-size: 0.7rem; font-weight: 700; color: #8898AA; + font-size: 0.7rem; font-weight: 700; color: var(--text-3); background: none; border: none; cursor: pointer; border-bottom: 2px solid transparent; transition: color .15s; } @@ -1908,11 +1908,11 @@ .cr-sp-section { display: flex; flex-direction: column; gap: 10px; } .cr-sp-section-label { font-family: 'Manrope',sans-serif; font-size: 0.68rem; font-weight: 700; - color: #8898AA; text-transform: uppercase; letter-spacing: 0.06em; + color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; } .cr-sp-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; } .cr-sp-row-lbl { font-family: 'Manrope',sans-serif; font-size: 0.82rem; font-weight: 600; color: #c8d0db; flex: 1; line-height: 1.4; } - .cr-sp-row-sub { font-size: 0.69rem; color: #8898AA; margin-top: 2px; } + .cr-sp-row-sub { font-size: 0.69rem; color: var(--text-3); margin-top: 2px; } /* Toggle */ .cr-toggle { position: relative; width: 38px; height: 22px; flex-shrink: 0; } .cr-toggle input { opacity: 0; width: 0; height: 0; } @@ -1931,7 +1931,7 @@ .cr-seg button { flex: 1; padding: 7px 8px; border: none; background: none; cursor: pointer; font-family: 'Manrope',sans-serif; font-size: 0.72rem; font-weight: 700; - color: #8898AA; transition: all .15s; + color: var(--text-3); transition: all .15s; } .cr-seg button.active { background: #9B5DE5; color: #fff; border-radius: 6px; } /* Mic test */ @@ -1946,7 +1946,7 @@ .cr-sp-btn.cyan { border-color: rgba(6,214,160,0.4); background: rgba(6,214,160,0.08); color: #06D6A0; } .cr-sp-btn.cyan:hover { background: rgba(6,214,160,0.16); } .cr-sp-btn.cyan.granted { opacity: 0.6; cursor: default; pointer-events: none; } - .cr-sp-note { font-family: 'Manrope',sans-serif; font-size: 0.72rem; color: #8898AA; line-height: 1.5; } + .cr-sp-note { font-family: 'Manrope',sans-serif; font-size: 0.72rem; color: var(--text-3); line-height: 1.5; } /* Chat font size */ #cr-messages .cr-msg-text { font-size: 0.82rem; } .cr-chat-fs-small #cr-messages .cr-msg-text { font-size: 0.74rem; } diff --git a/frontend/course.html b/frontend/course.html index f55435f..8348452 100644 --- a/frontend/course.html +++ b/frontend/course.html @@ -125,7 +125,7 @@ } .section-title { font-family: 'Unbounded', sans-serif; font-size: 0.72rem; font-weight: 800; - color: #8898AA; text-transform: uppercase; letter-spacing: 0.07em; + color: var(--text-3); text-transform: uppercase; letter-spacing: 0.07em; display: flex; align-items: center; gap: 7px; } .section-title::before { @@ -151,7 +151,7 @@ background: rgba(15,23,42,0.05); border: 1.5px solid rgba(15,23,42,0.08); display: flex; align-items: center; justify-content: center; font-family: 'Unbounded', sans-serif; font-size: 0.72rem; font-weight: 800; - color: #8898AA; flex-shrink: 0; + color: var(--text-3); flex-shrink: 0; } .lesson-num.done { background: rgba(5,150,82,0.1); border-color: rgba(5,150,82,0.2); color: #059652; @@ -160,11 +160,11 @@ .lesson-title { font-size: 0.92rem; font-weight: 700; color: #0F172A; } .lesson-meta-row { display: flex; align-items: center; gap: 8px; margin-top: 3px; } .lesson-draft-lbl { - font-size: 0.68rem; font-weight: 700; color: #8898AA; + font-size: 0.68rem; font-weight: 700; color: var(--text-3); background: rgba(15,23,42,0.05); padding: 2px 7px; border-radius: 99px; } .lesson-read-time { - font-size: 0.68rem; color: #8898AA; display: flex; align-items: center; gap: 3px; + font-size: 0.68rem; color: var(--text-3); display: flex; align-items: center; gap: 3px; } .lesson-stat-lbl { font-size: 0.7rem; font-weight: 700; color: #06D6A0; @@ -204,9 +204,9 @@ background: #f8f9fc; border: 1.5px solid rgba(15,23,42,0.07); border-radius: 14px; padding: 14px 16px; } - .stat-chip-label { font-size: 0.72rem; color: #8898AA; font-weight: 600; margin-bottom: 6px; } + .stat-chip-label { font-size: 0.72rem; color: var(--text-3); font-weight: 600; margin-bottom: 6px; } .stat-chip-val { font-family: 'Unbounded', sans-serif; font-size: 1.1rem; font-weight: 800; color: #0F172A; } - .stat-chip-sub { font-size: 0.7rem; color: #8898AA; margin-top: 2px; } + .stat-chip-sub { font-size: 0.7rem; color: var(--text-3); margin-top: 2px; } /* ── analytics dashboard ── */ .analytics-panel { @@ -229,11 +229,11 @@ .an-chip-val { font-family: 'Unbounded', sans-serif; font-size: 1.3rem; 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; } /* lesson bars */ .an-lessons-title { - font-size: 0.76rem; font-weight: 700; color: #8898AA; text-transform: uppercase; + font-size: 0.76rem; font-weight: 700; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 12px; } .an-lesson-row { @@ -276,14 +276,14 @@ } .an-stuck-info { flex: 1; } .an-stuck-name { font-size: 0.82rem; font-weight: 700; color: #0F172A; } - .an-stuck-detail { font-size: 0.72rem; color: #8898AA; margin-top: 2px; } + .an-stuck-detail { font-size: 0.72rem; color: var(--text-3); margin-top: 2px; } /* students table */ .an-students-section { margin-top: 20px; } .an-students-toggle { background: none; border: 1.5px solid rgba(15,23,42,0.1); border-radius: 10px; padding: 8px 16px; font-family: 'Manrope', sans-serif; font-size: 0.78rem; - font-weight: 700; color: #8898AA; cursor: pointer; transition: all 0.15s; + font-weight: 700; color: var(--text-3); cursor: pointer; transition: all 0.15s; display: flex; align-items: center; gap: 6px; } .an-students-toggle:hover { border-color: var(--violet); color: var(--violet); } @@ -293,7 +293,7 @@ } .an-students-table th { text-align: left; padding: 8px 10px; font-size: 0.7rem; font-weight: 700; - color: #8898AA; text-transform: uppercase; letter-spacing: 0.05em; + color: var(--text-3); text-transform: uppercase; letter-spacing: 0.05em; border-bottom: 1.5px solid rgba(15,23,42,0.08); } .an-students-table td { @@ -350,7 +350,7 @@ .form-input { width: 100%; padding: 11px 14px; border: 1.5px solid rgba(15,23,42,0.15); border-radius: 12px; font-family: 'Manrope', sans-serif; font-size: 0.92rem; color: var(--text); background: #f8f9fc; transition: border-color 0.2s; box-sizing: border-box; } .form-input:focus { outline: none; border-color: var(--violet); background: #fff; } .modal-footer { display: flex; gap: 10px; justify-content: flex-end; margin-top: 22px; } - .btn-cancel { padding: 10px 22px; border: 1.5px solid rgba(15,23,42,0.15); border-radius: 999px; background: transparent; font-family: 'Manrope', sans-serif; font-size: 0.88rem; font-weight: 600; color: #8898AA; cursor: pointer; transition: all 0.18s; } + .btn-cancel { padding: 10px 22px; border: 1.5px solid rgba(15,23,42,0.15); border-radius: 999px; background: transparent; font-family: 'Manrope', sans-serif; font-size: 0.88rem; font-weight: 600; color: var(--text-3); cursor: pointer; transition: all 0.18s; } .btn-cancel:hover { border-color: rgba(15,23,42,0.3); color: var(--text); } .btn-primary { padding: 10px 28px; border: none; border-radius: 999px; background: var(--violet); color: #fff; font-family: 'Manrope', sans-serif; font-size: 0.88rem; font-weight: 700; cursor: pointer; box-shadow: 0 2px 10px rgba(155,93,229,0.3); transition: all 0.18s; } .btn-primary:hover { background: #8a47d8; } @@ -702,7 +702,7 @@ document.getElementById('lessons-count').textContent = `Уроки · ${lessons.length}`; if (!lessons.length) { - list.innerHTML = `
+ list.innerHTML = `
${isTeacher ? 'Нажмите «Урок», чтобы создать первый урок' : 'В курсе пока нет уроков'}
`; return; @@ -795,7 +795,7 @@ const data = await LS.api(url); if (!data.totalStudents && !data.lessons?.length) { - body.innerHTML = '
Нет данных. Назначьте курс классу, чтобы видеть аналитику.
'; + body.innerHTML = '
Нет данных. Назначьте курс классу, чтобы видеть аналитику.
'; return; } @@ -886,7 +886,7 @@ body.innerHTML = html; lucide.createIcons(); } catch (e) { - body.innerHTML = '
Ошибка загрузки аналитики
'; + body.innerHTML = '
Ошибка загрузки аналитики
'; } } diff --git a/frontend/css/ls.css b/frontend/css/ls.css index c274efe..92b7088 100644 --- a/frontend/css/ls.css +++ b/frontend/css/ls.css @@ -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; } diff --git a/frontend/dashboard.html b/frontend/dashboard.html index 542a8cc..702e9a9 100644 --- a/frontend/dashboard.html +++ b/frontend/dashboard.html @@ -34,10 +34,10 @@ color: #0F172A; letter-spacing: -0.02em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } - .dh-sub { font-size: 0.78rem; color: #8898AA; font-weight: 500; margin-top: 2px; } + .dh-sub { font-size: 0.78rem; color: var(--text-3); font-weight: 500; margin-top: 2px; } .dh-stats { display: flex; gap: 14px; flex-shrink: 0; } .stat-ring { display: flex; flex-direction: column; align-items: center; gap: 2px; } - .stat-ring .sr-label { font-size: 0.62rem; color: #8898AA; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; } + .stat-ring .sr-label { font-size: 0.62rem; color: var(--text-3); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; } /* ── ZONE 2: Action Banner + Cards ── */ .action-zone { margin-bottom: 22px; } @@ -79,7 +79,7 @@ .ac-emoji { font-size: 1.4rem; flex-shrink: 0; } .ac-body { flex: 1; min-width: 0; } .ac-title { font-size: 0.84rem; font-weight: 700; color: #0F172A; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } - .ac-sub { font-size: 0.72rem; color: #8898AA; margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + .ac-sub { font-size: 0.72rem; color: var(--text-3); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .ac-badge { font-family: 'Unbounded', sans-serif; font-size: 0.82rem; font-weight: 800; color: var(--violet); flex-shrink: 0; } /* ── ZONE 3: Three-Column Grid ── */ @@ -117,7 +117,7 @@ } .w-title { font-family: 'Unbounded', sans-serif; font-size: 0.72rem; font-weight: 800; - color: #8898AA; text-transform: uppercase; letter-spacing: 0.08em; + color: var(--text-3); text-transform: uppercase; letter-spacing: 0.08em; display: flex; align-items: center; gap: 8px; } .w-title::before { @@ -142,14 +142,14 @@ .grade-pct { font-family: 'Unbounded', sans-serif; font-size: 0.88rem; font-weight: 900; min-width: 42px; text-align: center; } .grade-body { flex: 1; min-width: 0; } .grade-subj { font-size: 0.82rem; font-weight: 700; color: #0F172A; } - .grade-date { font-size: 0.7rem; color: #8898AA; } + .grade-date { font-size: 0.7rem; color: var(--text-3); } /* ── activity widget tabs ── */ .act-tabs { display: flex; gap: 4px; } .act-tab { padding: 3px 12px; border-radius: 99px; border: none; font-family: 'Manrope', sans-serif; font-size: 0.68rem; font-weight: 700; - color: #8898AA; background: transparent; cursor: pointer; transition: all 0.15s; + color: var(--text-3); background: transparent; cursor: pointer; transition: all 0.15s; } .act-tab:hover { color: var(--violet); } .act-tab.active { background: #0F172A; color: #fff; } @@ -157,7 +157,7 @@ .act-scale-btn { padding: 2px 8px; border-radius: 6px; border: 1px solid rgba(15,23,42,0.08); font-family: 'Manrope', sans-serif; font-size: 0.62rem; font-weight: 700; - color: #8898AA; background: transparent; cursor: pointer; transition: all 0.12s; + color: var(--text-3); background: transparent; cursor: pointer; transition: all 0.12s; } .act-scale-btn:hover { border-color: rgba(155,93,229,0.3); color: var(--violet); } .act-scale-btn.active { background: rgba(155,93,229,0.08); border-color: rgba(155,93,229,0.25); color: var(--violet); } @@ -166,10 +166,10 @@ /* ── mini heatmap (redesigned) ── */ .hm-months { display: flex; margin-bottom: 2px; padding-left: 22px; } - .hm-month-label { font-size: 0.56rem; font-weight: 700; color: #8898AA; text-transform: uppercase; letter-spacing: 0.02em; overflow: hidden; white-space: nowrap; } + .hm-month-label { font-size: 0.56rem; font-weight: 700; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.02em; overflow: hidden; white-space: nowrap; } .hm-body { display: flex; gap: 0; } .hm-weekdays { display: flex; flex-direction: column; gap: 2px; width: 22px; flex-shrink: 0; padding-top: 1px; } - .hm-wd { font-size: 0.5rem; font-weight: 700; color: #8898AA; height: 14px; line-height: 14px; } + .hm-wd { font-size: 0.5rem; font-weight: 700; color: var(--text-3); height: 14px; line-height: 14px; } .mini-heatmap { display: grid; grid-template-rows: repeat(7, 14px); grid-auto-flow: column; grid-auto-columns: 14px; gap: 2px; } .mhm-cell { width: 14px; height: 14px; border-radius: 50%; background: rgba(15,23,42,0.05); @@ -191,7 +191,7 @@ .hm-footer { display: flex; align-items: center; gap: 14px; margin-top: 8px; padding-top: 8px; border-top: 1px solid rgba(15,23,42,0.05); - font-size: 0.68rem; color: #8898AA; font-weight: 600; flex-wrap: wrap; + font-size: 0.68rem; color: var(--text-3); font-weight: 600; flex-wrap: wrap; } .hm-footer strong { color: #0F172A; font-weight: 800; } .hm-legend { display: flex; align-items: center; gap: 4px; margin-left: auto; } @@ -217,8 +217,8 @@ .hm-day-popup .hdp-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; } .hm-day-popup .hdp-subj { flex: 1; font-weight: 600; color: #0F172A; } .hm-day-popup .hdp-score { font-family: 'Unbounded', sans-serif; font-size: 0.72rem; font-weight: 900; } - .hm-day-popup .hdp-mode { font-size: 0.66rem; color: #8898AA; } - .hm-day-popup .hdp-empty { font-size: 0.75rem; color: #8898AA; padding: 4px 0; } + .hm-day-popup .hdp-mode { font-size: 0.66rem; color: var(--text-3); } + .hm-day-popup .hdp-empty { font-size: 0.75rem; color: var(--text-3); padding: 4px 0; } /* Dark mode */ .app-layout.dark .act-tab.active { background: #E8ECF2; color: #0F172A; } @@ -242,7 +242,7 @@ .cont-emoji { font-size: 1.5rem; flex-shrink: 0; } .cont-info { flex: 1; min-width: 0; } .cont-title { font-size: 0.85rem; font-weight: 700; color: #0F172A; } - .cont-sub { font-size: 0.72rem; color: #8898AA; margin-top: 2px; } + .cont-sub { font-size: 0.72rem; color: var(--text-3); margin-top: 2px; } .cont-pct { font-family: 'Unbounded', sans-serif; font-size: 0.82rem; font-weight: 800; color: var(--violet); } /* ── subjects progress bars ── */ @@ -274,8 +274,8 @@ .smc-icon svg, .smc-icon i { width: 20px; height: 20px; stroke: #fff; stroke-width: 1.8; } .smc-body { flex: 1; min-width: 0; } .smc-name { font-size: 0.86rem; font-weight: 700; color: #0F172A; } - .smc-meta { font-size: 0.72rem; color: #8898AA; margin-top: 2px; } - .smc-arrow { width: 18px; height: 18px; color: #8898AA; flex-shrink: 0; } + .smc-meta { font-size: 0.72rem; color: var(--text-3); margin-top: 2px; } + .smc-arrow { width: 18px; height: 18px; color: var(--text-3); flex-shrink: 0; } /* ── animations ── */ @keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } } @@ -355,7 +355,7 @@ .streak-cal { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; } .sc-day { aspect-ratio: 1; border-radius: 6px; display: flex; align-items: center; justify-content: center; - font-size: 0.62rem; font-weight: 700; color: #8898AA; background: rgba(15,23,42,0.03); + font-size: 0.62rem; font-weight: 700; color: var(--text-3); background: rgba(15,23,42,0.03); transition: transform 0.12s; } .sc-day.today { border: 1.5px solid var(--violet); color: var(--violet); font-weight: 800; } @@ -372,7 +372,7 @@ .sc-month { font-family: 'Unbounded', sans-serif; font-size: 0.7rem; font-weight: 800; color: #0F172A; } .sc-streak-badge { font-family: 'Unbounded', sans-serif; font-size: 0.7rem; font-weight: 800; color: #F59E0B; display: flex; align-items: center; gap: 4px; } .sc-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; margin-bottom: 3px; } - .sc-wd { font-size: 0.56rem; color: #8898AA; font-weight: 700; text-align: center; text-transform: uppercase; } + .sc-wd { font-size: 0.56rem; color: var(--text-3); font-weight: 700; text-align: center; text-transform: uppercase; } /* C4: Keyboard shortcuts hint */ .kb-hint { @@ -400,7 +400,7 @@ .qs-subj-icon svg { width: 14px; height: 14px; stroke: #fff; stroke-width: 2; } .qs-options { display: flex; flex-direction: column; gap: 12px; } .qs-row { display: flex; align-items: center; gap: 12px; } - .qs-label { font-size: 0.78rem; font-weight: 700; color: #8898AA; min-width: 80px; } + .qs-label { font-size: 0.78rem; font-weight: 700; color: var(--text-3); min-width: 80px; } .qs-select, .qs-input { flex: 1; padding: 8px 12px; border: 1.5px solid rgba(15,23,42,0.1); border-radius: 8px; font-family: 'Manrope', sans-serif; font-size: 0.82rem; @@ -441,7 +441,7 @@ display: flex; align-items: center; gap: 8px; padding: 6px 14px; border-radius: 10px; background: rgba(15,23,42,0.03); border: 1px solid rgba(15,23,42,0.06); - font-family: 'Manrope', sans-serif; font-size: 0.75rem; font-weight: 600; color: #8898AA; + font-family: 'Manrope', sans-serif; font-size: 0.75rem; font-weight: 600; color: var(--text-3); } .adm-stat-val { font-family: 'Unbounded', sans-serif; font-size: 0.82rem; font-weight: 900; @@ -466,7 +466,7 @@ } .adm-sess-row:last-child { border-bottom: none; } .adm-sess-name { flex: 1; font-weight: 600; color: #0F172A; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } - .adm-sess-subj { color: #8898AA; font-weight: 600; min-width: 60px; } + .adm-sess-subj { color: var(--text-3); font-weight: 600; min-width: 60px; } .adm-sess-pct { font-family: 'Unbounded', sans-serif; font-weight: 900; font-size: 0.74rem; min-width: 36px; text-align: right; } /* Dark mode for admin */ @@ -484,7 +484,7 @@ .cs-avatar { width: 36px; height: 36px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 1.1rem; flex-shrink: 0; } .cs-body { flex: 1; min-width: 0; } .cs-name { font-size: 0.84rem; font-weight: 700; color: #0F172A; } - .cs-stats { font-size: 0.72rem; color: #8898AA; margin-top: 2px; display: flex; gap: 10px; } + .cs-stats { font-size: 0.72rem; color: var(--text-3); margin-top: 2px; display: flex; gap: 10px; } .cs-stats span { display: flex; align-items: center; gap: 3px; } .cs-bar { width: 60px; height: 5px; border-radius: 99px; background: rgba(15,23,42,0.07); overflow: hidden; flex-shrink: 0; } .cs-fill { height: 100%; border-radius: 99px; background: var(--violet); } @@ -496,7 +496,7 @@ } .section-title { font-family: 'Unbounded', sans-serif; font-size: 0.78rem; font-weight: 800; - color: #8898AA; text-transform: uppercase; letter-spacing: 0.09em; + color: var(--text-3); text-transform: uppercase; letter-spacing: 0.09em; display: flex; align-items: center; gap: 8px; } .section-title::before { @@ -518,7 +518,7 @@ } .assign-chip:hover { border-color: rgba(155,93,229,0.3); color: var(--violet); } .assign-chip.active { background: #0F172A; color: #fff; border-color: #0F172A; } - .assign-stats { font-size: 0.75rem; color: #8898AA; font-weight: 600; display: flex; gap: 14px; flex-wrap: wrap; } + .assign-stats { font-size: 0.75rem; color: var(--text-3); font-weight: 600; display: flex; gap: 14px; flex-wrap: wrap; } .assign-stats .s-active { color: var(--violet); } .assign-stats .s-overdue { color: var(--pink); } .assign-stats .s-done { color: #059652; } @@ -527,7 +527,7 @@ .subj-filter-row { display: flex; gap: 5px; flex-wrap: wrap; margin-bottom: 14px; } .sf-chip { padding: 3px 11px 3px 8px; border-radius: 99px; border: 1.5px solid rgba(15,23,42,0.09); - background: #fff; color: #8898AA; + background: #fff; color: var(--text-3); font-family: 'Manrope', sans-serif; font-size: 0.72rem; font-weight: 700; cursor: pointer; transition: all 0.15s; display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; @@ -540,7 +540,7 @@ .assign-group-hdr { display: flex; align-items: center; gap: 10px; font-family: 'Unbounded', sans-serif; font-size: 0.72rem; font-weight: 800; - color: #8898AA; text-transform: uppercase; letter-spacing: 0.08em; + color: var(--text-3); text-transform: uppercase; letter-spacing: 0.08em; margin: 8px 0 4px; cursor: pointer; user-select: none; } .assign-group-hdr::before { content: ''; display: inline-block; width: 3px; height: 13px; border-radius: 99px; flex-shrink: 0; } @@ -569,7 +569,7 @@ .ae-pills { display: flex; gap: 6px; flex-wrap: wrap; flex: 1; } .ae-pill { padding: 3px 10px; border-radius: 99px; background: rgba(15,23,42,0.06); color: #6B7A8E; font-size: 0.72rem; font-weight: 600; } .ae-dl { flex: 1; } - .ae-dl-label { font-size: 0.70rem; color: #8898AA; margin-bottom: 5px; display: flex; justify-content: space-between; } + .ae-dl-label { font-size: 0.70rem; color: var(--text-3); margin-bottom: 5px; display: flex; justify-content: space-between; } .ae-dl-bar { height: 4px; border-radius: 99px; background: rgba(15,23,42,0.08); overflow: hidden; } .ae-dl-fill { height: 100%; border-radius: 99px; transition: width 0.4s; } .ae-btn { @@ -619,7 +619,7 @@ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.2; } .ar-meta { - font-size: 0.71rem; color: #8898AA; margin-top: 3px; + font-size: 0.71rem; color: var(--text-3); margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .ar-meta .ar-tag-urgent { color: #E83A1E; font-weight: 700; } @@ -635,7 +635,7 @@ .ar-progress { display: flex; align-items: center; gap: 8px; flex-shrink: 0; } .ar-prog-bar { width: 72px; height: 4px; border-radius: 99px; background: rgba(15,23,42,0.08); overflow: hidden; } .ar-prog-fill { height: 100%; border-radius: 99px; } - .ar-prog-text { font-size: 0.71rem; color: #8898AA; white-space: nowrap; min-width: 36px; } + .ar-prog-text { font-size: 0.71rem; color: var(--text-3); white-space: nowrap; min-width: 36px; } .ar-btn { padding: 6px 16px; border: none; border-radius: 99px; @@ -655,7 +655,7 @@ .ar-btn-result:hover { background: rgba(6,214,100,0.14); } .ar-btn-ghost { padding: 6px 16px; border: 1.5px solid rgba(15,23,42,0.12); border-radius: 99px; - background: transparent; color: #8898AA; + background: transparent; color: var(--text-3); font-family: 'Manrope', sans-serif; font-size: 0.76rem; font-weight: 600; text-decoration: none; display: inline-flex; align-items: center; white-space: nowrap; transition: all 0.15s; @@ -684,13 +684,13 @@ .hist-pct.lo { color: var(--pink); } .hist-info { flex: 1; } .hist-subj { font-size: 0.88rem; font-weight: 700; margin-bottom: 2px; color: #0F172A; } - .hist-meta { font-size: 0.75rem; color: #8898AA; } + .hist-meta { font-size: 0.75rem; color: var(--text-3); } .hist-score { font-size: 0.8rem; color: #3D4F6B; font-weight: 600; white-space: nowrap; } /* ── progress tab ── */ .chart-section-title { font-family: 'Unbounded', sans-serif; font-size: 0.76rem; font-weight: 800; - color: #8898AA; text-transform: uppercase; letter-spacing: 0.09em; + color: var(--text-3); text-transform: uppercase; letter-spacing: 0.09em; margin: 36px 0 16px; display: flex; align-items: center; gap: 8px; } @@ -716,7 +716,7 @@ } .subj-chart-card:hover { border-color: rgba(15,23,42,0.14); transform: translateY(-3px); box-shadow: 0 10px 32px rgba(15,23,42,0.1); } .subj-chart-name { font-family: 'Unbounded', sans-serif; font-size: 0.76rem; font-weight: 800; color: #0F172A; } - .subj-chart-sessions { font-size: 0.72rem; color: #8898AA; } + .subj-chart-sessions { font-size: 0.72rem; color: var(--text-3); } .canvas-wrap { position: relative; width: 130px; height: 130px; margin: 4px 0; } /* ── weak topics ── */ @@ -731,7 +731,7 @@ .weak-item:hover { border-color: rgba(15,23,42,0.12); transform: translateX(4px); box-shadow: 0 6px 24px rgba(15,23,42,0.08); } .weak-bar-wrap { flex: 1; } .weak-name { font-size: 0.88rem; font-weight: 700; margin-bottom: 2px; color: #0F172A; } - .weak-meta { font-size: 0.75rem; color: #8898AA; } + .weak-meta { font-size: 0.75rem; color: var(--text-3); } .weak-bar { height: 7px; background: rgba(15,23,42,0.07); border-radius: 99px; overflow: hidden; margin-top: 8px; } .weak-fill { height: 100%; border-radius: 99px; background: linear-gradient(90deg, #FF9F1C, #F15BB5); transition: width 0.8s cubic-bezier(0.34,1.2,0.64,1); } .weak-pct { font-family: 'Unbounded', sans-serif; font-size: 1rem; font-weight: 900; color: #E0335E; min-width: 48px; text-align: right; } @@ -741,7 +741,7 @@ display: flex; align-items: center; gap: 10px; padding-top: 8px; border-top: 1px solid rgba(15,23,42,0.06); flex-wrap: wrap; } - .ae-submit-label { font-size: 0.72rem; color: #8898AA; font-weight: 600; flex-shrink: 0; } + .ae-submit-label { font-size: 0.72rem; color: var(--text-3); font-weight: 600; flex-shrink: 0; } .ae-submit-status { display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px; border-radius: 99px; font-size: 0.72rem; font-weight: 700; @@ -775,7 +775,7 @@ .ms-row:hover { transform: translateX(3px); box-shadow: 0 4px 16px rgba(15,23,42,0.07); } .ms-title { flex: 1; font-size: 0.82rem; font-weight: 600; color: #0F172A; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } - .ms-file { font-size: 0.7rem; color: #8898AA; flex-shrink: 0; max-width: 120px; + .ms-file { font-size: 0.7rem; color: var(--text-3); flex-shrink: 0; max-width: 120px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .ms-grade { font-weight: 800; font-size: 0.78rem; flex-shrink: 0; } .ms-more { display: inline-block; margin-top: 8px; font-size: 0.78rem; font-weight: 700; color: var(--violet); text-decoration: none; } @@ -807,7 +807,7 @@ /* ── spinner / empty ── */ .spinner { width: 36px; height: 36px; border: 3px solid rgba(15,23,42,0.1); border-top-color: var(--violet); border-radius: 50%; animation: spin 0.75s linear infinite; margin: 48px auto; display: block; } @keyframes spin { to { transform: rotate(360deg); } } - .empty { text-align: center; padding: 36px; color: #8898AA; font-size: 0.88rem; } + .empty { text-align: center; padding: 36px; color: var(--text-3); font-size: 0.88rem; } /* ── empty CTA ── */ .empty-cta { @@ -850,7 +850,7 @@ .form-input { width: 100%; padding: 12px 16px; border: 1.5px solid rgba(15,23,42,0.15); border-radius: 12px; font-family: 'Manrope', sans-serif; font-size: 0.95rem; color: var(--text); background: #f8f9fc; transition: border-color 0.2s; box-sizing: border-box; } .form-input:focus { outline: none; border-color: var(--violet); background: #fff; } .modal-footer { display: flex; gap: 10px; justify-content: flex-end; margin-top: 22px; } - .btn-cancel { padding: 10px 22px; border: 1.5px solid rgba(15,23,42,0.15); border-radius: 999px; background: transparent; font-family: 'Manrope', sans-serif; font-size: 0.88rem; font-weight: 600; color: #8898AA; cursor: pointer; transition: all 0.18s; } + .btn-cancel { padding: 10px 22px; border: 1.5px solid rgba(15,23,42,0.15); border-radius: 999px; background: transparent; font-family: 'Manrope', sans-serif; font-size: 0.88rem; font-weight: 600; color: var(--text-3); cursor: pointer; transition: all 0.18s; } .btn-cancel:hover { border-color: rgba(15,23,42,0.3); color: var(--text); } .btn-join { padding: 10px 28px; border: none; border-radius: 999px; background: #0F172A; color: #fff; font-family: 'Manrope', sans-serif; font-size: 0.88rem; font-weight: 700; cursor: pointer; box-shadow: 0 2px 10px rgba(15,23,42,0.2); transition: all 0.18s; } .btn-join:hover { background: #1E2D4A; box-shadow: 0 6px 20px rgba(15,23,42,0.25); } @@ -860,7 +860,7 @@ /* ── history timeline ── */ .hist-date-sep { font-family: 'Unbounded', sans-serif; font-size: 0.68rem; font-weight: 800; - color: #8898AA; text-transform: uppercase; letter-spacing: 0.08em; + color: var(--text-3); text-transform: uppercase; letter-spacing: 0.08em; margin: 22px 0 10px; display: flex; align-items: center; gap: 12px; } .hist-date-sep:first-child { margin-top: 0; } @@ -876,7 +876,7 @@ border-radius: 18px; padding: 18px 20px; } .stats-chart-title { - font-size: 0.72rem; font-weight: 700; color: #8898AA; + font-size: 0.72rem; font-weight: 700; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 12px; } .stats-bar-chart { display: flex; align-items: flex-end; gap: 4px; height: 100px; } @@ -909,7 +909,7 @@ font-family: 'Unbounded', sans-serif; font-size: 1.1rem; font-weight: 800; color: #0F172A; line-height: 1; } - .stats-chip-lbl { font-size: 0.65rem; color: #8898AA; margin-top: 3px; font-weight: 600; } + .stats-chip-lbl { font-size: 0.65rem; color: var(--text-3); margin-top: 3px; font-weight: 600; } /* ── activity heatmap ── */ .heatmap-section { @@ -924,7 +924,7 @@ .hm-cell[data-n="3"] { background: rgba(155,93,229,0.65); } .hm-cell[data-n="4"] { background: rgba(155,93,229,0.88); } .hm-cell:hover { transform: scale(1.5); z-index: 5; position: relative; } - .heatmap-legend { display: flex; align-items: center; gap: 5px; margin-top: 14px; font-size: 0.72rem; color: #8898AA; } + .heatmap-legend { display: flex; align-items: center; gap: 5px; margin-top: 14px; font-size: 0.72rem; color: var(--text-3); } .hm-leg { width: 14px; height: 14px; border-radius: 3px; } /* ── subject card grid (legacy, kept for compatibility) ── */ @@ -945,12 +945,12 @@ .tc-emoji { font-size: 1.6rem; line-height: 1; } .tc-info { flex: 1; } .tc-title { font-size: 0.88rem; font-weight: 700; color: #0F172A; line-height: 1.35; } - .tc-subj { font-size: 0.7rem; font-weight: 700; color: #8898AA; margin-top: 2px; text-transform: uppercase; letter-spacing: 0.06em; } + .tc-subj { font-size: 0.7rem; font-weight: 700; color: var(--text-3); margin-top: 2px; text-transform: uppercase; letter-spacing: 0.06em; } .tc-progress { display: flex; align-items: center; gap: 8px; } .tc-bar { flex: 1; height: 5px; border-radius: 99px; background: rgba(15,23,42,0.07); } .tc-fill { height: 100%; border-radius: 99px; background: var(--violet); } .tc-pct { font-size: 0.72rem; font-weight: 700; color: var(--violet); flex-shrink: 0; } - .tc-meta { font-size: 0.74rem; color: #8898AA; } + .tc-meta { font-size: 0.74rem; color: var(--text-3); } /* ── Leaderboard widget ── */ .lb-widget { @@ -964,7 +964,7 @@ .lb-tab { padding: 5px 12px; border-radius: 99px; border: none; font-family: 'Manrope', sans-serif; font-size: 0.72rem; font-weight: 700; - background: transparent; color: #8898AA; cursor: pointer; transition: all 0.15s; + background: transparent; color: var(--text-3); cursor: pointer; transition: all 0.15s; } .lb-tab.active { background: linear-gradient(135deg, rgba(155,93,229,0.1), rgba(6,214,224,0.08)); color: #9B5DE5; } .lb-list { display: flex; flex-direction: column; gap: 4px; } @@ -978,7 +978,7 @@ width: 24px; height: 24px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center; justify-content: center; font-family: 'Unbounded', sans-serif; font-size: 0.68rem; font-weight: 900; - background: rgba(15,23,42,0.06); color: #8898AA; + background: rgba(15,23,42,0.06); color: var(--text-3); } .lb-pos.gold { background: linear-gradient(135deg, #FFD700, #FFA500); color: #fff; } .lb-pos.silver { background: linear-gradient(135deg, #C0C0C0, #A0A0A0); color: #fff; } @@ -991,9 +991,9 @@ } .lb-info { flex: 1; min-width: 0; } .lb-name { font-size: 0.82rem; font-weight: 700; color: #0F172A; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } - .lb-rank { font-size: 0.64rem; color: #8898AA; font-weight: 600; } + .lb-rank { font-size: 0.64rem; color: var(--text-3); font-weight: 600; } .lb-xp { font-family: 'Unbounded', sans-serif; font-size: 0.78rem; font-weight: 800; color: #9B5DE5; flex-shrink: 0; } - .lb-empty { text-align: center; padding: 20px; color: #8898AA; font-size: 0.82rem; } + .lb-empty { text-align: center; padding: 20px; color: var(--text-3); font-size: 0.82rem; } .lb-class-sel { padding: 5px 10px; border-radius: 10px; border: 1.5px solid rgba(15,23,42,0.1); background: #fff; font-family: 'Manrope', sans-serif; font-size: 0.72rem; font-weight: 600; @@ -1014,7 +1014,7 @@ .ch-icon { font-size: 1.3rem; flex-shrink: 0; } .ch-body { flex: 1; min-width: 0; } .ch-title { font-size: 0.84rem; font-weight: 700; color: #0F172A; } - .ch-desc { font-size: 0.72rem; color: #8898AA; margin-top: 2px; } + .ch-desc { font-size: 0.72rem; color: var(--text-3); margin-top: 2px; } .ch-prog { display: flex; align-items: center; gap: 8px; margin-top: 6px; } .ch-bar { flex: 1; height: 5px; border-radius: 99px; background: rgba(15,23,42,0.07); overflow: hidden; } .ch-fill { height: 100%; border-radius: 99px; background: linear-gradient(90deg, #9B5DE5, #06D6E0); transition: width 0.4s; } @@ -1047,7 +1047,7 @@ .gam-main { flex: 1; min-width: 0; } .gam-top { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; } .gam-rank { font-family: 'Unbounded', sans-serif; font-size: 0.82rem; font-weight: 800; color: #0F172A; } - .gam-xp-text { font-size: 0.72rem; color: #8898AA; font-weight: 600; } + .gam-xp-text { font-size: 0.72rem; color: var(--text-3); font-weight: 600; } .gam-progress { height: 8px; border-radius: 99px; background: rgba(15,23,42,0.07); overflow: hidden; } .gam-fill { height: 100%; border-radius: 99px; background: linear-gradient(90deg, #9B5DE5, #06D6E0); transition: width 0.6s ease; } .gam-chips { display: flex; gap: 10px; flex-shrink: 0; } @@ -1059,7 +1059,7 @@ } .gam-chip-icon { font-size: 1.1rem; line-height: 1; } .gam-chip-val { font-family: 'Unbounded', sans-serif; font-size: 0.78rem; font-weight: 800; color: #0F172A; } - .gam-chip-lbl { font-size: 0.58rem; color: #8898AA; font-weight: 600; text-transform: uppercase; } + .gam-chip-lbl { font-size: 0.58rem; color: var(--text-3); font-weight: 600; text-transform: uppercase; } .gam-goal-ring { position: relative; width: 40px; height: 40px; } .gam-goal-ring svg { width: 40px; height: 40px; } @@ -2640,11 +2640,11 @@ y: { min: 0, max: 100, grid: { color: 'rgba(15,23,42,0.05)' }, - ticks: { callback: v => v + '%', font: { family: 'Manrope', size: 11 }, color: '#8898AA' } + ticks: { callback: v => v + '%', font: { family: 'Manrope', size: 11 }, color: '#56687A' } }, x: { grid: { display: false }, - ticks: { font: { family: 'Manrope', size: 11 }, color: '#8898AA' } + ticks: { font: { family: 'Manrope', size: 11 }, color: '#56687A' } } } } @@ -2822,7 +2822,7 @@ Работа: ${lci(st.icon,'width:14px;height:14px')} ${st.label} ${gradeHtml} - ${esc(sub.original_name)} + ${esc(sub.original_name)} ${noteHtml} ${resubBtn} ${delBtn} @@ -2843,7 +2843,7 @@ if (!wrap || !list || isTeacher) return; if (!_allSubmissions.length) { - list.innerHTML = `
+ list.innerHTML = `
${lci('file-plus','width:24px;height:24px;opacity:0.4;display:block;margin:0 auto 8px')} Сданных работ пока нет.
Когда учитель назначит задание с прикреплением файла, вы сможете сдать его прямо здесь. @@ -3354,7 +3354,7 @@ ${monthNames[month]} ${lci('flame', 16)} ${streak} - ${bestStreak > streak ? `рекорд ${bestStreak}` : ''} + ${bestStreak > streak ? `рекорд ${bestStreak}` : ''}
`; html += `
${wdNames.map(d => `${d}`).join('')}
`; @@ -3454,7 +3454,7 @@ try { const classes = await LS.api('/api/classes'); if (!classes || !classes.length) { - body.innerHTML = '
Нет классов
'; + body.innerHTML = '
Нет классов
'; return; } const colors = ['#9B5DE5','#06D6A0','#F59E0B','#06B6D4','#E0335E']; @@ -3475,7 +3475,7 @@ }).join(''); reIcons(); } catch { - body.innerHTML = '
Ошибка загрузки
'; + body.innerHTML = '
Ошибка загрузки
'; } } @@ -3488,7 +3488,7 @@ const data = await LS.api('/api/admin/sessions?limit=8'); const rows = Array.isArray(data) ? data : (data.rows || []); if (!rows.length) { - body.innerHTML = '
Нет сессий
'; + body.innerHTML = '
Нет сессий
'; return; } body.innerHTML = rows.slice(0, 8).map(s => { @@ -3502,7 +3502,7 @@
`; }).join(''); } catch { - body.innerHTML = '
Ошибка
'; + body.innerHTML = '
Ошибка
'; } } @@ -3514,7 +3514,7 @@ try { const list = await LS.teacherAssignments(); if (!list.length) { - listEl.innerHTML = '
Заданий пока нет
'; + listEl.innerHTML = '
Заданий пока нет
'; return; } const sorted = [...list].sort((a, b) => urgencyScore(a) - urgencyScore(b)); @@ -3524,7 +3524,7 @@ } reIcons(); } catch { - listEl.innerHTML = '
Ошибка загрузки
'; + listEl.innerHTML = '
Ошибка загрузки
'; } } diff --git a/frontend/gradebook.html b/frontend/gradebook.html index c0412fb..aff7dc9 100644 --- a/frontend/gradebook.html +++ b/frontend/gradebook.html @@ -62,7 +62,7 @@ .gb-chip-val { font-family: 'Unbounded', sans-serif; font-size: 1.3rem; font-weight: 800; } - .gb-chip-label { font-size: 0.72rem; color: #8898AA; font-weight: 600; margin-top: 4px; } + .gb-chip-label { font-size: 0.72rem; color: var(--text-3); font-weight: 600; margin-top: 4px; } /* ── table container ── */ .gb-container { max-width: 1200px; margin: 0 auto; padding: 24px 28px 80px; } @@ -82,7 +82,7 @@ position: sticky; top: 0; z-index: 10; background: #f8f9fc; border-bottom: 1.5px solid rgba(15,23,42,0.08); padding: 12px 14px; text-align: left; - 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; white-space: nowrap; } @@ -134,7 +134,7 @@ flex-shrink: 0; } .gb-student-name { font-weight: 700; font-size: 0.82rem; } - .gb-student-email { font-size: 0.68rem; color: #8898AA; font-weight: 500; } + .gb-student-email { font-size: 0.68rem; color: var(--text-3); font-weight: 500; } /* ── footer row ── */ .gb-table tfoot td { @@ -155,7 +155,7 @@ /* ── empty state ── */ .gb-empty { - text-align: center; padding: 60px 20px; color: #8898AA; font-size: 0.88rem; + text-align: center; padding: 60px 20px; color: var(--text-3); font-size: 0.88rem; } .gb-empty-icon { font-size: 3rem; margin-bottom: 12px; opacity: 0.3; } @@ -448,7 +448,7 @@ html += `${gradeCell(classAvg)}`; html += `
`; } else { - html += `
+ html += `
Нет заданий в этом классе. Создать задание
`; } diff --git a/frontend/homework.html b/frontend/homework.html index 41d03ee..b9d6204 100644 --- a/frontend/homework.html +++ b/frontend/homework.html @@ -15,7 +15,7 @@ font-family: 'Unbounded', sans-serif; font-size: 1.1rem; font-weight: 800; color: #0F172A; margin-bottom: 6px; } - .page-sub { font-size: 0.82rem; color: #8898AA; margin-bottom: 24px; } + .page-sub { font-size: 0.82rem; color: var(--text-3); margin-bottom: 24px; } /* ── top bar with class selector ── */ .hw-top { display: flex; align-items: center; gap: 14px; margin-bottom: 24px; flex-wrap: wrap; } @@ -28,7 +28,7 @@ .hw-sf-btn { padding: 6px 14px; border-radius: 999px; border: 1.5px solid rgba(15,23,42,0.1); background: transparent; font-family: 'Manrope', sans-serif; font-size: 0.75rem; - font-weight: 600; color: #8898AA; cursor: pointer; transition: all .15s; + font-weight: 600; color: var(--text-3); cursor: pointer; transition: all .15s; } .hw-sf-btn:hover { border-color: var(--violet); color: var(--violet); } .hw-sf-btn.active { background: rgba(155,93,229,0.08); border-color: var(--violet); color: var(--violet); } @@ -48,7 +48,7 @@ } .hw-card-body { flex: 1; min-width: 0; } .hw-card-title { font-size: 0.88rem; font-weight: 700; color: #0F172A; margin-bottom: 4px; } - .hw-card-meta { font-size: 0.75rem; color: #8898AA; display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 6px; } + .hw-card-meta { font-size: 0.75rem; color: var(--text-3); display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 6px; } .hw-card-note { font-size: 0.78rem; color: #3D4F6B; background: rgba(15,23,42,0.03); padding: 8px 12px; border-radius: 10px; margin-top: 8px; line-height: 1.5; } .hw-card-note strong { color: #0F172A; } .hw-card-actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; } @@ -99,9 +99,9 @@ .hw-upload-area:hover, .hw-upload-area.dragover { border-color: var(--violet); background: rgba(155,93,229,0.02); } - .hw-upload-icon { color: #8898AA; margin-bottom: 8px; } + .hw-upload-icon { color: var(--text-3); margin-bottom: 8px; } .hw-upload-text { font-size: 0.85rem; font-weight: 600; color: #3D4F6B; margin-bottom: 4px; } - .hw-upload-hint { font-size: 0.72rem; color: #8898AA; } + .hw-upload-hint { font-size: 0.72rem; color: var(--text-3); } /* review modal (inline) */ .hw-review-panel { @@ -118,7 +118,7 @@ .hw-review-panel textarea { min-height: 60px; resize: vertical; } /* empty state */ - .hw-empty { text-align: center; padding: 60px 20px; color: #8898AA; } + .hw-empty { text-align: center; padding: 60px 20px; color: var(--text-3); } .hw-empty-icon { font-size: 3rem; margin-bottom: 12px; opacity: 0.3; } .hw-empty-text { font-size: 0.88rem; font-weight: 600; } @@ -164,13 +164,13 @@ accept=".pdf,.doc,.docx,.ppt,.pptx,.xls,.xlsx,.png,.jpg,.jpeg,.gif,.webp,.txt" />
- +
- +
- +
@@ -2085,7 +2085,7 @@ ${pairs.map((p, i) => `
- +
Элементы (текущий порядок = правильный)
-
Элементы будут перемешаны для ученика.
+
Элементы будут перемешаны для ученика.
${items.map((item, i) => `
- ${i+1} + ${i+1}