ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 50s
ci / ts / ts (packages + web) (push) Successful in 43s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 27s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m22s
- core: AuthSession keeps the access token in memory, refreshes it once for all parallel requests (single-flight) and retries them; refresh races between tabs are retried, reuse signs out; ApiError carries problem+json codes and field errors - web: TanStack Router with guards — guests go to /login, the bootstrap admin to /setup/admin, temporary passwords to /setup/password, admin pages by role - login, setup screens, Classic shell (top bar, role-based sidebar, empty player), settings: name, theme, language, password, devices - users admin: search, role filter, create with a one-time temporary password, reset, block, role change, delete as the policy allows; audit log for admins - ru/en strings for auth, admin and error codes; language and theme are saved in the profile Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
64 lines
1.2 KiB
CSS
64 lines
1.2 KiB
CSS
.home {
|
|
min-height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 24px;
|
|
text-align: center;
|
|
}
|
|
|
|
.greeting {
|
|
margin: 0;
|
|
font-family: var(--font-display);
|
|
font-size: 24px;
|
|
font-weight: 600;
|
|
letter-spacing: -0.01em;
|
|
}
|
|
|
|
.orb {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 6px;
|
|
width: 300px;
|
|
height: 300px;
|
|
max-width: 70vw;
|
|
max-height: 70vw;
|
|
border-radius: 50%;
|
|
color: #fff;
|
|
background:
|
|
radial-gradient(circle at 35% 30%, rgba(156, 198, 255, 0.55), transparent 45%),
|
|
radial-gradient(circle at 65% 70%, var(--wave-color3), transparent 55%),
|
|
radial-gradient(circle at 50% 50%, var(--wave-color2), var(--wave-color1) 70%);
|
|
box-shadow: 0 0 80px rgba(47, 128, 255, 0.35);
|
|
opacity: 0.85;
|
|
animation: breathe 6s ease-in-out infinite;
|
|
}
|
|
|
|
.orbLabel {
|
|
font-family: var(--font-display);
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
@keyframes breathe {
|
|
50% {
|
|
transform: scale(1.03);
|
|
}
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.orb {
|
|
animation: none;
|
|
}
|
|
}
|
|
|
|
.soon {
|
|
max-width: 420px;
|
|
margin: 0;
|
|
color: var(--text2);
|
|
line-height: 1.5;
|
|
}
|