/* skeleton.css - everything that is true regardless of how the site looks.
 *
 * This file is not a design system and must never become one. It holds the
 * browser reset and the accessibility mechanics that have to keep working even
 * if a theme is broken, missing or half-written. No colours, no type, no
 * layout: those belong to the theme, which is the part that gets swapped.
 *
 * A page with only this stylesheet is plain, but readable and operable. That is
 * the floor a theme builds on, and the reason a bad theme cannot lock anyone
 * out of the site.
 */

*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	-webkit-text-size-adjust: 100%;
}

body {
	margin: 0;
}

img,
svg,
video {
	max-width: 100%;
	height: auto;
}

/* Form controls do not inherit type by default, which leaves a theme that
 * styles body text alone with mismatched inputs. */
button,
input,
select,
textarea {
	font: inherit;
	color: inherit;
}

button {
	cursor: pointer;
}

fieldset {
	margin: 0;
	padding: 0;
	border: 0;
	min-width: 0;
}

[hidden] {
	display: none !important;
}

/* The backdrop layer.
 *
 * Only its position is fixed here, because "behind everything, covering the
 * window, never in the way" is structural rather than stylistic. What is drawn
 * in it belongs entirely to the chosen backdrop stylesheet, and a page whose
 * backdrop says nothing simply has an empty one.
 *
 * The negative z-index puts it above the canvas - which is where the theme's
 * body background lands - and below every in-flow element, so no theme has to
 * arrange its own stacking to stay readable. It never takes a pointer event.
 */
.backdrop {
	position: fixed;
	inset: 0;
	z-index: -1;
	overflow: hidden;
	pointer-events: none;
}

.backdrop__layer {
	position: absolute;
	inset: 0;
	display: block;

	/* The one hint, and it is structural rather than stylistic: whatever a
	 * backdrop draws, these three elements are the ones that move, and they are
	 * the full size of the window. Left unpromoted, a scroll-linked translation
	 * repaints a window-sized masked gradient on every frame the page moves,
	 * which is the difference between a background that glides and one that
	 * stutters. Three layers is a bounded cost; it does not scale with what is
	 * drawn in them. */
	will-change: transform, translate;
}

/* The pointer's two acknowledgements: the tint and the wave.
 *
 * Placed by the coordinates the pointer script writes, and nothing more: what
 * either is, how big, what colour and whether it appears at all is entirely
 * the backdrop's business. A backdrop that says nothing about them has two
 * invisible points.
 */
.backdrop__tint,
.backdrop__wave {
	position: absolute;
	left: 0;
	top: 0;
	display: block;
	translate: calc(var(--px) * 100vw) calc(var(--py) * 100vh);
}

/* A visible focus ring is not a stylistic choice. A theme may restyle it; it
 * may not remove it, and this is what is left if it says nothing at all. */
:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 3px;
}

/* The skip link's mechanics: reachable by keyboard, out of the way otherwise.
 * How it looks is the theme's business. */
.skip {
	position: absolute;
	left: 0;
	top: 0;
	z-index: 100;
	transform: translateY(-200%);
}

.skip:focus {
	transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		transition-duration: 0.01ms !important;
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		scroll-behavior: auto !important;
	}

	/* The backdrop is removed from the animation system outright rather than
	 * sped up to nothing. Collapsing its duration would leave every layer
	 * parked on the last frame of a drift it never performed, which is not what
	 * any of them were composed to look like. The Motion control can still be
	 * turned down by hand; this is the floor under it.
	 *
	 * Both displacement properties are named, not just transform. A backdrop is
	 * free to carry its scroll on either of them - parallax uses translate,
	 * everything else uses transform - so naming one of the two left the other
	 * backdrop still answering the scrollbar under a setting that says nothing
	 * should move. */
	.backdrop *,
	.backdrop *::before,
	.backdrop *::after {
		animation: none !important;
		transform: none !important;
		translate: none !important;
	}

	/* The pointer marks are removed rather than stilled: a tint that
	 * teleports to the cursor is more movement than one that eases to it, not
	 * less. The script bows out under the same query, so this is the belt to
	 * its braces. */
	.backdrop__tint,
	.backdrop__wave {
		display: none !important;
	}
}
