:root {
  color-scheme: light;
  --paper: #f4f5f2;
  --ink: #171b1b;
  --muted: #737b7a;
  --line: rgba(23, 27, 27, 0.13);
  --accent: #1769f5;
  --body-copy: #454d4c;
  --surface: #e6e9e7;
  --dock-height: calc(112 * var(--u));
  font-family: "Inter", sans-serif;
  font-synthesis: none;
  text-rendering: optimizeLegibility;
}

/* Fluid scale. The desktop design is drawn for a 1920 × 927 window and every size in it is written in --u, one pixel
   of that reference: calc(13.5 * var(--u)) is 13.5px there. --vw and --vh are the design's viewport units, the
   reference screen's 1vw and 1vh in --u; the real 100vw / 100vh are kept for what really is the screen (page height,
   slide distances). Phones and tablets use plain pixels and viewport units, so all three are their usual values. */
@property --u { syntax: "<length>"; inherits: true; initial-value: 1px; }
@property --vw { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --vh { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --fit { syntax: "<length>"; inherits: true; initial-value: 1px; }
:root { --u: 1px; --vw: 1vw; --vh: 1vh; }
/* --fit is the window's size against the reference: the smaller of the width and height ratios, as a length.
   --u only follows it three quarters of the way, so browser zoom, in and out, still changes the size of things
   (CSS can't tell a zoomed-out window from a bigger screen, so very large screens get a slightly smaller block). It is
   set in rem so a reader's larger default text size carries through, and it stays between 0.8 and 4 reference pixels. */
@media (min-width: 1181px) {
  :root {
    --fit: min(100vw / 1920, 100vh / 927);
    --u: clamp(.05rem, calc(.015625rem + .75 * var(--fit)), .25rem);
    --vw: calc(19.2 * var(--u));
    --vh: calc(9.27 * var(--u));
  }
}


* { box-sizing: border-box; }
html { min-width: 320px; background: var(--paper); overflow-x: hidden; }
body {
  min-width: 320px;
  min-height: 100vh;
  margin: 0;
  color: var(--ink);
  overflow-x: hidden;
  background-color: var(--paper);
  background-image: url("../Assets/identity/background.png");
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  background-attachment: fixed;
}
button, a { color: inherit; font: inherit; }
button:focus-visible, a:focus-visible { outline: calc(3 * var(--u)) solid var(--accent); outline-offset: calc(4 * var(--u)); }

.portfolio { min-height: 100vh; padding: 0 calc(5.3 * var(--vw)) calc(var(--dock-height) + 54 * var(--u)); }
.topline {
  position: relative;
  left: 50%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: min(1540 * var(--u), calc(100% + 1.6 * var(--vw)));
  height: calc(70 * var(--u));
  margin: 0;
  transform: translateX(-50%);
}
.topline::after { position: absolute; right: 0; bottom: calc(12 * var(--u)); left: 0; height: 1px; background: var(--line); content: ""; }
@property --wordmark-hover {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}
.wordmark { --wordmark-hover: 0%; color: color-mix(in srgb, var(--ink), var(--accent) var(--wordmark-hover)); font-size: clamp(10 * var(--u), .65 * var(--vw), 13 * var(--u)); font-weight: 600; letter-spacing: .14em; text-decoration: none; text-transform: uppercase; transition: --wordmark-hover 160ms ease; }
.wordmark:hover { --wordmark-hover: 100%; }
.wordmark span { color: color-mix(in srgb, var(--muted), var(--accent) var(--wordmark-hover)); font-weight: 400; }
.topline-actions { display: flex; align-items: center; gap: calc(12 * var(--u)); }
.resume-link { --wordmark-hover: 0%; display: inline-flex; align-items: center; gap: calc(8 * var(--u)); color: color-mix(in srgb, var(--ink), var(--accent) var(--wordmark-hover)); font-size: clamp(9 * var(--u), .55 * var(--vw), 11 * var(--u)); font-weight: 400; letter-spacing: .14em; text-decoration: none; text-transform: uppercase; transition: --wordmark-hover 160ms ease; }
.resume-link:hover { --wordmark-hover: 100%; }
.resume-link[aria-disabled="true"], .resume-link[aria-disabled="true"]:hover { --wordmark-hover: 0%; transition: none; }
.resume-link[aria-disabled="true"], .resume-link[aria-disabled="true"] * { -webkit-user-select: none; user-select: none; }
.resume-prefix { color: color-mix(in srgb, var(--muted), var(--accent) var(--wordmark-hover)); }
.resume-copy { white-space: nowrap; }
.resume-copy strong { font-weight: 600; }
.resume-icon { display: grid; width: calc(22 * var(--u)); height: calc(22 * var(--u)); place-items: center; border: 1px solid var(--line); border-radius: 50%; font-size: calc(14 * var(--u)); letter-spacing: 0; line-height: 1; }
/* On click the arrow drops out of the circle and falls back in from the top. */
.resume-icon { overflow: hidden; transition: scale 120ms ease; }
.resume-arrow { display: block; }
.resume-link:not([aria-disabled="true"]):active .resume-icon { scale: .9; }
.resume-link.is-downloading .resume-arrow { animation: resume-arrow-drop 640ms cubic-bezier(.5, 0, .3, 1); }
@keyframes resume-arrow-drop {
  45% { translate: 0 calc(20 * var(--u)); }
  45.1% { translate: 0 calc(-20 * var(--u)); }
  100% { translate: 0 0; }
}
.project-view {
  position: relative;
  left: 50%;
  isolation: isolate;
  display: grid;
  align-items: center;
  width: min(1540 * var(--u), calc(100% + 1.6 * var(--vw)));
  min-height: calc(100vh - 70 * var(--u) - var(--dock-height) - 54 * var(--u));
  margin: 0;
  transform: translateX(-50%);
}
.project-view.is-pointer-dragging { cursor: grabbing; user-select: none; }
.project-view.is-pointer-dragging * { user-select: none; }
.page-returning { transition: translate 180ms cubic-bezier(.2, .7, .25, 1); }
.project-view > .page-drag-preview { position: absolute; top: 50%; right: 0; left: 0; width: 100%; transform: translateY(-50%); pointer-events: none; }
.page-arrows { position: fixed; z-index: 4; top: 50%; right: 0; left: 0; display: flex; justify-content: space-between; padding: 0 clamp(12 * var(--u), 2.2 * var(--vw), 32 * var(--u)); transform: translateY(-50%); pointer-events: none; }
.page-arrows[hidden] { display: none; }
.page-arrow { user-select: none; display: grid; width: calc(38 * var(--u)); height: calc(52 * var(--u)); place-items: center; padding: 0; border: 0; border-radius: calc(2 * var(--u)); color: var(--muted); background: transparent; cursor: pointer; font-family: "Raleway", sans-serif; font-size: calc(42 * var(--u)); font-weight: 400; line-height: 1; opacity: .72; pointer-events: auto; transition: color 180ms ease, opacity 180ms ease, transform 180ms ease; }
.page-arrow-previous:hover:not(:disabled) { transform: translateX(calc(-3 * var(--u))); color: var(--accent); opacity: 1; }
.page-arrow-next:hover:not(:disabled) { transform: translateX(calc(3 * var(--u))); color: var(--accent); opacity: 1; }
.page-arrow:disabled { cursor: default; opacity: .22; }
.project-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(calc(290 * var(--u)), .8fr);
  align-items: start;
  gap: clamp(34 * var(--u), 5.2 * var(--vw), 86 * var(--u));
  padding: calc(40 * var(--u)) 0 calc(48 * var(--u));
}
.page-entering { position: relative; z-index: 1; }
.project-view > .page-outgoing { position: absolute; z-index: 2; top: var(--page-outgoing-top); right: 0; left: 0; width: 100%; margin: 0; pointer-events: none; }
#project-view[data-navigation-direction="next"] .page-entering { animation: page-enter-from-right 900ms cubic-bezier(.65, 0, .35, 1) both; }
#project-view[data-navigation-direction="previous"] .page-entering { animation: page-enter-from-left 900ms cubic-bezier(.65, 0, .35, 1) both; }
#project-view[data-navigation-direction="next"] .page-outgoing { animation: page-exit-to-left 900ms cubic-bezier(.65, 0, .35, 1) both; }
#project-view[data-navigation-direction="previous"] .page-outgoing { animation: page-exit-to-right 900ms cubic-bezier(.65, 0, .35, 1) both; }
.media-stack { min-width: 0; }
.hero-frame {
  position: relative;
  overflow: hidden;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
  border-radius: calc(6 * var(--u));
  background: var(--surface);
  box-shadow: 0 calc(18 * var(--u)) calc(50 * var(--u)) rgba(28, 35, 33, .08);
}
/* The frame's fine edge is a dark see-through line, like the gallery thumbnails': it vanishes on dark pictures (a light
   grey one showed as a pale rim, broken into specks in the rounded corners) and still outlines light ones. */
.hero-frame::after {
  position: absolute;
  inset: 0;
  border: 1px solid rgba(23, 27, 27, .15);
  border-radius: inherit;
  content: "";
  pointer-events: none;
}
.hero-image { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: contain; }
/* The video fills its frame exactly like the stills: a 1px overscan made the picture shift when the
   poster handed over to the first frame. The neutral filter keeps Chrome from handing a playing video
   to a hardware overlay, which places it a fraction of a pixel away from the normal rendering: the
   picture moved inside its frame whenever the video started or paused (on every page change). */
video.hero-image { object-fit: cover; border: 0; filter: brightness(1.001); }
/* The Space Age and ARUP video files have two black pixel columns down their sides (ARUP: the right one, at the start
   and end). They are drawn 0.3% bigger than the frame so the columns fall outside it, and so are their posters wherever
   they stand in for them (slide preview, fallback), so the hand-over to the video doesn't move the picture. The clip
   trims the enlarged picture back to its own box: without it, a preview waiting beside the frame spilled ~1.3px into
   it (a thin dark line down the next media's edge, e.g. the left of the controller viewer). */
video.hero-image:is([src$="/spaceage.mp4"], [src$="/ARUP.mp4"]),
:is(.hero-preview, .hero-video-fallback):is([src$="/spaceage1.webp"], [src$="/arup1-back.webp"]) { scale: 1.003; clip-path: inset(calc(50% - 50% / 1.003)); }
.hero-track { position: absolute; inset: 0; }
img.hero-image { object-fit: cover; }
.hero-video-fallback { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.hero-video-fallback[hidden] { display: none; }
.toy-canvas { touch-action: none; background: url("../three.js/impact/cube.svg?v=6") center / contain no-repeat; }
.toy-canvas[data-ready="true"] { background: transparent; }
.project-title-row { position: relative; display: flex; align-items: flex-start; gap: 0; width: fit-content; max-width: 100%; }
.project-title-row .project-title { flex: 0 1 auto; min-width: 0; }
.project-title-row > .toy-widget { position: absolute; left: 100%; top: 50%; margin-left: calc(-20 * var(--u)); margin-top: 0; transform: translateY(-50%); }
.project-title-row > .toy-widget[data-toy="magnetic-cube"] { margin-left: calc(-40 * var(--u)); transform: translateY(-50%) scale(.9); }
.project-layout[data-project-id="impact"] .project-title-row > .toy-widget[data-toy="magnetic-cube"] { margin-top: calc(-5 * var(--u)); }
.project-title-row > .toy-widget[data-toy="source-light"] { margin-left: calc(-40 * var(--u)); margin-top: 0; transform: translateY(-50%) scale(.9); }
.toy-widget { position: relative; flex: 0 0 calc(152 * var(--u)); width: calc(152 * var(--u)); height: calc(114 * var(--u)); }
.toy-widget .toy-canvas { cursor: default; background: none; }
.toy-widget[data-toy="magnetic-cube"], .toy-widget[data-toy="magnetic-cube"] .toy-canvas { cursor: pointer; }
.toy-widget[data-toy="voxel-title"], .toy-widget[data-toy="voxel-title"] .toy-canvas { cursor: pointer; }
.toy-widget[data-toy="source-light"], .toy-widget[data-toy="source-light"] .toy-canvas { cursor: pointer; }
/* Until Impact's cube is ready, a picture of it at rest holds its place, drawn by the cube itself (remade with
   tools/impact-cube-poster.sh). It covers the whole screen pixels around the frame in the reference window, so there it
   lands on the cube's very pixels: 138 × 104 starting .85 and .8875 left of and above the frame, divided by the
   frame's .9 scale. On standard screens it is drawn unsmoothed: the frame sits between pixels, and smoothing blurred
   the picture against the crisp cube that replaces it. */
.toy-widget[data-toy="magnetic-cube"] .toy-canvas:not([data-ready="true"]) { background: image-set(url("../three.js/impact/cube-poster-1x.png?v=1") 1x, url("../three.js/impact/cube-poster-1.75x.png?v=1") 1.75x) calc(-.9444 * var(--u)) calc(-.9861 * var(--u)) / calc(153.3333 * var(--u)) calc(115.5556 * var(--u)) no-repeat; }
@media (max-resolution: 1dppx) {
  .toy-widget[data-toy="magnetic-cube"] .toy-canvas:not([data-ready="true"]), .page-drag-preview .toy-widget .toy-canvas:not([data-placeholder="true"]) { image-rendering: pixelated; }
}
.toy-widget[data-toy="source-light"] .toy-canvas:not([data-ready="true"], [data-placeholder="true"]), .page-drag-preview [data-toy="source-light"] .toy-canvas:not([data-placeholder="true"]) {
  background-image: url("../three.js/source/source-avatar.svg?v=2");
  background-position: center;
  background-size: auto 77.727%;
  background-repeat: no-repeat;
}
.toy-widget[data-toy="source-light"]::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: radial-gradient(circle, #b9e1ff99 0%, #7aafff2e 38%, #7aafff00 70%);
  background-position: center; background-size: 43.55% 58.06%; background-repeat: no-repeat;
  opacity: calc(var(--source-light-alpha, 1) * var(--source-hover-glow, 1));
}
.toy-widget[data-toy="source-light"][data-hit="true"]::before { background-image: radial-gradient(circle, #ff7285cc 0%, #f43c5759 38%, #f43c5700 70%); opacity: calc(var(--source-light-alpha, 1) * var(--source-hit-glow, 1)); }
.toy-widget[data-toy="source-light"]::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(circle, #fff 0%, #e4faff 40%, #80b5f0 68%, transparent 73%) center / 7.573% 10.097% no-repeat;
  opacity: var(--source-light-alpha, 1);
}
.toy-widget { cursor: default; touch-action: none; }
/* No drop shadow: the running toy draws on the page surface without one, and a shadowed placeholder looked bolder while the page slid in. */
.toy-stage { position: relative; isolation: isolate; }
.toy-stage > .media-stack, .toy-stage > .project-copy { position: relative; z-index: 1; }
.toy-stage > .toy-surface-canvas { z-index: 0; max-width: none; pointer-events: none; background: none; touch-action: auto; }
.toy-stage[data-project-id="impact"] > .toy-surface-canvas { z-index: 2; }
/* Impact's destructible tags: the cube layer sits over the copy and never takes the pointer. */
.project-layout:has(> .voxel-tags-canvas) { position: relative; }
.project-layout:has(> .voxel-tags-canvas) .project-meta > span { cursor: pointer; user-select: none; }
.voxel-tags-canvas { position: absolute; inset: 0; z-index: 3; display: block; width: 100%; height: 100%; pointer-events: none; }
.voxel-title { position: relative; width: fit-content; max-width: 100%; }
.voxel-title .toy-widget { position: absolute; inset: 0; width: 100%; height: 100%; }
.voxel-title.is-ready .voxel-title-label { visibility: hidden; }
.light-reactive-title { position: relative; }
.space-racer-title-row { position: relative; }
.space-racer-heading { position: relative; width: fit-content; max-width: 100%; }
.space-racer-title-row .project-title { min-width: 0; }
.space-racer-title-row.is-playing { cursor: pointer; touch-action: none; user-select: none; }
.space-racer-title-row.is-playing .project-title { visibility: hidden; }
.space-racer-title-row.is-launching .project-title { visibility: visible; }
.space-racer-word { display: inline-block; white-space: nowrap; }
.space-racer-letter { display: inline-block; transform-origin: center bottom; }
.space-racer-launch-pod { position: absolute; z-index: 3; pointer-events: none; }
.space-racer-title-row.is-launching .space-racer-stage { visibility: hidden; }
.space-racer-title-row .space-racer-play { position: absolute; left: calc(100% - 6 * var(--u)); top: 50%; transform: translateY(-50%); z-index: 2; }
.space-racer-play { display: grid; flex: 0 0 calc(100 * var(--u)); width: calc(100 * var(--u)); height: calc(64 * var(--u)); place-items: center; padding: 0; border: 0; background: transparent; color: #587079; cursor: pointer; }
.space-racer-preview { display: block; width: 100%; height: auto; }
@keyframes space-racer-hover {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  35% { transform: translateY(calc(-4 * var(--u))) rotate(-3deg); }
  70% { transform: translateY(calc(-2 * var(--u))) rotate(2deg); }
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .space-racer-play[aria-pressed="false"]:hover .space-racer-preview { animation: space-racer-hover 1.4s ease-in-out infinite; }
}

.space-racer-play:has(.space-racer-preview) svg { display: none; }
.space-racer-play[aria-pressed="true"] .space-racer-preview { display: none; }
.space-racer-play[aria-pressed="true"] { visibility: hidden; pointer-events: none; }
.space-racer-play[aria-pressed="true"] svg { display: none; }
.space-racer-play:hover { color: #263f49; border-color: currentColor; }
.space-racer-play[aria-pressed="true"] svg path { d: path("M7 7H17V17H7Z"); }
.space-racer-stage { position: absolute; left: 0; top: calc(-35 * var(--u)); z-index: 1; display: block; width: 100%; height: calc(100% + 70 * var(--u)); pointer-events: none; }
.aeon-title-row { position: relative; display: flex; align-items: center; width: fit-content; max-width: 100%; }
.aeon-title-row .project-title { min-width: 0; }
.aeon-title-logo { position: absolute; z-index: 1; left: calc(100% + 12 * var(--u)); top: 50%; display: block; width: clamp(35 * var(--u), 2.8 * var(--vw), 48 * var(--u)); height: auto; aspect-ratio: 1; object-fit: contain; user-select: none; transform: translateY(calc(-50% - 4 * var(--u))); }
.aeon-title-logo[role="button"] { cursor: pointer; touch-action: none; transform-origin: center; }
.aeon-fist-halo { position: absolute; z-index: 0; left: calc(100% + 12 * var(--u)); top: 50%; width: clamp(35 * var(--u), 2.8 * var(--vw), 48 * var(--u)); aspect-ratio: 1; transform: translateY(calc(-50% - 4 * var(--u))); pointer-events: none; opacity: 0; }
.aeon-fist-halo::before { content: ""; position: absolute; inset: -32%; border-radius: 50%; background: radial-gradient(circle, #ef345a38 0%, #df224223 35%, #df22420c 55%, transparent 72%); }
@keyframes aeon-halo-breathe {
  0%, 100% { opacity: .35; scale: .94; }
  50% { opacity: .85; scale: 1.06; }
}
@keyframes aeon-fist-pulse {
  0%, 100% { transform: translate(0, calc(-50% - 4 * var(--u))) rotate(0deg) scale(1); }
  30% { transform: translate(-1px, calc(-50% - 5 * var(--u))) rotate(-2deg) scale(1.015); }
  50% { transform: translate(0, calc(-50% - 6 * var(--u))) rotate(-1deg) scale(1.025); }
  75% { transform: translate(1px, calc(-50% - 5 * var(--u))) rotate(1deg) scale(1.01); }
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .aeon-title-row:has(.aeon-title-logo[aria-pressed="false"]:hover) .aeon-fist-halo { animation: aeon-halo-breathe 2.4s ease-in-out infinite; }
  .aeon-title-logo[aria-pressed="false"]:hover { animation: aeon-fist-pulse 2.4s ease-in-out infinite; }
}

.aeon-strike { position: relative; display: inline-block; max-width: 100%; padding: 0; border: 0; background: transparent; color: inherit; font: inherit; line-height: inherit; letter-spacing: inherit; text-align: left; cursor: default; touch-action: none; user-select: none; }
.aeon-strike:focus { outline: none; }
.aeon-hand-cursor, .aeon-hand-cursor * { cursor: none !important; }
.aeon-game-active, .aeon-game-active * { -webkit-user-select: none; user-select: none; }
.aeon-brawler-stage { position: fixed; top: 0; left: 0; z-index: 6; pointer-events: none; }
.aeon-word { display: inline-block; white-space: nowrap; }
.aeon-letter { display: inline-block; transform-origin: center 70%; }
.arup-title-toggle { position: relative; display: inline-block; min-width: 3.5em; padding: 0; border: 0; background: transparent; color: inherit; font: inherit; line-height: inherit; letter-spacing: inherit; text-align: left; }
.proteo-title-row { position: relative; width: fit-content; max-width: 100%; }
.proteo-play { position: absolute; left: calc(100% + 8 * var(--u)); top: 50%; width: calc(44 * var(--u)); height: calc(44 * var(--u)); padding: 0; border: 0; background: transparent; transform: translateY(-50%); cursor: pointer; touch-action: manipulation; }
.proteo-play img { position: relative; display: block; width: 100%; height: 100%; filter: drop-shadow(1px calc(2 * var(--u)) calc(2 * var(--u)) #22222224); transition: transform 180ms ease; }
@keyframes proteo-ball-hover {
  0%, 100% { transform: translateY(0) scale(1); }
  12% { transform: translateY(calc(3 * var(--u))) scale(1.14, .86); }
  42% { transform: translateY(calc(-12 * var(--u))) scale(.94, 1.06) rotate(-12deg); }
  64% { transform: translateY(0) scale(1); }
  72% { transform: translateY(calc(3 * var(--u))) scale(1.16, .84); }
  85% { transform: translateY(calc(-3 * var(--u))) scale(.98, 1.02); }
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .proteo-play[aria-pressed="false"]:hover img { animation: proteo-ball-hover 1.35s ease-in-out infinite; }
}

.project-layout:where([data-project-id="proteo"]) { position: relative; }
.proteo-shape-stage { position: absolute; inset: 0 auto auto 0; z-index: 5; width: calc(52 * var(--u)); height: calc(52 * var(--u)); padding: 0; border: 0; border-radius: 50%; background: transparent; cursor: grab; touch-action: none; user-select: none; }
.proteo-shape-stage.is-grabbed { cursor: grabbing; }
.proteo-play { cursor: grab; touch-action: none; }
.proteo-shape-stage[hidden] { display: none; }
.proteo-shape-stage img { display: block; width: 100%; height: 100%; filter: drop-shadow(1px calc(3 * var(--u)) calc(3 * var(--u)) #22222226); }
@media (prefers-reduced-motion: reduce) { .proteo-play img { transition: none; } .proteo-play:is(:hover, :focus-visible) img { transform: none; } }
.necro-title-row { position: relative; width: fit-content; max-width: 100%; }
.necro-play { position: absolute; left: calc(100% + 10 * var(--u)); top: 50%; transform: translateY(-50%); width: calc(68 * var(--u)); height: calc(34 * var(--u)); border: 0; padding: 0; background: transparent; cursor: pointer; }
.necro-play img { display: block; width: 100%; height: 100%; transform: rotate(-12deg); }
.necro-play .necro-rifle-bolt { position: absolute; inset: 0; pointer-events: none; }
.necro-play[hidden] { display: none; }
.necro-play:disabled { cursor: default; }
.necro-play::before, .necro-play::after { content: ""; position: absolute; left: 96%; top: 28%; pointer-events: none; opacity: 0; }
.necro-play::before { width: calc(15 * var(--u)); height: calc(11 * var(--u)); margin-top: calc(-5 * var(--u)); background: #ffd581; clip-path: polygon(0 40%, 40% 30%, 80% 0, 65% 40%, 100% 50%, 65% 60%, 80% 100%, 40% 70%, 0 60%); transform: rotate(-12deg); }
.necro-play::after { width: calc(8 * var(--u)); height: calc(3 * var(--u)); margin-top: -1px; border-radius: 1px 60% 60% 1px; background: linear-gradient(#ffe5ad, #b98a47); transform: rotate(-12deg); }
@keyframes necro-hover-bullet {
  0%, 31.99% { opacity: 0; transform: translate(0, 0) rotate(-12deg); }
  32% { opacity: 1; transform: translate(0, 0) rotate(-12deg); }
  43% { opacity: 1; }
  50%, 100% { opacity: 0; transform: translate(calc(65 * var(--u)), calc(-14 * var(--u))) rotate(-12deg); }
}
@keyframes necro-hover-flash { 0%, 31.99%, 40%, 100% { opacity: 0; } 32%, 35% { opacity: 1; } }
@keyframes necro-hover-recoil {
  0%, 31.99%, 49%, 100% { transform: translateY(-50%); }
  35% { transform: translateY(-50%) translate(calc(-3 * var(--u)), 1px) rotate(-2deg); }
}
@keyframes necro-bolt-hover {
  0%, 30%, 100% { transform: rotate(-12deg) translateX(0); }
  15%, 21% { transform: rotate(-12deg) translateX(calc(-7 * var(--u))); }
}

@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .necro-play[aria-pressed="false"]:not(:disabled):hover { animation: necro-hover-recoil 1.6s ease infinite; }
  .necro-play[aria-pressed="false"]:not(:disabled):hover .necro-rifle-bolt { animation: necro-bolt-hover 1.6s ease infinite; }
  .necro-play[aria-pressed="false"]:not(:disabled):hover::before { animation: necro-hover-flash 1.6s linear infinite; }
  .necro-play[aria-pressed="false"]:not(:disabled):hover::after { animation: necro-hover-bullet 1.6s linear infinite; }
}
.necro-word { display: inline-block; white-space: nowrap; }
.necro-word > span { display: inline-block; }
.necro-gallery-stage { position: fixed; inset: 0 auto auto 0; z-index: 4; pointer-events: none; }
.necro-aiming, .necro-aiming * { cursor: none !important; }
.sigmar-title-row { position: relative; width: fit-content; max-width: 100%; padding-right: calc(52 * var(--u)); }
.sigmar-hammer { position: absolute; right: 0; top: calc(50% - 4 * var(--u)); transform: translateY(-50%); width: calc(42 * var(--u)); height: calc(42 * var(--u)); pointer-events: none; }
.sigmar-hammer img { display: block; width: 100%; height: 100%; object-fit: contain; rotate: -13deg; user-select: none; filter: drop-shadow(calc(2 * var(--u)) calc(3 * var(--u)) calc(2 * var(--u)) #23374c30); }
@media (max-width: 600px) {
  .sigmar-title-row { padding-right: 44px; }
  .sigmar-hammer { width: 34px; height: 34px; }
}
.arup-title-row { position: relative; display: flex; align-items: center; gap: 0; width: fit-content; max-width: 100%; }
.arup-play { position: absolute; top: 50%; left: calc(100% - 18 * var(--u)); display: grid; place-items: center; width: calc(48 * var(--u)); height: calc(48 * var(--u)); padding: 0; border: 0; background: transparent; cursor: pointer; transform: translateY(-50%); }
.arup-play::before { content: ""; position: absolute; left: calc(12 * var(--u)); bottom: 1px; width: calc(30 * var(--u)); height: calc(9 * var(--u)); background: radial-gradient(ellipse, #00000024 0%, #0000000a 45%, transparent 72%); pointer-events: none; }
.arup-play-cube { position: relative; display: block; width: calc(38 * var(--u)); height: calc(43 * var(--u)); pointer-events: none; shape-rendering: geometricPrecision; transition: transform 200ms ease; }
.arup-play[aria-pressed="true"] .arup-play-cube { visibility: hidden; }
.arup-play[aria-pressed="true"]::before { visibility: hidden; }
@keyframes arup-title-return {
  from { opacity: 0; transform: translateY(calc(8 * var(--u))); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes arup-cube-return {
  from { opacity: 0; transform: translateY(-50%) scale(.85); }
  to { opacity: 1; transform: translateY(-50%) scale(1); }
}
@media (prefers-reduced-motion: no-preference) {
  .arup-title-row.is-returning .arup-title-text { animation: arup-title-return 500ms cubic-bezier(.2, .7, .25, 1) backwards; }
  .arup-title-row.is-returning .arup-play { animation: arup-cube-return 400ms 550ms ease-out backwards; }
  .page-outgoing .arup-title-row.is-returning .arup-play, .page-drag-preview .arup-title-row.is-returning .arup-play { animation: none; }
}
:is(.space-racer-play, .aeon-title-logo, .necro-play, .proteo-play, .arup-play), .sigmar-hammer img { filter: drop-shadow(0 calc(4 * var(--u)) calc(3 * var(--u)) #23303d35); }
.proteo-play img { filter: none; }
@media (prefers-reduced-motion: reduce) { .arup-play-cube { transition: none; } }
.arup-title-row .arup-title { margin: 0; min-width: 0; }
.arup-ground { position: relative; }
.arup-runner-hud, .mini-game-score { display: none; position: absolute; right: 0; top: calc(10 * var(--u)); color: var(--muted); font: calc(9 * var(--u))/1.5 monospace; letter-spacing: .06em; pointer-events: none; }
.game-score-anchor { position: relative; }
.mini-game-score:not([hidden]) { display: block; }
.arup-ground.is-running .arup-runner-hud:not([hidden]) { display: block; }
.arup-runner-scene { display: none; position: absolute; left: 0; right: 0; bottom: 0; height: calc(1.8em + 16 * var(--u)); overflow: hidden; pointer-events: none; }
.arup-ground.is-running .arup-runner-scene { display: block; z-index: 2; pointer-events: auto; cursor: pointer; touch-action: manipulation; user-select: none; }
.is-running .arup-title-toggle .arup-title-logos { top: auto; bottom: 0; height: 1.05em; transform-origin: left bottom; transform: translateY(calc(var(--ground-offset, 0px) + var(--entry-offset, 0px) + var(--jump, 0em))); transition: opacity 220ms; pointer-events: auto; }
.arup-runner-obstacle { position: absolute; bottom: 0; border: 1px solid #653b35; border-radius: .035em .035em 0 0; background: #b65d50; box-shadow: inset 0 calc(2 * var(--u)) 0 #ffffff40, 0 calc(2 * var(--u)) calc(3 * var(--u)) #35201b26; }
.arup-runner-obstacle.is-airborne { border-radius: 0; box-shadow: inset 0 calc(2 * var(--u)) 0 #ffffff60, 0 calc(3 * var(--u)) calc(5 * var(--u)) #35201b26; }
.arup-runner-obstacle.is-bonus { border: 0 !important; background: transparent !important; box-shadow: none; filter: drop-shadow(0 0 calc(2 * var(--u)) #b77900) drop-shadow(0 0 calc(5 * var(--u)) #ffc800cc); }
.arup-runner-obstacle.is-bonus::before { content: ""; position: absolute; inset: calc(-13 * var(--u)); border-radius: 50%; background: radial-gradient(circle, #ffdf4380 0, #ffdc3933 40%, transparent 70%); pointer-events: none; }
.arup-runner-obstacle.is-bonus::after { content: ""; position: absolute; inset: calc(-6 * var(--u)); background: linear-gradient(135deg, #fffef0 10%, #ffe570 35%, #ffca18 65%, #eba700); clip-path: polygon(50% 0, 61% 35%, 98% 35%, 68% 57%, 79% 93%, 50% 71%, 21% 93%, 32% 57%, 2% 35%, 39% 35%); }
@keyframes arup-star-shine { from { opacity: .55; transform: scale(.85); } to { opacity: 1; transform: scale(1.15); } }
.arup-runner-obstacle.is-heart { filter: drop-shadow(0 0 calc(2 * var(--u)) #c83457) drop-shadow(0 0 calc(5 * var(--u)) #ff6385aa); }
.arup-runner-obstacle.is-heart::before { background: radial-gradient(circle, #ff638580 0, #ff638533 40%, transparent 70%); }
.arup-runner-obstacle.is-heart::after { background: linear-gradient(135deg, #ffbacb, #ef426b 55%, #bc2148); clip-path: polygon(50% 95%, 8% 52%, 0 30%, 6% 12%, 22% 3%, 38% 7%, 50% 22%, 62% 7%, 78% 3%, 94% 12%, 100% 30%, 92% 52%); }
.arup-title-logos.is-shielded img:not(.is-lost) { filter: drop-shadow(1px 0 0 #fff1a3) drop-shadow(-1px 0 0 #fff1a3) drop-shadow(0 1px 0 #ffda49) drop-shadow(0 -1px 0 #ffda49) drop-shadow(0 0 calc(4 * var(--u)) #ffc52ed9); animation: arup-shield-shimmer 180ms steps(2, end) infinite alternate; }
.arup-title-logos.is-shielded img:nth-child(even) { animation-delay: -90ms; }
.arup-title-logos.is-shield-fading img:not(.is-lost) { animation-duration: 90ms; }
.arup-title-logos.is-shield-breaking img:not(.is-lost) { animation: arup-shield-break 350ms ease-out both; }
@keyframes arup-shield-shimmer {
  from { filter: drop-shadow(1px 0 0 #fff5bd) drop-shadow(-1px 0 0 #fff5bd) drop-shadow(0 1px 0 #ffda49) drop-shadow(0 -1px 0 #ffda49) drop-shadow(-.6px .4px calc(3 * var(--u)) #ffc52eb3); }
  to { filter: drop-shadow(1px 0 0 #fffde3) drop-shadow(-1px 0 0 #fffde3) drop-shadow(0 1px 0 #ffe779) drop-shadow(0 -1px 0 #ffe779) drop-shadow(.6px -.4px calc(6 * var(--u)) #ffd54ff2); }
}
@keyframes arup-shield-break {
  from { filter: drop-shadow(1px 0 0 #fffde3) drop-shadow(-1px 0 0 #fffde3) drop-shadow(0 1px 0 #ffe779) drop-shadow(0 -1px 0 #ffe779) drop-shadow(0 0 calc(8 * var(--u)) #ffd54f); }
  to { filter: drop-shadow(0 0 0 transparent); }
}
@media (prefers-reduced-motion: reduce) { .arup-title-logos.is-shielded img:not(.is-lost), .arup-title-logos.is-shield-breaking img:not(.is-lost) { animation: none; } }
@media (prefers-reduced-motion: no-preference) { .arup-runner-obstacle.is-bonus::before { animation: arup-star-shine 700ms ease-in-out infinite alternate; } }
.arup-title-logos img.is-restored { animation: arup-letter-restore 300ms ease-out; }
@keyframes arup-letter-restore { from { opacity: 0; scale: .7; } 65% { opacity: 1; scale: 1.12; } to { opacity: 1; scale: 1; } }
@media (prefers-reduced-motion: reduce) { .arup-title-logos img.is-restored { animation: none; } }
.is-crashed .arup-title-logos { filter: saturate(.3); }
.arup-title-text { display: block; }
.arup-title-toggle[aria-pressed="true"] .arup-title-text { visibility: hidden; }
.is-entering .arup-title-toggle[aria-pressed="true"] .arup-title-text { visibility: visible; }
.arup-title-logos img { transform-origin: center bottom; }
.arup-title-logos { position: absolute; left: 0; right: 0; bottom: 0; height: 1.05em; display: flex; align-items: center; gap: 0; opacity: 0; pointer-events: none; transition: opacity 220ms ease; }
.arup-title-toggle[aria-pressed="false"] .arup-title-logos { visibility: hidden; opacity: 0; transition: none; }
.arup-title-logos img { display: block; flex: 0 0 .875em; width: .875em; height: 1.05em; object-fit: contain; object-position: center bottom; user-select: none; }
.arup-title-logos img + img { margin-left: -.15em; }
.arup-title-logos img:first-child { position: relative; z-index: 1; }
.arup-title-logos img:nth-child(2) { margin-left: -.23em; }
.arup-title-logos img:nth-child(2), .arup-title-logos img:nth-child(4) { transform: translateY(-.06em); }
.is-running .arup-title-logos { opacity: 1; }
.arup-title-logos img.is-lost { animation: arup-letter-lost 450ms ease-in forwards; }
.arup-title-logos.is-hit { animation: arup-hit 140ms steps(1) infinite; }
@keyframes arup-letter-lost { 0% { opacity: 1; translate: 0 0; rotate: 0deg; } 35% { opacity: 1; translate: .2em -.35em; } 100% { opacity: 0; translate: .5em .5em; rotate: 30deg; } }
@keyframes arup-hit { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .arup-title-logos img.is-lost { animation: none; opacity: 0; } .arup-title-logos.is-hit { animation: none; } }
@media (prefers-reduced-motion: reduce) { .arup-title-text, .arup-title-logos { transition: none; } }
.beam-title-highlight { position: absolute; inset: 0; font: inherit; line-height: inherit; letter-spacing: inherit; white-space: inherit; pointer-events: none; opacity: 0; }
.page-drag-preview .voxel-title .toy-widget .toy-canvas { background: none; }
.page-drag-preview .toy-widget .toy-canvas:not([data-placeholder="true"]) { background: image-set(url("../three.js/impact/cube-poster-1x.png?v=1") 1x, url("../three.js/impact/cube-poster-1.75x.png?v=1") 1.75x) calc(-.9444 * var(--u)) calc(-.9861 * var(--u)) / calc(153.3333 * var(--u)) calc(115.5556 * var(--u)) no-repeat; }
@media (max-width: 600px) { .toy-widget { flex-basis: 112px; width: 112px; height: 94px; } }
.hero-frame { cursor: grab; user-select: none; }
.hero-frame.is-dragging, .hero-frame.is-settling { cursor: grabbing; }
.hero-preview { pointer-events: none; }
.hero-frame.is-dragging .hero-track, .hero-frame.is-settling .hero-track { will-change: translate; }
.hero-frame.is-dragging::after, .hero-frame.is-settling::after { border-color: transparent; }
.hero-arrow { position: absolute; z-index: 1; top: 50%; display: grid; width: calc(36 * var(--u)); height: calc(48 * var(--u)); place-items: center; padding: 0; transform: translateY(-50%); border: 0; border-radius: calc(3 * var(--u)); color: #fff; background: transparent; cursor: pointer; font-size: calc(32 * var(--u)); line-height: 1; text-shadow: 0 1px calc(4 * var(--u)) rgba(0, 0, 0, .45); opacity: 0; pointer-events: none; transition: opacity 160ms ease; }
.hero-arrow span { display: block; transform: scaleY(1.4); }
.hero-arrow[data-media-direction="-1"] { left: calc(8 * var(--u)); }
.hero-arrow[data-media-direction="1"] { right: calc(8 * var(--u)); }
.hero-frame:hover .hero-arrow, .hero-frame:focus-within .hero-arrow { opacity: 1; pointer-events: auto; }
.hero-frame.is-dragging .hero-arrow { opacity: 0; pointer-events: none; }
.hero-frame.is-settling .hero-arrow { opacity: 1; }
.controller-frame, .controller-viewer, .hero-preview[src$="/viewer-poster.webp"] { background: radial-gradient(ellipse at 48% 30%, #e1e4e5 0%, #cdd2d5 52%, #b9c0c5 100%); }
.controller-frame.is-settling .controller-viewer { pointer-events: none; }
.controller-frame { --controller-toolbar-height: calc(44 * var(--u)); cursor: default; }
.controller-viewer, .controller-canvas, .controller-poster { position: absolute; inset: 0; width: 100%; height: 100%; }
.controller-poster { object-fit: contain; }
.controller-canvas { display: block; touch-action: none; cursor: grab; opacity: 0; }
.controller-canvas[data-hover="press"] { cursor: pointer; }
.controller-canvas.is-grabbed { cursor: grabbing; }
.controller-ready .controller-canvas { opacity: 1; }
.controller-ready .controller-poster { visibility: hidden; }
.controller-overlay { position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity 250ms ease; font-family: "Inter", sans-serif; }
.controller-ready .controller-overlay { opacity: 1; }
.controller-overlay button { pointer-events: auto; cursor: pointer; }
.controller-detail-connector { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.controller-detail-connector path { fill: none; stroke: #ffffffe0; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.controller-view-actions button[hidden] { display: none; }
.controller-hotspots { position: absolute; inset: 0; pointer-events: none; }
.controller-hotspot { position: absolute; display: grid; place-items: center; width: calc(34 * var(--u)); height: calc(34 * var(--u)); padding: 0; border: 0; border-radius: 50%; background: transparent; transform: translate(-50%, -50%); pointer-events: auto; cursor: pointer; }
.controller-hotspot::before { content: ""; width: calc(10 * var(--u)); height: calc(10 * var(--u)); border: 1px solid #fff; border-radius: 50%; background: #fff; box-shadow: 0 0 0 calc(4 * var(--u)) #ffffff24, 0 1px calc(5 * var(--u)) #34434d4d; transition: box-shadow 160ms ease, transform 160ms ease; }
.controller-hotspot:hover::before, .controller-hotspot[aria-pressed="true"]::before { transform: scale(1.15); box-shadow: 0 0 0 calc(6 * var(--u)) #ffffff42, 0 1px calc(7 * var(--u)) #34434d55; }
.controller-hotspot[hidden], .controller-detail[hidden] { display: none; }
.controller-detail { position: absolute; top: calc(16 * var(--u)); right: calc(17 * var(--u)); width: clamp(170 * var(--u), 24%, 220 * var(--u)); box-sizing: border-box; padding: calc(15 * var(--u)) calc(18 * var(--u)) calc(17 * var(--u)); border: 1px solid #ffffff80; border-radius: calc(10 * var(--u)); background: #ffffffe0; color: #526470; backdrop-filter: blur(calc(16 * var(--u))); box-shadow: 0 calc(8 * var(--u)) calc(28 * var(--u)) #3346520a; pointer-events: auto; }
/* Small-caps label, left-aligned title and copy, in the site's header style; no justified gaps. */
.controller-detail-copy::before { display: block; margin-bottom: calc(7 * var(--u)); color: #8a98a3; font-size: calc(9 * var(--u)); font-weight: 600; letter-spacing: .2em; text-transform: uppercase; content: attr(data-label); }
.controller-detail h3 { margin: 0 0 calc(8 * var(--u)); color: #2f3e48; font-size: calc(15 * var(--u)); font-weight: 600; line-height: 1.25; letter-spacing: -.01em; }
.controller-detail p { margin: 0; color: #5f707b; font-size: calc(11 * var(--u)); line-height: 1.6; text-wrap: pretty; }
.controller-hotspot[aria-pressed="true"]::before { box-shadow: 0 0 0 calc(6 * var(--u)) #dcefff66, 0 0 calc(14 * var(--u)) calc(3 * var(--u)) #b9ddff80; animation: controller-point-pulse 280ms ease-out; }
.controller-detail-connector.is-revealing path { stroke-dasharray: 1; animation: controller-connector-reveal 220ms 40ms ease-out both; }
.controller-detail.is-revealing { animation: controller-detail-reveal 220ms 110ms ease-out both; }
@keyframes controller-point-pulse {
  0% { transform: scale(1); box-shadow: 0 0 0 calc(4 * var(--u)) #ffffff42; }
  45% { transform: scale(1.35); box-shadow: 0 0 0 calc(10 * var(--u)) #dcefff30, 0 0 calc(18 * var(--u)) calc(4 * var(--u)) #b9ddff80; }
  100% { transform: scale(1.15); box-shadow: 0 0 0 calc(6 * var(--u)) #dcefff66, 0 0 calc(14 * var(--u)) calc(3 * var(--u)) #b9ddff80; }
}
@keyframes controller-connector-reveal {
  from { stroke-dashoffset: 1; opacity: 0; }
  to { stroke-dashoffset: 0; opacity: 1; }
}
@keyframes controller-detail-reveal {
  from { opacity: 0; translate: 0 calc(5 * var(--u)); }
  to { opacity: 1; translate: 0 0; }
}
@media (prefers-reduced-motion: reduce) {
  .controller-hotspot[aria-pressed="true"]::before, .controller-detail-connector.is-revealing path, .controller-detail.is-revealing { animation: none; }
}
.controller-gesture { position: absolute; left: calc(18 * var(--u)); top: calc(16 * var(--u)); display: flex; align-items: center; max-width: calc(100% - 18 * var(--u) - clamp(170 * var(--u), 24%, 220 * var(--u)) - 30 * var(--u)); min-height: var(--controller-toolbar-height); box-sizing: border-box; padding: calc(9 * var(--u)) calc(16 * var(--u)); border: 1px solid #ffffff80; border-radius: calc(10 * var(--u)); background: #ffffffe0; color: #526470; backdrop-filter: blur(calc(16 * var(--u))); }
.controller-gesture-item { display: flex; align-items: center; gap: calc(10 * var(--u)); min-width: 0; }
.controller-gesture-item + .controller-gesture-item { margin-left: calc(19 * var(--u)); padding-left: calc(19 * var(--u)); border-left: 1px solid #52647026; }
.controller-gesture-item > svg { flex: 0 0 calc(24 * var(--u)); width: calc(24 * var(--u)); height: calc(30 * var(--u)); }
.controller-gesture-item > span { display: grid; gap: calc(2 * var(--u)); font-size: calc(11 * var(--u)); line-height: 1.35; }
.controller-gesture-item strong { color: #40535f; font-size: calc(12 * var(--u)); font-weight: 500; }
.controller-gesture-item > span > span { color: #7b8b96; }
.controller-view-actions { position: absolute; right: calc(17 * var(--u)); bottom: calc(16 * var(--u)); display: flex; gap: calc(9 * var(--u)); }
.controller-view-actions button { display: grid; place-items: center; width: var(--controller-toolbar-height); height: var(--controller-toolbar-height); box-sizing: border-box; padding: 0; border: 1px solid #ffffff80; border-radius: calc(10 * var(--u)); background: #ffffffe0; color: #526470; }
.controller-view-actions button svg { display: block; width: calc(20 * var(--u)); height: calc(20 * var(--u)); }
.controller-unavailable .controller-overlay { display: none; }
.controller-frame :is(.controller-detail, .controller-gesture, .controller-view-actions button) { box-sizing: border-box; border: 1px solid #ffffff80; border-radius: calc(10 * var(--u)); background: #ffffffe0; color: #526470; backdrop-filter: blur(calc(16 * var(--u))); box-shadow: 0 calc(8 * var(--u)) calc(28 * var(--u)) #3346520a; }
.controller-frame .controller-view-actions button { transition: background 160ms ease, box-shadow 160ms ease, opacity 160ms ease; }
.controller-frame .controller-view-actions button:hover { background: #ffffff; box-shadow: 0 calc(4 * var(--u)) calc(16 * var(--u)) #33465214; }.controller-frame .controller-view-actions button:focus-visible { outline: calc(2 * var(--u)) solid #526470; outline-offset: calc(3 * var(--u)); }
.controller-frame .controller-hotspot:focus-visible { outline: none; }
.controller-error { position: absolute; bottom: calc(10 * var(--u)); left: calc(45 * var(--u)); right: calc(45 * var(--u)); color: #526267; font-size: calc(11 * var(--u)); text-align: center; }
.controller-unavailable .controller-canvas { display: none; }
.controller-thumb { position: relative; }
.controller-thumb-icon { position: absolute; inset: 0; display: grid; place-items: center; color: #fff; pointer-events: none; }
.controller-thumb-icon svg { box-sizing: content-box; padding: calc(7 * var(--u)); border: 1px solid rgba(255, 255, 255, .65); border-radius: 50%; background: rgba(0, 0, 0, .6); }
@media (max-width: 600px) {
  .controller-frame { --controller-toolbar-height: 40px; aspect-ratio: 1 / 1; }
  .controller-detail { top: 16px; right: 15px; width: 38%; padding: 12px; }
  .controller-detail h3 { margin: 0 0 5px; font-size: 13px; }
  .controller-detail p { font-size: 10px; line-height: 1.5; }
  .controller-hotspot { width: 40px; height: 40px; }
  .controller-view-actions { bottom: 14px; }
  .controller-gesture { left: 12px; top: 16px; max-width: calc(62% - 27px); padding: 5px 9px; }
  .controller-gesture-item { gap: 6px; }
  .controller-gesture-item + .controller-gesture-item { margin-left: 10px; padding-left: 10px; }
  .controller-gesture-item > svg { flex-basis: 18px; width: 18px; height: 24px; }
  .controller-gesture-item > span { font-size: 9px; }
  .controller-gesture-item strong { font-size: 10px; }
  .controller-viewer[data-cover-open="true"] .controller-gesture { flex-direction: column; align-items: flex-start; gap: 8px; max-width: 42%; }
  .controller-viewer[data-cover-open="true"] .controller-gesture-item + .controller-gesture-item { margin-left: 0; padding: 8px 0 0; border-left: 0; border-top: 1px solid #52647026; }
}
@media (hover: none) {
  .hero-arrow { opacity: 1; pointer-events: auto; }
}
.gallery-shell { position: relative; width: 100%; margin-top: calc(8 * var(--u)); }
.gallery-arrow { position: absolute; z-index: 1; top: 0; bottom: calc(3 * var(--u)); display: grid; width: calc(32 * var(--u)); place-items: center; padding: 0; border: 0; border-radius: calc(4 * var(--u)); color: #fff; cursor: pointer; font-size: calc(28 * var(--u)); line-height: 1; opacity: 0; pointer-events: none; transition: opacity 160ms ease; }
.gallery-arrow span { display: block; transform: scaleY(1.6); }
.gallery-arrow[data-gallery-direction="-1"] { left: 0; background: transparent; }
.gallery-arrow[data-gallery-direction="1"] { right: 0; background: transparent; }
.gallery-arrow:not(:disabled) { opacity: 1; pointer-events: auto; }
.gallery-arrow:hover:not(:disabled) { color: #fff; }
.gallery-arrow:disabled { cursor: default; opacity: 0; pointer-events: none; }
.gallery { display: flex; gap: calc(8 * var(--u)); overflow-x: auto; width: 100%; min-width: 0; margin: 0; padding: 0 0 calc(3 * var(--u)); overscroll-behavior-x: contain; scroll-snap-type: none; scroll-behavior: auto; scrollbar-width: none; }
.gallery::-webkit-scrollbar { display: none; }
.video-thumb { position: relative; }
.video-play { position: absolute; inset: 0; display: grid; place-items: center; color: #fff; pointer-events: none; }
.video-play svg { box-sizing: content-box; padding: calc(7 * var(--u)); border: 1px solid rgba(255, 255, 255, .65); border-radius: 50%; background: rgba(0, 0, 0, .6); }
.gallery, .gallery .gallery-thumb { cursor: grab; }
.gallery { user-select: none; }
.gallery.is-dragging, .gallery.is-coasting { scroll-snap-type: none; scroll-behavior: auto; }
.gallery.is-dragging, .gallery.is-dragging .gallery-thumb { cursor: grabbing; }
.gallery-thumb {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  flex: 0 0 calc((100% - 32 * var(--u)) / 5);
  min-width: 0;
  aspect-ratio: 16 / 9;
  padding: 0;
  border: 1px solid rgba(23, 27, 27, .15);
  border-radius: calc(4 * var(--u));
  background: var(--surface);
  cursor: pointer;
  opacity: 1;
  transition: border-color 80ms ease;
  scroll-snap-align: start;
}
.gallery-thumb img { display: block; width: 100%; height: 100%; object-fit: fill; opacity: 0; transition: opacity 260ms ease; }
.gallery-thumb img.is-loaded { opacity: 1; }
.gallery-thumb::after { position: absolute; z-index: 1; inset: 0; border: 1px solid color-mix(in srgb, var(--accent) 65%, transparent); border-radius: calc(3 * var(--u)); content: ""; opacity: 0; pointer-events: none; transition: opacity 80ms ease; }
.gallery-thumb:hover, .gallery-thumb[aria-pressed="true"] { border-color: color-mix(in srgb, var(--accent) 65%, transparent); }
.gallery-thumb:hover::after, .gallery-thumb[aria-pressed="true"]::after { opacity: 1; }
/* The thumbnail a hovered text link leads to (see highlightLinkedThumbnails in JS/main.js): a thicker accent frame
   with a soft inner glow, kept inside the thumbnail as the strip clips anything outside it. */
.gallery-thumb.is-link-target { border-color: color-mix(in srgb, var(--accent) 65%, transparent); }
.gallery-thumb.is-link-target::after { border-width: 2px; box-shadow: inset 0 0 calc(12 * var(--u)) color-mix(in srgb, var(--accent) 45%, transparent); opacity: 1; transition: opacity 160ms ease; }
.gallery-thumb.is-link-target img { filter: brightness(1.08); }
.project-copy { position: relative; isolation: isolate; max-width: calc(520 * var(--u)); padding: 0; }
.project-copy::before { content: ""; position: absolute; z-index: -1; inset: calc(-48 * var(--u)) calc(-36 * var(--u)); background: radial-gradient(ellipse at center, #ffffffc2 0%, #ffffffa3 42%, #ffffff47 65%, #ffffff00 80%); opacity: .7; filter: blur(calc(16 * var(--u))); pointer-events: none; }
.project-title, .about-title { --title-size: clamp(34 * var(--u), 4 * var(--vw), 64 * var(--u)); margin: 0; font-family: "Raleway", sans-serif; font-size: calc(var(--title-size) * .45); font-weight: 700; line-height: 1.02; overflow-wrap: anywhere; }
.project-title { font-size: calc(var(--title-size) * .5); font-weight: 800; }
.project-subtitle { margin: calc(12.6 * var(--u)) 0 0; color: #747b7a; font-size: calc(16.5 * var(--u)); font-style: italic; font-weight: 500; letter-spacing: .05em; }
.project-subtitle + .project-description { margin-top: calc(14.4 * var(--u)); }
.project-paragraph { margin-top: calc(25.2 * var(--u)); }
.project-copy > .project-subtitle { margin-top: calc(8 * var(--u)); font-weight: 700; }
.project-paragraph > .project-subtitle { color: #444849; font-size: calc(12 * var(--u)); font-style: normal; font-weight: 600; letter-spacing: .12em; }
.section-dot { display: inline-block; width: calc(8 * var(--u)); height: calc(8 * var(--u)); margin-right: calc(9 * var(--u)); border: 1px solid #a4b6c8; border-radius: 50%; background: radial-gradient(circle at 30% 25%, #eef4fa 0%, #d5e0ea 28%, #c5d3e0 55%, #adbed0 100%); box-shadow: 0 1px calc(2 * var(--u)) #26384a26, inset 0 -1px 1px #667e9633; vertical-align: 1px; }
.project-description { white-space: pre-line; }
.project-description { max-width: 52ch; margin: calc(25.2 * var(--u)) 0 0; color: var(--body-copy); font-size: calc(13.5 * var(--u)); line-height: 1.8; }
.project-copy > .project-description,
.project-copy > .project-paragraph > .project-description { max-width: none; font-size: calc(var(--pitch-font-size, calc(13.5 * var(--u))) * .95); }
/* The browser avoids leaving a lone word on a paragraph's last line (Chrome, Edge, Safari; Firefox ignores it). */
.project-copy > .project-paragraph > .project-description { text-wrap: pretty; }
.project-description .project-text-bold { font-weight: 800; }
/* A link in the text to one of the project's media (see formatProjectText in JS/main.js): words of the text in bold
   and the home pitch's accent blue, no underline; on hover a darker blue, an underline, a magnifier cursor ("see
   something") and the linked thumbnail lighting up in the strip. */
.project-description .project-text-link { padding: 0; border: 0; background: none; color: #3269aa; font-weight: 800; text-decoration: underline solid transparent; text-underline-offset: .22em; cursor: zoom-in; transition: color .2s ease, text-decoration-color .2s ease; }
.project-description .project-text-link:hover { color: #234f86; text-decoration-color: #234f86; }.project-meta { display: flex; flex-wrap: wrap; gap: calc(7.2 * var(--u)); margin-top: calc(24.3 * var(--u)); }
.project-meta span { padding: calc(7.2 * var(--u)) calc(9 * var(--u)); border: 1px solid #cdd7e1; border-radius: calc(3 * var(--u)); background: #e9eef3; color: #4d6075; box-shadow: 0 calc(2 * var(--u)) calc(4 * var(--u)) #26384a0d; font-size: calc(9 * var(--u)); letter-spacing: .04em; }
.is-qa-project .project-meta span { border-color: #cbd8dc; background: #e7eef1; color: #506774; }
.copy-rule { width: 100%; height: 1px; margin-top: calc(27.9 * var(--u)); background: var(--line); }
.project-copy > .project-description,
.project-copy > .project-meta { margin-top: calc(14.4 * var(--u)); }
.project-copy > .copy-rule { margin-top: calc(10 * var(--u)); }
.project-copy > .project-description { margin-top: calc(20 * var(--u)); }
.project-copy > .project-paragraph { margin-top: calc(24 * var(--u)); }
.project-copy > .project-paragraph + .project-paragraph { margin-top: calc(30 * var(--u)); }
/* Under the identity card, a touch less visible gap than between two sections (where the line spacing of the text above
   adds about 5 to the margin). */
.project-copy > .project-facts + .project-paragraph { margin-top: calc(26 * var(--u)); }
.project-paragraph > .copy-rule { margin-top: calc(6 * var(--u)); }
.project-layout .project-paragraph > .project-subtitle { display: flex; align-items: center; gap: calc(9 * var(--u)); }
.project-layout .project-paragraph > .project-subtitle .section-dot { flex: 0 0 calc(8 * var(--u)); margin-right: 0; }
.project-layout .project-paragraph > .project-subtitle::after { content: ""; flex: 1; min-width: calc(16 * var(--u)); height: calc(9 * var(--u)); margin-left: calc(5 * var(--u)); background: linear-gradient(var(--line), var(--line)) left center / 100% 1px no-repeat; }
.project-layout .project-paragraph > .project-subtitle + .copy-rule { display: none; }
.project-paragraph > .project-description { width: calc(100% - 17 * var(--u)); margin-top: calc(6 * var(--u)); margin-left: calc(17 * var(--u)); text-align: left; }
.project-copy > .project-meta { margin-top: calc(14.4 * var(--u)); }
/* Same header language as the home page: small-caps context. */
.project-copy > .project-subtitle { margin-top: calc(16 * var(--u)); color: #748396; font-size: calc(14 * var(--u)); font-style: normal; font-weight: 600; letter-spacing: .22em; text-transform: uppercase; }
/* Section markers: small white circles outlined --ring-width thick in a gradient from --ring-top to --ring-bottom (the
   gradient fills the circle, a soft-edged white disc covers the inside: a real border can't be 1.5px, it's drawn 1px).
   By default a plain grey a few shades darker than the identity card's border; a project can set its own two colours.
   The size is a whole number of pixels: a fractional one is rounded differently across and down depending on where the
   circle falls, which made some of them ovals. */
.project-layout .project-paragraph > .project-subtitle .section-dot { --ring-top: #a3aeb8; --ring-bottom: #a3aeb8; --ring-width: 1.5px; --ring-size: round(calc(8 * var(--u)), 1px); flex-basis: var(--ring-size); width: var(--ring-size); height: var(--ring-size); border: 0; background: radial-gradient(circle closest-side, #fff calc(100% - var(--ring-width) - .25px), #fff0 calc(100% - var(--ring-width) + .25px)), linear-gradient(var(--ring-top), var(--ring-bottom)); box-shadow: none; }
/* Aeon Must Die!: a flame, orange at the top to red at the bottom, like its fist's fire. */
.project-layout[data-project-id="aeon"] .project-paragraph > .project-subtitle .section-dot { --ring-top: #f9a03f; --ring-bottom: #d42a2a; }
/* Age of Sigmar: Storm Ground: the deep teal green of its logo's plate, lighter at the top. */
.project-layout[data-project-id="age"] .project-paragraph > .project-subtitle .section-dot { --ring-top: #74b99f; --ring-bottom: #1a5e4a; }
/* Necromunda: Underhive Wars: the steel of the rifle beside its title, a bright polished highlight at the top to its
   darker body at the bottom. */
.project-layout[data-project-id="necromunda"] .project-paragraph > .project-subtitle .section-dot { --ring-top: #a9b4b1; --ring-bottom: #4c5759; }
/* Impact: its pink, very light at the top to a deep magenta at the bottom. */
.project-layout[data-project-id="impact"] .project-paragraph > .project-subtitle .section-dot { --ring-top: #ffb0d9; --ring-bottom: #e6007f; }
/* Source: the blue of its glowing orb, light sky blue at the top to a deep blue at the bottom. */
.project-layout[data-project-id="source"] .project-paragraph > .project-subtitle .section-dot { --ring-top: #a9d6ff; --ring-bottom: #3d7fd9; }
/* Space Age Racer: the sky blue its dots used to have, light at the top to a deeper blue at the bottom. */
.project-layout[data-project-id="spaceage"] .project-paragraph > .project-subtitle .section-dot { --ring-top: #9ccaf0; --ring-bottom: #3a7fc4; }
/* Proteo: the red of its ball, a soft red at the top to a deep crimson at the bottom. */
.project-layout[data-project-id="proteo"] .project-paragraph > .project-subtitle .section-dot { --ring-top: #fb7a82; --ring-bottom: #b3143a; }
/* Arup: no gradient, one flat colour per section taken from its title's letters: yellow (P), red (U), green (A). */
.project-layout[data-project-id="arup"] .project-paragraph > .project-subtitle .section-dot { --ring-top: #ecc70a; --ring-bottom: #ecc70a; }
.project-layout[data-project-id="arup"] .project-paragraph:nth-child(2 of .project-paragraph) > .project-subtitle .section-dot { --ring-top: #e61e19; --ring-bottom: #e61e19; }
.project-layout[data-project-id="arup"] .project-paragraph:nth-child(3 of .project-paragraph) > .project-subtitle .section-dot { --ring-top: #0bcf44; --ring-bottom: #0bcf44; }
/* Tags: flat chips, no outline or shadow, in a faint tint and the identity card's lettering, a size smaller. */
.project-copy > .project-meta { gap: calc(6 * var(--u)); }
.project-copy > .project-meta span, .is-qa-project .project-copy > .project-meta span { padding: calc(5.5 * var(--u)) calc(8 * var(--u)); border: 0; border-radius: calc(3 * var(--u)); background: #5264700f; color: #2f3a40; box-shadow: none; font-size: calc(11 * var(--u)); font-weight: 600; letter-spacing: 0; }
/* Identity card: the project's key facts in labelled columns in a thinly outlined, lightly tinted card between the
   context and the tags, split by fine rules, the card ending where the facts do. Each column has its rule in the middle
   of the gap on its left; the list cuts off the ones that would start a line, so the first column and lines the facts
   wrap onto start bare and flush left. */
.project-facts { width: fit-content; max-width: 100%; margin: calc(22 * var(--u)) 0 0; padding: calc(9 * var(--u)) calc(16 * var(--u)); border: 1px solid #d5dde2; border-radius: calc(4 * var(--u)); background: #5264700f; }
.project-facts dl { display: flex; flex-wrap: wrap; gap: calc(10 * var(--u)) calc(32 * var(--u)); overflow: hidden; margin: 0; }
.project-facts dl > div { position: relative; }
.project-facts dl > div::before { content: ""; position: absolute; top: 0; bottom: 0; left: calc(-16 * var(--u) - .5px); width: 1px; background: #52647030; }
/* Label and value lines are a whole number of reference pixels tall, so the value sits on the same sub-pixel phase as its
   label: with the font's own line height (11.5 for the label) the value fell half a pixel off and its text jumped while
   the page slid. */
.project-facts dt { color: #8a959c; font-size: calc(9.5 * var(--u)); font-weight: 600; line-height: calc(12 * var(--u)); letter-spacing: .14em; text-transform: uppercase; }
.project-facts dd { margin: calc(4 * var(--u)) 0 0; color: #2f3a40; font-size: calc(13.5 * var(--u)); font-weight: 600; line-height: calc(17 * var(--u)); }
/* Home: a slanted photo panel on the left, identity and pitch on the right. */
.about-layout { position: relative; display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr); align-items: center; gap: clamp(28 * var(--u), 3.5 * var(--vw), 64 * var(--u)); min-height: calc(100dvh - 70 * var(--u) - var(--dock-height) - 54 * var(--u)); padding: calc(40 * var(--u)) 0; }
.about-photo { --slant: 0deg; position: relative; justify-self: center; width: min(100%, 500 * var(--u)); height: clamp(340 * var(--u), 60 * var(--vh), 640 * var(--u)); margin: 0; }
.about-photo-panel { position: absolute; inset: 0 9% 0 13%; overflow: hidden; border-radius: calc(4 * var(--u)); background: linear-gradient(165deg, #dfe4e7 0%, #c3ccd2 100%); box-shadow: 0 calc(34 * var(--u)) calc(60 * var(--u)) calc(-34 * var(--u)) #1c232155; transform: skewX(var(--slant)); }
.about-photo-image { position: absolute; inset: 0 -22%; display: block; width: 144%; height: 100%; object-fit: cover; filter: grayscale(1) contrast(1.04); transform: skewX(calc(var(--slant) * -1)); transition: filter 700ms ease; }
.about-photo:hover .about-photo-image { filter: grayscale(.15); }
/* A desk diorama fills the free space right of the pitch, sharing the copy's grid cell. */
.about-room { position: relative; justify-self: end; width: calc(100% - 420 * var(--u)); height: clamp(300 * var(--u), 52 * var(--vh), 540 * var(--u)); }
/* The canvas overflows the frame by a quarter on every side, so things can spill past it (the layout only sees the frame).
   The room's script then nudges it onto whole screen pixels (see resize in desk-room.js). */
.about-room-canvas { position: absolute; top: -25%; left: -25%; display: block; width: 150%; height: 150%; opacity: 0; pointer-events: none; }
.about-room.has-room .about-room-canvas { opacity: 1; }
/* A picture of the room at rest holds its place until the room is ready, then gives way to it at once. Square, over the
   canvas's area: the camera fits the room to the frame's narrower side, so "contain" lines the two up. Remade with
   tools/desk-room-poster.sh. */
.about-room-poster { position: absolute; top: -25%; left: -25%; display: block; width: 150%; height: 150%; object-fit: contain; pointer-events: none; user-select: none; }
.about-room.has-room .about-room-poster { visibility: hidden; }
.is-pointing-room, .is-pointing-room * { cursor: pointer; }
.is-on-room-screen, .is-on-room-screen * { cursor: none; }
@media (max-width: 1180px) { .about-room { display: none; } }
/* Wide screens: three equal columns, photo | pitch | room. */
@media (min-width: 1181px) {
  .about-layout { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .about-layout > .about-photo { grid-column: 1; grid-row: 1; width: min(108%, 540 * var(--u)); height: auto; aspect-ratio: 25 / 24; }
  .about-layout > .about-copy-wrap { grid-column: 2; grid-row: 1; justify-self: center; max-width: calc(500 * var(--u)); text-align: center; }
  .about-layout .about-copy-wrap .about-title { font-size: clamp(30 * var(--u), 2.95 * var(--vw), 50 * var(--u)); white-space: nowrap; }
  .about-layout .about-hello { font-size: clamp(26 * var(--u), 2 * var(--vw), 34 * var(--u)); }
  .about-layout .about-roles { font-size: clamp(14 * var(--u), 1.04 * var(--vw), 16.5 * var(--u)); }
  .about-layout .about-tagline { margin-inline: auto; font-size: clamp(15 * var(--u), 1.09 * var(--vw), 17 * var(--u)); }
  .about-layout .about-rule { margin-inline: auto; }
  .about-layout .about-actions, .about-layout .about-contacts { justify-content: center; }
  .about-layout > .about-room { grid-column: 3; grid-row: 1; width: 110%; height: clamp(324 * var(--u), 56 * var(--vh), 584 * var(--u)); transform: translate(-1%, -6%); }
}
.about-copy-wrap { justify-self: start; width: 100%; max-width: calc(500 * var(--u)); padding: 0; text-align: left; }
.about-copy-wrap .about-title { max-width: none; color: #07111d; font-size: clamp(31 * var(--u), 3.6 * var(--vw), 59 * var(--u)); font-weight: 800; line-height: 1.04; letter-spacing: -.02em; }
.about-hello { display: inline-block; margin: 0 0 calc(4 * var(--u)); color: #07111d; font-family: "Caveat", cursive; font-size: clamp(26 * var(--u), 2 * var(--vw), 34 * var(--u)); font-weight: 400; line-height: 1; transform: rotate(-4deg); transform-origin: left bottom; }
.about-roles { margin: calc(14 * var(--u)) 0 0; color: #748396; font-size: clamp(12 * var(--u), .9 * var(--vw), 14.5 * var(--u)); font-weight: 600; letter-spacing: .24em; text-transform: uppercase; }
.about-rule { width: calc(48 * var(--u)); height: calc(2 * var(--u)); margin: calc(25 * var(--u)) 0 0; background: #3269aa; }
.about-tagline { max-width: 34ch; margin: calc(24 * var(--u)) 0 0; color: #1f2a33; font-size: clamp(15 * var(--u), 1.08 * var(--vw), 17 * var(--u)); font-weight: 400; line-height: 1.35; letter-spacing: -.025em; }
.about-tagline-accent { color: #3269aa; font-weight: 600; }
.about-bio { max-width: 52ch; margin: calc(14 * var(--u)) 0 0; color: var(--body-copy); font-size: calc(13.5 * var(--u)); line-height: 1.8; }
.about-actions { display: flex; flex-wrap: wrap; align-items: center; gap: calc(20 * var(--u)) calc(10 * var(--u)); margin-top: calc(25 * var(--u)); }
/* Solid blue-slate button with small caps; on hover it deepens and the label turns light blue. */
.about-discover, .about-contacts a { display: inline-flex; align-items: center; justify-content: center; min-height: calc(35 * var(--u)); padding: 0 calc(18 * var(--u)); border-radius: calc(6 * var(--u)); font-size: calc(10 * var(--u)); font-weight: 600; letter-spacing: .16em; text-transform: uppercase; }
.about-discover { border: 0; background: #4a86c8; color: #fff; box-shadow: 0 calc(6 * var(--u)) calc(16 * var(--u)) calc(-10 * var(--u)) #4a86c880; cursor: pointer; transition: background 180ms ease; }
.about-discover:hover, .about-discover:focus-visible { background: #1f4f86; }
.about-contacts { display: flex; flex-wrap: wrap; gap: calc(10 * var(--u)); }
.about-contacts a { gap: calc(8 * var(--u)); border: 1px solid #cbd3d9; background: transparent; color: #3f505d; text-decoration: none; box-shadow: none; transition: background 180ms ease, color 180ms ease, border-color 180ms ease; }
.about-contacts > * { color: var(--ink); font-size: calc(10 * var(--u)); letter-spacing: .16em; text-decoration: none; text-transform: uppercase; }
.about-contacts a:hover { border-color: #3269aa; background: #eaf1f8; color: #24588f; }
.about-contacts .is-pending { opacity: .4; cursor: default; }

.project-dock { position: fixed; z-index: 5; right: 0; bottom: 0; left: 0; min-height: var(--dock-height); padding: calc(19 * var(--u)) calc(4.5 * var(--vw)) max(7 * var(--u), env(safe-area-inset-bottom)); background: transparent; overflow: hidden; isolation: isolate; }
.dock-inner { position: relative; display: flex; align-items: center; gap: calc(15 * var(--u)); width: min(1540 * var(--u), 100%); min-height: calc(var(--dock-height) - 26 * var(--u)); margin: 0 auto; padding-top: calc(6 * var(--u)); }
.dock-inner::before { position: absolute; top: calc(6 * var(--u)); right: 0; left: 0; height: 1px; background: var(--line); content: ""; pointer-events: none; }
.dock-inner > .about-link, .dock-inner > .project-rail { position: relative; top: calc(4 * var(--u)); }
.dock-inner > .about-link { display: grid; flex: 0 0 calc((100% - 180 * var(--u)) / 19); grid-template-columns: minmax(0, 1fr); grid-template-rows: auto; gap: 0; justify-items: center; min-width: 0; padding: calc(4 * var(--u)) calc(3 * var(--u)) calc(3 * var(--u)); border: 0; border-radius: calc(4 * var(--u)); background: transparent; cursor: pointer; opacity: .72; transition: opacity 180ms ease, transform 180ms ease; }
.about-link:hover { z-index: 2; opacity: 1; }
.about-link[aria-pressed="true"] { opacity: 1; }
.about-preview { position: relative; display: block; background: transparent; transition: transform 220ms ease; }
.about-thumbnail { display: block; width: 100%; height: 100%; object-fit: contain; filter: grayscale(1); transition: filter 600ms ease; }
.about-link:hover .about-thumbnail, .about-link[aria-pressed="true"] .about-thumbnail { filter: grayscale(0); }
.project-rail { display: flex; flex: 1 1 auto; align-items: center; gap: calc(24 * var(--u)); min-width: 0; overflow-x: auto; overflow-y: hidden; contain: paint; overscroll-behavior: contain; scrollbar-width: none; }
.project-rail::-webkit-scrollbar { display: none; width: 0; height: 0; }
.project-rail { margin-inline: calc(-5 * var(--u)); padding: calc(8 * var(--u)) calc(5 * var(--u)); scroll-behavior: auto; user-select: none; cursor: grab; }
.project-rail .project-link { flex: 0 0 calc((100% - (var(--visible-project-count) - 1) * 20 * var(--u)) / var(--visible-project-count)); cursor: grab; }
.project-rail .project-link[data-project="source"] { margin-inline: calc(-18 * var(--u)); }
.project-rail.is-dragging, .project-rail.is-dragging .project-link { cursor: grabbing; }
.project-rail.is-static { overflow-x: hidden; cursor: default; }
.project-rail.is-static .project-link { cursor: pointer; }
.project-link { position: relative; display: grid; flex: 1 1 0; grid-template-rows: auto; gap: 0; justify-items: center; min-width: 0; padding: calc(4 * var(--u)) calc(3 * var(--u)) calc(3 * var(--u)); border: 0; border-radius: calc(4 * var(--u)); background: transparent; cursor: pointer; opacity: .72; transition: flex-grow 220ms ease, opacity 180ms ease, transform 180ms ease; }
.project-link:hover { z-index: 2; opacity: 1; }
.project-link, .about-link { position: relative; filter: drop-shadow(0 calc(5 * var(--u)) calc(4 * var(--u)) rgba(23, 27, 27, .42)); }
.project-link[aria-current="page"] { z-index: 1; opacity: 1; }
.project-link:focus-visible, .about-link:focus-visible { outline: none; }
.project-link :is(img, svg.dock-logo) { display: block; border: 1px solid rgba(23, 27, 27, .16); object-fit: cover; filter: saturate(.12); transition: filter 600ms ease, border-color 180ms ease, transform 220ms ease; }
.project-link[data-project="necromunda"] :is(img, svg.dock-logo), .project-link[data-project="age"] :is(img, svg.dock-logo) { transition: border-color 180ms ease, transform 220ms ease; }
.about-preview, .project-link :is(img, svg.dock-logo) { width: 100%; height: auto; aspect-ratio: 2 / 1; border-radius: calc(6 * var(--u)); }
.about-preview, .project-link :is(img, svg.dock-logo).about-thumbnail { aspect-ratio: 1 / 1; }
.project-link :is(img, svg.dock-logo).dock-logo { position: relative; left: 0; border: 0; border-radius: 0; background: transparent; object-fit: contain; }
.project-link :is(img, svg.dock-logo).about-thumbnail { border: 0; border-radius: 0; background: transparent; object-fit: contain; }
.about-preview, .project-link :is(img, svg.dock-logo).dock-logo { width: 76.3%; }
.project-link[data-project="vahana"] :is(img, svg.dock-logo).dock-logo { width: 82.8%; }
.project-link[data-project="source"] :is(img, svg.dock-logo).dock-logo { width: 78.605%; }
.project-link[data-project="arup"] :is(img, svg.dock-logo).dock-logo { width: 74.012%; }
.project-link[data-project="age"] :is(img, svg.dock-logo).dock-logo { width: 81.276%; }
.project-link[data-project="aeon"] :is(img, svg.dock-logo).dock-logo { width: 71.324%; }
.project-link[data-project="necromunda"] :is(img, svg.dock-logo), .project-link[data-project="vahana"] :is(img, svg.dock-logo) { position: relative; top: calc(3 * var(--u)); }
.project-link[data-project="aeon"] :is(img, svg.dock-logo).dock-logo { position: relative; top: calc(2 * var(--u)); }
.project-link:hover :is(img, svg.dock-logo), .project-link[aria-current="page"] :is(img, svg.dock-logo) { transform: scale(1.12); filter: grayscale(0); }
.project-link[data-project="proteo"]:hover :is(img, svg.dock-logo), .project-link[data-project="proteo"][aria-current="page"] :is(img, svg.dock-logo) { filter: saturate(.7); }
.project-link[data-project="impact"]:hover :is(img, svg.dock-logo), .project-link[data-project="impact"][aria-current="page"] :is(img, svg.dock-logo) { filter: saturate(.8); }

/* The pages only slide: fading two whole pages into each other made the GPU redraw and blend both every frame. */
@keyframes page-enter-from-right { from { translate: var(--page-entry-offset, 100vw) 0; } to { translate: 0 0; } }
@keyframes page-enter-from-left { from { translate: var(--page-entry-offset, -100vw) 0; } to { translate: 0 0; } }
@keyframes page-exit-to-left { from { translate: var(--drag-offset, 0px) 0; } to { translate: -100vw 0; } }
@keyframes page-exit-to-right { from { translate: var(--drag-offset, 0px) 0; } to { translate: 100vw 0; } }

@media (min-width: 901px) {
  /* The footer separator sits 25px below the top of the dock. */
  :root { --page-bottom-space: calc(-25 * var(--u)); }
  .portfolio { padding-bottom: calc(var(--dock-height) + var(--page-bottom-space)); }
  /* Center the content between the two decorative separators. */
  .project-view { margin-top: calc(-12 * var(--u)); min-height: calc(100dvh - 58 * var(--u) - var(--dock-height) - var(--page-bottom-space)); }
  .about-layout { min-height: calc(100dvh - 58 * var(--u) - var(--dock-height) - var(--page-bottom-space)); }
  .project-layout, .about-layout { padding: calc(24 * var(--u)) 0; }
  .media-stack {
    width: min(100%, max(240 * var(--u), calc((100dvh - 58 * var(--u) - var(--dock-height) - var(--page-bottom-space) - 48 * var(--u) - 11 * var(--u)) * 1.48148)));
  }
}

/* Short tablets in landscape get tighter copy. Desktops don't need it: --u already shrinks them with the screen. */
@media (min-width: 901px) and (max-width: 1180px) and (max-height: 760px) {
  .project-copy { --pitch-font-size: 12.6px; }
  .project-title, .about-title { --title-size: clamp(30px, 3vw, 42px); }
  .project-description { margin-top: 14.4px; font-size: 12.6px; line-height: 1.6; }
  .project-meta { margin-top: 14.4px; }
  .copy-rule { margin-top: 18px; }
}

/* Desktop: the reference layout's wider pitch column and slightly larger tags. */
@media (min-width: 1181px) {
  .project-copy { max-width: calc(680 * var(--u)); }
  .project-meta span { font-size: calc(9.9 * var(--u)); }
}

/* Small laptops: a little more air on the left and right edges (real screen width, as their margins are). */
@media (min-width: 1181px) and (max-width: 1400px) {
  .portfolio { padding-inline: 7.3vw; }
  .project-dock { padding-inline: 6.5vw; }
}

@media (max-width: 900px) {
  :root { --dock-height: 98px; }
  .portfolio { padding: 0 24px calc(var(--dock-height) + 38px + env(safe-area-inset-bottom)); }
  .topline { left: auto; width: 100%; height: 58px; transform: none; }
  .project-view { left: auto; width: 100%; min-height: auto; transform: none; }
  .page-arrows { display: none; }
  .project-layout, .about-layout { grid-template-columns: minmax(0, 1fr); gap: 27px; padding: 27px 0 38px; }
  .project-copy { max-width: 720px; }
  .project-title, .about-title { --title-size: clamp(34px, 7vw, 54px); }
  .project-description { margin-top: 19.8px; }
  .project-dock { min-height: calc(var(--dock-height) + env(safe-area-inset-bottom)); padding: 14px 24px max(2px, env(safe-area-inset-bottom)); }
  .dock-inner { gap: 11px; min-height: 82px; padding-top: 7px; }
  .dock-inner::before { top: 7px; }
  .dock-inner > .about-link { flex-basis: 46px; grid-template-rows: auto; gap: 0; padding: 3px 2px; }
  .project-rail { gap: 20px; overflow-x: auto; scroll-behavior: auto; }
  .project-rail .project-link { flex-basis: 92px; }
  .project-rail .project-link[data-project="source"] { margin-inline: -12px; }
  .project-link { flex-basis: 92px; grid-template-rows: auto; gap: 0; padding: 3px 2px; }
}

@media (max-width: 520px) {
  .project-copy { --pitch-font-size: 12.6px; }
  .portfolio { padding-right: 16px; padding-left: 16px; }
  .project-dock { padding-right: 16px; padding-left: 16px; }
  .topline-actions { gap: 8px; }
  .topline { flex-wrap: wrap; gap: 10px; height: auto; min-height: 70px; padding: 12px 0 24px; }
  .resume-link { gap: 5px; }
  .resume-icon { width: 20px; height: 20px; font-size: 13px; }
  .project-layout, .about-layout { gap: 22px; padding-top: 20px; }
  .gallery-shell { margin-top: 7px; }
  .gallery-arrow { width: 25px; }
  .gallery { gap: 5px; }
  .gallery-thumb { flex-basis: calc((100% - 20px) / 5); }
  .project-title, .about-title { --title-size: 36px; }
  .project-description { font-size: 12.6px; line-height: 1.75; }
  .project-meta { margin-top: 18px; }
}

@media (max-width: 360px) {
  .wordmark { font-size: 9px; }
  .topline-actions { gap: 6px; }
  .resume-link { gap: 4px; font-size: 9px; }
  .resume-icon { flex: 0 0 18px; width: 18px; height: 18px; font-size: 12px; }
}

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

:is(.toy-canvas, .toy-widget, .space-racer-play, .aeon-title-logo, .aeon-strike, .proteo-play, .necro-play, .arup-play, .arup-title-toggle):focus-visible { outline: none; }

.dock-reveal-zone { display: none; }
@media (hover: hover) and (pointer: fine) {
  .project-dock { opacity: 1; translate: 0 0; visibility: visible; transition: opacity 320ms ease, translate 400ms ease, visibility 0s; }
}

@media (max-width: 900px) {
  .about-layout { grid-template-columns: minmax(0, 1fr); gap: 28px; min-height: auto; padding: 24px 0 38px; }
  .about-photo { justify-self: center; width: min(460px, 100%); height: clamp(220px, 56vw, 360px); }
  .about-copy-wrap { max-width: 640px; }
  .about-copy-wrap .about-title { font-size: clamp(30px, 6vw, 46px); }
  .about-rule { margin-top: 22px; }
  .about-tagline { margin-top: 46px; }
  .about-actions { margin-top: 26px; }
}

/* Arrival animation of the home page, on the first load only (index.html's head script, playIntro in JS/main.js),
   hidden until it starts. The pitch comes first: the top line drawn, the hello written, the name and title rising from
   behind a line, the buttons popping in; then the photo and the desk slide in from their sides while the dock rises from
   the bottom of the screen in one piece. --intro-pace stretches every duration and delay at once. Each keyframe gives
   only the starting state when it can, so an element ends on its own resting values. */
html.has-intro:not(.intro-play) :is(.topline, .project-view, .page-arrows, .project-dock) { visibility: hidden; }
:root { --intro-pace: 1.35; --intro-ease: cubic-bezier(.2, .7, .2, 1); --intro-swing: cubic-bezier(.65, 0, .35, 1); --intro-bounce: cubic-bezier(.34, 1.5, .64, 1); }
@keyframes intro-fade { from { opacity: 0; } }
@keyframes intro-draw { from { scale: 0 1; } }
@keyframes intro-rise { from { opacity: 0; translate: 0 calc(14 * var(--u)); } }
@keyframes intro-lower { from { opacity: 0; translate: 0 calc(-8 * var(--u)); } }
@keyframes intro-from-left { from { opacity: 0; translate: calc(-48 * var(--u)) 0; } }
@keyframes intro-from-right { from { opacity: 0; translate: calc(48 * var(--u)) 0; } }
@keyframes intro-pop { from { opacity: 0; scale: .88; } }
@keyframes intro-dock-rise { from { translate: 0 100%; } }
/* Written from left to right, like a pen stroke. */
@keyframes intro-write { from { clip-path: inset(-40% 100% -40% -10%); } to { clip-path: inset(-40% -10% -40% -10%); } }
/* Rises from behind a line at its own bottom edge. */
@keyframes intro-mask-rise { from { translate: 0 100%; clip-path: inset(-20% -5% 100% -5%); } to { translate: 0 0; clip-path: inset(-20% -5% -20% -5%); } }
html.intro-play .topline::after { animation: intro-draw calc(800ms * var(--intro-pace)) var(--intro-swing) both; }
html.intro-play :is(.wordmark, .topline-actions) { animation: intro-lower calc(500ms * var(--intro-pace)) var(--intro-ease) calc(150ms * var(--intro-pace)) both; }
html.intro-play .about-hello { animation: intro-write calc(550ms * var(--intro-pace)) cubic-bezier(.45, 0, .35, 1) calc(150ms * var(--intro-pace)) both; }
html.intro-play .about-title { animation: intro-mask-rise calc(750ms * var(--intro-pace)) var(--intro-ease) calc(300ms * var(--intro-pace)) both; }
html.intro-play .about-roles { animation: intro-mask-rise calc(650ms * var(--intro-pace)) var(--intro-ease) calc(420ms * var(--intro-pace)) both; }
html.intro-play :is(.about-tagline, .about-bio) { animation: intro-rise calc(600ms * var(--intro-pace)) var(--intro-ease) calc(520ms * var(--intro-pace)) both; }
html.intro-play .about-discover { animation: intro-pop calc(450ms * var(--intro-pace)) var(--intro-bounce) calc(600ms * var(--intro-pace)) both; }
html.intro-play .about-contacts > :nth-child(1) { animation: intro-pop calc(450ms * var(--intro-pace)) var(--intro-bounce) calc(660ms * var(--intro-pace)) both; }
html.intro-play .about-contacts > :nth-child(2) { animation: intro-pop calc(450ms * var(--intro-pace)) var(--intro-bounce) calc(720ms * var(--intro-pace)) both; }
html.intro-play .about-photo { animation: intro-from-left calc(800ms * var(--intro-pace)) var(--intro-ease) calc(850ms * var(--intro-pace)) both; }
html.intro-play .about-room { animation: intro-from-right calc(800ms * var(--intro-pace)) var(--intro-ease) calc(910ms * var(--intro-pace)) both; }
html.intro-play .project-dock { animation: intro-dock-rise calc(800ms * var(--intro-pace)) var(--intro-ease) calc(850ms * var(--intro-pace)) both; }
html.intro-play .page-arrows { animation: intro-fade calc(500ms * var(--intro-pace)) ease calc(800ms * var(--intro-pace)) both; }
