/* ═══════════════════════════════════════════════════════════════════
   Site enhancements — responsive behavior + motion polish.
   Loaded after the Nocturne design-system stylesheet on every page.
   Everything here reads from the DS tokens; no new colors invented.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Global feel ─────────────────────────────────────────────────── */
html {
	scroll-behavior: smooth;
	scroll-padding-top: 76px; /* keep anchors clear of the sticky nav */
	scrollbar-color: var(--color-neutral-800) var(--color-bg);
}
html, body { overflow-x: clip; }
img { max-width: 100%; }
code { overflow-wrap: anywhere; }
h1, h2, h3 { text-wrap: balance; }
p { text-wrap: pretty; }

a, button {
	-webkit-tap-highlight-color: transparent;
	touch-action: manipulation;
	transition: color .18s ease, background-color .18s ease,
		border-color .18s ease, transform .18s ease, opacity .18s ease;
}

/* Themed scrollbar (WebKit) */
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--color-bg); }
::-webkit-scrollbar-thumb {
	background: var(--color-neutral-800);
	border-radius: 8px;
	border: 3px solid var(--color-bg);
}
::-webkit-scrollbar-thumb:hover { background: var(--color-neutral-700); }

/* Page titles pick up a whisper of the accent at the tail */
h1 {
	background: linear-gradient(100deg, var(--color-text) 55%, var(--color-accent-300) 115%);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
}

/* ── Accessibility: skip link + visible focus ────────────────────── */
.skip-link {
	position: absolute;
	left: 12px;
	top: -60px;
	z-index: 100;
	padding: 10px 18px;
	border-radius: 0 0 var(--radius-md) var(--radius-md);
	background: var(--color-accent-900);
	color: var(--color-accent-100);
	border: 1px solid var(--color-accent-600);
	font-size: 14px;
	text-decoration: none;
	transition: top .18s ease;
}
.skip-link:focus { top: 0; }

:focus-visible {
	outline: 2px solid var(--color-accent-400);
	outline-offset: 3px;
	border-radius: 4px;
}
/* Mouse users don't get the ring; keyboard users always do. */
:focus:not(:focus-visible) { outline: none; }

::selection {
	background: color-mix(in srgb, var(--color-accent) 40%, transparent);
	color: var(--color-text);
}

/* ── Data loading bar — a thin accent sweep until site data resolves.
      Removed by site-enhancements.js; harmless if JS never runs. ─── */
.data-loading-bar {
	position: fixed;
	inset: 0 auto auto 0;
	height: 2px;
	width: 100%;
	z-index: 200;
	background: linear-gradient(90deg,
		transparent, var(--color-accent), var(--color-accent-300), transparent);
	background-size: 40% 100%;
	background-repeat: no-repeat;
	animation: loadsweep 1.1s ease-in-out infinite;
	transition: opacity .35s ease;
	pointer-events: none;
}
.data-loading-bar.done { opacity: 0; }
@keyframes loadsweep {
	0%   { background-position: -40% 0; }
	100% { background-position: 140% 0; }
}

/* ── Entrance motion (backwards fill only, so it never fights
      inline hover transforms after it finishes) ────────────────── */
@media (prefers-reduced-motion: no-preference) {
	@keyframes riseIn {
		from { opacity: 0; transform: translateY(14px); }
		to   { opacity: 1; transform: none; }
	}
	@keyframes cardIn {
		from { opacity: 0; transform: translateY(12px); }
		to   { opacity: 1; transform: none; }
	}
	/* Entrance animations use `backwards` fill, which holds the element at
	   opacity 0 until the animation runs. That is only safe where frames
	   actually tick — site-enhancements.js sets .anim-ready once it has
	   confirmed the document timeline is advancing. Without it (JS off,
	   non-animating renderer, crawler) content simply renders visible. */
	.anim-ready header,
	.anim-ready section,
	.anim-ready footer {
		animation: riseIn .65s cubic-bezier(.22, .7, .3, 1) backwards;
	}
	.anim-ready section:nth-of-type(1) { animation-delay: .06s; }
	.anim-ready section:nth-of-type(2) { animation-delay: .12s; }
	.anim-ready section:nth-of-type(3) { animation-delay: .18s; }
	.anim-ready section:nth-of-type(4) { animation-delay: .24s; }
	.anim-ready footer { animation-delay: .3s; }

	/* Scroll-triggered reveal for content below the fold. Gated on the
	   .has-reveal class that site-enhancements.js sets — without JS the
	   content is simply visible, never stuck hidden. */
	.has-reveal [data-reveal]:not(.revealed) {
		opacity: 0;
		transform: translateY(18px);
	}
	.has-reveal [data-reveal] {
		transition: opacity .6s cubic-bezier(.22, .7, .3, 1),
			transform .6s cubic-bezier(.22, .7, .3, 1);
	}
	.has-reveal [data-reveal].revealed {
		opacity: 1;
		transform: none;
	}
	/* Sections that reveal on scroll skip the load-time animation. */
	.has-reveal section[data-reveal] { animation: none; }

	.anim-ready .stagger > * { animation: cardIn .5s cubic-bezier(.22, .7, .3, 1) .1s backwards; }
	.anim-ready .stagger > *:nth-child(1) { animation-delay: .10s; }
	.anim-ready .stagger > *:nth-child(2) { animation-delay: .15s; }
	.anim-ready .stagger > *:nth-child(3) { animation-delay: .20s; }
	.anim-ready .stagger > *:nth-child(4) { animation-delay: .25s; }
	.anim-ready .stagger > *:nth-child(5) { animation-delay: .30s; }
	.anim-ready .stagger > *:nth-child(6) { animation-delay: .35s; }
	.anim-ready .stagger > *:nth-child(7) { animation-delay: .40s; }
	.anim-ready .stagger > *:nth-child(8) { animation-delay: .45s; }
	.anim-ready .stagger > *:nth-child(n+9) { animation-delay: .5s; }
}

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

/* ── Navigation: one row that scrolls on narrow screens ─────────── */
@media (max-width: 920px) {
	nav { gap: 14px !important; padding: 12px 16px !important; }
	nav > div {
		flex-wrap: nowrap !important;
		overflow-x: auto;
		max-width: 100%;
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;
		-webkit-mask-image: linear-gradient(90deg, transparent, #000 14px, #000 calc(100% - 22px), transparent);
		mask-image: linear-gradient(90deg, transparent, #000 14px, #000 calc(100% - 22px), transparent);
	}
	nav > div::-webkit-scrollbar { display: none; }
	nav > div a {
		white-space: nowrap;
		flex: 0 0 auto;
		padding: 8px 12px !important;
	}
}

/* ── Tablet and below ────────────────────────────────────────────── */
@media (max-width: 760px) {
	/* Home about photo: don't let the square crop eat the viewport */
	#about img {
		aspect-ratio: 4 / 3 !important;
		max-height: 420px;
	}
	/* Timeline notes: drop the desktop hanging indent */
	#timeline p { margin-left: 0 !important; }
	/* Big framed cards (featured publication, teaching thesis) */
	.feature-card { padding: 20px 18px !important; }
}

/* ── Phones ──────────────────────────────────────────────────────── */
@media (max-width: 480px) {
	body h1 { font-size: clamp(30px, 9.5vw, 38px) !important; }
	body section, body header { padding-left: 16px !important; padding-right: 16px !important; }
	body footer > div { padding-left: 16px !important; padding-right: 16px !important; }
	/* Filter pills & action buttons: comfortable touch targets */
	section button { min-height: 34px; }
}

/* ── Print: academics print publication lists and CVs ────────────── */
@media print {
	nav, .skip-link, .data-loading-bar, footer a[href*="admin"] { display: none !important; }
	html, body { background: #fff !important; color: #000 !important; }
	body * {
		background: transparent !important;
		color: #000 !important;
		box-shadow: none !important;
		text-shadow: none !important;
	}
	h1 {
		-webkit-text-fill-color: #000 !important;
		background: none !important;
	}
	header, section, footer, article, [data-reveal] {
		animation: none !important;
		opacity: 1 !important;
		transform: none !important;
		page-break-inside: avoid;
	}
	article, .card { border: 1px solid #bbb !important; }
	/* Surface link targets on paper */
	a[href^="http"]::after {
		content: " (" attr(href) ")";
		font-size: 10px;
		word-break: break-all;
	}
	a[href^="#"]::after, a[href$=".html"]::after { content: ""; }
	svg[style*="position:absolute"] { display: none !important; }
}
