Поправил шрифты и некоторые визуальные косяки
This commit is contained in:
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