/* ==========================================================================
   hi_class — https://miguelzuma.github.io/hi_class_public/
   Self-contained stylesheet. No build step, no external dependencies.
   ========================================================================== */

:root {
	color-scheme: dark;

	/* Surfaces */
	--bg:            #07090b;
	--bg-soft:       #0b0f13;
	--surface:       #10161b;
	--surface-hi:    #151d24;
	--border:        #1d262e;
	--border-hi:     #2c3843;

	/* Ink */
	--text:          #d3dbe3;
	--text-dim:      #8b98a6;
	--heading:       #f1f5f9;

	/* Brand — the hi_class green, carried over from the original site */
	--accent:        #39e600;
	--accent-soft:   #6cf03f;
	--accent-deep:   #1f8a00;
	--accent-wash:   rgba(57, 230, 0, 0.10);
	--accent-line:   rgba(57, 230, 0, 0.32);
	/* Links carry a desaturated green: same family as the accent, but far
	   enough from it in saturation that a link never reads as a highlight. */
	--link:          #cdeec4;
	--link-line:     rgba(57, 230, 0, 0.55);

	/* Type */
	--sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
	--mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

	/* Metrics */
	--wrap:  1080px;
	--prose: 730px;
	--nav-h: 56px;
	--radius: 10px;
}

/* ---- Reset / base ------------------------------------------------------ */

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

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
	scroll-padding-top: calc(var(--nav-h) + 16px);
}

body {
	margin: 0;
	background: var(--bg);
	color: var(--text);
	font-family: var(--sans);
	font-size: 16px;
	line-height: 1.65;
	overflow-wrap: break-word;
	-webkit-font-smoothing: antialiased;
}

img, svg, video { max-width: 100%; height: auto; }

/* Visible to screen readers only: for meaning that is otherwise carried by
   colour or shape alone (the main-developer ring in the team list). */
.sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* Green is the highlight colour, so it is not also the link colour: links are
   marked by an underline instead. That keeps the accent meaningful where it is
   used deliberately (counts, code, labels), and gives links an affordance that
   survives on touch screens and for readers who cannot separate the hues.
   Navigation, buttons and title links opt out below - their container already
   says they are clickable. */
a {
	color: var(--link);
	text-decoration: underline;
	text-decoration-color: var(--link-line);
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
}
a:hover {
	color: var(--accent);
	text-decoration-color: currentColor;
}

/* Links that are their own affordance: a button, a nav item, a card, or a
   title standing alone on its line. These stay undecorated and reveal the
   accent on hover, the pattern the reference and publication lists use. */
.brand,
.nav-links a,
.nav-gh,
.btn,
a.badge,
a.res,
a.skip-link,
.member a,
.refs a.ref-title,
a.pub-title {
	text-decoration: none;
}

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

code, .mono { font-family: var(--mono); }

code {
	font-size: 0.92em;
	color: var(--accent-soft);
	background: var(--accent-wash);
	padding: 0.08em 0.34em;
	border-radius: 4px;
	white-space: nowrap;
}

h1, h2, h3, h4 {
	color: var(--heading);
	line-height: 1.2;
	letter-spacing: -0.015em;
	margin: 0;
	text-wrap: balance;
}

p { margin: 0 0 1.05em; }
p:last-child { margin-bottom: 0; }

.skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	background: var(--accent);
	color: #06210a;
	padding: 0.6em 1em;
	font-weight: 600;
	z-index: 100;
}
.skip-link:focus { left: 0; }

/* ---- Layout ------------------------------------------------------------ */

.wrap {
	width: 100%;
	max-width: var(--wrap);
	margin: 0 auto;
	padding: 0 24px;
}

.prose { max-width: var(--prose); }

section[id],
h3[id] { scroll-margin-top: calc(var(--nav-h) + 16px); }

.band {
	padding: 68px 0;
	border-top: 1px solid var(--border);
}

.band--soft { background: var(--bg-soft); }

.eyebrow {
	font-family: var(--mono);
	font-size: 12px;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--accent);
	margin: 0 0 10px;
}

/* The h1 belongs to the hero on the front page, but a subpage (news.html) has
   no hero and its title is the section heading -- so both carry the same size
   here, and .hero h1 overrides it further down. */
.band > .wrap > h2,
.band h1,
.band h2 {
	font-size: clamp(24px, 3.4vw, 32px);
	margin: 0 0 20px;
}

.lede {
	font-size: 17px;
	color: var(--text);
}

/* ---- Navigation -------------------------------------------------------- */

.nav {
	position: sticky;
	top: 0;
	z-index: 50;
	height: var(--nav-h);
	background: rgba(7, 9, 11, 0.82);
	backdrop-filter: blur(10px);
	-webkit-backdrop-filter: blur(10px);
	border-bottom: 1px solid var(--border);
}

.nav-inner {
	height: 100%;
	display: flex;
	align-items: center;
	gap: 20px;
}

.brand {
	font-family: var(--mono);
	font-size: 16px;
	font-weight: 700;
	color: var(--accent);
	white-space: nowrap;
	flex: none;
}
.brand:hover { text-decoration: none; color: var(--accent-soft); }

.nav-links {
	display: flex;
	align-items: center;
	gap: 4px;
	margin-left: auto;
	overflow-x: auto;
	scrollbar-width: none;
	-ms-overflow-style: none;
}
.nav-links::-webkit-scrollbar { display: none; }

.nav-links a {
	color: var(--text-dim);
	font-size: 14px;
	padding: 6px 10px;
	border-radius: 6px;
	white-space: nowrap;
	transition: color 0.15s, background 0.15s;
}

.nav-links a:hover {
	color: var(--heading);
	background: var(--surface-hi);
	text-decoration: none;
}

.nav-links a.is-active {
	color: var(--accent);
	background: var(--accent-wash);
}

/* "Publications" on wide screens, "Papers" once space is tight */
.nav-short { display: none; }

.nav-gh {
	flex: none;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	color: var(--text-dim);
	font-size: 14px;
	padding: 6px 10px;
	border: 1px solid var(--border-hi);
	border-radius: 6px;
	white-space: nowrap;
}
.nav-gh:hover { color: var(--heading); border-color: var(--accent-line); text-decoration: none; }
.nav-gh svg { width: 16px; height: 16px; fill: currentColor; }

/* ---- Hero -------------------------------------------------------------- */

.hero {
	position: relative;
	text-align: center;
	padding: 56px 0 64px;
	overflow: hidden;
}

/* Soft green bloom behind the logo, echoing the original glow */
.hero::before {
	content: "";
	position: absolute;
	top: -10%;
	left: 50%;
	width: min(780px, 120%);
	aspect-ratio: 1;
	transform: translateX(-50%);
	background: radial-gradient(circle, var(--accent-wash) 0%, transparent 62%);
	pointer-events: none;
	z-index: 0;
}

/* position only, no z-index: a stacking context here would isolate the logo's
   mix-blend-mode from the glow painted by .hero::before. Tree order already
   paints this after the pseudo-element. */
.hero > .wrap { position: relative; }

/* The rain. Painted by logo/rain.js over the whole hero, behind everything in
   .wrap; .hero's overflow:hidden clips it. It stays invisible until the script
   has a first frame up, so a failed build shows nothing rather than a flash of
   empty box. The script clears the rain behind the wordmark and washes it out
   over the lower hero, so the heading and buttons keep their contrast. */
.hero-rain {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	z-index: 0;
	pointer-events: none;
	opacity: 0;
	transition: opacity 0.7s ease;
}

.hero-rain.is-live { opacity: 1; }

/* The wordmark, lifted from the original logo (frame 2, where the caret is
   hidden) and alpha-keyed, so it needs no blend mode and can sit over moving
   rain. The caret is a real element again, as it was a GIF frame before. */
.hero-mark {
	position: relative;
	display: block;
	width: min(360px, 78vw);
	margin: 0 auto 26px;
}

.hero-wordmark {
	display: block;
	width: 100%;
	height: auto;
	filter: drop-shadow(0 0 9px rgba(57, 230, 0, 0.42));
}

/* Percentages, not pixels: the caret's slot was measured in the source artwork
   (x 92.54-98.38%, y 5.84-94.16%) so it tracks the wordmark at any width. */
.hero-caret {
	position: absolute;
	left: 92.54%;
	top: 5.84%;
	width: 5.84%;
	height: 88.32%;
	background: #00cc33;
	box-shadow: 0 0 12px rgba(57, 230, 0, 0.7);
	animation: caret-blink 1.6s steps(1) infinite;
}

/* 0.8s on, 0.8s off - the cadence of the two GIF frames it replaces. */
@keyframes caret-blink {
	0%, 50%       { opacity: 1; }
	50.01%, 100%  { opacity: 0; }
}

.hero-logo {
	display: block;
	width: min(360px, 78vw);
	margin: 0 auto 26px;
	/* The logo is green-on-black; screen blending drops its black field so it
	   sits in the hero glow instead of on a visible dark square. */
	mix-blend-mode: screen;
}

.hero h1 {
	font-family: var(--mono);
	font-size: clamp(20px, 3.2vw, 29px);
	font-weight: 700;
	color: var(--accent);
	letter-spacing: -0.01em;
	margin: 0 auto 14px;
	max-width: 30ch;
}

.hero-tagline {
	font-size: clamp(15px, 2vw, 18px);
	color: var(--text-dim);
	max-width: 46ch;
	margin: 0 auto 30px;
}

.hero-actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 12px;
	margin-bottom: 26px;
}

.btn {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 11px 20px;
	border-radius: 8px;
	font-size: 15px;
	font-weight: 600;
	border: 1px solid var(--border-hi);
	color: var(--heading);
	transition: border-color 0.15s, background 0.15s, transform 0.15s;
}
.btn:hover { text-decoration: none; border-color: var(--accent-line); background: var(--surface-hi); }
.btn svg { width: 17px; height: 17px; fill: currentColor; flex: none; }

.btn--primary {
	background: var(--accent);
	border-color: var(--accent);
	color: #062600;
}
.btn--primary:hover {
	background: var(--accent-soft);
	border-color: var(--accent-soft);
	color: #062600;
}

.badges {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: center;
	gap: 8px 10px;
	font-family: var(--mono);
	font-size: 12px;
	color: var(--text-dim);
}

.badge {
	border: 1px solid var(--border);
	border-radius: 999px;
	padding: 3px 11px;
	background: var(--surface);
}
a.badge:hover { border-color: var(--accent-line); color: var(--accent); text-decoration: none; }

/* Paper count in the hero: the one badge that carries a number */
.badge--count {
	border-color: var(--accent-line);
	color: var(--text);
	background: var(--accent-wash);
}
.badge--count b { color: var(--accent); font-weight: 700; }

/* Headline count above the publication list */
.pub-headline {
	display: flex;
	align-items: baseline;
	gap: 12px;
	margin: 0 0 14px;
	flex-wrap: wrap;
}

.pub-headline b {
	font-family: var(--mono);
	font-size: clamp(38px, 6vw, 54px);
	font-weight: 700;
	color: var(--accent);
	line-height: 1;
}

.pub-headline span {
	font-size: 17px;
	color: var(--text-dim);
}

/* ---- Cards ------------------------------------------------------------- */

.cards {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(228px, 1fr));
	gap: 16px;
	margin-top: 28px;
}

.card {
	background: var(--surface);
	border: 1px solid var(--border);
	border-radius: var(--radius);
	padding: 20px;
}

.card h3 {
	font-size: 15px;
	margin: 0 0 7px;
	color: var(--heading);
}

.card p {
	font-size: 14px;
	color: var(--text-dim);
	margin: 0;
	line-height: 1.55;
}

.card--link { transition: border-color 0.15s, background 0.15s; display: block; }
.card--link:hover { border-color: var(--accent-line); background: var(--surface-hi); text-decoration: none; }
.card--link:hover h3 { color: var(--accent); }

/* Statement of the key numeric result */
.stat {
	font-family: var(--mono);
	font-size: 26px;
	font-weight: 700;
	color: var(--accent);
	display: block;
	line-height: 1.1;
	margin-bottom: 4px;
}

/* ---- Feature block: prose beside a config snippet ---------------------- */

.feature {
	display: grid;
	grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
	gap: 28px;
	align-items: start;
	margin-top: 44px;
	padding-top: 34px;
	border-top: 1px solid var(--border);
}

.feature-body p {
	font-size: 15.5px;
	color: var(--text);
}

/* Full-width variant: prose above, snippet below, for longer listings */
.feature--stack { grid-template-columns: 1fr; }
.feature--stack .feature-body { max-width: var(--prose); }

.feature-title {
	font-size: clamp(19px, 2.4vw, 23px);
	margin: 0 0 14px;
}

.feature-body em { color: var(--heading); font-style: italic; }

/* The two input styles sit in their own boxes: they are alternatives, not a
   sequence, and one box with a comment between them read as a single file. */
.snippet-pair {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 18px;
	align-content: start;
	min-width: 0;
	margin-top: 28px;
}

.snippet-item { min-width: 0; }

.snippet-label {
	font-family: var(--mono);
	font-size: 11.5px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--text-dim);
	margin: 0 0 8px;
}

/* ---- Interoperability list ----------------------------------------------
   Each entry states how well it is supported, because "can be made to work"
   and "we support this" are different promises. */
.interop {
	list-style: none;
	margin: 18px 0 0;
	padding: 0;
	max-width: var(--prose);
}

.interop li {
	padding: 14px 0;
	border-top: 1px solid var(--border);
}

.interop-name {
	font-weight: 600;
	color: var(--heading);
	margin-right: 10px;
}

.interop-note {
	display: block;
	color: var(--text-dim);
	font-size: 14.5px;
	margin-top: 5px;
}

.tag {
	font-family: var(--mono);
	font-size: 11px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	padding: 2px 8px;
	border-radius: 999px;
	border: 1px solid var(--border-hi);
	color: var(--text-dim);
	white-space: nowrap;
}

.tag--yes { color: var(--accent); border-color: var(--accent-line); background: var(--accent-wash); }
.tag--pub { color: var(--link); border-color: var(--link-line); }

/* ---- Master diagram: the two routes to a prediction ---------------------- */

.diagram { margin: 44px 0 0; }

/* Below ~640px the labels would be unreadable if scaled down, so the diagram
   scrolls sideways inside its own box rather than shrinking the whole page. */
.diagram-scroll { overflow-x: auto; }

.dgm {
	display: block;
	width: 100%;
	min-width: 640px;
	height: auto;
}

.dgm-box {
	fill: var(--surface);
	stroke: var(--border-hi);
	stroke-width: 1;
}

.dgm-stage text {
	font-family: var(--mono);
	font-size: 12px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	fill: var(--accent);
}

.dgm-math text { font-size: 17px; fill: var(--heading); }
.dgm-sym { font-style: italic; font-family: Georgia, "Times New Roman", serif; }

.dgm-note { font-size: 12.5px; fill: var(--text-dim); font-family: var(--sans); }
.dgm-note text { font-size: 12.5px; fill: var(--text-dim); }

.dgm-flow line { stroke: var(--text-dim); stroke-width: 1.5; }
.dgm-head { fill: var(--text-dim); }

/* The two approaches are told apart by line style as well as colour, the same
   rule the links follow: never let hue be the only signal. */
.dgm-path text { font-family: var(--mono); font-size: 12.5px; }
.dgm-path--cov line { stroke: var(--accent); stroke-width: 2; }
.dgm-path--cov text { fill: var(--accent); }
.dgm-head-cov { fill: var(--accent); }

.dgm-path--eft line { stroke: var(--link); stroke-width: 2; stroke-dasharray: 7 5; }
.dgm-path--eft text { fill: var(--link); }
.dgm-head-eft { fill: var(--link); }

/* Config snippet — real hi_class.ini syntax, so it must never wrap silently */
.snippet {
	margin: 0;
	background: #05070a;
	border: 1px solid var(--border-hi);
	border-left: 2px solid var(--accent-line);
	border-radius: var(--radius);
	padding: 18px 20px;
	overflow-x: auto;
	font-family: var(--mono);
	font-size: 13px;
	line-height: 1.65;
	color: var(--text);
	tab-size: 2;
}

.snippet code {
	background: none;
	padding: 0;
	border-radius: 0;
	color: inherit;
	font-size: inherit;
	white-space: pre;
}

.snippet .c { color: #6b7a88; }              /* comments */
.snippet .k { color: var(--accent); }        /* parameter names */

@media (max-width: 820px) {
	.feature { grid-template-columns: 1fr; gap: 22px; }
}

@media (max-width: 620px) {
	.snippet-pair { grid-template-columns: 1fr; }
}

/* Shrink the snippet just enough that the longest config line fits a phone
   without sideways scrolling. It still scrolls if a longer line is ever added. */
@media (max-width: 480px) {
	.snippet { font-size: 11.5px; padding: 15px 16px; }
}

@media (max-width: 380px) {
	.snippet { font-size: 11px; padding: 14px 12px; }
}

/* ---- Figures ----------------------------------------------------------- */

figure {
	margin: 30px 0 0;
	max-width: 100%;
}

figure img {
	display: block;
	margin: 0 auto;
	border-radius: var(--radius);
}

figcaption {
	margin-top: 12px;
	font-size: 13.5px;
	line-height: 1.5;
	color: var(--text-dim);
	max-width: var(--prose);
}

/* ---- Reference lists (papers to cite, key results) ---------------------- */

.refs {
	list-style: none;
	margin: 22px 0 0;
	padding: 0;
	display: grid;
	gap: 14px;
	max-width: var(--prose);
}

.refs li {
	border-left: 2px solid var(--border-hi);
	padding-left: 16px;
}

/* The two method papers are not just references, they are the ones to cite when
   you use the code — the "How to cite" block below points back here. So they get
   the accent on the rule and a wash behind them, while the results lists keep the
   neutral rule: the difference in weight is the difference in what they are for. */
.refs--cite li {
	border-left-color: var(--accent);
	border-left-width: 3px;
	background: var(--accent-wash);
	padding: 10px 14px 10px 15px;
	border-radius: 0 var(--radius) var(--radius) 0;
}

.refs .ref-title {
	display: block;
	color: var(--heading);
	font-weight: 600;
	font-size: 15px;
	line-height: 1.4;
}
.refs a.ref-title:hover { color: var(--accent); text-decoration: none; }

.refs .ref-meta {
	display: block;
	font-size: 13.5px;
	color: var(--text-dim);
	margin-top: 3px;
}

.refs .ref-meta .mono { color: var(--accent); }

/* ---- Qualities: the three claims of "The Code", each argued in prose ---- */

.qualities {
	margin: 30px 0 0;
	padding: 0;
	display: grid;
	gap: 22px;
	max-width: 760px;
}

.qualities > div {
	border-left: 2px solid var(--border-hi);
	padding-left: 18px;
	transition: border-left-color 0.15s;
}

.qualities > div:hover { border-left-color: var(--accent-line); }

.qualities dt {
	font-family: var(--mono);
	font-size: 12px;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--accent);
	margin-bottom: 7px;
}

.qualities dd {
	margin: 0;
	font-size: 15.5px;
	color: var(--text);
	line-height: 1.62;
}

/* Figures for the measured numbers, so they read at a glance in running text */
.num {
	font-family: var(--mono);
	font-weight: 700;
	color: var(--accent);
	white-space: nowrap;
}

/* ---- Resources --------------------------------------------------------- */

.res-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
	gap: 14px;
	margin-top: 26px;
}

.res {
	display: block;
	background: var(--surface);
	border: 1px solid var(--border);
	border-radius: var(--radius);
	padding: 17px 19px;
	transition: border-color 0.15s, background 0.15s;
}
.res:hover { border-color: var(--accent-line); background: var(--surface-hi); text-decoration: none; }

.res-name {
	display: block;
	color: var(--heading);
	font-weight: 600;
	font-size: 15px;
	margin-bottom: 4px;
}
.res:hover .res-name { color: var(--accent); }

.res-desc {
	display: block;
	font-size: 13.5px;
	color: var(--text-dim);
	line-height: 1.5;
}

.res-desc a { color: var(--link); }

/* ---- Team -------------------------------------------------------------- */

.team {
	display: grid;
	/* Capped width so the current team lands as a balanced 4 x 2 rather than 6 + 2 */
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	max-width: 700px;
	gap: 26px 18px;
	margin-top: 28px;
	list-style: none;
	padding: 0;
}

.member { text-align: center; }

.member img {
	width: 92px;
	height: 92px;
	object-fit: cover;
	border-radius: 50%;
	border: 1px solid var(--border-hi);
	background: var(--surface);
	margin: 0 auto 10px;
	display: block;
	filter: grayscale(0.25);
	transition: filter 0.2s, border-color 0.2s;
}

.member a { display: block; color: var(--heading); font-size: 14.5px; font-weight: 600; }
.member a:hover { color: var(--accent); text-decoration: none; }
.member a:hover img { filter: grayscale(0); border-color: var(--accent-line); }

/* The two main developers wear the brand green as a ring. The border sits
   inside the 92px box (box-sizing: border-box), so the portraits stay on the
   same grid as the rest; the wash is a box-shadow, which follows the circle.
   Colour is never the only carrier: the key below the list says what the ring
   means, and each link repeats it for screen readers. */
.member--lead img {
	border: 2px solid var(--accent);
	box-shadow: 0 0 0 3px var(--accent-wash);
	filter: grayscale(0);
}

/* Keep the ring at full strength on hover, where .member a:hover img would
   otherwise fade the border to --accent-line. */
.member--lead a:hover img { border-color: var(--accent); }

.team-note {
	margin: 24px 0 0;
	color: var(--text-dim);
	font-size: 14px;
}

/* A miniature of the ring, so the key shows what it describes. */
.lead-key {
	display: inline-block;
	width: 10px;
	height: 10px;
	border: 2px solid var(--accent);
	border-radius: 50%;
	box-shadow: 0 0 0 2px var(--accent-wash);
	margin-right: 10px;
	vertical-align: 1px;
}

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

.contact-mail {
	font-family: var(--mono);
	font-size: 14.5px;
	color: var(--accent);
	background: var(--surface);
	border: 1px solid var(--border);
	border-radius: 6px;
	padding: 3px 9px;
	display: inline;
	/* No nowrap: the address stays on one line wherever it fits, and wraps at its
	   spaces on narrow phones instead of pushing the page sideways. */
	overflow-wrap: break-word;
}

/* ---- Publications ------------------------------------------------------ */

.pub-toolbar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 12px;
	margin: 24px 0 8px;
}

.pub-search {
	flex: 1 1 300px;
	position: relative;
	display: flex;
	align-items: center;
}

.pub-search svg {
	position: absolute;
	left: 13px;
	width: 15px;
	height: 15px;
	fill: var(--text-dim);
	pointer-events: none;
}

#pub-filter {
	width: 100%;
	font: inherit;
	font-size: 15px;
	color: var(--text);
	background: var(--surface);
	border: 1px solid var(--border-hi);
	border-radius: 8px;
	padding: 10px 14px 10px 36px;
}
#pub-filter::placeholder { color: var(--text-dim); }
#pub-filter:focus {
	outline: none;
	border-color: var(--accent-line);
	box-shadow: 0 0 0 3px var(--accent-wash);
}

.pub-count {
	font-family: var(--mono);
	font-size: 13px;
	color: var(--text-dim);
	flex: none;
}
.pub-count b { color: var(--accent); font-weight: 700; }

.pub-year { margin-top: 34px; }

.pub-year-head {
	font-family: var(--mono);
	font-size: 15px;
	color: var(--accent);
	padding-bottom: 8px;
	margin-bottom: 4px;
	border-bottom: 1px solid var(--border);
	display: flex;
	align-items: baseline;
	gap: 10px;
}

.pub-year-count {
	font-size: 12px;
	color: var(--text-dim);
	font-weight: 400;
}

.pub-list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.pub {
	padding: 13px 0 13px 15px;
	border-left: 2px solid transparent;
	border-bottom: 1px solid var(--border);
	transition: border-left-color 0.15s, background 0.15s;
}
.pub:last-child { border-bottom: none; }
.pub:hover { border-left-color: var(--accent); background: var(--surface); }

.pub-title {
	color: var(--heading);
	font-weight: 600;
	font-size: 15px;
	line-height: 1.42;
	display: block;
}
.pub-title:hover { color: var(--accent); text-decoration: none; }

.pub-meta {
	margin: 4px 0 0;
	font-size: 13.5px;
	color: var(--text-dim);
	line-height: 1.5;
}

.pub-authors { margin-right: 10px; }

.pub-ref,
.pub-arxiv,
.pub-extra {
	font-family: var(--mono);
	font-size: 12.5px;
	white-space: nowrap;
}

/* The primary reference is the journal one where it exists, the arXiv number
   otherwise, so .pub-ref always carries the accent. The arXiv number then
   trails behind it, dimmed: still there to cite and still matched by the
   filter, without competing with the journal line. */
.pub-ref { color: var(--accent-deep); }
.pub:hover .pub-ref { color: var(--accent); }

.pub-arxiv { margin-left: 8px; color: var(--text-dim); }

.pub-extra { margin-left: 8px; }

.pub-empty {
	display: none;
	margin-top: 30px;
	color: var(--text-dim);
	font-size: 15px;
}
.pub-empty.is-shown { display: block; }

/* Hidden by the client-side filter */
[hidden] { display: none !important; }

/* ---- Artwork ----------------------------------------------------------- */

.artwork {
	margin: 0;
	padding: 60px 0 0;
	text-align: center;
}

.artwork img {
	border-radius: var(--radius);
	margin: 0 auto;
}

.artwork figcaption {
	margin: 12px auto 0;
	text-align: center;
	max-width: 56ch;
	font-style: italic;
}

/* ---- Footer ------------------------------------------------------------ */

.footer {
	border-top: 1px solid var(--border);
	margin-top: 60px;
	padding: 34px 0 44px;
	font-size: 13.5px;
	color: var(--text-dim);
}

.footer-inner {
	display: flex;
	flex-wrap: wrap;
	gap: 12px 26px;
	align-items: center;
	justify-content: space-between;
}

.footer p { margin: 0; }

/* Logo credit: its own line below the footer links, quiet but legible */
.footer-credit {
	flex-basis: 100%;
	margin-top: 6px;
	padding-top: 14px;
	border-top: 1px solid var(--border);
	font-size: 12.5px;
	color: #6f7c8a;
}

.footer-credit code {
	color: #8b98a6;
	background: none;
	padding: 0;
	font-size: 12.5px;
}

/* ---- Small screens ----------------------------------------------------- */

@media (max-width: 760px) {
	.wrap { padding: 0 18px; }
	.band { padding: 48px 0; }
	.hero { padding: 36px 0 48px; }
	/* Phones: the nav stacks into a brand row and a link row that wraps freely,
	   so every section stays reachable and adding a new one just flows onto the
	   next line instead of scrolling out of sight. --nav-h is re-declared to
	   match the taller bar, keeping anchor scroll offsets correct. */
	:root { --nav-h: 84px; }

	.nav { height: auto; }

	.nav-inner {
		flex-direction: column;
		align-items: center;
		gap: 3px;
		padding: 7px 0;
	}

	.nav-links {
		margin-left: 0;
		justify-content: center;
		flex-wrap: wrap;
		overflow-x: visible;
		gap: 1px 0;
	}

	.nav-links a { padding: 5px 7px; font-size: 13px; }
	.brand { font-size: 14px; }

	/* The GitHub button duplicates the hero CTA; drop it when space is tight */
	.nav-gh { display: none; }

	/* Shorter label so the row wraps later, but every section stays listed */
	.nav-long { display: none; }
	.nav-short { display: inline; }
	.team { grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 18px 12px; }
	.member img { width: 74px; height: 74px; }
	.artwork { padding-top: 40px; }
}

@media (max-width: 420px) {
	.hero-actions .btn { width: 100%; justify-content: center; }
}

/* Narrow phones: claw back enough width that all four nav items still fit. */
/* Narrow phones: tighten the links so the row wraps as late as possible.
   The column gap on .nav-inner is deliberately left alone — it now separates
   the brand row from the link row, not two items in a row. */
@media (max-width: 400px) {
	.nav-links a { padding: 5px 6px; font-size: 12.5px; }
	.brand { font-size: 13px; }
}

@media (max-width: 360px) {
	.wrap { padding: 0 12px; }
	.nav-links a { padding: 5px 5px; font-size: 12px; }
	.brand { font-size: 12.5px; }
}

/* ---- News --------------------------------------------------------------
   Dated one-liners at the top of the page. The date sits in its own column so
   the list scans as a timeline rather than as prose. Same structure as the
   news lists on miguelzuma.github.io and the GLoW ERC site.

   Two lists use this: the newest few on the front page, and the whole archive
   on news.html. */

.news {
	list-style: none;
	padding: 0;
	margin: 24px 0 0;
	border-top: 1px solid var(--border);
}

.news li {
	display: flex;
	gap: 14px;
	padding: 13px 0;
	border-bottom: 1px solid var(--border);
}

/* Narrow enough to read as a margin note rather than a column of its own.
   Tabular figures keep the dates stacked even at an abbreviated width. */
.news-date {
	flex: 0 0 68px;
	color: var(--text-dim);
	font-size: 13.5px;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
	padding-top: 3px;
}

.news-body { margin: 0; max-width: var(--prose); }
.news-links { color: var(--text-dim); font-size: 14.5px; }

/* Link out of the list: to the archive from the front page, back to the front
   page from the archive. Sized with .news-links rather than with body text,
   because it is an exit from the section and not another item in it. */
.news-more {
	margin: 16px 0 0;
	font-size: 14.5px;
}

/* Only items inside the freshness window carry this, and the script removes it
   once they age out - so the motion always means something. The other two sites
   cycle between two accent hues; this one has a single green, so the pulse runs
   on luminance instead, accent -> accent-deep with a halo. Cycling to a
   borrowed second hue here would read as a different website.
   Readers who ask for reduced motion get a still flag: the blanket rule in the
   prefers-reduced-motion block below already stops this animation. */
.news-flag {
	display: inline-block;
	font-size: 11px;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	font-weight: 600;
	padding: 2px 7px;
	border-radius: 4px;
	margin-right: 8px;
	vertical-align: 1px;
	color: var(--bg);
	background: var(--accent);
	animation: news-pulse 4.5s ease-in-out infinite;
}

@keyframes news-pulse {
	0%, 100% {
		background: var(--accent);
		box-shadow: 0 0 0 0 rgba(57, 230, 0, 0.5);
	}
	50% {
		background: var(--accent-deep);
		box-shadow: 0 0 10px 2px rgba(57, 230, 0, 0.4);
	}
}

@media (max-width: 620px) {
	.news li { flex-direction: column; gap: 4px; }
	.news-date { flex-basis: auto; padding-top: 0; }
}

/* ---- Animations: the two dark-energy clips ------------------------------ */

/* The renders are 1560x780 on #07090b, the same colour as --bg, so the video
   edge is invisible in the page and the figure needs no frame of its own. */
.anim { margin: 28px 0 0; }

.anim video,
.anim .anim-poster {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--radius);
	background: var(--bg);
}

/* The poster <img> is a fallback for reduced motion only; the <video> carries
   its own poster attribute for the loading state. */
.anim .anim-poster { display: none; }

.anim figcaption {
	margin-top: 10px;
	color: var(--text-dim);
	font-size: 14.5px;
	line-height: 1.6;
	max-width: var(--prose);
}
.anim figcaption strong { color: var(--text); font-weight: 600; }

/* ---- Motion / print ---------------------------------------------------- */

@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;
	}
	/* An autoplaying <video> ignores the rules above - it is not a CSS
	   animation - so the element itself has to go, and the still takes over. */
	.anim video { display: none; }
	.anim .anim-poster { display: block; }
	/* Same problem again: a <canvas> driven by requestAnimationFrame is not a
	   CSS animation either. logo/rain.js checks this query itself and holds a
	   single painted frame; all this rule does is stop the caret mid-blink so
	   it rests solid rather than wherever the 0.01ms above left it. */
	.hero-caret { animation: none; opacity: 1; }
}

@media print {
	.nav, .hero::before, .hero-rain, .hero-caret, .pub-toolbar { display: none; }
	body { background: #fff; color: #000; }
	a { color: #000; }
}
