/* ===== Box model ===== */

/* Padding and borders stay inside the declared size. */
*,
*::before,
*::after {
	box-sizing: border-box;
}


/* ===== Spacing and relationships ===== */

/* Zero margins on flow elements — voice classes set rhythm explicitly. */
html, body,
h1, h2, h3, h4, h5, h6,
p,
blockquote, pre,
dl, dt, dd,
figure, figcaption,
hr {
	margin: 0;
	padding: 0;
}


/* ===== Type ===== */

/* Form controls don't inherit font / color by default — browsers ship them
   with system defaults that visually disconnect from the page. */
button,
input,
textarea,
select {
	font: inherit;
	color: inherit;
}

/*
	Mobile browsers sometimes auto-inflate text on landscape rotation
	or with desktop-formatted content - this prevents that. User zoom
	(pinch, browser controls, OS text scaling) is unaffected.
*/
html {
	-moz-text-size-adjust: 100%;
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
	-webkit-tap-highlight-color: transparent;
}

/* Drop browser auto-inserted quote marks on <q>/<blockquote> — authors
   type curly quotes inline (survives style-stripping, RSS, reader view). */
blockquote, q {
	quotes: none;
}
blockquote::before, blockquote::after,
q::before, q::after {
	content: '';
	content: none;
}


/* ===== Structure ===== */

/* Fieldset's beveled border + padding aren't usually wanted. */
fieldset {
	margin: 0;
	padding: 0;
	border: 0;
}

/* Collapsed borders by default. */
table {
	border-collapse: collapse;
	border-spacing: 0;
}

/*
	Viewport interaction

	how the page behaves with the browser viewport.
	Scroll, scrollbar gutter, modal scroll lock.
*/

html {
	scrollbar-gutter: stable;
	/*
		Reserves the scrollbar's space so layout doesn't shift between short
		pages (no scrollbar) and long pages (scrollbar) - or when modals lock
		body scroll. Plug in a mouse to show it clearly. 

		The cost of being persistent is almost always worth it.
	*/
}

html:has(dialog[open]) {
	overflow: hidden;
	/*
		Lock page scroll while a native <dialog> is open via showModal().
		The platform doesn't do this automatically - the page behind the
		dialog stays scrollable by default. Pairs with scrollbar-gutter
		above so no horizontal jolt when the scrollbar visually disappears.

		iOS caveat: Safari ignores overflow: hidden for touch scroll on the
		document. Page can still rubber-band behind the modal. Full lock on
		iOS needs JS to fix the body in place and restore scroll position.
	*/
}

:target {
	scroll-margin-block: var(--target-scroll-margin, 3rem);
	/*
		Fragment-link navigation jumps to the target with breathing room
		instead of jamming it against the viewport edge. 3rem is predictable
		regardless of target type (vs an ex unit that varies with font size
		and breaks consistency between contexts).
	*/
}
