html, body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}

/* Remove the grey tap-highlight flash on mobile, and stop taps from selecting
   the text inside interactive controls (text content stays selectable). */
* {
    -webkit-tap-highlight-color: transparent;
}
button, [role="button"], summary {
    -webkit-user-select: none;
    user-select: none;
}

/* Press feedback: the control just darkens slightly while held (mouse or finger).
   Driven by pointer events (JS in index.html) so it behaves the same on touch and
   desktop, and never sticks (pointerup / pointercancel / sliding off all release it). */
.ui-hold { filter: brightness(0.9); }

h1:focus { outline: none; }

/* Soft slide-up used when the login screen swaps between the credentials and
   code steps (keyed on the step so it replays each time). */
@keyframes authStepIn {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}
.auth-step-in { animation: authStepIn 0.35s cubic-bezier(0.22, 1, 0.36, 1) both; }

#blazor-error-ui {
    color-scheme: light only;
    animation: blazorToastIn 0.28s cubic-bezier(0.22, 1, 0.36, 1) both;
}

#blazor-error-ui .dismiss { cursor: pointer; }

/* Toast slide-in; replays each time Blazor switches display none -> block. */
@keyframes blazorToastIn {
    from { opacity: 0; transform: translateY(-10px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Same entrance for component toasts (Shared/ToastHost.razor). `touch-action:
   pan-y` lets the swipe-to-dismiss handler (index.html) own horizontal drags
   while vertical touches still scroll the page. */
.toast-in { animation: blazorToastIn 0.28s cubic-bezier(0.22, 1, 0.36, 1) both; touch-action: pan-y; }

/* Countdown bar under the toast; JS restarts it on every appearance (5s).
   Animates `width` rather than `transform: scaleX` on purpose: a transform
   animation on a child of an overflow-hidden + rounded-2xl card freezes the
   paint on mobile WebKit (iOS Safari) — the bar sat full and never moved on
   phones. Width is layout-driven, so it's clipped normally and stays reliable. */
@keyframes blazorToastProgress {
    from { width: 100%; }
    to   { width: 0%; }
}

.blazor-error-boundary {
    background: #b32121;
    padding: 0.75rem 1rem;
    color: white;
    border-radius: 0.5rem;
}
.blazor-error-boundary::after {
    content: "Произошла ошибка.";
    margin-left: 0.5rem;
}

.valid.modified:not([type=checkbox]) {
    box-shadow: 0 0 0 1px #10b981;
}
.invalid {
    box-shadow: 0 0 0 1px #ef4444;
}
.validation-message {
    color: #b91c1c;
    font-size: 0.75rem;
    margin-top: 0.125rem;
}
