422 lines
10 KiB
CSS
422 lines
10 KiB
CSS
/*
|
||
* Единая визуальная основа 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;
|
||
}
|
||
}
|