Поправил шрифты и некоторые визуальные косяки
This commit is contained in:
@@ -18,6 +18,7 @@ COPY edu-office/ /usr/local/apache2/htdocs/edu-office/
|
||||
COPY student/ /usr/local/apache2/htdocs/student/
|
||||
COPY teacher/ /usr/local/apache2/htdocs/teacher/
|
||||
COPY index.html script.js style.css theme-toggle.js auth-session.js telemetry.js /usr/local/apache2/htdocs/
|
||||
COPY ui-foundation.css schedule-overview.css schedule-overview.js /usr/local/apache2/htdocs/
|
||||
COPY --from=frontend-assets /build/dist/vendor/ /usr/local/apache2/htdocs/vendor/
|
||||
COPY security.conf /usr/local/apache2/conf/extra/magistr-security.conf
|
||||
COPY proxy.conf /usr/local/apache2/conf/extra/magistr-proxy.conf
|
||||
|
||||
@@ -219,6 +219,13 @@
|
||||
align-content: flex-start;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.25rem;
|
||||
height: 180px;
|
||||
min-height: 180px;
|
||||
max-height: 180px;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
scrollbar-gutter: stable;
|
||||
padding-right: 0.25rem;
|
||||
}
|
||||
|
||||
.dashboard-actions {
|
||||
|
||||
@@ -67,7 +67,7 @@ html {
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
font-family: var(--ui-font-sans, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
|
||||
background: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
min-height: 100vh;
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
.quality-hero h2 {
|
||||
max-width: 790px;
|
||||
margin: 0;
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-family: var(--ui-font-display);
|
||||
font-size: clamp(2rem, 4.5vw, 4.4rem);
|
||||
font-weight: 500;
|
||||
letter-spacing: -0.045em;
|
||||
@@ -229,7 +229,7 @@
|
||||
|
||||
.quality-score-inner strong {
|
||||
color: var(--text-primary);
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-family: var(--ui-font-display);
|
||||
font-size: 3.2rem;
|
||||
font-weight: 500;
|
||||
line-height: 0.95;
|
||||
@@ -271,7 +271,7 @@
|
||||
.quality-score-copy h3 {
|
||||
margin: 0.55rem 0 0;
|
||||
color: var(--text-primary);
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-family: var(--ui-font-display);
|
||||
font-size: clamp(1.6rem, 3vw, 2.5rem);
|
||||
font-weight: 500;
|
||||
}
|
||||
@@ -338,7 +338,7 @@
|
||||
|
||||
.quality-metric-index {
|
||||
color: color-mix(in srgb, var(--text-secondary) 65%, transparent);
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-family: var(--ui-font-display);
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@
|
||||
display: block;
|
||||
margin-top: 1.25rem;
|
||||
color: var(--text-primary);
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-family: var(--ui-font-display);
|
||||
font-size: 2rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
@@ -402,7 +402,7 @@
|
||||
.quality-recommendations h3 {
|
||||
margin: 0;
|
||||
color: var(--text-primary);
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-family: var(--ui-font-display);
|
||||
font-size: 1.65rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
@@ -537,7 +537,7 @@
|
||||
|
||||
.quality-penalty {
|
||||
color: var(--quality-red);
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-family: var(--ui-font-display);
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
@@ -583,7 +583,7 @@
|
||||
background: color-mix(in srgb, var(--quality-cyan) 10%, transparent);
|
||||
border: 1px solid color-mix(in srgb, var(--quality-cyan) 35%, transparent);
|
||||
border-radius: 50%;
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-family: var(--ui-font-display);
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
right: -1.5rem;
|
||||
bottom: 1.2rem;
|
||||
color: rgba(255, 255, 255, .055);
|
||||
font-family: Georgia, serif;
|
||||
font-family: var(--ui-font-display);
|
||||
font-size: clamp(4rem, 10vw, 9rem);
|
||||
letter-spacing: -.08em;
|
||||
pointer-events: none;
|
||||
@@ -53,7 +53,7 @@
|
||||
.version-hero h2 {
|
||||
max-width: 760px;
|
||||
margin: 0;
|
||||
font-family: Georgia, 'Times New Roman', serif;
|
||||
font-family: var(--ui-font-display);
|
||||
font-size: clamp(2rem, 4.5vw, 4.5rem);
|
||||
font-weight: 500;
|
||||
letter-spacing: -.05em;
|
||||
@@ -136,7 +136,7 @@
|
||||
background: linear-gradient(105deg, color-mix(in srgb, var(--version-copper) 10%, var(--bg-card)), var(--bg-card));
|
||||
border-color: color-mix(in srgb, var(--version-copper) 35%, var(--bg-card-border));
|
||||
}
|
||||
.version-constructor-bar h2 { margin: 0; color: var(--text-primary); font-family: Georgia, serif; font-size: 1.55rem; }
|
||||
.version-constructor-bar h2 { margin: 0; color: var(--text-primary); font-family: var(--ui-font-display); font-size: 1.55rem; }
|
||||
.version-constructor-bar p { margin: .35rem 0 0; color: var(--text-secondary); font-size: .82rem; }
|
||||
.version-constructor-controls { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .65rem; align-items: end; }
|
||||
.version-constructor-field { min-width: 0; }
|
||||
@@ -219,7 +219,7 @@
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.version-section-head > span { color: var(--version-copper); font-family: Georgia, serif; font-size: 2rem; }
|
||||
.version-section-head > span { color: var(--version-copper); font-family: var(--ui-font-display); font-size: 2rem; }
|
||||
.version-draft-list { display: grid; gap: .8rem; }
|
||||
|
||||
.version-card {
|
||||
@@ -237,7 +237,7 @@
|
||||
right: .5rem;
|
||||
top: -.8rem;
|
||||
color: color-mix(in srgb, var(--version-copper) 12%, transparent);
|
||||
font-family: Georgia, serif;
|
||||
font-family: var(--ui-font-display);
|
||||
font-size: 5rem;
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
place-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
.version-empty > span { color: var(--version-copper); font-family: Georgia, serif; font-size: 4rem; }
|
||||
.version-empty > span { color: var(--version-copper); font-family: var(--ui-font-display); font-size: 4rem; }
|
||||
.version-empty p { max-width: 360px; }
|
||||
|
||||
.version-diff-score {
|
||||
@@ -262,7 +262,7 @@
|
||||
margin: 1rem 0;
|
||||
}
|
||||
.version-diff-score div { padding: .75rem; background: var(--bg-input); border-radius: var(--radius-sm); text-align: center; }
|
||||
.version-diff-score strong { display: block; color: var(--text-primary); font-family: Georgia, serif; font-size: 1.75rem; }
|
||||
.version-diff-score strong { display: block; color: var(--text-primary); font-family: var(--ui-font-display); font-size: 1.75rem; }
|
||||
.version-diff-score span { color: var(--text-secondary); font-size: .68rem; text-transform: uppercase; }
|
||||
|
||||
.version-change-list { display: grid; gap: .55rem; max-height: 390px; overflow: auto; }
|
||||
@@ -292,7 +292,7 @@
|
||||
}
|
||||
.version-modal[hidden] { display: none; }
|
||||
.version-modal-card { position: relative; width: min(560px, 100%); padding: 1.6rem; background: var(--bg-primary); border: 1px solid var(--bg-card-border); border-radius: var(--radius-lg, 20px); box-shadow: 0 30px 80px rgba(0, 0, 0, .45); }
|
||||
.version-modal-card h3 { margin: 0; color: var(--text-primary); font-family: Georgia, serif; font-size: 2rem; }
|
||||
.version-modal-card h3 { margin: 0; color: var(--text-primary); font-family: var(--ui-font-display); font-size: 2rem; }
|
||||
.version-modal-card > p { margin: .6rem 0 1rem; color: var(--text-secondary); line-height: 1.55; }
|
||||
.version-modal-card form { display: grid; gap: .65rem; }
|
||||
.version-modal-card label { color: var(--text-secondary); font-size: .75rem; font-weight: 700; }
|
||||
|
||||
@@ -187,6 +187,7 @@
|
||||
}
|
||||
|
||||
.absence-registry-title {
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
}
|
||||
@@ -220,21 +221,31 @@
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 28px;
|
||||
padding: 0 0.65rem;
|
||||
padding: 0.25rem 0.65rem;
|
||||
flex: 0 0 auto;
|
||||
align-self: flex-start;
|
||||
max-width: 100%;
|
||||
line-height: 1.4;
|
||||
border: 1px solid currentColor;
|
||||
border-radius: 999px;
|
||||
font-size: 0.69rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.03em;
|
||||
white-space: nowrap;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.absence-status.is-pending { color: #f59e0b; }
|
||||
.absence-status.is-approved { color: #fb7185; }
|
||||
.absence-status.is-approved { color: #34d399; }
|
||||
.absence-status.is-resolved { color: #34d399; }
|
||||
.absence-status.is-rejected,
|
||||
.absence-status.is-cancelled { color: var(--text-secondary); }
|
||||
|
||||
[data-theme="light"] .absence-status.is-pending { color: #92400e; }
|
||||
[data-theme="light"] .absence-status.is-approved,
|
||||
[data-theme="light"] .absence-status.is-resolved { color: #047857; }
|
||||
.absence-status.is-rejected { color: #fb7185; }
|
||||
[data-theme="light"] .absence-status.is-rejected { color: #be123c; }
|
||||
|
||||
.absence-registry-buttons {
|
||||
justify-content: flex-end;
|
||||
flex-wrap: wrap;
|
||||
@@ -481,7 +492,7 @@ body.absence-wizard-open {
|
||||
|
||||
.teacher-dialogue-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
@@ -604,7 +615,7 @@ body.absence-wizard-open {
|
||||
|
||||
.teacher-dialogue-item {
|
||||
display: grid;
|
||||
grid-template-columns: 7px minmax(0, 1fr) minmax(180px, .42fr);
|
||||
grid-template-columns: 7px minmax(0, 1fr);
|
||||
gap: .85rem;
|
||||
padding: .85rem;
|
||||
border: 1px solid var(--bg-card-border);
|
||||
@@ -613,6 +624,7 @@ body.absence-wizard-open {
|
||||
}
|
||||
|
||||
.teacher-dialogue-mark {
|
||||
grid-row: 1 / 3;
|
||||
border-radius: 99px;
|
||||
background: #94a3b8;
|
||||
}
|
||||
@@ -631,6 +643,11 @@ body.absence-wizard-open {
|
||||
font-size: .68rem;
|
||||
}
|
||||
|
||||
.teacher-dialogue-copy {
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.teacher-dialogue-copy h3 {
|
||||
margin: .22rem 0;
|
||||
font-size: .92rem;
|
||||
@@ -668,17 +685,32 @@ body.absence-wizard-open {
|
||||
.teacher-dialogue-copy ol { display: grid; gap: .3rem; padding-left: 1.15rem; }
|
||||
|
||||
.teacher-dialogue-action {
|
||||
grid-column: 2;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
align-items: stretch;
|
||||
gap: .55rem;
|
||||
}
|
||||
|
||||
.teacher-dialogue-action > div {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
gap: .35rem;
|
||||
gap: .5rem;
|
||||
}
|
||||
|
||||
.teacher-dialogue-action > div > .btn {
|
||||
flex: 1 1 120px;
|
||||
min-width: 0;
|
||||
white-space: normal;
|
||||
line-height: 1.35;
|
||||
padding-block: 0.4rem;
|
||||
}
|
||||
|
||||
.teacher-dialogue-toolbar > .btn {
|
||||
align-self: center;
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
.teacher-dialogue-comment {
|
||||
@@ -801,6 +833,6 @@ body.absence-wizard-open {
|
||||
|
||||
.teacher-dialogue-action {
|
||||
grid-column: 2;
|
||||
align-items: flex-start;
|
||||
align-items: stretch;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<link rel="stylesheet" href="css/teacher-absences.css">
|
||||
<link rel="stylesheet" href="css/schedule-quality.css">
|
||||
<link rel="stylesheet" href="css/schedule-versions.css">
|
||||
<link rel="stylesheet" href="../ui-foundation.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -78,7 +79,7 @@
|
||||
|
||||
<!-- Раздел: Расписание -->
|
||||
<div class="sidebar-section-divider"></div>
|
||||
<div class="sidebar-section-title" style="font-size: 0.7rem; font-weight: 700; color: rgba(255,255,255,0.4); padding: 0.5rem 1.25rem 0.25rem; text-transform: uppercase; letter-spacing: 0.05em;">Расписание</div>
|
||||
<div class="sidebar-section-title">Расписание</div>
|
||||
|
||||
<a href="#" class="nav-item" data-tab="schedule">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
@@ -149,7 +150,7 @@
|
||||
|
||||
<!-- Раздел: Субъекты и ресурсы -->
|
||||
<div class="sidebar-section-divider"></div>
|
||||
<div class="sidebar-section-title" style="font-size: 0.7rem; font-weight: 700; color: rgba(255,255,255,0.4); padding: 0.5rem 1.25rem 0.25rem; text-transform: uppercase; letter-spacing: 0.05em;">Ресурсы</div>
|
||||
<div class="sidebar-section-title">Ресурсы</div>
|
||||
|
||||
<a href="#" class="nav-item" data-tab="classrooms">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
@@ -184,7 +185,7 @@
|
||||
|
||||
<!-- Раздел: Система -->
|
||||
<div class="sidebar-section-divider"></div>
|
||||
<div class="sidebar-section-title" style="font-size: 0.7rem; font-weight: 700; color: rgba(255,255,255,0.4); padding: 0.5rem 1.25rem 0.25rem; text-transform: uppercase; letter-spacing: 0.05em;">Система</div>
|
||||
<div class="sidebar-section-title">Система</div>
|
||||
|
||||
<a href="#" class="nav-item" data-tab="users">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
|
||||
@@ -935,7 +935,7 @@ export async function initAcademicCalendar() {
|
||||
<span class="calendar-subject-chip">
|
||||
<span>${escapeHtml(subjectRowLabel(row))}</span>
|
||||
<button type="button"
|
||||
class="calendar-subject-remove"
|
||||
class="btn btn-icon-sm btn-danger-subtle calendar-subject-remove"
|
||||
data-semester="${escapeHtml(String(row.semesterNumber))}"
|
||||
data-subject="${escapeHtml(String(row.subjectId))}"
|
||||
aria-label="Убрать ${escapeHtml(subjectRowLabel(row))}">×</button>
|
||||
|
||||
@@ -94,11 +94,13 @@ export async function initClassrooms() {
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<button class="btn btn-sm btn-secondary classroom-edit-action" data-id="${c.id}">Изменить</button>
|
||||
${c.status === 'ARCHIVED'
|
||||
? `<button class="btn-restore-classroom" data-id="${c.id}" style="margin-left: 0.5rem;">Восстановить</button>`
|
||||
: `<button class="btn btn-sm btn-danger-subtle btn-archive-classroom" data-id="${c.id}" style="margin-left: 0.5rem;">Архивировать</button>`}
|
||||
<td class="table-actions-cell">
|
||||
<div class="table-actions">
|
||||
<button class="btn btn-sm btn-secondary classroom-edit-action" data-id="${c.id}">Изменить</button>
|
||||
${c.status === 'ARCHIVED'
|
||||
? `<button class="btn btn-sm btn-secondary btn-restore-classroom" data-id="${c.id}">Восстановить</button>`
|
||||
: `<button class="btn btn-sm btn-danger-subtle btn-archive-classroom" data-id="${c.id}">Архивировать</button>`}
|
||||
</div>
|
||||
</td>
|
||||
</tr>`;
|
||||
}).join('');
|
||||
|
||||
@@ -333,7 +333,7 @@ export async function initGroups() {
|
||||
<button class="btn btn-sm btn-secondary btn-manage-subgroups group-action-btn" data-id="${group.id}">Подгруппы</button>
|
||||
<button class="btn btn-sm btn-secondary btn-manage-calendar group-action-btn" data-id="${group.id}">Календарь</button>
|
||||
${group.status === 'ARCHIVED'
|
||||
? `<button class="btn-restore-group group-action-btn" data-id="${group.id}">Восстановить</button>`
|
||||
? `<button class="btn btn-sm btn-secondary btn-restore-group group-action-btn" data-id="${group.id}">Восстановить</button>`
|
||||
: `<button class="btn btn-sm btn-danger-subtle btn-archive-group group-action-btn" data-id="${group.id}">Архив</button>`}
|
||||
</div>
|
||||
</td>
|
||||
|
||||
@@ -865,7 +865,7 @@ export async function initScheduleView() {
|
||||
const editButton = canEditScheduleOverrides(role) && lesson.scheduleRuleSlotId && sourceDate
|
||||
? `
|
||||
<button type="button"
|
||||
class="schedule-override-edit"
|
||||
class="btn btn-sm btn-secondary schedule-override-edit"
|
||||
data-schedule-override-edit
|
||||
data-base-rule-slot-id="${escapeHtml(lesson.scheduleRuleSlotId)}"
|
||||
data-lesson-date="${escapeHtml(sourceDate)}">
|
||||
|
||||
@@ -990,7 +990,7 @@ export async function initSchedule() {
|
||||
${subgroupText ? `<small>${escapeHtml(subgroupText)}</small>` : ''}
|
||||
${meta ? `<small>${escapeHtml(meta)}</small>` : ''}
|
||||
<button type="button"
|
||||
class="schedule-visual-edit-rule"
|
||||
class="btn btn-icon-sm btn-ghost schedule-visual-edit-rule"
|
||||
data-rule-id="${escapeHtml(String(lesson.ruleId))}"
|
||||
data-slot-id="${escapeHtml(String(lesson.slotId || ''))}"
|
||||
data-slot-index="${escapeHtml(String(lesson.slotIndex ?? ''))}"
|
||||
|
||||
@@ -86,7 +86,7 @@ export async function initUsers() {
|
||||
<td><span class="badge ${ROLE_BADGE[u.role] || ''}">${ROLE_LABELS[u.role] || escapeHtml(u.role)}</span></td>
|
||||
<td>
|
||||
${u.status === 'ARCHIVED'
|
||||
? `<button class="btn-restore-user" data-id="${u.id}">Восстановить</button>`
|
||||
? `<button class="btn btn-sm btn-secondary btn-restore-user" data-id="${u.id}">Восстановить</button>`
|
||||
: `<button class="btn btn-sm btn-danger-subtle btn-archive-user" data-id="${u.id}">Архивировать</button>`}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -61,7 +61,7 @@ html {
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
font-family: var(--ui-font-sans, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
|
||||
background: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
min-height: 100vh;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<link rel="stylesheet" href="../css/components.css">
|
||||
<link rel="stylesheet" href="css/main.css">
|
||||
<link rel="stylesheet" href="css/layout.css">
|
||||
<link rel="stylesheet" href="../../ui-foundation.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
<h3 id="time-slot-scope-modal-title">Новая ручная сетка</h3>
|
||||
<p class="settings-modal-subtitle">Создайте отдельную сетку времени, которую затем можно назначать датам в календарном графике.</p>
|
||||
</div>
|
||||
<button type="button" class="btn btn-icon-sm btn-secondary settings-modal-close" id="time-slot-scope-modal-close" aria-label="Закрыть">
|
||||
<button type="button" class="btn btn-icon-md btn-ghost settings-modal-close" id="time-slot-scope-modal-close" aria-label="Закрыть окно">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||
|
||||
@@ -273,7 +273,7 @@
|
||||
<div class="modal-overlay" id="calendar-day-dialog">
|
||||
<div class="modal-content card calendar-day-dialog-card">
|
||||
<h2>Ячейка графика</h2>
|
||||
<button class="modal-close" id="calendar-day-dialog-close">×</button>
|
||||
<button type="button" class="btn btn-icon-md btn-ghost modal-close" id="calendar-day-dialog-close" aria-label="Закрыть окно">×</button>
|
||||
<div class="calendar-day-dialog-grid">
|
||||
<div>
|
||||
<span>Дата</span>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<div class="modal-overlay" id="modal-edit-classroom">
|
||||
<div class="modal-content card">
|
||||
<h2>Редактировать аудиторию</h2>
|
||||
<button class="modal-close" id="modal-edit-classroom-close">×</button>
|
||||
<button type="button" class="btn btn-icon-md btn-ghost modal-close" id="modal-edit-classroom-close" aria-label="Закрыть окно">×</button>
|
||||
<form id="edit-classroom-form">
|
||||
<input type="hidden" id="edit-classroom-id">
|
||||
<div class="form-row" style="margin-top: 1rem;">
|
||||
@@ -116,7 +116,7 @@
|
||||
<div class="modal-content card" style="max-width: 600px; width: 90%;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;">
|
||||
<h2>Справочник оборудования</h2>
|
||||
<button class="modal-close" id="modal-manage-equipments-close" style="position: static; font-size: 2rem; background: none; border: none; cursor: pointer; color: var(--text-secondary);">×</button>
|
||||
<button type="button" class="btn btn-icon-md btn-ghost modal-close modal-close--static" id="modal-manage-equipments-close" aria-label="Закрыть окно">×</button>
|
||||
</div>
|
||||
|
||||
<!-- Форма добавления -->
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
<!-- Свободные аудитории -->
|
||||
<div class="card dashboard-compact-card">
|
||||
<h3 class="dashboard-card-title">Свободные аудитории (ближайшие)</h3>
|
||||
<div id="free-classrooms-list" class="dashboard-badge-list">
|
||||
<div id="free-classrooms-list" class="dashboard-badge-list" tabindex="0" role="region" aria-label="Свободные аудитории">
|
||||
<div style="color: var(--text-secondary); font-size: 0.9rem;">Загрузка...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
<div class="modal-overlay" id="modal-edit-group">
|
||||
<div class="modal-content card edit-group-modal">
|
||||
<h2>Редактировать группу</h2>
|
||||
<button class="modal-close" id="modal-edit-group-close">×</button>
|
||||
<button type="button" class="btn btn-icon-md btn-ghost modal-close" id="modal-edit-group-close" aria-label="Закрыть окно">×</button>
|
||||
<form id="edit-group-form">
|
||||
<input type="hidden" id="edit-group-id">
|
||||
<div class="form-row edit-group-form-row edit-group-form-row-main">
|
||||
@@ -177,7 +177,7 @@
|
||||
<h2>Подгруппы группы</h2>
|
||||
<div id="subgroups-group-context" style="color: var(--text-secondary); font-size: 0.9rem; margin-top: 0.25rem;"></div>
|
||||
</div>
|
||||
<button class="modal-close" id="modal-manage-subgroups-close" style="position: static; font-size: 2rem; background: none; border: none; cursor: pointer; color: var(--text-secondary);">×</button>
|
||||
<button type="button" class="btn btn-icon-md btn-ghost modal-close modal-close--static" id="modal-manage-subgroups-close" aria-label="Закрыть окно">×</button>
|
||||
</div>
|
||||
|
||||
<!-- Форма -->
|
||||
@@ -233,7 +233,7 @@
|
||||
<h2>Календарные графики группы</h2>
|
||||
<div id="calendar-group-context" style="color: var(--text-secondary); font-size: 0.9rem; margin-top: 0.25rem;"></div>
|
||||
</div>
|
||||
<button class="modal-close" id="modal-manage-calendar-close" style="position: static; font-size: 2rem; background: none; border: none; cursor: pointer; color: var(--text-secondary);">×</button>
|
||||
<button type="button" class="btn btn-icon-md btn-ghost modal-close modal-close--static" id="modal-manage-calendar-close" aria-label="Закрыть окно">×</button>
|
||||
</div>
|
||||
|
||||
<!-- Форма -->
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
|
||||
<div class="version-modal" id="version-modal" hidden>
|
||||
<div class="version-modal-card" role="dialog" aria-modal="true" aria-labelledby="version-modal-title">
|
||||
<button type="button" class="version-modal-close" id="version-modal-close" aria-label="Закрыть">×</button>
|
||||
<button type="button" class="btn btn-icon-md btn-ghost version-modal-close" id="version-modal-close" aria-label="Закрыть окно">×</button>
|
||||
<span class="version-eyebrow" id="version-modal-kicker">Новая операция</span>
|
||||
<h3 id="version-modal-title">Версия расписания</h3>
|
||||
<p id="version-modal-copy"></p>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
<div class="version-modal schedule-draft-modal" id="schedule-draft-modal" hidden>
|
||||
<div class="version-modal-card" role="dialog" aria-modal="true" aria-labelledby="schedule-draft-title">
|
||||
<button type="button" class="version-modal-close" id="schedule-draft-close" aria-label="Закрыть">×</button>
|
||||
<button type="button" class="btn btn-icon-md btn-ghost version-modal-close" id="schedule-draft-close" aria-label="Закрыть окно">×</button>
|
||||
<span class="version-eyebrow">Новая рабочая копия</span>
|
||||
<h3 id="schedule-draft-title">Создать черновик</h3>
|
||||
<p id="schedule-draft-copy">Все правила выбранного расписания будут скопированы.</p>
|
||||
@@ -152,7 +152,7 @@
|
||||
|
||||
<div class="modal-overlay schedule-conflict-modal" id="schedule-conflict-modal" role="dialog" aria-modal="true" aria-hidden="true">
|
||||
<div class="modal-content schedule-conflict-card">
|
||||
<button type="button" class="modal-close" id="schedule-conflict-close" aria-label="Закрыть окно">×</button>
|
||||
<button type="button" class="btn btn-icon-md btn-ghost modal-close" id="schedule-conflict-close" aria-label="Закрыть окно">×</button>
|
||||
<div class="schedule-conflict-head">
|
||||
<span class="schedule-conflict-kicker">Конфликт слота</span>
|
||||
<h2>Освободите место для нового правила</h2>
|
||||
@@ -190,7 +190,7 @@
|
||||
|
||||
<div class="modal-overlay schedule-move-slot-modal" id="schedule-move-slot-modal" role="dialog" aria-modal="true" aria-hidden="true">
|
||||
<div class="modal-content schedule-move-slot-card">
|
||||
<button type="button" class="modal-close" id="schedule-move-slot-close" aria-label="Закрыть окно">×</button>
|
||||
<button type="button" class="btn btn-icon-md btn-ghost modal-close" id="schedule-move-slot-close" aria-label="Закрыть окно">×</button>
|
||||
<div class="schedule-conflict-head">
|
||||
<span class="schedule-conflict-kicker">Перенос слота</span>
|
||||
<h2 id="schedule-move-slot-title">Изменить день и пару</h2>
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
<h2>Преподаватели дисциплины</h2>
|
||||
<div id="subject-teachers-context" style="color: var(--text-secondary); font-size: 0.9rem; margin-top: 0.25rem;"></div>
|
||||
</div>
|
||||
<button class="modal-close" id="modal-manage-teachers-close" style="position: static; font-size: 2rem; background: none; border: none; cursor: pointer; color: var(--text-secondary);">×</button>
|
||||
<button type="button" class="btn btn-icon-md btn-ghost modal-close modal-close--static" id="modal-manage-teachers-close" aria-label="Закрыть окно">×</button>
|
||||
</div>
|
||||
|
||||
<!-- Форма -->
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
<div class="modal-overlay" id="modal-edit-department">
|
||||
<div class="modal-content card">
|
||||
<h2>Редактирование кафедры</h2>
|
||||
<button class="modal-close" id="modal-edit-department-close">×</button>
|
||||
<button type="button" class="btn btn-icon-md btn-ghost modal-close" id="modal-edit-department-close" aria-label="Закрыть окно">×</button>
|
||||
<form id="edit-department-form">
|
||||
<input type="hidden" id="edit-dept-id">
|
||||
<div class="form-row">
|
||||
@@ -192,7 +192,7 @@
|
||||
<div class="modal-overlay" id="modal-edit-specialty">
|
||||
<div class="modal-content card">
|
||||
<h2>Редактирование специальности</h2>
|
||||
<button class="modal-close" id="modal-edit-specialty-close">×</button>
|
||||
<button type="button" class="btn btn-icon-md btn-ghost modal-close" id="modal-edit-specialty-close" aria-label="Закрыть окно">×</button>
|
||||
<form id="edit-specialty-form">
|
||||
<input type="hidden" id="edit-spec-id">
|
||||
<div class="form-row">
|
||||
@@ -219,7 +219,7 @@
|
||||
<h2>Профили обучения</h2>
|
||||
<div id="profiles-spec-context" style="color: var(--text-secondary); font-size: 0.9rem; margin-top: 0.25rem;"></div>
|
||||
</div>
|
||||
<button class="modal-close" id="modal-manage-profiles-close" style="position: static; font-size: 2rem; background: none; border: none; cursor: pointer; color: var(--text-secondary);">×</button>
|
||||
<button type="button" class="btn btn-icon-md btn-ghost modal-close modal-close--static" id="modal-manage-profiles-close" aria-label="Закрыть окно">×</button>
|
||||
</div>
|
||||
|
||||
<!-- Форма создания/редактирования профиля -->
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<meta name="description" content="Страница авторизации">
|
||||
<title>Авторизация</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="stylesheet" href="ui-foundation.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="background">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Header always set Content-Security-Policy "default-src 'self'; base-uri 'self'; connect-src 'self'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data:; object-src 'none'; script-src 'self'; script-src-attr 'none'; style-src 'self'; style-src-attr 'unsafe-hashes' 'sha256-Ap89pw6Ru+bI6/fvSZrLRErTB0Vlrkjhr+GBUApiIWk=' 'sha256-SIXM20kwgT/LFCXoUieNCZ2zVEtDEJLBMFkzuqTDiEs=' 'sha256-Gg5P79IEFo2naj0u+NnV/XRNhPpmG+qszzSTXOPUj1A=' 'sha256-TnG5YZ63fruUpLo7bQSZmwEy7iaTHxpbBhwz5vu9uSg=' 'sha256-XzNZtBQ5RVU4zPLtfvXv2K6GCBeoCM2HUIIQSlEaULA=' 'sha256-nULJId45lkSYkp9G7rs5Ucrzkl/RvOYcmolE2LAWGy0=' 'sha256-zxhlsg7XWHprQXI4sW8mCF1bkpJgB7ybVJwWOPVLGRE=' 'sha256-K0Xrmwt6pAGUrGVS8MwRZJExIhykcVQ8SI1byCheVwc=' 'sha256-4YmfPYnVNL8IzZiGb/0iwhc6yUgCF19Y33KOfCPVmCw=' 'sha256-iNZSE5e3vOhMyMQkK5rpl8610z7E4ZtyqgP2Svv49PU=' 'sha256-MhqAPfMbUlw1OEgW5/QfCxo+BaJmIHx/8235W2X3bVI=' 'sha256-foNl8DYrtM07r6llOCuEQkuDC3P+Z9AhhM6r+IJDuvE=' 'sha256-TZ/59DFnpMwCdrSuMVhcjfKS2+Uktb1ikcGdbop+LrY=' 'sha256-bouNTXMWL7OeoflvcP2VmNuyQ00CJIpU091rlJcNh0o=' 'sha256-SWPOf/xgJrjLW+pINXE1lz0iy53MqwWqXeVJ6eC/feI=' 'sha256-1N/gWxc/W4gFlj8zf/p3KcADNes7ROePFaTOWiqwF4E=' 'sha256-biLFinpqYMtWHmXfkA1BPeCY0/fNt46SAZ+BBk5YUog=' 'sha256-/dAGmjflKS5r+hQF1hmagGz5QABPHf+YFadZo1ne2rc=' 'sha256-Xrwk3bvnw8h9hvxxkkKe/tGHcDa4FiyIkZgQh7zZ5OM=' 'sha256-yg9xEhg50yeViXuIpHVfY4ORsctQahuBNAF5elcPo2o=' 'sha256-wJR14aiwE2jYijrg7Fjqg/N0F1aAZ5CIcUtwN05LcGg=' 'sha256-aYnI2FBeHDuscjjfM9Mw136ryNwuYO8SA40Zevg1KoY=' 'sha256-y6K4epLEZv6QKwcoJSp/0xGIN8fOl7DSHSPNd5QT6Xo=' 'sha256-tdUysXRHnX2Z4LXERihNGxflbZuvaer3/ZEbjN2vQYE=' 'sha256-scdHk/Xhx12Q7ITYKMEP661eR9qxmkAEEIEGSoSvhnk=' 'sha256-SQjLChNmhyZMwxbpXjOF6LYFFUEHnV6PvzvTEmWb7eA=' 'sha256-50MALp7OIkg8n1p4VILXcnKO8ypKpLNL/QYLOgWPOCk=' 'sha256-clWb9y4Y/RHEr3K6egWYXbH1r5Hi2fgpzDHlBdskEeo=' 'sha256-chNIGV8ioVlRP9Ypn/XhEA2EhWFAeWCuUGJL5S+vzz0=' 'sha256-W998Pje85WadRdREdYtdQtKylzNM5QOtfq5HJWoaeTc=' 'sha256-s6IpehL1Dcfvbn/QY1MA4otfjj+O7fzMbbfi7Qc6pmA=' 'sha256-AC3CbEeLPJf2W6daVbkfUpWh5e6gLviBovIHzqhb7I4=' 'sha256-+j7xWNheSULp9DWeiEHZrhTxGekhyQ9qIjUgAiPhJ50=' 'sha256-moRhvd2U0JZLbFHJNyPJuevxlkfGXw5XWMByVNv9Vig=' 'sha256-203TZuzrYa786NHRsoV1tXZ8L/9lEl+/UL46E0VAiGI=' 'sha256-032ZxPG0oQ3+/U6NXKrgm5LnBreb9401xJrjrsb+p+U=' 'sha256-JamKOmpIVQSPv+gDrYtzbxnVclnrvhrOMLmA+WaGPIE=' 'sha256-mnRyqew64Lcv5/Qgb/4HP8LfJi5MjjQCGLPt+/cJZis=' 'sha256-Fx6gwPzP46ZjBgLjBZ6QLksJxr+0rXElPelXtSQMnxE=' 'sha256-fug/5+Ut6nV0WD+m4YV23l7GiD/oMKUnUvZdMiDCZmw=' 'sha256-AkGc/9SiOd74zk72UnCdLs+k10sM4iy2uKmgoXkaHe0=' 'sha256-Ar6JjQB5XpqI8eiPMCdTp/UuHaqgHiv6I+MV5V0AqD0=' 'sha256-q3nqK4VzeI/SowYCYQ/tCfo056B/JMutuSpzbJbHczk=' 'sha256-FHr5kWe1pqEckj58767LzvY6a0Jefvryb6NDWnX+9iA=' 'sha256-3bpbcQ42x+1MqmADGJ3zikAZX1tMXcOSJO5HaQgBLd0=' 'sha256-JZXmJpz7JH1a0DyiOr/syUiirSXF8caWHSEs55ZeuvM=' 'sha256-5z4wfnbsEag4kdsuEHpgdTrXYzlAY7n+RR18FQrPaEk=' 'sha256-97KgMmG+SNbCjjLJMC4FFguhozddOvNKLVC6hCmCMsg=' 'sha256-K1k356n2KePxr1iToCyZJNdGCm9eq1GSLPiovYYcGJw=' 'sha256-Wbi+cQ7sBtwXXZqWfFgLJRH4d6W8PogiptWNj9KIw8c=' 'sha256-ZGygktZXqOYjv8SF3rIcpWd19YFA1qMbC3LhD9PPSIk=' 'sha256-C1diVwUHC99dr4LcsUyLWfgQa8cu0K/7SBK+bd24TWg=' 'sha256-gKWvnkygeYkz1lyPSLpgVWSsmFaaDT2lY+hqijL4Gd8=' 'sha256-XhqU3am1TiOnFUKLIcPS5JCePjRUcUoGqQvjnfL92ik=' 'sha256-COR0sjBXRz2BkYmsZyQELjCUGLEbVii9YMmpBGwfFhM=' 'sha256-N90MKmRow2DpYEVeqcc3uc8pOUsS4Rg4sNmkau1k0xQ=' 'sha256-qcFcRsF+ljnThVJj80IfggPdbDjDPk/ZEeeiFCw/f4s=' 'sha256-niVdTxYNBhpZEFDz7d87VgN56BaVHxkE1mKzrSiTEa8=' 'sha256-N6tSydZ64AHCaOWfwKbUhxXx2fRFDxHOaL3e3CO7GPI=' 'sha256-V3Yf08rYNHRd1lYyQK1mcEb3duonX88OA6nfz8qDvuY=' 'sha256-7VXlcg/uSZugHSa6UtIG2/44ju460LiO4M0CyQfraX8='; upgrade-insecure-requests"
|
||||
Header always set Content-Security-Policy "default-src 'self'; base-uri 'self'; connect-src 'self'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src 'self' data:; object-src 'none'; script-src 'self'; script-src-attr 'none'; style-src 'self'; style-src-attr 'unsafe-hashes' 'sha256-Ap89pw6Ru+bI6/fvSZrLRErTB0Vlrkjhr+GBUApiIWk=' 'sha256-SIXM20kwgT/LFCXoUieNCZ2zVEtDEJLBMFkzuqTDiEs=' 'sha256-Gg5P79IEFo2naj0u+NnV/XRNhPpmG+qszzSTXOPUj1A=' 'sha256-TnG5YZ63fruUpLo7bQSZmwEy7iaTHxpbBhwz5vu9uSg=' 'sha256-XzNZtBQ5RVU4zPLtfvXv2K6GCBeoCM2HUIIQSlEaULA=' 'sha256-nULJId45lkSYkp9G7rs5Ucrzkl/RvOYcmolE2LAWGy0=' 'sha256-zxhlsg7XWHprQXI4sW8mCF1bkpJgB7ybVJwWOPVLGRE=' 'sha256-K0Xrmwt6pAGUrGVS8MwRZJExIhykcVQ8SI1byCheVwc=' 'sha256-4YmfPYnVNL8IzZiGb/0iwhc6yUgCF19Y33KOfCPVmCw=' 'sha256-iNZSE5e3vOhMyMQkK5rpl8610z7E4ZtyqgP2Svv49PU=' 'sha256-MhqAPfMbUlw1OEgW5/QfCxo+BaJmIHx/8235W2X3bVI=' 'sha256-foNl8DYrtM07r6llOCuEQkuDC3P+Z9AhhM6r+IJDuvE=' 'sha256-TZ/59DFnpMwCdrSuMVhcjfKS2+Uktb1ikcGdbop+LrY=' 'sha256-bouNTXMWL7OeoflvcP2VmNuyQ00CJIpU091rlJcNh0o=' 'sha256-SWPOf/xgJrjLW+pINXE1lz0iy53MqwWqXeVJ6eC/feI=' 'sha256-1N/gWxc/W4gFlj8zf/p3KcADNes7ROePFaTOWiqwF4E=' 'sha256-biLFinpqYMtWHmXfkA1BPeCY0/fNt46SAZ+BBk5YUog=' 'sha256-/dAGmjflKS5r+hQF1hmagGz5QABPHf+YFadZo1ne2rc=' 'sha256-Xrwk3bvnw8h9hvxxkkKe/tGHcDa4FiyIkZgQh7zZ5OM=' 'sha256-yg9xEhg50yeViXuIpHVfY4ORsctQahuBNAF5elcPo2o=' 'sha256-wJR14aiwE2jYijrg7Fjqg/N0F1aAZ5CIcUtwN05LcGg=' 'sha256-aYnI2FBeHDuscjjfM9Mw136ryNwuYO8SA40Zevg1KoY=' 'sha256-y6K4epLEZv6QKwcoJSp/0xGIN8fOl7DSHSPNd5QT6Xo=' 'sha256-scdHk/Xhx12Q7ITYKMEP661eR9qxmkAEEIEGSoSvhnk=' 'sha256-SQjLChNmhyZMwxbpXjOF6LYFFUEHnV6PvzvTEmWb7eA=' 'sha256-50MALp7OIkg8n1p4VILXcnKO8ypKpLNL/QYLOgWPOCk=' 'sha256-clWb9y4Y/RHEr3K6egWYXbH1r5Hi2fgpzDHlBdskEeo=' 'sha256-chNIGV8ioVlRP9Ypn/XhEA2EhWFAeWCuUGJL5S+vzz0=' 'sha256-W998Pje85WadRdREdYtdQtKylzNM5QOtfq5HJWoaeTc=' 'sha256-s6IpehL1Dcfvbn/QY1MA4otfjj+O7fzMbbfi7Qc6pmA=' 'sha256-AC3CbEeLPJf2W6daVbkfUpWh5e6gLviBovIHzqhb7I4=' 'sha256-+j7xWNheSULp9DWeiEHZrhTxGekhyQ9qIjUgAiPhJ50=' 'sha256-moRhvd2U0JZLbFHJNyPJuevxlkfGXw5XWMByVNv9Vig=' 'sha256-032ZxPG0oQ3+/U6NXKrgm5LnBreb9401xJrjrsb+p+U=' 'sha256-JamKOmpIVQSPv+gDrYtzbxnVclnrvhrOMLmA+WaGPIE=' 'sha256-mnRyqew64Lcv5/Qgb/4HP8LfJi5MjjQCGLPt+/cJZis=' 'sha256-Fx6gwPzP46ZjBgLjBZ6QLksJxr+0rXElPelXtSQMnxE=' 'sha256-fug/5+Ut6nV0WD+m4YV23l7GiD/oMKUnUvZdMiDCZmw=' 'sha256-AkGc/9SiOd74zk72UnCdLs+k10sM4iy2uKmgoXkaHe0=' 'sha256-Ar6JjQB5XpqI8eiPMCdTp/UuHaqgHiv6I+MV5V0AqD0=' 'sha256-q3nqK4VzeI/SowYCYQ/tCfo056B/JMutuSpzbJbHczk=' 'sha256-FHr5kWe1pqEckj58767LzvY6a0Jefvryb6NDWnX+9iA=' 'sha256-3bpbcQ42x+1MqmADGJ3zikAZX1tMXcOSJO5HaQgBLd0=' 'sha256-JZXmJpz7JH1a0DyiOr/syUiirSXF8caWHSEs55ZeuvM=' 'sha256-5z4wfnbsEag4kdsuEHpgdTrXYzlAY7n+RR18FQrPaEk=' 'sha256-97KgMmG+SNbCjjLJMC4FFguhozddOvNKLVC6hCmCMsg=' 'sha256-K1k356n2KePxr1iToCyZJNdGCm9eq1GSLPiovYYcGJw=' 'sha256-Wbi+cQ7sBtwXXZqWfFgLJRH4d6W8PogiptWNj9KIw8c=' 'sha256-ZGygktZXqOYjv8SF3rIcpWd19YFA1qMbC3LhD9PPSIk=' 'sha256-C1diVwUHC99dr4LcsUyLWfgQa8cu0K/7SBK+bd24TWg=' 'sha256-XhqU3am1TiOnFUKLIcPS5JCePjRUcUoGqQvjnfL92ik=' 'sha256-COR0sjBXRz2BkYmsZyQELjCUGLEbVii9YMmpBGwfFhM=' 'sha256-N90MKmRow2DpYEVeqcc3uc8pOUsS4Rg4sNmkau1k0xQ=' 'sha256-qcFcRsF+ljnThVJj80IfggPdbDjDPk/ZEeeiFCw/f4s=' 'sha256-niVdTxYNBhpZEFDz7d87VgN56BaVHxkE1mKzrSiTEa8=' 'sha256-N6tSydZ64AHCaOWfwKbUhxXx2fRFDxHOaL3e3CO7GPI=' 'sha256-V3Yf08rYNHRd1lYyQK1mcEb3duonX88OA6nfz8qDvuY=' 'sha256-7VXlcg/uSZugHSa6UtIG2/44ju460LiO4M0CyQfraX8='; upgrade-insecure-requests"
|
||||
Header always set Referrer-Policy "strict-origin-when-cross-origin"
|
||||
Header always set X-Content-Type-Options "nosniff"
|
||||
Header always set X-Frame-Options "DENY"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<title>Расписание студента</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="stylesheet" href="../schedule-overview.css">
|
||||
<link rel="stylesheet" href="../ui-foundation.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
|
||||
@@ -33,7 +33,7 @@ body {
|
||||
min-height: 100vh;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
|
||||
font-family: var(--ui-font-sans, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
|
||||
}
|
||||
|
||||
.shell {
|
||||
|
||||
@@ -110,7 +110,7 @@ html {
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
font-family: var(--ui-font-sans, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
|
||||
background: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
min-height: 100vh;
|
||||
|
||||
@@ -220,7 +220,7 @@ import { trackUxEvent } from '../telemetry.js';
|
||||
: 'Добавить отметку';
|
||||
return `<button type="button" class="preference-cell ${typeClass}${pendingClass}"
|
||||
data-day="${index + 1}" data-slot="${slot.id}" data-preference-id="${item?.id || ''}"
|
||||
data-preference-status="${item?.status || ''}" title="${escapeHtml(title)}">
|
||||
data-preference-status="${item?.status || ''}" title="${escapeHtml(title)}" aria-label="${escapeHtml(title)}">
|
||||
<span>${item ? preferenceTypeSymbol(item.preferenceType) : '+'}</span>
|
||||
</button>`;
|
||||
})
|
||||
@@ -681,7 +681,7 @@ import { trackUxEvent } from '../telemetry.js';
|
||||
${groups ? `<span class="chip">${escapeHtml(groups)}</span>` : ''}
|
||||
</div>
|
||||
${lesson.scheduleRuleSlotId && !lesson.scheduleOverrideId ? `
|
||||
<button class="lesson-request-button" type="button" data-request-lesson="${escapeHtml(lessonKey(lesson))}">
|
||||
<button class="btn btn-sm btn-secondary lesson-request-button" type="button" data-request-lesson="${escapeHtml(lessonKey(lesson))}">
|
||||
Запросить изменение
|
||||
</button>
|
||||
` : '<span class="lesson-change-note">Занятие уже изменено учебным отделом</span>'}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<title>Кабинет преподавателя</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="stylesheet" href="../schedule-overview.css">
|
||||
<link rel="stylesheet" href="../ui-foundation.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
|
||||
@@ -207,7 +207,7 @@ body {
|
||||
min-height: 100vh;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
|
||||
font-family: var(--ui-font-sans, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
|
||||
}
|
||||
|
||||
.shell {
|
||||
|
||||
@@ -81,6 +81,12 @@ test('Docker-образ включает локальный telemetry bundle и
|
||||
assert.match(dockerfile, /scripts\/build-vendor\.mjs/);
|
||||
assert.match(dockerfile, /COPY --from=frontend-assets \/build\/dist\/vendor\//);
|
||||
assert.match(dockerfile, /magistr-security\.conf/);
|
||||
for (const asset of ['ui-foundation.css', 'schedule-overview.css', 'schedule-overview.js']) {
|
||||
const copiesAsset = dockerfile.split('\n').some(line =>
|
||||
line.startsWith('COPY ') && line.includes(asset) && line.includes('/usr/local/apache2/htdocs/')
|
||||
);
|
||||
assert.ok(copiesAsset, `Общий ресурс отсутствует в Docker-образе: ${asset}`);
|
||||
}
|
||||
assert.match(telemetry, /import\('\/vendor\/otel\.js'\)/);
|
||||
assert.doesNotMatch(telemetry, /https?:\/\//);
|
||||
});
|
||||
|
||||
94
frontend/tests/ui-consistency.test.mjs
Normal file
94
frontend/tests/ui-consistency.test.mjs
Normal file
@@ -0,0 +1,94 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import test from 'node:test';
|
||||
|
||||
const readFrontendFile = relativePath => readFile(
|
||||
new URL(`../${relativePath}`, import.meta.url),
|
||||
'utf8'
|
||||
);
|
||||
|
||||
test('все пользовательские оболочки завершают каскад единой визуальной основой', async () => {
|
||||
const entrypoints = [
|
||||
['index.html', 'ui-foundation.css'],
|
||||
['admin/index.html', '../ui-foundation.css'],
|
||||
['admin/settings/index.html', '../../ui-foundation.css'],
|
||||
['teacher/index.html', '../ui-foundation.css'],
|
||||
['student/index.html', '../ui-foundation.css']
|
||||
];
|
||||
|
||||
for (const [file, expectedHref] of entrypoints) {
|
||||
const html = await readFrontendFile(file);
|
||||
const stylesheets = Array.from(
|
||||
html.matchAll(/<link\b[^>]*rel="stylesheet"[^>]*href="([^"]+)"[^>]*>/g),
|
||||
match => match[1]
|
||||
);
|
||||
|
||||
assert.equal(stylesheets.at(-1), expectedHref, file);
|
||||
}
|
||||
});
|
||||
|
||||
test('единая визуальная основа фиксирует типографику, размеры и доступный фокус', async () => {
|
||||
const foundation = await readFrontendFile('ui-foundation.css');
|
||||
|
||||
assert.match(foundation, /--ui-font-sans:/);
|
||||
assert.match(foundation, /--ui-control-sm:\s*32px/);
|
||||
assert.match(foundation, /--ui-control-md:\s*40px/);
|
||||
assert.match(foundation, /--ui-control-lg:\s*48px/);
|
||||
assert.match(foundation, /\.btn-sm\s*\{[^}]*min-height:\s*var\(--ui-control-sm\)/s);
|
||||
assert.match(foundation, /\.btn-md\s*\{[^}]*min-height:\s*var\(--ui-control-md\)/s);
|
||||
assert.match(foundation, /\.btn-lg\s*\{[^}]*min-height:\s*var\(--ui-control-lg\)/s);
|
||||
assert.match(foundation, /:focus-visible\s*\{[^}]*outline:/s);
|
||||
assert.match(foundation, /prefers-reduced-motion:\s*reduce/);
|
||||
});
|
||||
|
||||
test('локальные стили используют общие шрифтовые токены', async () => {
|
||||
const files = [
|
||||
'style.css',
|
||||
'student/style.css',
|
||||
'teacher/style.css',
|
||||
'admin/css/main.css',
|
||||
'admin/settings/css/main.css',
|
||||
'admin/css/schedule-quality.css',
|
||||
'admin/css/schedule-versions.css'
|
||||
];
|
||||
|
||||
for (const file of files) {
|
||||
const css = await readFrontendFile(file);
|
||||
assert.doesNotMatch(css, /font-family:\s*(?:['"]?Inter|['"]?Segoe UI|Georgia|['"]Times New Roman)/, file);
|
||||
}
|
||||
});
|
||||
|
||||
test('архивные действия и кнопки закрытия используют системные размеры', async () => {
|
||||
const actionSources = await Promise.all([
|
||||
readFrontendFile('admin/js/views/classrooms.js'),
|
||||
readFrontendFile('admin/js/views/groups.js'),
|
||||
readFrontendFile('admin/js/views/users.js')
|
||||
]);
|
||||
|
||||
actionSources.forEach(source => {
|
||||
assert.match(source, /class="btn btn-sm btn-secondary btn-restore-/);
|
||||
});
|
||||
|
||||
const modalViews = await Promise.all([
|
||||
'admin/views/academic-calendar.html',
|
||||
'admin/views/classrooms.html',
|
||||
'admin/views/groups.html',
|
||||
'admin/views/schedule.html',
|
||||
'admin/views/schedule-versions.html',
|
||||
'admin/views/subjects.html',
|
||||
'admin/views/university-structure.html',
|
||||
'admin/settings/views/time-slots.html'
|
||||
].map(readFrontendFile));
|
||||
|
||||
const closeButtons = modalViews.flatMap(html => Array.from(
|
||||
html.matchAll(/<button\b[^>]*class="[^"]*(?:modal-close|version-modal-close|settings-modal-close)[^"]*"[^>]*>/g),
|
||||
match => match[0]
|
||||
));
|
||||
|
||||
assert.ok(closeButtons.length > 0);
|
||||
closeButtons.forEach(button => {
|
||||
assert.match(button, /type="button"/);
|
||||
assert.match(button, /class="[^"]*\bbtn\b[^"]*\bbtn-icon-md\b/);
|
||||
assert.match(button, /aria-label="Закрыть окно"/);
|
||||
});
|
||||
});
|
||||
421
frontend/ui-foundation.css
Normal file
421
frontend/ui-foundation.css
Normal file
@@ -0,0 +1,421 @@
|
||||
/*
|
||||
* Единая визуальная основа Magistr.
|
||||
*
|
||||
* Файл подключается последним во всех пользовательских оболочках и задаёт
|
||||
* общие инварианты: типографику, размеры элементов управления, фокус,
|
||||
* радиусы, ритм и поведение на узких экранах. Локальные CSS отвечают только
|
||||
* за компоновку и предметные компоненты конкретного раздела.
|
||||
*/
|
||||
|
||||
:root {
|
||||
--ui-font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
--ui-font-display: var(--ui-font-sans);
|
||||
--ui-font-mono: "Cascadia Mono", "SFMono-Regular", Consolas, monospace;
|
||||
|
||||
--ui-control-sm: 32px;
|
||||
--ui-control-md: 40px;
|
||||
--ui-control-lg: 48px;
|
||||
--ui-radius-control: 8px;
|
||||
--ui-radius-field: 10px;
|
||||
--ui-radius-panel: 16px;
|
||||
--ui-radius-large: 24px;
|
||||
|
||||
--ui-space-1: 4px;
|
||||
--ui-space-2: 8px;
|
||||
--ui-space-3: 12px;
|
||||
--ui-space-4: 16px;
|
||||
--ui-space-5: 20px;
|
||||
--ui-space-6: 24px;
|
||||
--ui-space-8: 32px;
|
||||
|
||||
--ui-shadow-panel: 0 12px 32px rgba(15, 23, 42, 0.08);
|
||||
--ui-shadow-floating: 0 20px 56px rgba(15, 23, 42, 0.18);
|
||||
--ui-transition: 160ms cubic-bezier(0.2, 0, 0, 1);
|
||||
--ui-focus-ring: var(--button-focus-ring, rgba(79, 70, 229, 0.35));
|
||||
|
||||
/* Совместимость с уже существующими токенами разделов. */
|
||||
--button-radius: var(--ui-radius-control);
|
||||
}
|
||||
|
||||
html {
|
||||
color-scheme: dark;
|
||||
font-size: 16px;
|
||||
text-size-adjust: 100%;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
html[data-theme="light"] {
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--ui-font-sans);
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font: inherit;
|
||||
letter-spacing: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
[role="button"],
|
||||
a {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: var(--ui-font-display);
|
||||
font-weight: 700;
|
||||
line-height: 1.18;
|
||||
letter-spacing: -0.025em;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
p,
|
||||
li,
|
||||
dd {
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
time,
|
||||
input[type="date"],
|
||||
input[type="time"],
|
||||
.schedule-overview-next-time,
|
||||
.academic-year-code,
|
||||
.version-number,
|
||||
.metric-value {
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: color-mix(in srgb, var(--accent, #4f46e5) 28%, transparent);
|
||||
}
|
||||
|
||||
/* ===== Доступный фокус ===== */
|
||||
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
|
||||
outline: 2px solid var(--accent, #4f46e5);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
:where(input, select, textarea):focus-visible {
|
||||
border-color: var(--accent, #4f46e5);
|
||||
box-shadow: 0 0 0 3px var(--ui-focus-ring);
|
||||
}
|
||||
|
||||
/* ===== Кнопки ===== */
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--ui-space-2);
|
||||
min-width: 0;
|
||||
min-height: var(--ui-control-md);
|
||||
padding: 0 var(--ui-space-4);
|
||||
border: 1px solid var(--button-secondary-border, var(--panel-border, var(--bg-card-border)));
|
||||
border-radius: var(--ui-radius-control);
|
||||
font-family: var(--ui-font-sans);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 650;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition:
|
||||
background-color var(--ui-transition),
|
||||
border-color var(--ui-transition),
|
||||
color var(--ui-transition),
|
||||
box-shadow var(--ui-transition),
|
||||
transform var(--ui-transition);
|
||||
}
|
||||
|
||||
.btn:hover:not(:disabled):not([aria-disabled="true"]) {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn:active:not(:disabled):not([aria-disabled="true"]) {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.btn:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px var(--ui-focus-ring);
|
||||
}
|
||||
|
||||
.btn:disabled,
|
||||
.btn[aria-disabled="true"] {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.62;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
min-height: var(--ui-control-sm);
|
||||
padding-inline: var(--ui-space-3);
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
|
||||
.btn-md {
|
||||
min-height: var(--ui-control-md);
|
||||
padding-inline: var(--ui-space-4);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.btn-lg {
|
||||
min-height: var(--ui-control-lg);
|
||||
padding-inline: var(--ui-space-5);
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.btn-icon-sm,
|
||||
.btn-icon-md {
|
||||
flex: 0 0 auto;
|
||||
padding: 0;
|
||||
border-radius: var(--ui-radius-control);
|
||||
}
|
||||
|
||||
.btn-icon-sm {
|
||||
width: var(--ui-control-sm);
|
||||
height: var(--ui-control-sm);
|
||||
min-height: var(--ui-control-sm);
|
||||
}
|
||||
|
||||
.btn-icon-md {
|
||||
width: var(--ui-control-md);
|
||||
height: var(--ui-control-md);
|
||||
min-height: var(--ui-control-md);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
border-color: var(--button-primary-border, var(--accent, #4f46e5));
|
||||
background: var(--button-primary-bg, var(--accent, #4f46e5));
|
||||
color: var(--button-primary-text, #fff);
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
border-color: var(--button-primary-border, var(--accent-strong, var(--accent-hover, #4338ca)));
|
||||
background: var(--button-primary-bg-hover, var(--accent-strong, var(--accent-hover, #4338ca)));
|
||||
color: var(--button-primary-text, #fff);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
border-color: var(--button-secondary-border, var(--panel-border, var(--bg-card-border)));
|
||||
background: var(--button-secondary-bg, var(--panel, var(--bg-card)));
|
||||
color: var(--button-secondary-text, var(--text, var(--text-primary)));
|
||||
}
|
||||
|
||||
.btn-secondary:hover:not(:disabled) {
|
||||
border-color: color-mix(in srgb, var(--accent, #4f46e5) 38%, var(--button-secondary-border, var(--panel-border, var(--bg-card-border))));
|
||||
background: var(--button-secondary-bg-hover, var(--bg-hover, color-mix(in srgb, var(--accent, #4f46e5) 7%, var(--panel, var(--bg-card)))));
|
||||
color: var(--button-secondary-text, var(--text, var(--text-primary)));
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
border-color: var(--button-ghost-border, transparent);
|
||||
background: transparent;
|
||||
color: var(--text-secondary, var(--muted));
|
||||
}
|
||||
|
||||
.btn-ghost:hover:not(:disabled) {
|
||||
border-color: var(--button-ghost-border, var(--panel-border, var(--bg-card-border)));
|
||||
background: var(--button-ghost-bg-hover, var(--bg-hover, rgba(148, 163, 184, 0.1)));
|
||||
color: var(--text-primary, var(--text));
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
border-color: var(--button-danger-border, #b91c1c);
|
||||
background: var(--button-danger-bg, #dc2626);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-danger-subtle {
|
||||
border-color: var(--button-danger-subtle-border, rgba(239, 68, 68, 0.28));
|
||||
background: var(--button-danger-subtle-bg, rgba(239, 68, 68, 0.12));
|
||||
color: var(--button-danger-subtle-text, #b91c1c);
|
||||
}
|
||||
|
||||
.btn-danger-subtle:hover:not(:disabled) {
|
||||
border-color: var(--button-danger-subtle-border, rgba(239, 68, 68, 0.38));
|
||||
background: var(--button-danger-subtle-bg-hover, rgba(239, 68, 68, 0.18));
|
||||
color: var(--button-danger-subtle-text, #b91c1c);
|
||||
}
|
||||
|
||||
.input-wrapper .toggle-password {
|
||||
border-color: transparent;
|
||||
background: transparent;
|
||||
color: var(--text-placeholder, var(--muted));
|
||||
}
|
||||
|
||||
/* ===== Поля форм ===== */
|
||||
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]),
|
||||
select,
|
||||
textarea {
|
||||
border-radius: var(--ui-radius-field);
|
||||
}
|
||||
|
||||
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]),
|
||||
select {
|
||||
min-height: var(--ui-control-md);
|
||||
}
|
||||
|
||||
textarea {
|
||||
min-height: 96px;
|
||||
line-height: 1.5;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
input::placeholder,
|
||||
textarea::placeholder {
|
||||
color: var(--text-placeholder, var(--muted));
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
label {
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
/* ===== Поверхности и ритм ===== */
|
||||
.card,
|
||||
.settings-card,
|
||||
.toolbar,
|
||||
.schedule-overview,
|
||||
.teacher-absence-panel,
|
||||
.preference-board,
|
||||
.preference-card,
|
||||
.request-ledger-head,
|
||||
.request-dialog {
|
||||
border-radius: var(--ui-radius-panel);
|
||||
}
|
||||
|
||||
.card,
|
||||
.settings-card,
|
||||
.toolbar,
|
||||
.schedule-overview {
|
||||
box-shadow: var(--ui-shadow-panel);
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: none;
|
||||
box-shadow: var(--ui-shadow-panel);
|
||||
}
|
||||
|
||||
.card-header-row,
|
||||
.settings-header-row,
|
||||
.dashboard-card-header,
|
||||
.preference-board-head {
|
||||
gap: var(--ui-space-4);
|
||||
}
|
||||
|
||||
.form-row,
|
||||
.filter-row,
|
||||
.actions,
|
||||
.week-nav {
|
||||
column-gap: var(--ui-space-3);
|
||||
}
|
||||
|
||||
table {
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
th {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.035em;
|
||||
}
|
||||
|
||||
.table-actions-cell {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.table-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
gap: var(--ui-space-2);
|
||||
}
|
||||
|
||||
.schedule-visual-lesson {
|
||||
padding-right: 2.55rem;
|
||||
}
|
||||
|
||||
/* ===== Унифицированные кнопки закрытия ===== */
|
||||
.modal-close,
|
||||
.version-modal-close,
|
||||
.settings-modal-close {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: var(--ui-control-md);
|
||||
height: var(--ui-control-md);
|
||||
min-height: var(--ui-control-md);
|
||||
padding: 0;
|
||||
border: 1px solid var(--button-ghost-border, var(--panel-border, var(--bg-card-border)));
|
||||
border-radius: var(--ui-radius-control);
|
||||
background: transparent;
|
||||
color: var(--text-secondary, var(--muted));
|
||||
font-family: var(--ui-font-sans);
|
||||
font-size: 1.35rem;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
transition: background-color var(--ui-transition), border-color var(--ui-transition), color var(--ui-transition);
|
||||
}
|
||||
|
||||
.modal-close:hover,
|
||||
.version-modal-close:hover,
|
||||
.settings-modal-close:hover {
|
||||
border-color: color-mix(in srgb, var(--error, #ef4444) 35%, transparent);
|
||||
background: color-mix(in srgb, var(--error, #ef4444) 10%, transparent);
|
||||
color: var(--error, #ef4444);
|
||||
}
|
||||
|
||||
.modal-close--static {
|
||||
position: static;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
/* ===== Скролл и движение ===== */
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: color-mix(in srgb, var(--text-secondary, var(--muted)) 42%, transparent) transparent;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.shell {
|
||||
padding: var(--ui-space-4);
|
||||
}
|
||||
|
||||
.actions .btn:not(.btn-icon-sm):not(.btn-icon-md) {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.modal-content,
|
||||
.request-dialog,
|
||||
.version-modal-card {
|
||||
border-radius: var(--ui-radius-panel);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
scroll-behavior: auto !important;
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user