/* Self-hosted type (SIL Open Font License): Inter Tight and JetBrains Mono, Latin subsets */
@font-face { font-family: "Inter Tight"; font-style: normal; font-weight: 500 600; font-display: swap; src: url("fonts/inter-tight.woff2") format("woff2"); }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400; font-display: swap; src: url("fonts/jetbrains-mono-400.woff2") format("woff2"); }

:root {
  --bg: #ffffff;
  --fg: #111111;
  --muted: #8a8a8a;
  --rule: #e8e8e8;
  --accent: #0c869b;
  --tile: #f4f4f3;
  --gutter: clamp(16px, 2.5vw, 32px);
  --measure: 36rem;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0e0e0e; --fg: #ededed; --muted: #7a7a7a; --rule: #232323; --accent: #3fb0c4; --tile: #171717;
  }
}
:root[data-theme="dark"] {
  --bg: #0e0e0e; --fg: #ededed; --muted: #7a7a7a; --rule: #232323; --accent: #3fb0c4; --tile: #171717;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: "Inter Tight", system-ui, -apple-system, sans-serif;
  font-weight: 500;
  font-size: 15px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
img { display: block; }
.mono { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; }
.small { font-size: 11px; color: var(--muted); letter-spacing: 0.01em; }

/* ---------- Top ---------- */
.top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 2rem;
  padding: var(--gutter);
}
.blurb {
  margin: 0;
  max-width: var(--measure);
  font-weight: 600;
  font-size: 15px;
  line-height: 1.4;
  letter-spacing: -0.005em;
}
.blurb a, .home { text-decoration: none; transition: color .15s; }
.blurb sup { font-size: .6em; line-height: 0; vertical-align: super; margin-left: .05em; color: var(--accent); font-weight: 500; letter-spacing: 0; }
.blurb a:hover sup { color: var(--accent); }
.blurb a:hover, .home:hover { color: var(--accent); }
.home { font-weight: 600; }
.utility { display: flex; gap: 1.1rem; align-items: center; }
.utility .icon { display: inline-flex; color: var(--muted); transition: color .2s, transform .2s; }
.utility .icon svg { display: block; fill: currentColor; }
.utility .icon:hover { transform: translateY(-1px); }
.utility .linkedin:hover { color: #0a66c2; }
.utility .github:hover { color: var(--fg); }
.utility .mail:hover { color: var(--accent); }
.utility .mail svg, .utility .calendar svg { fill: none; }
.utility .calendar:hover { color: var(--accent); }
/* Giving What We Can: grey until hovered, then the brand orange and red */
.utility .gwwc svg path { fill: currentColor; transition: fill .25s; }
.utility .gwwc:hover svg .o { fill: #f78c50; }
.utility .gwwc:hover svg .r { fill: #da353b; }
/* light/dark toggle: a moon in light mode, a sun in dark */
.utility .theme { background: none; border: 0; padding: 0; margin: 0; cursor: pointer; font: inherit; }
.utility .theme:hover { color: var(--fg); }
.utility .theme svg { fill: none; }
.utility .theme .sun { display: none; }
/* The bar: name left, icons right, the full width of the page, pinned to the top. Every page has it.
   On the home page it stays out of the way until the intro has scrolled off, then slides in. */
.bar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 3;
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  height: 52px; padding: 0 var(--gutter);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rule);
  transition: opacity .3s, transform .3s;
}
.bar.away { opacity: 0; transform: translateY(-100%); pointer-events: none; }
body.sub { padding-top: 64px; }   /* the bar plus a little air, so the page starts below it */

/* ---------- Art band ---------- */
.art {
  padding: 0 var(--gutter);
  margin: clamp(8px, 2vh, 24px) 0 clamp(40px, 8vh, 96px);
}
.art { height: clamp(220px, 34vh, 380px); }
.hero { position: relative; display: flow-root; }   /* keeps the band's bottom margin inside, so the canvas covers it */
/* the canvas is pinned to the viewport: the rover lives in the hero, but can be driven anywhere on the page */
.hero canvas {
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 1;
}
/* on touch devices the canvas is laid over the whole page instead and scrolls with it, which stays smooth on iOS */
.hero canvas.page { position: absolute; }

/* ---------- Groups ---------- */
.group { padding: 0 var(--gutter); margin-bottom: clamp(40px, 7vh, 80px); }
.label {
  margin: 0 0 1rem;
  font-size: 11px;
  font-weight: 400;
  color: var(--muted);
  letter-spacing: 0.02em;
  padding-bottom: .6rem;
  border-bottom: 1px solid var(--rule);
}

/* Work list: one grid for the whole list so the columns line up across rows */
.roles {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: 56px 1.2fr 1fr auto;
  column-gap: 1.5rem;
}
.roles li { display: contents; }
.roles .row { color: inherit; }
.roles a, .roles .row {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  align-items: center;
  padding: 1.25rem 0;
  border-bottom: 1px solid var(--rule);
  transition: color .15s;
}
.roles a:hover { color: var(--accent); }
.roles .badge { width: 56px; height: 56px; display: flex; align-items: center; justify-content: center; border-radius: 8px; background: var(--tile); font-size: 12px; color: var(--muted); }
.roles img { width: 56px; height: 56px; object-fit: contain; border-radius: 8px; background: var(--tile); padding: 8px; }
.roles .org { font-weight: 600; font-size: 20px; letter-spacing: -0.01em; }
.roles .role { color: var(--muted); font-size: 15px; text-align: center; }
.roles a:hover .role { color: inherit; }
.roles .when { color: var(--muted); font-size: 12px; }
.roles .arrow { color: var(--muted); font-size: 11px; margin-left: .75rem; }

/* Project cards */
.cards {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--gutter);
}
.card { display: block; min-width: 0; }
.card img {
  display: block;   /* no inline baseline gap, so swapping a light image for a dark one can never shift the row */
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  background: var(--tile);
  border-radius: 4px;
  transition: opacity .2s;
}
.card img.contain { object-fit: contain; padding: 12%; }
.card:hover img { opacity: .8; }
.card h3 { margin: .7rem 0 .15rem; font-size: 15px; font-weight: 600; line-height: 1.3; }
.card:hover h3 { color: var(--accent); }
.card p { margin: 0 0 .3rem; color: var(--muted); font-size: 13px; line-height: 1.4; }
.card .when { font-size: 11px; color: var(--muted); }

/* ---------- Footer ---------- */
.foot {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: clamp(32px, 6vh, 80px) var(--gutter) var(--gutter);
}

/* ---------- Project page ---------- */
.project { padding: 0 var(--gutter); margin-bottom: clamp(40px, 7vh, 80px); }
.project .kicker { margin: 0 0 .6rem; }
.project .kicker a:hover { color: var(--accent); }
.project h1 { font-size: clamp(26px, 3.2vw, 40px); font-weight: 600; letter-spacing: -0.02em; margin: 0 0 .5rem; line-height: 1.1; max-width: 26ch; }
.project .meta { margin: 0 0 2.25rem; }
.project .lede { max-width: 40rem; margin: 0 0 2.5rem; font-size: 18px; line-height: 1.5; }
.project .lede a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .18em; text-decoration-color: var(--muted); }
.project .lede a:hover { color: var(--accent); text-decoration-color: var(--accent); }

.entries { margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.entries > div {
  display: grid;
  grid-template-columns: minmax(180px, 1fr) 3fr;
  gap: 2rem;
  padding: 1.25rem 0;
  border-bottom: 1px solid var(--rule);
}
.entries dt { margin: 0; font-weight: 600; }
.entries dt .sub { display: block; margin-top: .25rem; font-family: "JetBrains Mono", monospace; font-size: 11px; font-weight: 400; color: var(--muted); }
.entries dd { margin: 0; max-width: 40rem; }
.entries ul { margin: 0; padding-left: 1.1rem; }
.entries li { margin-bottom: .35rem; }
.entries li:last-child { margin-bottom: 0; }
.entries p { margin: 0 0 .5rem; }
.entries a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .18em; text-decoration-color: var(--muted); }
.entries a:hover { color: var(--accent); text-decoration-color: var(--accent); }

.links { list-style: none; margin: 2rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; }
.links a { font-weight: 600; }
.links a:hover { color: var(--accent); }
.links a::after { content: " ↗"; color: var(--muted); font-family: "JetBrains Mono", monospace; font-size: 11px; }

.embed { width: 100%; height: 80vh; border: 1px solid var(--rule); border-radius: 4px; background: var(--tile); }
.video { position: relative; aspect-ratio: 16 / 9; }
.video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.figure { margin: 0 0 2rem; }
.figure img { width: 100%; height: auto; border-radius: 4px; background: var(--tile); }

/* ---------- Responsive ---------- */
@media (max-width: 1100px) { .cards { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 800px) {
  .cards { grid-template-columns: repeat(2, 1fr); }
  .roles { grid-template-columns: 48px 1fr auto; }
  .roles a { row-gap: .15rem; }
  .roles img, .roles .badge { width: 48px; height: 48px; }
  .roles .org { font-size: 17px; white-space: normal; }
  .roles img { grid-column: 1; grid-row: 1 / span 2; }
  .roles .org { grid-column: 2; grid-row: 1; }
  .roles .role { grid-column: 2; grid-row: 2; font-size: 13px; }
  .roles .when { grid-column: 3; grid-row: 1 / span 2; }
  .entries > div { grid-template-columns: 1fr; gap: .75rem; }
}
@media (max-width: 600px) {
  .top { flex-direction: column; gap: 1rem; align-items: flex-end; }   /* icons right-aligned under the intro */
  .blurb { font-size: 16px; align-self: stretch; }
  .foot { flex-wrap: wrap; row-gap: .25rem; }   /* stays one row across the bottom on phones */
}
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

/* Work tiles: logo on a tile, text centred */
.cards.orgs .card { text-align: center; }
.cards.orgs .card img.contain { padding: var(--pad, 22%); }
.cards.orgs .card img { outline: 1px solid var(--rule); outline-offset: -1px; }
.cards.orgs div.card:hover img { opacity: 1; }
.cards.orgs div.card:hover h3 { color: inherit; }
.cards.orgs .card h3 { margin-top: .9rem; }

/* Credits */
.credits { padding: 0 var(--gutter); max-width: var(--measure); margin-bottom: clamp(40px, 7vh, 80px); }
.credits h1 { font-size: 24px; font-weight: 600; margin: 0 0 1.5rem; }
.credits ul { list-style: none; margin: 0; padding: 0; }
.credits li { padding: .7rem 0; border-bottom: 1px solid var(--rule); font-size: 14px; }
.credits li a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .18em; text-decoration-color: var(--muted); }
.credits li a:hover { color: var(--accent); text-decoration-color: var(--accent); }
.foot a:hover { color: var(--accent); }

/* Dark mode: monochrome logos flip to light; white-background charts invert with hues preserved */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .mono-logo { filter: brightness(0) invert(1); }
  :root:not([data-theme="light"]) .invertible { filter: invert(1) hue-rotate(180deg); }
}
:root[data-theme="dark"] .mono-logo { filter: brightness(0) invert(1); }
:root[data-theme="dark"] .invertible { filter: invert(1) hue-rotate(180deg); }

/* Images with a dark variant: both are in the markup, and the theme picks one (the hidden one is never fetched) */
.card img.dark { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .card img.light { display: none; }
  :root:not([data-theme="light"]) .card img.dark { display: block; }
  :root:not([data-theme="light"]) .utility .theme .moon { display: none; }
  :root:not([data-theme="light"]) .utility .theme .sun { display: block; }
}
:root[data-theme="dark"] .card img.light { display: none; }
:root[data-theme="dark"] .card img.dark { display: block; }
:root[data-theme="dark"] .utility .theme .moon { display: none; }
:root[data-theme="dark"] .utility .theme .sun { display: block; }

/* a project page can carry a grid of cards (the BSc page lists the physics projects) */
.project .cards { margin-top: .5rem; }

/* A tile wrapper for images that get a dark-mode filter: the filter must not touch the tile itself */
.card .tile { display: block; aspect-ratio: 3 / 2; background: var(--tile); border-radius: 4px; overflow: hidden; }
.card .tile img, .cards.orgs .card .tile img { background: transparent; outline: none; }

/* Driving hint for the rover */
.drive-hint { position: absolute; right: var(--gutter); bottom: 0; margin: 0; z-index: 2; opacity: .8; transition: opacity .6s; pointer-events: none; }
.hero.driven .drive-hint { opacity: 0; }
.drive-hint .coarse { display: none; }
@media (hover: none) { .drive-hint .fine { display: none; } .drive-hint .coarse { display: inline; } }

/* Thumbstick for driving the rover on touch devices. Hidden until the band is tapped; it then appears
   under the finger, pinned to the screen so it stays put while the page scrolls, and fades once let go. */
.stick { position: fixed; left: 0; top: 0; width: 76px; height: 76px; margin: -38px 0 0 -38px; z-index: 4;
  border-radius: 50%; border: 1px solid var(--rule); background: color-mix(in srgb, var(--bg) 70%, transparent);
  touch-action: none; -webkit-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent;
  opacity: 0; pointer-events: none; transition: opacity .35s; }
.stick.show { opacity: .9; pointer-events: auto; }
.stick .knob { position: absolute; left: 50%; top: 50%; width: 30px; height: 30px; margin: -15px 0 0 -15px; border-radius: 50%;
  background: var(--muted); opacity: .8; transition: transform .08s; }
.stick.active .knob { background: var(--accent); opacity: 1; transition: none; }
@media (pointer: fine) { .stick { display: none; } }

/* Project pages: links as buttons, prev/next, footer at the bottom */
body { min-height: 100vh; display: flex; flex-direction: column; }
.foot { margin-top: auto; }
.links.buttons { gap: .6rem; margin-top: .5rem; }
.links.buttons a { display: inline-flex; align-items: center; gap: .5em; padding: .55rem .9rem; border: 1px solid var(--rule); border-radius: 999px; font-weight: 600; transition: border-color .15s, color .15s; }
.links.buttons a::after { content: "↗"; color: var(--muted); font-family: "JetBrains Mono", monospace; font-size: 12px; }
.links.buttons a:hover { color: var(--accent); border-color: var(--accent); }
.links.buttons a:hover::after { color: var(--accent); }
.pager { display: flex; justify-content: space-between; gap: 1rem; margin: 0 var(--gutter); padding: 1.25rem 0; border-top: 1px solid var(--rule); }
.pager a { color: var(--muted); max-width: 45%; }
.pager a:hover { color: var(--accent); }

.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
