/* ==========================================================================
   Reset, base elements, typography.
   ========================================================================== */

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

* {
	margin: 0;
}

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
	scroll-padding-top: var(--space-10);
}

body {
	background-color: var(--color-bg);
	color: var(--color-text-muted);
	font-family: var(--font-body);
	font-size: var(--fs-base);
	font-weight: 400;
	line-height: var(--lh-body);
	/* dvh, not vh: on mobile `vh` is measured against the largest viewport,
	   toolbars included, so 100vh is taller than what's actually on screen with
	   the address bar shown. A short page's body then floors out taller than the
	   visible viewport, and the difference is scrollable empty space below the
	   real content — the vh fallback stays for browsers without dvh support (all
	   current mobile browsers have it; this is a legacy floor, not the fix). Same
	   argument as the scheduler modal's max-height; see scheduler.css. */
	min-height: 100vh;
	min-height: 100dvh;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
	overflow-x: hidden;
}

img,
picture,
svg,
video,
canvas {
	display: block;
	max-width: 100%;
	height: auto;
}

input,
button,
textarea,
select {
	font: inherit;
	color: inherit;
}

/* --- Headings ------------------------------------------------------------ */

h1,
h2,
h3,
h4,
h5,
h6 {
	color: var(--color-text);
	font-family: var(--font-heading);
	font-weight: 800;
	line-height: var(--lh-heading);
	letter-spacing: var(--tracking-heading);
	text-wrap: balance;
	/* Display sizes and narrow phones meet at words that are simply wider than
	   the column — a search term, a client name, a compound. Breaking one is
	   worse than ideal; letting it run off the side of the screen is worse than
	   that. Only applies when the word can't fit on a line of its own. */
	overflow-wrap: break-word;
}

h1 {
	font-size: var(--fs-h1);
	line-height: var(--lh-tight);
	letter-spacing: var(--tracking-display);
}

h2 {
	font-size: var(--fs-h2);
}

h3 {
	font-size: var(--fs-h3);
	font-weight: 700;
}

h4 {
	font-size: var(--fs-lg);
	font-weight: 700;
}

p {
	text-wrap: pretty;
}

strong,
b {
	color: var(--color-text);
	font-weight: 500;
}

/* --- Links ---------------------------------------------------------------- */

a {
	color: var(--color-text);
	text-decoration: none;
	transition: color var(--dur-fast) var(--ease);
}

a:hover {
	color: var(--color-brand);
}

/* Prose links keep an underline — inside body copy, color alone isn't enough
   of an affordance and it's the one place we can't rely on layout to signal it. */
.zd-prose a:not(.zd-btn) {
	color: var(--color-brand);
	text-decoration: underline;
	text-decoration-color: rgba(var(--brand-rgb), 0.4);
	text-underline-offset: 3px;
}

.zd-prose a:not(.zd-btn):hover {
	text-decoration-color: var(--color-brand);
}

/* --- Focus ---------------------------------------------------------------- */

:focus-visible {
	outline: 2px solid var(--color-brand);
	outline-offset: 2px;
	border-radius: var(--radius-sm);
}

/* Only safe because :focus-visible above restores a ring for keyboard users. */
:focus:not(:focus-visible) {
	outline: none;
}

/* --- Selection ------------------------------------------------------------ */

::selection {
	background: var(--color-brand);
	color: var(--color-brand-ink);
}

/* --- Code ----------------------------------------------------------------- */

code,
kbd,
pre,
samp {
	font-family: var(--font-mono);
	font-size: 0.9em;
}

:not(pre) > code {
	background: var(--color-surface-2);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-sm);
	color: var(--color-brand);
	padding: 0.15em 0.4em;
}

pre {
	background: var(--color-surface);
	border: 1px solid var(--color-border);
	border-radius: var(--radius-card);
	overflow-x: auto;
	padding: var(--space-3);
}

/* --- Lists, quotes, rules ------------------------------------------------- */

blockquote {
	border-left: 2px solid var(--color-brand);
	color: var(--color-text);
	font-size: var(--fs-lg);
	padding-left: var(--space-3);
}

hr {
	border: 0;
	border-top: 1px solid var(--color-border);
	margin-block: var(--space-6);
}

table {
	border-collapse: collapse;
	width: 100%;
}

th,
td {
	border-bottom: 1px solid var(--color-border);
	padding: var(--space-2);
	text-align: left;
}

th {
	color: var(--color-text);
	font-weight: 500;
}

/* --- Accessibility helpers ------------------------------------------------ */

.screen-reader-text {
	border: 0;
	clip-path: inset(50%);
	height: 1px;
	overflow: hidden;
	position: absolute;
	white-space: nowrap;
	width: 1px;
}

/* --- Section rhythm ------------------------------------------------------- */

@media (max-width: 768px) {
	:root {
		--section-gap: var(--space-10);
	}
}

/* --- Reduced motion -------------------------------------------------------
   Everything collapses. Reveals are handled in main.js, which skips observing
   entirely when this matches — but this is the backstop. */

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}

	[data-reveal] {
		opacity: 1 !important;
		transform: none !important;
	}
}
