/* Blazor reveals this with an inline display rule on an unhandled error. Keep it
   hidden during healthy startup, above the shell, and operable without a mouse. */
#blazor-error-ui {
	display: none;
	position: fixed;
	inset: auto 0 0;
	z-index: 9999;
	padding: var(--space-5) calc(2 * var(--space-7)) max(var(--space-5), env(safe-area-inset-bottom)) var(--space-5);
	background: var(--surface);
	color: var(--text);
	border-top: 2px solid var(--accent);
	box-shadow: var(--shadow-pop);
	font-family: var(--font-ui);
	line-height: 1.5;
	overflow-wrap: anywhere;
}

#blazor-error-ui .reload {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	margin-inline: 0.5rem;
	color: var(--accent);
	text-decoration: underline;
}

#blazor-error-ui .dismiss {
	position: absolute;
	top: 0.5rem;
	right: 0.5rem;
	width: 44px;
	height: 44px;
	border: 1px solid var(--border);
	border-radius: var(--radius);
	background: var(--surface-2);
	color: var(--text);
	font-size: var(--text-xl);
	cursor: pointer;
}

#blazor-error-ui :is(.reload, .dismiss):focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
}

/* CharacterPicker popover width. Global (not scoped .razor.css) because the class sits
   on the component's root <MudPaper>, which carries MudPaper's scope, not the picker's —
   a scoped `::deep` rule has no HTML ancestor to anchor to. */
.char-picker {
	min-width: 320px;
}
@media (max-width: 760px) {
	.char-picker {
		min-width: 0;
		width: 100%;
		box-sizing: border-box;
	}
}

/* A user preference, not a viewport size, so it belongs to neither the shell's breakpoints nor a
   page's tiers. Zeroing the tokens rather than declaring `animation: none`: this sheet is layered
   and the scoped bundle is not, so a rule here could never win. Only movement goes: a colour fading
   moves nothing on screen (WCAG 2.3.3), so --duration-effect and --duration-linger stand. The
   --motion-* pairs are declared on :root too, so they pick these up. */
@media (prefers-reduced-motion: reduce) {
	:root {
		--duration-enter: 0s;
		--duration-exit: 0s;
		--duration-spring: 0s;
		--duration-sweep: 0s;
	}
	/* A theme's loops (css/themes/motion.css) stand still too, on the page and in a theme's preview. */
	:root, [data-scheme] {
		--select-motion: none;
		--texture-motion: none;
		--ambient-play: paused;
		--ambient-flow: var(--no-drawing);
		--ambient-rest: initial;
	}
}
/* The same, when the player turns on Reduce motion in the portal (data-reduce-motion="on", ThemeService.ReduceMotionPart)
   rather than in the browser. */
:root[data-reduce-motion="on"] {
	--duration-enter: 0s;
	--duration-exit: 0s;
	--duration-spring: 0s;
	--duration-sweep: 0s;
}
:root[data-reduce-motion="on"], [data-reduce-motion="on"] [data-scheme] {
	--select-motion: none;
	--texture-motion: none;
	--ambient-play: paused;
	--ambient-flow: var(--no-drawing);
	--ambient-rest: initial;
}

/* Loading placeholders: the portal's own (.kit-skeleton, Kit/SkeletonLines and friends) and MudSkeleton, whose
   wave is MudBlazor's own timing and a black sheen no dark theme shows. The block keeps the size of what it stands
   in for from the start, so nothing moves when that arrives, but it fades in only after --delay-skeleton, so a read
   that answers sooner shows no placeholder at all. A sheen then crosses it once per --duration-sweep, three times
   and no more: moving content beside the rest of the page stops within five seconds (WCAG 2.2.2), and a placeholder
   still there after that is plainly still loading. Under reduced motion --duration-sweep is zero, an animation of no
   length shows nothing, and the placeholder stands still. */
.kit-skeleton,
.mud-skeleton {
	background-color: var(--skeleton);
	cursor: progress;
	animation: kit-skeleton-appear var(--motion-fade) var(--delay-skeleton) both;
}
.kit-skeleton,
.mud-skeleton-wave {
	position: relative;
	overflow: hidden;
}
.kit-skeleton::after,
.mud-skeleton-wave::after {
	content: "";
	position: absolute;
	inset: 0;
	transform: translateX(-100%);
	background: linear-gradient(90deg, transparent, var(--skeleton-sheen), transparent);
	animation: kit-skeleton-sweep var(--motion-sweep) var(--delay-skeleton) 3;
}
.mud-skeleton-pulse {
	animation: kit-skeleton-appear var(--motion-fade) var(--delay-skeleton) both, kit-skeleton-pulse var(--motion-sweep) var(--delay-skeleton) 3;
}
@keyframes kit-skeleton-appear {
	from { opacity: 0; }
}
@keyframes kit-skeleton-sweep {
	to { transform: translateX(100%); }
}
@keyframes kit-skeleton-pulse {
	50% { opacity: 0.4; }
}
/* Forced colours replace the placeholder's fill with the page's own, and the shape would vanish. An outline
   drawn inside it keeps the shape without changing its size. */
@media (forced-colors: active) {
	.kit-skeleton, .mud-skeleton {
		outline: 1px solid GrayText;
		outline-offset: -1px;
	}
}

/* MudBlazor's components move on Material 2's curves and their own durations, and ignore reduced
   motion. These put them on the portal's tokens, which also stills them under reduced motion. */
.mud-collapse-container,
.mud-expand-panel,
.mud-tab-slider,
.mud-tabs-panels,
.mud-drawer,
.mud-main-content {
	transition-duration: var(--duration-enter);
	transition-timing-function: var(--ease-standard);
}
.mud-dialog {
	animation-duration: var(--duration-exit);
	animation-timing-function: var(--ease-enter);
}
/* The thumb's left and transform, then its background-color and box-shadow, in MudBlazor's order. */
.mud-switch-base {
	transition-duration: var(--duration-spring), var(--duration-spring), var(--duration-effect), var(--duration-effect);
	transition-timing-function: var(--ease-spring), var(--ease-spring), var(--ease-standard), var(--ease-standard);
}
.mud-ripple-effect {
	transition-duration: var(--duration-enter), var(--duration-effect);
}

/* FocusOnNavigate (App.razor) moves focus to the page's h1 so a screen reader announces the new page.
   The heading is not something the visitor tabbed to, so it draws no focus ring; on a page whose h1
   is already rendered when the route loads (Login, Setup) the ring was a white box around the title. */
h1:focus {
	outline: none;
}

/* MudBlazor's stylesheet takes the browser's outline off every button and link (button:focus,
   a:focus-visible), so a plain button the keyboard reached looked unfocused: every Setup button, the
   account button. This puts a ring back for keyboard focus only: WCAG 2.4.7. */
:is(button, a, [role="button"], [role="tab"]):focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
}
