/* Reset & Base */
*,
*::before,
*::after {
	margin: 0;
	padding: 0;
	box-sizing: border-box;
}

/* Berkeley Mono — used for the code blocks (self-hosted) */
@font-face {
	font-family: "Berkeley Mono";
	src:
		url("/fonts/BerkeleyMono-Regular.woff2") format("woff2"),
		url("/fonts/BerkeleyMono-Regular.woff") format("woff");
	font-weight: 400;
	font-style: normal;
	font-display: swap;
}
@font-face {
	font-family: "Berkeley Mono";
	src:
		url("/fonts/BerkeleyMono-Bold.woff2") format("woff2"),
		url("/fonts/BerkeleyMono-Bold.woff") format("woff");
	font-weight: 700;
	font-style: normal;
	font-display: swap;
}

:root {
	--color-bg: #0a0a0a; /* near-black */
	--color-ink: #f5f5f5; /* near-white for emphasis */
	--color-body: #f5f5f5; /* body/paragraph text, same bright white as ink */
	--color-muted: #999999; /* mid gray titles + labels (7:1 on the dark bg) */
	--color-info: #a8a8a8; /* fainter grey than ink — static/informational text (badges, Currently, Education) that isn't clickable */
	--color-accent: #d97b96; /* brightened rose/maroon so it stays readable on black */
	--color-line: #2a2a2a; /* hairline borders */
	--font-serif: "Instrument Serif", Georgia, serif;
	--font-display: "Geist", -apple-system, BlinkMacSystemFont, sans-serif;
	--font-sans: "Geist", -apple-system, BlinkMacSystemFont, sans-serif;
	--font-mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
	--font-code:
		"Berkeley Mono", "Geist Mono", ui-monospace, SFMono-Regular, Menlo,
		monospace;
	--column: 600px; /* body + list column */
	--text-size: 1rem; /* 16px — every piece of text on the site, no exceptions */
	--line-height: 1.55; /* one line-height used everywhere, for even rhythm */
	--space-xs: 0.25rem; /* 4px — title to body text */
	--space-lg: 2rem; /* 32px — between larger items */
	--tooltip-bg: rgba(255, 255, 255, 0.06); /* little pop-up bubbles (the term + copy toast) */
	--tooltip-ink: #f0f0f0;
	/* One pink hover wash, everywhere — same tinge as the info badge's
	   background (#2a1520), used for every hoverable link/button on the site. */
	--hover-bg: #2a1520;
	--hover-bg-accent: #2a1520;
	color-scheme: dark;
}

html {
	scroll-behavior: smooth;
	scrollbar-gutter: stable;
	overflow-y: scroll;
}

body {
	font-family: var(--font-sans);
	font-size: var(--text-size);
	font-weight: 400;
	background: var(--color-bg);
	color: var(--color-body);
	line-height: var(--line-height);
	letter-spacing: -0.015em;
	min-height: 100vh;
	display: flex;
	flex-direction: column;
	cursor: default;
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
}

/* Skip links — hidden until focused by keyboard */
.skip-link {
	position: absolute;
	top: 0.75rem;
	left: 0.75rem;
	z-index: 1000;
	padding: 0.55rem 0.95rem;
	background: var(--color-ink);
	color: var(--color-bg);
	font-size: var(--text-size);
	border-radius: 4px;
	text-decoration: none;
	transform: translateY(-150%);
	transition: transform 0.15s ease;
}

.skip-link:focus {
	transform: translateY(0);
	outline: 2px solid var(--color-bg);
	outline-offset: 2px;
}

/* Visible keyboard focus everywhere */
a:focus-visible,
button:focus-visible,
.project:focus-visible {
	outline: 2px solid var(--color-accent);
	outline-offset: 3px;
	border-radius: 2px;
}

/* Target that receives focus from a skip link shouldn't show a box outline */
[tabindex="-1"]:focus {
	outline: none;
}

/* Centered narrow column — wide margins on each side */
.column {
	width: 100%;
	max-width: var(--column);
	margin: 0 auto;
	padding: 0 1.5rem;
}

/* Navigation */
nav {
	padding: 1.4rem 0;
}

.nav-inner {
	max-width: var(--column);
	margin: 0 auto;
	padding: 0 1.5rem;
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 0.75rem;
}

.nav-links {
	display: flex;
	gap: 1.25rem;
}

.nav-links a {
	color: var(--color-muted);
	text-decoration: none;
	font-size: var(--text-size);
	padding: 0.3rem 0.55rem;
	margin: -0.3rem -0.55rem;
	border-radius: 3px;
	transition:
		color 0.2s,
		background-color 0.2s;
}

.nav-links a:hover {
	color: var(--color-ink);
	background: var(--hover-bg);
}

/* Current page in the nav */
.nav-links a.is-current {
	color: var(--color-ink);
	font-weight: 600;
}

/* On mobile, stack the nav: Dribbble/LinkedIn/Email on top, Home/About below */
@media (max-width: 480px) {
	.nav-inner {
		flex-direction: column;
		align-items: flex-start;
	}
	.nav-links {
		order: 2;
		margin: 0;
	}
	.nav-links-right {
		order: 1;
		margin: 0;
	}
}

/* Main */
main {
	flex: 1;
	width: 100%;
}

/* Hero — portrait + short intro, left-aligned like the rest of the page.
   Only top padding: each section owns the gap above it, so section-to-section
   spacing stays a single 32px everywhere (matching the blog), never doubled. */
.hero {
	padding: var(--space-lg) 0 0;
}

.portrait-wrap {
	width: max-content;
	margin-bottom: var(--space-lg);
}

.portrait {
	display: block;
	width: 96px;
	height: 96px;
}

/* The silhouette fades to golden yellow on hover; background/gaps stay put */
.portrait-bg {
	fill: var(--color-bg);
}

.portrait .portrait-ink {
	transition: fill 0.3s ease;
}

.portrait-wrap:hover .portrait-ink {
	fill: #ff2ec4;
}

/* A little squash-and-stretch pop, triggered from script.js on click. */
@keyframes portrait-bounce {
	0% {
		transform: scale(1, 1);
	}
	30% {
		transform: scale(0.85, 1.18);
	}
	50% {
		transform: scale(1.16, 0.86);
	}
	70% {
		transform: scale(0.94, 1.06);
	}
	100% {
		transform: scale(1, 1);
	}
}

.portrait-wrap.is-bouncing .portrait {
	animation: portrait-bounce 0.5s cubic-bezier(0.36, 0.07, 0.19, 0.97);
	transform-origin: bottom center;
}

.portrait-wrap.is-bouncing .portrait-ink {
	fill: #ff3b3b;
}

/* Shared "this click didn't do anything new" feedback — a small nav link
   clicked while already the current page, or a click on an inline phrase
   that has no destination. Bounces and flashes red instead of navigating. */
@keyframes error-bounce {
	0%,
	100% {
		transform: translateY(0);
	}
	30% {
		transform: translateY(-3px);
	}
	55% {
		transform: translateY(0);
	}
	75% {
		transform: translateY(-1.5px);
	}
}

.nav-links a.is-error-bounce,
.term.is-error-bounce {
	color: #ff3b3b;
	animation: error-bounce 0.4s ease;
}

.hero-tagline {
	font-family: var(--font-sans);
	font-weight: 400;
	font-size: var(--text-size);
	color: var(--color-muted);
	margin-bottom: var(--space-xs);
}

.hero-tagline .hero-dash {
	color: var(--color-muted);
}

.hero-tagline .role {
	color: var(--color-muted);
}

.hero-intro {
	font-size: var(--text-size);
	color: var(--color-ink);
	max-width: 34rem;
}

.hero-intro a {
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 2px;
}

/* Hover/focus tooltip for explaining a term in plain words */
.term {
	position: relative;
	font-family: var(--font-sans);
	color: inherit;
	text-decoration: underline;
	text-decoration-style: dotted;
	text-decoration-thickness: 2px;
	text-underline-offset: 3px;
	cursor: help;
	transition: color 0.25s ease;
}

/* While the tooltip is showing, the phrase turns the same golden yellow the
   pixel portrait uses on hover, then fades back. On mobile the tooltip auto-
   closes after a few seconds (script.js removes .is-open), so it reverts then. */
.term:hover,
.term:focus-visible,
.term.is-open {
	color: #d6b877; /* a milder, softer gold than the portrait's #e0a82e */
}

.term-bubble {
	position: absolute;
	left: 50%;
	bottom: calc(100% + 6px);
	transform: translateX(-50%) translateY(2px);
	width: max-content;
	max-width: 260px;
	background: var(--tooltip-bg);
	color: var(--tooltip-ink);
	font-family: var(--font-sans);
	font-weight: 400;
	font-size: 0.875rem;
	line-height: 1.3;
	letter-spacing: 0;
	padding: 0.4rem 0.6rem;
	border-radius: 4px;
	text-align: center;
	text-decoration: none;
	opacity: 0;
	pointer-events: none;
	/* Fade in and fade out */
	transition:
		opacity 0.25s ease,
		transform 0.25s ease;
	z-index: 20;
}

.term:hover .term-bubble,
.term:focus-visible .term-bubble,
.term.is-open .term-bubble {
	opacity: 1;
	transform: translateX(-50%) translateY(0);
}

/* On mobile, float the tooltip up next to the pixel portrait so it doesn't
   cover the bio text below. Positioned relative to the hero, to the right of
   the 96px portrait. */
@media (max-width: 480px) {
	.hero {
		position: relative;
	}
	.term {
		position: static;
	}
	.term-bubble {
		position: absolute;
		top: var(--space-lg);
		left: calc(96px + 1.25rem);
		right: 0;
		bottom: auto;
		width: auto;
		max-width: none;
		text-align: left;
		transform: translateY(6px);
		z-index: 1000;
	}
	.term:hover .term-bubble,
	.term:focus-visible .term-bubble,
	.term.is-open .term-bubble {
		transform: translateY(0);
	}
}

/* Small label */
.label {
	font-family: var(--font-mono);
	font-size: var(--text-size);
	font-weight: 400;
	text-transform: uppercase;
	color: var(--color-muted);
	margin-bottom: var(--space-xs);
}

.label.center {
	text-align: center;
}

/* Body sections — top padding only, so the gap between any two sections is a
   single 32px (matching the blog), not 32px stacked on 32px. */
section.block {
	padding: var(--space-lg) 0 0;
}

/* Education / status badge */
/* Same grey as the tooltip bubble, not its own color — the icon is nudged
   down a touch so its circle optically lines up with the text's cap-height. */
.badge {
	display: flex;
	align-items: flex-start;
	gap: 0.4rem;
	margin: 0 0 1.25rem;
	padding: 0.6em 0.6em;
	border-radius: 0.25em;
	background: var(--tooltip-bg);
	color: var(--color-info);
	font-family: var(--font-sans);
	font-size: var(--text-size);
}

.badge svg {
	flex: 0 0 auto;
	width: 16px;
	height: 16px;
	margin-top: 0.3rem;
	stroke: currentColor;
}

/* "Open for work" badge (Currently section) — hugs its content, green status. */
.badge-open {
	width: fit-content;
	background: #142a1c;
	color: #8fe3ac;
}

/* Currently (1/3) + Previously (2/3) side by side */
.now-grid {
	display: grid;
	grid-template-columns: 1fr 2fr;
	gap: 1.5rem;
	align-items: start;
}

.now-grid .now {
	padding-top: var(--space-lg);
}

@media (max-width: 480px) {
	.now-grid {
		grid-template-columns: 1fr;
		gap: 0;
	}
}

/* On the homepage the badge is the whole Currently section — drop its bottom
   margin so the gap to Projects is a single 32px (the next section's top pad),
   not 32px + 32px. The About-page badge keeps its default bottom margin. */
.now .badge {
	margin-bottom: 0;
}

/* Plain bordered row list (e.g. education) */
.rows {
	border-top: none;
}

.row {
	padding: 0.85rem 0;
	border-bottom: 1px solid var(--color-line);
}

.row:first-child {
	padding-top: 0;
}

.row-title {
	font-size: var(--text-size);
	font-weight: 500;
	color: var(--color-info);
}

.in-progress {
	font-family: var(--font-sans);
	font-weight: 400;
	color: #6a6a6a;
}

.row-sub {
	font-size: var(--text-size);
	color: var(--color-muted);
}

/* Current role row (below the portrait, above Work) */
.now {
	padding: var(--space-lg) 0 0;
}

/* Plain text, not a link — flows like a normal sentence (no flex) so the
   role and the institution wrap together naturally on narrow screens. */
.now-row .project-name,
.now-row .project-desc,
.now-sep {
	color: var(--color-info);
	white-space: normal;
}

.now-row .project-desc {
	overflow: visible;
	text-overflow: clip;
}

/* On phones, drop the "·" and put the institution on its own line instead
   of running it into the role on one crowded line. */
@media (max-width: 480px) {
	.now-sep {
		display: none;
	}

	.now-row .project-desc {
		display: block;
	}

	.row-sub {
		font-size: 0.875rem;
	}
}

/* Project rows: one line, name + short description, styled like the
   Previously link below — a compact pill hugging its own content, no divider
   lines. The trailing arrow signals it leads to a case study; it nudges
   forward on hover the same way the Previous/Next links do at page bottom. */
/* width is widened by exactly twice the horizontal padding, so the negative
   margin bleeds the hover background outward symmetrically while the text
   inside (inset by that same padding) still lines up with every other
   section's left/right edge. Plain "width: 100%" here would let the
   negative margin shift the whole row left instead of bleeding both sides. */
.project {
	display: flex;
	align-items: baseline;
	gap: 0.45rem;
	width: calc(100% + 1.1rem);
	padding: 0.3rem 0.55rem;
	margin: -0.3rem -0.55rem;
	border-radius: 4px;
	text-decoration: none;
	color: inherit;
	transition: background-color 0.2s ease;
}

.project + .project {
	margin-top: 0.35rem;
}

.project:hover {
	background: var(--hover-bg-accent);
}

.project:hover .project-desc {
	color: #c4c4c4;
}

.project:hover .project-arrow {
	transform: translateX(2px);
	color: var(--color-ink);
}

/* The Dribbble row is a genuine external link, so its arrow points diagonally
   (out of the page) instead of the straight right arrow the case-study rows
   use — the nudge on hover matches that direction too. */
.project:hover .project-arrow-external {
	transform: translate(1.5px, -1.5px);
}

.project-name {
	font-size: var(--text-size);
	font-weight: 400;
	color: var(--color-ink);
	white-space: nowrap;
	flex: 0 0 auto;
}

.project-desc {
	font-size: var(--text-size);
	color: var(--color-muted);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	min-width: 0;
	transition: color 0.2s ease;
}

.project-arrow {
	flex: 0 0 auto;
	color: var(--color-muted);
	margin-left: auto;
	padding-left: 0.5rem;
	transition:
		transform 0.2s ease,
		color 0.2s ease;
}

/* On narrow screens, Projects rows show just the title + arrow — the short
   description doesn't add enough to be worth the extra line/crowding. */
@media (max-width: 480px) {
	.project .project-desc {
		display: none;
	}
}

/* "Previously" role — links to the startup case study. Same compact pill and
   rose-tinted hover as the Projects rows since it leads to the same kind of
   destination (a case study), plus the same forward-pointing arrow cue. */
/* Same width/padding/margin relationship as .project above — see that
   comment for why "width: 100%" alone would shift the row left instead of
   bleeding the hover background symmetrically. */
.prev-link {
	display: flex;
	align-items: baseline;
	gap: 0.45rem;
	width: calc(100% + 1rem);
	text-decoration: none;
	padding: 0.25rem 0.5rem;
	margin: -0.25rem -0.5rem;
	border-radius: 4px;
	transition: background-color 0.2s ease;
}

.prev-link:hover {
	background: var(--hover-bg-accent);
}

.prev-link:hover .project-arrow {
	transform: translateX(2px);
	color: var(--color-ink);
}

/* Case-study / prose pages */
.prose {
	padding: 0.85rem 0 0;
}

.page-title {
	font-family: var(--font-mono);
	font-weight: 400;
	font-size: var(--text-size);
	text-transform: uppercase;
	color: var(--color-muted);
	margin-bottom: var(--space-xs);
}

.page-lede {
	font-size: var(--text-size);
	color: var(--color-muted);
	margin-bottom: var(--space-lg);
}

/* Chrome Web Store link under the lede — a little space above, 32px below */
.store-link {
	font-size: var(--text-size);
	margin-top: calc(0.9rem - var(--space-lg));
	margin-bottom: var(--space-lg);
}

/* Specificity note: this link sits inside .prose, so it needs to outrank the
   generic ".prose a" rule below (same "a inside .prose" shape) — the extra
   "p" keeps that guaranteed regardless of source order. */
p.store-link a {
	padding: 0.15em 0.35em;
	margin: 0 -0.35em;
	border-radius: 2px;
	transition:
		color 0.2s ease,
		background-color 0.2s ease;
}

p.store-link a:hover,
p.store-link a:focus-visible {
	color: #be5f7a; /* a little darker than the rose accent */
	background: var(--hover-bg-accent);
}

.prose h2 {
	font-family: var(--font-mono);
	font-size: var(--text-size);
	font-weight: 400;
	text-transform: uppercase;
	color: var(--color-muted);
	margin: var(--space-lg) 0 var(--space-xs);
}

.prose p {
	color: var(--color-body);
	margin-bottom: 1.1rem;
}

.prose ul {
	margin: 0 0 1.1rem 1.1rem;
	padding: 0;
	color: var(--color-body);
}

.prose li {
	margin-bottom: 0.5rem;
	padding-left: 0.3rem;
}

.prose strong {
	color: var(--color-ink);
	font-weight: 600;
}

.prose a {
	color: var(--color-accent);
	text-decoration: underline;
	text-underline-offset: 2px;
	padding: 0.1em 0.3em;
	margin: 0 -0.3em;
	border-radius: 2px;
	-webkit-box-decoration-break: clone;
	box-decoration-break: clone;
	transition:
		color 0.2s ease,
		background-color 0.2s ease;
}

.prose a:hover,
.prose a:focus-visible {
	color: var(--color-ink);
	background: var(--hover-bg-accent);
}

/* About page: a wide photo across the top, then two square photos side by side */
.about-gallery {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 1rem;
	margin-top: var(--space-lg);
	align-items: start;
}

/* Full-width photo spanning both columns (the keyboard shot at the top) */
.about-photo-wide {
	grid-column: 1 / -1;
}

.about-gallery figure {
	margin: 0;
}

.about-gallery img {
	display: block;
	width: 100%;
	height: auto;
}

.about-gallery figcaption {
	font-family: var(--font-sans);
	font-size: var(--text-size);
	color: var(--color-muted);
	text-align: center;
	margin-top: var(--space-xs);
}

@media (max-width: 480px) {
	.about-gallery {
		grid-template-columns: 1fr;
	}
}

/* Full-width image inside a case-study page. No top margin: it should sit close
   to whatever title or lede introduces it, matching every other title's spacing. */
.prose-figure {
	margin: 0 0 var(--space-lg);
}

.prose-image {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 2px;
	border: 1px solid var(--color-line);
	transition:
		opacity 0.2s ease,
		border-color 0.2s ease;
}

/* Session-code screenshot: full width on mobile, small and centered on desktop,
   with a hard, faint, offset shadow to the lower-right (no blur). */
.prose-figure-shadow .prose-image {
	width: 100%;
	margin-left: auto;
	margin-right: auto;
	box-shadow: 6px 6px 0 rgba(245, 245, 245, 0.16);
}

/* Nudge only this caption down a touch so it clears the drop shadow */
.prose-figure-shadow figcaption {
	margin-top: 8px;
}

@media (min-width: 768px) {
	.prose-figure-shadow .prose-image {
		width: 50%;
	}
	/* On desktop the image is small and centered, so keep its caption the same
     width and centered under it — wrapping onto multiple lines. */
	.prose-figure-shadow figcaption {
		max-width: 50%;
		margin-top: 8px;
		margin-left: auto;
		margin-right: auto;
	}
}

/* On screens above tablet, shrink the tall mockups image a bit so it doesn't tower over the text */
@media (min-width: 768px) {
	.prose-figure-mockups .prose-image {
		width: 75%;
		margin: 0 auto;
	}
}

.prose-figure figcaption {
	font-family: var(--font-sans);
	font-size: var(--text-size);
	color: var(--color-muted);
	text-align: center;
}

/* Small "click to zoom" hint above a clickable figure */
.zoom-hint {
	display: flex;
	align-items: center;
	gap: 0.4rem;
	font-family: var(--font-sans);
	font-size: var(--text-size);
	color: var(--color-muted);
	margin: 0 0 var(--space-xs);
}

.zoom-hint svg {
	flex: 0 0 auto;
	width: 16px;
	height: 16px;
	stroke: currentColor;
}

/* Explicitly zeroes padding/margin: it ties in specificity with the generic
   ".prose a" text-link rule (which pads/insets for its hover highlight), but
   this anchor just wraps an image and shouldn't inherit that inset. */
.prose-figure a {
	display: block;
	padding: 0;
	margin: 0;
	cursor: zoom-in;
}

/* This link wraps an opaque screenshot, so a background wash would be hidden
   behind it — dim the image itself instead, the equivalent hover cue here. */
.prose-figure a:hover .prose-image,
.prose-figure a:focus-visible .prose-image {
	opacity: 0.85;
	border-color: var(--color-accent);
}

/* Code examples inside the prose */
.code-block {
	background: #0d1117;
	border: 1px solid #1c222c;
	border-radius: 3px;
	padding: 1rem 1.15rem;
	margin: 1.1rem 0 1.4rem;
	overflow-x: auto;
}

.code-block code {
	display: block;
	font-family: var(--font-code);
	/* One step down from the 16px body size: 0.875rem = 14px, still in rem so
     it scales rather than being locked to a fixed pixel value. */
	font-size: 0.875rem;
	line-height: 1.35;
	letter-spacing: -0.01em;
	color: #e0af68;
	white-space: pre;
}

/* Inline code in prose — same font and color as the code blocks */
.prose p code,
.prose li code {
	font-family: var(--font-code);
	letter-spacing: -0.01em;
	color: #9fb4d8;
}

/* Same padding, radius, and hover treatment as the nav menu links — just
   keeps its own arrow and muted color instead of nav's current-page state.
   Written as "a.back-link" (not just ".back-link") so it outranks the
   generic ".prose a" rule this link sits inside of. */
a.back-link {
	display: inline-block;
	font-size: var(--text-size);
	color: var(--color-muted);
	text-decoration: none;
	padding: 0.3rem 0.55rem;
	margin: -0.3rem -0.55rem 1.3rem -0.55rem;
	border-radius: 3px;
	transition:
		color 0.2s,
		background-color 0.2s;
}

a.back-link:hover {
	color: var(--color-ink);
	background: var(--hover-bg);
}

/* Previous / next project navigation at the bottom of a case study */
.prose-nav {
	display: flex;
	justify-content: space-between;
	gap: var(--space-lg);
	margin-top: var(--space-lg);
	padding-top: var(--space-lg);
	border-top: 1px solid var(--color-line);
}

/* The whole link is not underlined — only the blog title is (below) */
.prose-nav a {
	text-decoration: none;
}

/* Written as "a.prose-nav-link" so it outranks the generic ".prose a" rule
   these cards sit inside of (same specificity, but appearing later here
   isn't enough on its own once color/padding/margin overlap — matching the
   "type + class" shape guarantees the win). */
a.prose-nav-link {
	display: flex;
	flex-direction: column;
	gap: var(--space-xs);
	color: inherit;
	padding: 0.7rem 0.9rem;
	margin: -0.7rem -0.9rem;
	border-radius: 5px;
	border: 1px solid transparent;
	transition:
		background-color 0.2s ease,
		border-color 0.2s ease;
}

a.prose-nav-link:hover {
	background: var(--hover-bg);
	border-color: var(--color-line);
}

a.prose-nav-next {
	margin-left: auto;
	text-align: right;
	align-items: flex-end;
}

.prose-nav-dir {
	font-family: var(--font-mono);
	text-transform: uppercase;
	font-size: var(--text-size);
	color: var(--color-muted);
}

.prose-nav-title {
	font-size: var(--text-size);
	color: var(--color-ink);
	text-decoration: underline;
	text-underline-offset: 2px;
}

/* Footer */
footer {
	/* One 32px gap above the footer (from its own top padding) — no extra margin,
     so the content above sits a consistent 32px from the footer, not 90px+. */
	padding: var(--space-lg) 0 var(--space-lg);
	margin-top: 0;
}

.footer-inner {
	max-width: var(--column);
	margin: 0 auto;
	padding: 0 1.5rem;
}

.footer-content {
	display: flex;
	justify-content: space-between;
	align-items: flex-start;
	gap: var(--space-lg);
}

.footer-main {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-lg);
}

/* Home link on the right of the footer */
/* Plain text, same as Copy Email/Sound — not the mono-uppercase label look
   used for section labels like "Currently"/"Projects" elsewhere on the page. */
.footer-home {
	flex: 0 0 auto;
}

footer p,
footer a,
footer button {
	color: var(--color-muted);
	font-size: var(--text-size);
}

/* Same padding, radius, and hover as the nav menu links and the Copy Email /
   Sound buttons — every clickable thing in the footer reads as one family. */
footer a {
	text-decoration: none;
	padding: 0.3rem 0.55rem;
	margin: -0.3rem -0.55rem;
	border-radius: 3px;
	transition:
		color 0.2s,
		background-color 0.2s;
}

footer a:hover {
	color: var(--color-ink);
	background: var(--hover-bg);
}

.footer-contact {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: var(--space-xs);
}

/* Plain text here too, not the mono-uppercase section-label look — this is a
   clickable action next to Copy Email/Sound, not a heading like "Currently". */
.footer-contact .label {
	margin-bottom: 0;
	font-family: var(--font-sans);
	text-transform: none;
}

/* Footer buttons match the nav menu links exactly: same padding, radius,
   and hover treatment (no underline) — one consistent "clickable chrome"
   look across the whole site. */
.footer-email {
	appearance: none;
	background: none;
	border: none;
	color: var(--color-muted);
	font-family: inherit;
	text-decoration: none;
	cursor: pointer;
	padding: 0.3rem 0.55rem;
	margin: -0.3rem -0.55rem;
	border-radius: 3px;
	transition:
		color 0.2s,
		background-color 0.2s;
}

.footer-email:hover {
	color: var(--color-ink);
	background: var(--hover-bg);
}

/* Sound on/off toggle — sits inline in the copyright line. Same nav-button
   look as the email button above. */
.footer-sound {
	appearance: none;
	background: none;
	border: none;
	color: var(--color-muted);
	font-family: inherit;
	font-size: inherit;
	text-decoration: none;
	cursor: pointer;
	padding: 0.3rem 0.55rem;
	margin: -0.3rem -0.55rem;
	border-radius: 3px;
	transition:
		color 0.2s,
		background-color 0.2s;
}

.footer-sound:hover {
	color: var(--color-ink);
	background: var(--hover-bg);
}

.footer-copyright {
	margin: 0;
}


/* Fixed bottom message for "that click did nothing" feedback (e.g. tapping
   Home while already on the homepage) — same shape as the toast above, red
   instead of green, anchored to the viewport since it isn't tied to one link. */
.bottom-toast {
	position: fixed;
	left: 50%;
	bottom: 1.5rem;
	transform: translateX(-50%) translateY(8px);
	width: max-content;
	max-width: calc(100vw - 2.5rem);
	font-family: var(--font-sans);
	font-weight: 400;
	font-size: 0.875rem;
	padding: 0.6rem 0.9rem;
	border-radius: 4px;
	text-align: center;
	opacity: 0;
	pointer-events: none;
	transition:
		opacity 0.2s ease,
		transform 0.2s ease;
	z-index: 40;
}

.bottom-toast.is-success {
	background: #142a1c;
	color: #8fe3ac;
}

.bottom-toast.is-error {
	background: #2a1414;
	color: #ff9e9e;
}

.bottom-toast.is-visible {
	opacity: 1;
	transform: translateX(-50%) translateY(0);
}

/* Motion — subtle entrance + micro-interactions */
@keyframes rise {
	from {
		opacity: 0;
		transform: translateY(10px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

/* One fade-in for the whole page — every section, the hero, prose, and footer
   all rise in together at the same time (no stagger). */
.hero,
.column > section,
.column > .now-grid,
.prose,
footer {
	animation: rise 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* Respect users who prefer less motion.
   Some people set their device to "reduce motion" (for comfort, or because
   movement makes them dizzy). This one block quiets ALL animation and sliding
   across every page — the homepage, the About page, and the project write-ups
   (the "blog" posts) — so nothing moves for them. It works for any page we add
   later, too, because it targets everything at once. */
@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* High-contrast mode. When someone turns on Windows High Contrast Mode (or a
   similar OS setting), the browser throws out our colors and paints everything
   with the visitor's own high-contrast palette. That's on purpose — but a few
   pieces need help so nothing disappears: keep the keyboard focus ring using
   the system's highlight color, and give the floating pop-up bubbles a real
   border so they don't blend into the page. We use system color keywords
   (Highlight, AccentColor, CanvasText) so it always matches the user's theme. */
@media (forced-colors: active) {
	a:focus-visible,
	button:focus-visible,
	.project:focus-visible {
		outline: 2px solid Highlight;
	}

	/* Keep the "Design Engineering" phrase reading as an accent, using the
     visitor's own system accent color instead of our rose/gold. */
	.term:hover,
	.term:focus-visible,
	.term.is-open,
	.prose a {
		color: AccentColor;
	}

	/* Pop-up bubbles + tinted badges get a visible outline so their edges show. */
	.term-bubble,
	.toast,
	.badge,
	.badge-open,
	.code-block {
		border: 1px solid CanvasText;
	}
}

/* Responsive */
@media (max-width: 560px) {
	/* Center the nav links on narrow screens */
	.nav-inner {
		flex-direction: column;
		align-items: center;
		text-align: center;
	}

	.nav-links {
		justify-content: center;
		flex-wrap: wrap;
	}
}

/* Extra-small phones */
@media (max-width: 360px) {
	/* Stack the footer and put the copyright under the links, both centered */
	.footer-inner {
		flex-direction: column;
		justify-content: center;
		text-align: center;
	}

	.footer-inner p {
		order: 2;
	}

	.footer-links {
		order: 1;
	}
}
