/* ==========================================================================
   steftweepenninckx.xyz
   Hand-written. No framework, no JavaScript, no web fonts, no external requests.

   Layout is a two-column grid: a sticky rail carrying identity and navigation,
   and a content column whose sections are separated by rules that mark real
   structure. Section labels sit in the margin rather than above the text.
   ========================================================================== */

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

/* --------------------------------------------------------------------------
   Tokens
   -------------------------------------------------------------------------- */

:root {
	color-scheme: light dark;

	/* Two type roles. Prose is set in a grotesque; anything that is data —
	   dates, places, stacks, skills — is set in mono so it reads as data. */
	--sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
	--mono: ui-monospace, SFMono-Regular, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, Consolas, "Liberation Mono", monospace;

	--t-lede: clamp(1.6rem, 0.95rem + 2.9vw, 3.25rem);
	--t-name: clamp(1.3rem, 1.18rem + 0.45vw, 1.55rem);
	--t-h3: clamp(1.0625rem, 1.02rem + 0.2vw, 1.1875rem);
	--t-body: clamp(1rem, 0.985rem + 0.1vw, 1.0625rem);
	--t-small: 0.8125rem;
	--t-micro: 0.6875rem;

	--sp-1: 0.35rem;
	--sp-2: 0.7rem;
	--sp-3: 1.15rem;
	--sp-4: 1.8rem;
	--sp-5: 2.8rem;
	--sp-6: clamp(2.6rem, 1.6rem + 3.6vw, 4.4rem);

	--measure: 64ch;
	--gutter: clamp(1.35rem, 4vw, 3.25rem);
	--rail: 17rem;

	/* Neutrals are biased cool, toward the accent, so they read as chosen. */
	--ground: #edeff1;
	--raised: #e4e7ea;
	--ink: #111417;
	--ink-2: #5a6169;
	--ink-3: #868e96;
	--rule: #d2d7dc;
	--rule-soft: #e2e6e9;
	--accent: #1b45d8;
	--accent-hover: #12309b;
	--on-accent: #ffffff;

	/* The lightbox is a dark surface in both themes, so what sits on it is
	   fixed rather than themed. These are deliberately not redefined below. */
	--scrim: rgba(8, 10, 12, 0.88);
	--on-scrim: #eef1f4;
	--on-scrim-dim: #a8b0b8;
	--scrim-rule: rgba(255, 255, 255, 0.16);
}

@media (prefers-color-scheme: dark) {
	:root {
		--ground: #0e1114;
		--raised: #171b20;
		--ink: #e7eaed;
		--ink-2: #98a1a9;
		--ink-3: #6d767e;
		--rule: #262d34;
		--rule-soft: #1c2227;
		--accent: #6f92ff;
		--accent-hover: #99b3ff;
		--on-accent: #0e1114;
	}
}

/* The viewer's own toggle must win over the OS preference, in both directions. */
:root[data-theme="dark"] {
	--ground: #0e1114;
	--raised: #171b20;
	--ink: #e7eaed;
	--ink-2: #98a1a9;
	--ink-3: #6d767e;
	--rule: #262d34;
	--rule-soft: #1c2227;
	--accent: #6f92ff;
	--accent-hover: #99b3ff;
	--on-accent: #0e1114;
}

:root[data-theme="light"] {
	--ground: #edeff1;
	--raised: #e4e7ea;
	--ink: #111417;
	--ink-2: #5a6169;
	--ink-3: #868e96;
	--rule: #d2d7dc;
	--rule-soft: #e2e6e9;
	--accent: #1b45d8;
	--accent-hover: #12309b;
	--on-accent: #ffffff;
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */

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

@media (prefers-reduced-motion: no-preference) {
	html {
		scroll-behavior: smooth;
	}
}

body {
	margin: 0;
	background: var(--ground);
	color: var(--ink);
	font-family: var(--sans);
	font-size: var(--t-body);
	line-height: 1.6;
	-webkit-font-smoothing: antialiased;
}

a {
	color: inherit;
}

:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 3px;
}

.skip {
	position: absolute;
	left: -9999px;
	top: 0;
	background: var(--accent);
	color: var(--on-accent);
	padding: var(--sp-2) var(--sp-3);
	font: 600 var(--t-small) / 1 var(--mono);
	z-index: 10;
}

.skip:focus {
	left: 0;
}

/* --------------------------------------------------------------------------
   Shell
   -------------------------------------------------------------------------- */

.page {
	max-width: 78rem;
	margin-inline: auto;
	padding-inline: var(--gutter);
}

@media (min-width: 60rem) {
	.page {
		display: grid;
		grid-template-columns: var(--rail) minmax(0, 1fr);
		gap: 0 var(--sp-6);
		align-items: start;
	}
}

/* --------------------------------------------------------------------------
   Rail — identity and navigation
   -------------------------------------------------------------------------- */

.rail {
	display: flex;
	flex-direction: column;
	gap: var(--sp-3);
	padding-block: var(--sp-5) var(--sp-4);
}

@media (min-width: 60rem) {
	.rail {
		position: sticky;
		top: 0;
		min-height: 100vh;
		min-height: 100dvh;
		padding-block: var(--sp-6);
		border-right: 1px solid var(--rule);
	}
}

.portrait {
	width: 3.75rem;
	height: 3.75rem;
	object-fit: cover;
	display: block;
	filter: grayscale(1) contrast(1.05);
	border: 1px solid var(--rule);
}

.name {
	font-size: var(--t-name);
	font-weight: 600;
	letter-spacing: -0.021em;
	line-height: 1.15;
	margin: 0;
	text-wrap: balance;
}

.role {
	font-family: var(--mono);
	font-size: var(--t-small);
	color: var(--ink-2);
	line-height: 1.45;
	margin: 0;
}

.nav {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-1) var(--sp-3);
	font-family: var(--mono);
	font-size: var(--t-small);
}

@media (min-width: 60rem) {
	.nav {
		flex-direction: column;
		gap: 0.15rem;
		margin-top: auto;
	}
}

.nav a {
	text-decoration: none;
	color: var(--ink-2);
	padding-block: 0.15rem;
	border-bottom: 1px solid transparent;
	transition: color 0.15s ease, border-color 0.15s ease;
}

.nav a:hover {
	color: var(--ink);
	border-bottom-color: var(--accent);
}

.rail-links {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	gap: var(--sp-3);
	font-family: var(--mono);
	font-size: var(--t-small);
}

.rail-links a {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	text-decoration: none;
	color: var(--ink-2);
	transition: color 0.15s ease;
}

.rail-links a:hover {
	color: var(--accent);
}

.rail-links svg {
	width: 1rem;
	height: 1rem;
	fill: currentColor;
	flex: none;
}

/* --------------------------------------------------------------------------
   Content
   -------------------------------------------------------------------------- */

/* The column opens straight on a .section, so it carries its own top padding and the
   first section drops its rule - otherwise the page starts on a border. */
.content {
	min-width: 0;
	padding-block: var(--sp-5) var(--sp-6);
}

.content > .section:first-of-type {
	border-top: none;
}

/* No lede in the markup at the moment; kept for when the slot is used again. */
.lede {
	font-size: var(--t-lede);
	font-weight: 600;
	letter-spacing: -0.032em;
	line-height: 1.04;
	margin: 0;
	padding-block: var(--sp-5) var(--sp-6);
	max-width: 20ch;
	text-wrap: balance;
}

.lede em {
	font-style: normal;
	color: var(--accent);
}

.section {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--sp-3);
	padding-block: var(--sp-5);
	border-top: 1px solid var(--rule);
}

@media (min-width: 48rem) {
	.section {
		grid-template-columns: 7.5rem minmax(0, 1fr);
		gap: 0 var(--sp-4);
	}
}

/* Section names are marginalia, not headings above the text. */
.section > h2 {
	font-family: var(--mono);
	font-size: var(--t-micro);
	font-weight: 500;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--ink-3);
	margin: 0;
	padding-top: 0.32rem;
}

.body {
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: var(--sp-3);
}

.body > p {
	margin: 0;
	max-width: var(--measure);
	color: var(--ink-2);
}

.body > p strong {
	color: var(--ink);
	font-weight: 600;
}

/* --------------------------------------------------------------------------
   Entries — one job, one project
   -------------------------------------------------------------------------- */

.entry {
	display: flex;
	flex-direction: column;
	gap: var(--sp-2);
}

.entry h3 {
	font-size: var(--t-h3);
	font-weight: 600;
	letter-spacing: -0.014em;
	line-height: 1.3;
	margin: 0;
	text-wrap: balance;
}

.meta {
	font-family: var(--mono);
	font-size: var(--t-small);
	font-variant-numeric: tabular-nums;
	color: var(--ink-3);
	margin: 0;
	line-height: 1.5;
}

.entry p:not(.meta) {
	margin: 0;
	max-width: var(--measure);
	color: var(--ink-2);
}

.entry ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: var(--sp-2);
	max-width: var(--measure);
	color: var(--ink-2);
}

.entry ul li {
	position: relative;
	padding-left: var(--sp-3);
}

.entry ul li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.72em;
	width: 0.4rem;
	height: 1px;
	background: var(--accent);
}

/* --------------------------------------------------------------------------
   Skills — inline, so a short list reads as a short list
   -------------------------------------------------------------------------- */

.skills {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--sp-3) var(--sp-5);
}

@media (min-width: 40rem) {
	.skills {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

.skill-group {
	display: flex;
	flex-direction: column;
	gap: var(--sp-2);
}

.skill-group h3 {
	font-family: var(--mono);
	font-size: var(--t-micro);
	font-weight: 500;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: var(--ink-3);
	margin: 0;
}

.chips {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem;
}

.chips li {
	font-family: var(--mono);
	font-size: var(--t-small);
	line-height: 1;
	padding: 0.36rem 0.5rem;
	background: var(--raised);
	border: 1px solid var(--rule);
	color: var(--ink-2);
	white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Gallery — a snapping strip on narrow screens, three abreast on wide.

   Thumbnails crop to 16:10 from the top, which trims the empty lower third
   the full captures carry without touching the files.
   -------------------------------------------------------------------------- */

.shots {
	list-style: none;
	margin: var(--sp-1) 0 0;
	padding: 0 0 var(--sp-2);
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: 76%;
	gap: var(--sp-2);
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
}

.shots > li {
	min-width: 0;
	scroll-snap-align: start;
}

@media (min-width: 40rem) {
	.shots {
		grid-auto-flow: row;
		grid-auto-columns: auto;
		grid-template-columns: repeat(3, minmax(0, 1fr));
		overflow-x: visible;
	}
}

.shot {
	display: flex;
	flex-direction: column;
	gap: var(--sp-1);
	text-decoration: none;
	color: var(--ink-3);
}

.shot img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 10;
	object-fit: cover;
	object-position: top center;
	background: var(--raised);
	border: 1px solid var(--rule);
	transition: border-color 0.15s ease;
}

.shot:hover img {
	border-color: var(--accent);
}

.shot-label {
	font-family: var(--mono);
	font-size: var(--t-micro);
	letter-spacing: 0.13em;
	text-transform: uppercase;
	transition: color 0.15s ease;
}

.shot:hover .shot-label {
	color: var(--ink);
}

/* --------------------------------------------------------------------------
   Lightbox — :target driven, so exactly one can be open and no script runs.
   Back closes it, which is the right gesture on a phone.
   -------------------------------------------------------------------------- */

.viewer {
	display: none;
}

.viewer:target {
	display: grid;
	place-items: center;
	position: fixed;
	inset: 0;
	z-index: 50;
	padding: clamp(0.75rem, 3vw, 2rem);
	background: var(--scrim);
}

/* Sits behind the frame and fills the rest of the overlay, so a click
   anywhere outside the image dismisses. */
.viewer-dismiss {
	position: absolute;
	inset: 0;
}

.viewer-frame {
	position: relative;
	margin: 0;
	display: flex;
	flex-direction: column;
	gap: var(--sp-2);
	max-width: 100%;
	min-width: 0;
}

.viewer-frame img {
	display: block;
	width: auto;
	height: auto;
	max-width: 100%;
	max-height: calc(100dvh - 10rem);
	object-fit: contain;
	background: var(--raised);
	border: 1px solid var(--scrim-rule);
}

.viewer-frame figcaption {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-2) var(--sp-3);
	font-family: var(--mono);
	font-size: var(--t-micro);
	line-height: 1.4;
	color: var(--on-scrim-dim);
}

.viewer-nav {
	display: flex;
	align-items: center;
	gap: var(--sp-3);
	flex: none;
}

.viewer-nav a {
	text-decoration: none;
	color: var(--on-scrim-dim);
	transition: color 0.15s ease;
}

.viewer-nav a:hover {
	color: var(--on-scrim);
}

.viewer-count {
	font-variant-numeric: tabular-nums;
	color: var(--on-scrim-dim);
}

.viewer-close {
	padding: 0.3rem 0.6rem;
	border: 1px solid var(--scrim-rule);
	color: var(--on-scrim);
}

.viewer-close:hover {
	border-color: var(--on-scrim);
}

/* The accent is a dark blue in the light theme and would disappear against
   the scrim, so focus rings inside the overlay switch to the light ink. */
.viewer :focus-visible {
	outline-color: var(--on-scrim);
}

/* --------------------------------------------------------------------------
   Contact
   -------------------------------------------------------------------------- */

/* The one solid block on the page. Everything else is type on the ground, so
   the single action worth taking is the only thing that carries a fill. */
.mailto {
	display: inline-block;
	align-self: flex-start;
	max-width: 100%;
	padding: 0.75rem 1.1rem;
	font-family: var(--mono);
	font-size: 0.875rem;
	font-weight: 500;
	line-height: 1.2;
	text-decoration: none;
	color: var(--on-accent);
	background: var(--accent);
	border: 1px solid var(--accent);
	overflow-wrap: anywhere;
	transition: background-color 0.15s ease, border-color 0.15s ease;
}

.mailto:hover {
	background: var(--accent-hover);
	border-color: var(--accent-hover);
}

.mailto:focus-visible {
	outline-offset: 3px;
}

/* --------------------------------------------------------------------------
   Colophon
   -------------------------------------------------------------------------- */

.colophon {
	border-top: 1px solid var(--rule);
	padding-block: var(--sp-4) var(--sp-5);
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-1) var(--sp-4);
	font-family: var(--mono);
	font-size: var(--t-micro);
	letter-spacing: 0.05em;
	color: var(--ink-3);
}

@media (min-width: 60rem) {
	.colophon {
		grid-column: 1 / -1;
	}
}
