/* Inter for everything, and Geist Serif for the greeting. Both are hosted with the site, under the
   SIL Open Font License. */
@font-face {
  font-family: Inter;
  src: url(/fonts/InterVF.woff2) format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Serif";
  src: url(/fonts/GeistSerif-Regular.woff2) format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* One typeface at one size, with soft grey text. Names come first: they're the darkest thing in
   a line and the only thing at a heavier weight. */
:root {
  --column: 560px; /* the text column, the same on every page and in the footer */
  --paper: #fff;
  --ink: #111110; /* on hover */
  --name: #3c4142;
  --text: #6f7778;
  --dash: #9aa4a5;
  --on-sky: #4d5557; /* text over the sky, which needs to be darker to read the same */
  --chip: #eef1f1;
  --chip-on: #dfe4e4;
  --chip-text: #535a5b;
  --chip-sky: rgb(255 255 255 / 0.6);
  --chip-sky-on: rgb(255 255 255 / 0.95);
  --sky-top: #b6d4f1;
  --sky-mid: #dcebf7;
  --card-fill: #14509a;
  --card-sky: none;
  --hairline: rgb(0 0 0 / 0.08);
  --under: #141308;
  color-scheme: light;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #121211;
    --ink: #f6f7f7;
    --name: #e4e7e7;
    --text: #979fa1;
    --dash: #5f686a;
    --on-sky: #a9b2b6;
    --chip: #242627;
    --chip-on: #303334;
    --chip-text: #cdd2d3;
    --chip-sky: rgb(255 255 255 / 0.1);
    --chip-sky-on: rgb(255 255 255 / 0.2);
    --sky-top: #1a2540;
    --sky-mid: #151b2a;
    --card-fill: #0a3365;
    --card-sky: brightness(0.62) saturate(1.1);
    --hairline: rgb(255 255 255 / 0.1);
    --under: #0d0d0a;
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --paper: #121211;
  --ink: #f6f7f7;
  --name: #e4e7e7;
  --text: #979fa1;
  --dash: #5f686a;
  --on-sky: #a9b2b6;
  --chip: #242627;
  --chip-on: #303334;
  --chip-text: #cdd2d3;
  --chip-sky: rgb(255 255 255 / 0.1);
  --chip-sky-on: rgb(255 255 255 / 0.2);
  --sky-top: #1a2540;
  --sky-mid: #151b2a;
  --card-fill: #0a3365;
  --card-sky: brightness(0.62) saturate(1.1);
  --hairline: rgb(255 255 255 / 0.1);
  --under: #0d0d0a;
  color-scheme: dark;
}

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

html {
  background: var(--paper);
  -webkit-text-size-adjust: 100%;
}
/* Pulled past the end of the page, the bottom of the picture carries on, not a bright band. Browsers
   show the background of html and body there, so the paper itself is a layer behind the page. */
html.at-foot { background: var(--under); }

body::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--paper);
}

body {
  position: relative;
  margin: 0;
  color: var(--text);
  font: 400 14px/24.5px Inter, ui-sans-serif, system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, p, ul, dl, dd, figure { margin: 0; padding: 0; }
h1, h2 { font: inherit; }
strong { font-weight: 500; color: var(--name); }
ul { list-style: none; }
img { display: block; max-width: 100%; height: auto; }

a { color: var(--name); text-decoration: none; transition: color 150ms; }
@media (hover: hover) {
  a:hover { color: var(--ink); }
}
/* Plain links (the footer's, the one under the film, and Copy email at the top of the home page): on hover a soft rounded fill comes up behind the words, like the
   highlight in the Appearance menu. It reaches a little past the text without moving it, and shows
   on a tap too. */
:is(.foot-top a, .film-figure figcaption a, .hero-link) { position: relative; z-index: 0; }
:is(.foot-top, .film-figure figcaption) a { display: inline-block; }
:is(.foot-top a, .film-figure figcaption a, .hero-link)::before {
  content: '';
  position: absolute;
  inset: -2px -6px;
  z-index: -1;
  border-radius: 6px;
  background: color-mix(in srgb, var(--ink) 7%, transparent);
  opacity: 0;
  transform: scale(0.94);
  transition: opacity 150ms, transform 220ms cubic-bezier(0.3, 1.25, 0.5, 1);
}
/* Beside the button, the fill is the button's height and shape, so the two sit level. */
.hero-actions .hero-link::before { inset: -4.75px -10px; border-radius: 8px; }
:is(.foot-top a, .film-figure figcaption a, .hero-link):active::before { opacity: 1; transform: none; }
@media (hover: hover) {
  :is(.foot-top a, .film-figure figcaption a, .hero-link):hover::before { opacity: 1; transform: none; }
}
/* From the keyboard, the same shape with a ring round it. */
:is(.foot-top a, .film-figure figcaption a, .hero-link):focus-visible { outline: none; }
:is(.foot-top a, .film-figure figcaption a, .hero-link):focus-visible::before { opacity: 1; transform: none; box-shadow: 0 0 0 2px currentColor; }
@media (prefers-reduced-motion: reduce) {
  :is(.foot-top a, .film-figure figcaption a, .hero-link)::before { transform: none; }
}
:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; border-radius: 4px; }
/* When Tab scrolls something into view, the browser stops at its edge; this leaves room for the
   ring drawn outside it. */
:where(a, button, input, [tabindex]) { scroll-margin-block: 24px; }
::selection { background: var(--ink); color: var(--paper); }

/* A link inside a sentence. */
.chip {
  display: inline-block;
  margin: 0 1px;
  padding: 0 4px;
  border-radius: 4px;
  background: var(--chip);
  color: var(--chip-text);
  font-weight: 500;
  line-height: 21px;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 200ms, color 200ms;
}
@media (hover: hover) {
  .chip:hover { background: var(--chip-on); color: var(--ink); }
}

.dash { margin: 0 2px; color: var(--dash); }

button {
  all: unset;
  display: inline-grid;
  place-items: center;
  cursor: pointer;
}

/* The sky at the top of the home page. scene.js adds moving clouds on a canvas inside it. */
.sky {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: clamp(560px, 86vh, 860px);
  background: linear-gradient(var(--sky-top), var(--sky-mid) 42%, var(--paper));
  pointer-events: none;
}
/* More sky above the page, for when the page is pulled past its top. */
.sky::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 100vh;
  background: var(--sky-top);
  will-change: transform;
}
.sky canvas { display: block; width: 100%; height: 100%; opacity: 0; transition: opacity 1200ms; }
.sky canvas.on { opacity: 1; }

/* Appearance: a frosted button showing the mode in use, opening a small frosted menu of Dark, Light
   and Auto (follow the system). The button shows the right mode before any script runs, from the
   theme itself. In the menu one soft highlight glides from item to item, and each icon moves a
   little: the sun's rays turn, the moon tilts, Auto's half flips. */
.theme { position: absolute; z-index: 3; top: 24px; right: 24px; }
.theme.is-open { z-index: 101; }
/* Where Eugene is just now, in the other corner. "In:" is grey, the place is the name. */
.where {
  position: absolute;
  z-index: 3;
  top: 24px;
  left: 24px;
  display: flex;
  align-items: center;
  gap: 7px;
  height: 32px;
  padding: 0 13px 0 10px;
  border-radius: 999px;
  color: var(--name);
  font-weight: 500;
  line-height: 20px;
  white-space: nowrap;
}
.where svg { flex: none; }
.where-label { color: var(--text); font-weight: 400; }
/* On the narrowest phones it says just the place, to keep clear of the Appearance switch. */
@media (max-width: 359px) {
  .where-label { display: none; }
}
/* The menu is frosted; the button and the location are just words on the sky, the button getting
   a soft fill when pointed at. */
.theme-menu {
  background: color-mix(in srgb, var(--paper) 46%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink) 9%, transparent), 0 2px 12px rgb(0 0 0 / 0.06);
  -webkit-backdrop-filter: blur(16px) saturate(1.5);
  backdrop-filter: blur(16px) saturate(1.5);
}
.theme-button {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 32px;
  padding: 0 10px 0 11px;
  border-radius: 999px;
  color: var(--text);
  font-weight: 500;
  line-height: 20px;
  transition: color 200ms, background-color 200ms, box-shadow 200ms;
}
.theme-button:focus-visible { border-radius: 999px; }
/* Grey at rest, like "In:" on the home page (and Back on the inner pages); the name's colour when
   pointed at, reached with Tab, or open. */
.theme-button:focus-visible, .theme.is-open .theme-button,
.theme-button:focus-visible .theme-chevron, .theme.is-open .theme-chevron { color: var(--name); }
@media (hover: hover) {
  .theme-button:hover { color: var(--name); background: color-mix(in srgb, var(--paper) 70%, transparent); }
  .theme-button:hover .theme-chevron { color: var(--name); transform: translateY(1px); }
}
.theme-now { display: none; align-items: center; gap: 7px; }
:root:not([data-theme]) .theme-now[data-mode="auto"],
:root[data-theme="light"] .theme-now[data-mode="light"],
:root[data-theme="dark"] .theme-now[data-mode="dark"] { display: flex; }
.theme-chevron { color: var(--text); transition: transform 250ms cubic-bezier(0.3, 0.7, 0.2, 1), color 200ms; }
.theme.is-open .theme-chevron { transform: rotate(180deg); }
.theme-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  display: grid;
  min-width: 152px;
  padding: 4px;
  border-radius: 14px;
  background: color-mix(in srgb, var(--paper) 74%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink) 9%, transparent), 0 14px 36px rgb(0 0 0 / 0.14);
  opacity: 0;
  transform: translateY(-4px) scale(0.97);
  transform-origin: top right;
  transition: opacity 160ms, transform 220ms cubic-bezier(0.3, 0.7, 0.2, 1);
}
.theme-menu[hidden] { display: none; }
.theme.is-open .theme-menu { opacity: 1; transform: none; }
.theme-menu button {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  height: 34px;
  padding: 0 10px;
  border-radius: 10px;
  color: var(--text);
  font-weight: 500;
  transition: color 200ms;
}
.theme-menu button[aria-checked="true"], .theme-menu button:hover, .theme-menu button:focus-visible { color: var(--ink); }
.theme-menu button:focus-visible { outline: none; }
.theme-menu button > svg:first-child { transition: transform 450ms cubic-bezier(0.3, 1.4, 0.5, 1); }
.theme-menu [data-mode="light"]:hover > svg:first-child, .theme-menu [data-mode="light"]:focus-visible > svg:first-child { transform: rotate(22deg); }
.theme-menu [data-mode="dark"]:hover > svg:first-child, .theme-menu [data-mode="dark"]:focus-visible > svg:first-child { transform: rotate(-12deg); }
.theme-menu [data-mode="auto"]:hover > svg:first-child, .theme-menu [data-mode="auto"]:focus-visible > svg:first-child { transform: rotate(40deg); }
.theme-check { margin-left: auto; opacity: 0; transform: scale(0.6); transition: opacity 200ms, transform 250ms cubic-bezier(0.3, 1.4, 0.5, 1); }
.theme-menu button[aria-checked="true"] .theme-check { opacity: 1; transform: none; }
/* The highlight behind the item under the pointer or the keyboard. */
.theme-hover {
  position: absolute;
  top: 0;
  left: 4px;
  right: 4px;
  height: 34px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--ink) 7%, transparent);
  opacity: 0;
  pointer-events: none;
  transition: transform 260ms cubic-bezier(0.3, 1.25, 0.5, 1), opacity 160ms;
}
.theme-hover.is-on { opacity: 1; }
/* From the keyboard the highlight gets a ring, as the plain links do, so it can't be missed. */
.theme-menu:has(button:focus-visible) .theme-hover { box-shadow: 0 0 0 2px var(--ink); }
/* Safari doesn't count the arrow keys after a click as keyboard use, so script.js marks the switch
   while keys are in use (data-keys) and the same ring shows, on the items and on the button. */
.theme[data-keys] .theme-menu:has(button:focus) .theme-hover { box-shadow: 0 0 0 2px var(--ink); }
.theme[data-keys] .theme-menu button:focus { color: var(--ink); }
.theme[data-keys] .theme-button:focus { outline: 2px solid currentColor; outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
  .theme-menu, .theme-hover, .theme-chevron, .theme-check, .theme-menu button > svg:first-child { transition: none; }
  .theme-menu button > svg:first-child { transform: none !important; }
}

/* The text column on the home page */
.text {
  position: relative;
  z-index: 1;
  width: min(var(--column), 100% - 48px);
  margin: 0 auto;
  padding-top: 96px;
}
/* The photo as a small print: a thin white border and round corners, straight until it's pointed
   at, when it tilts a little. The photo is mirrored, at Eugene's request. */
.portrait {
  --frame: 2px;
  position: relative;
  display: block;
  width: 112px;
  margin-bottom: 30px;
  padding: var(--frame);
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 0 0 1px rgb(0 0 0 / 0.05), 0 2px 4px rgb(0 0 0 / 0.06), 0 12px 28px rgb(0 0 0 / 0.14);
  transition: transform 450ms cubic-bezier(0.3, 1.4, 0.5, 1);
}
.portrait img { display: block; width: 100%; height: auto; border-radius: 10px; }
/* In dark mode the same shot at blue hour (relit from the day one, source/avatar-dusk.png) lies over
   it, and fades in or out as the theme changes. */
.portrait .portrait-dusk {
  position: absolute;
  top: var(--frame);
  left: var(--frame);
  width: calc(100% - 2 * var(--frame));
  height: calc(100% - 2 * var(--frame));
  object-fit: cover;
  opacity: 0;
  transition: opacity 400ms ease;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .portrait .portrait-dusk { opacity: 1; }
}
:root[data-theme="dark"] .portrait .portrait-dusk { opacity: 1; }
@media (hover: hover) {
  .portrait:hover { transform: rotate(-4deg) scale(1.04); }
}
@media (prefers-reduced-motion: reduce) {
  .portrait, .portrait .portrait-dusk { transition: none; }
}
.text > h1, .text > p { color: var(--on-sky); text-wrap: pretty; }
.text > h1 .dash { color: var(--on-sky); }
/* The opening, after amperos.com's hero: a large greeting in Geist Serif, the introduction, and
   two buttons. */
.text > h1.hero-title {
  color: var(--name);
  font-family: "Geist Serif", Georgia, "Times New Roman", serif;
  font-size: clamp(34px, 8.5vw, 44px);
  font-weight: 400;
  line-height: 1.04;
  letter-spacing: -0.02em;
}
.text > .hero-title + p { margin-top: 20px; }
/* The call to action, after framer.com's: a small, flat button with tight type. Pointed at, a soft
   ring comes up around it and it lightens a touch, as on mora.com. Beside it, the email is a plain
   link with a copy icon, which turns into a tick once it's copied. */
.hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; margin-top: 32px; }
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 34px;
  padding: 0 14px;
  border-radius: 8px;
  background: var(--ink);
  color: var(--paper);
  letter-spacing: -0.02em;
  text-decoration: none;
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--ink) 20%, transparent);
  transition: background-color 200ms, box-shadow 200ms, color 200ms;
}
@media (hover: hover) {
  .button:hover {
    background: color-mix(in srgb, var(--ink) 92%, var(--paper));
    color: var(--paper);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--ink) 20%, transparent);
  }
}
/* The ring is the page's ink, not the button's own text colour, which matches the page and vanished. */
.button:focus-visible { outline-color: var(--ink); border-radius: 8px; }
.hero-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--on-sky);
  letter-spacing: -0.02em;
  text-decoration: none;
  transition: color 150ms;
}
.hero-link svg { flex: none; }
.hero-check, .hero-link.is-copied .hero-copy { display: none; }
.hero-link.is-copied .hero-check { display: block; }
@media (hover: hover) {
  .hero-link:hover { color: var(--ink); }
}
.text > p + p { margin-top: 14px; }
.text > p .chip { background: var(--chip-sky); color: var(--name); }
@media (hover: hover) {
  .text > p .chip:hover { background: var(--chip-sky-on); color: var(--ink); }
}
.text > h2 { margin: 56px 0 12px; color: var(--on-sky); }
.not-found > h1 + p { margin-top: 16px; }
.not-found > p .chip { background: var(--chip); }
@media (hover: hover) {
  .not-found > p .chip:hover { background: var(--chip-on); }
}

.jobs { display: grid; row-gap: 12px; line-height: 20px; }
.jobs li:not(.job-feature) {
  display: grid;
  grid-template-columns: 210px 1fr var(--years);
  column-gap: 16px;
}
.jobs li:not(.job-feature) > :first-child { color: var(--name); }
/* The years sit in a column of one width on every row, the card's included, starting at the same
   place each time. */
.jobs { --years: 6.6em; }
.jobs .when { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Each company's logo before its name, as on the old site, and its Y Combinator batch in brackets.
   The fine ring keeps the black logos round on a dark page. */
.job-name { display: flex; align-items: center; gap: 8px; min-width: 0; }
.logo { flex: none; width: 20px; height: 20px; border-radius: 50%; outline: 1px solid var(--hairline); outline-offset: -1px; }
.yc { color: var(--text); font-weight: 400; }

/* Each job's story, from the old site, is in the page for search engines and screen readers. With
   a mouse it comes up as a frosted card under the row, over the rows below, while the row is
   pointed at or reached with the keyboard; on touch screens, which can't point, it's simply
   shown under the row. */
.job { position: relative; isolation: isolate; }
.job::before {
  content: "";
  position: absolute;
  inset: -6px -10px;
  z-index: -1;
  border-radius: 10px;
  background: color-mix(in srgb, var(--ink) 5%, transparent);
  opacity: 0;
  transition: opacity 150ms;
}
.job-note {
  position: absolute;
  top: calc(100% + 10px);
  left: -10px;
  right: -10px;
  z-index: 1;
  padding: 12px 14px;
  border-radius: 14px;
  background: color-mix(in srgb, var(--paper) 84%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink) 9%, transparent), 0 14px 36px rgb(0 0 0 / 0.14);
  -webkit-backdrop-filter: blur(16px) saturate(1.5);
  backdrop-filter: blur(16px) saturate(1.5);
  color: var(--text);
  line-height: 22px;
  /* Plain wrapping, so every line runs to the box's edge; 'pretty' made Safari end them early. */
  opacity: 0;
  transform: translateY(-4px) scale(0.98);
  transform-origin: 50% 0;
  pointer-events: none;
  transition: opacity 160ms, transform 220ms cubic-bezier(0.3, 0.7, 0.2, 1);
}
/* A line of proof under some of them, as on the old site: the App Store rating, a Product Hunt win. */
.job-proof { display: flex; align-items: center; gap: 8px; margin-top: 8px; color: var(--name); }
.job-proof svg { flex: none; }
@media (hover: hover) {
  .job:hover { z-index: 2; }
  .job:hover::before { opacity: 1; }
  .job:hover .job-note { opacity: 1; transform: none; }
}
.job:focus-visible { z-index: 2; outline: none; }
.job:focus-visible::before { opacity: 1; box-shadow: 0 0 0 2px currentColor; }
.job:focus-visible .job-note { opacity: 1; transform: none; }
/* One story at a time. When the keyboard is on one row and the mouse rests on another, whichever
   was used last decides which story shows (script.js marks the list with data-input), and that
   row sits above the rest; the focused row keeps its ring either way. */
@media (hover: hover) {
  .jobs[data-input="keys"] .job:hover:not(:focus-visible)::before { opacity: 0; }
  .jobs[data-input="keys"] .job:hover:not(:focus-visible) .job-note,
  .jobs[data-input="mouse"]:has(.job:hover) .job:focus-visible:not(:hover) .job-note { opacity: 0; transform: translateY(-4px) scale(0.98); }
  .jobs[data-input="keys"] .job:focus-visible,
  .jobs[data-input="mouse"] .job:hover { z-index: 3; }
  /* Escape puts the story away until focus or the mouse moves on to another row (script.js). */
  .jobs[data-dismissed] .job .job-note { opacity: 0; transform: translateY(-4px) scale(0.98); }
}
@media (hover: none) {
  .jobs { row-gap: 20px; }
  .job-note {
    position: static;
    grid-column: 1 / -1;
    margin-top: 4px;
    padding: 0 0 0 28px;
    border-radius: 0;
    background: none;
    box-shadow: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    opacity: 1;
    transform: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .job-note { transform: none; transition: opacity 160ms; }
}

/* Hyperbound, the one job with a case study, as a card at the head of the list. A soft panel
   comes up behind it on hover, and on sharp screens the picture leans towards the cursor, with
   the phone nearest and the sky furthest. script.js sets --mx and --my. */
.job-feature { margin-bottom: 20px; }
.job-card { position: relative; display: block; color: var(--text); text-decoration: none; }
.job-card::before {
  content: "";
  position: absolute;
  inset: -10px;
  z-index: -1;
  border-radius: 16px;
  background: color-mix(in srgb, var(--ink) 3%, transparent);
  opacity: 0;
  transition: opacity 250ms ease-out;
  pointer-events: none;
}
/* 16:9 for the looping film; the still picture, shown instead with reduced motion, is drawn for
   4:3 (below). */
.job-art {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 12px;
  background: var(--card-fill);
  transform: perspective(1100px) rotateX(calc(var(--my, 0) * -1.6deg)) rotateY(calc(var(--mx, 0) * 1.6deg)) scale(var(--lift, 1));
}
/* The fine frame sits over the picture. */
.job-art::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.07);
  pointer-events: none;
}
.job-art img { position: absolute; max-width: none; }
.job-art, .job-art img { transition: transform 500ms cubic-bezier(0.22, 1, 0.36, 1); }
.job-sky {
  inset: -3%;
  width: 106%;
  height: 106%;
  filter: var(--card-sky);
  transform: translate(calc(var(--mx, 0) * 4px), calc(var(--my, 0) * 3px));
}
.job-screen {
  left: 9%;
  top: 13%;
  width: 120%;
  height: auto;
  border-radius: 10px;
  box-shadow: 0 2px 6px rgb(8 40 90 / 0.18), 0 24px 56px rgb(8 40 90 / 0.34);
  transform: translate(calc(var(--mx, 0) * -5px), calc(var(--my, 0) * -3.5px));
}
.job-phone {
  right: 2%;
  top: 25%;
  width: 27%;
  height: auto;
  filter: drop-shadow(0 16px 30px rgb(8 40 90 / 0.42));
  transform: translate(calc(var(--mx, 0) * -10px), calc(var(--my, 0) * -7px));
}
/* The case study's silent preview, looping over the picture while the card is on screen
   (script.js). It fades in once it's playing, so the picture shows until then, and stays the
   whole time with reduced motion. */
.job-film {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 100%;
  opacity: 0;
  transition: opacity 600ms;
}
.job-art.is-moving .job-film { opacity: 1; }
/* Once it has faded in, the picture under it goes, so none of it shows along the rounded edges. */
.job-art.is-moving { background: none; transition: transform 500ms cubic-bezier(0.22, 1, 0.36, 1), background 0s 600ms; }
.job-art.is-moving img { visibility: hidden; transition: visibility 0s 600ms; }
@media (prefers-reduced-motion: reduce) {
  .job-art { aspect-ratio: 4 / 3; }
  .job-film { display: none; }
}
.job-line { display: flex; margin-top: 12px; }
.job-line .dash { margin: 0 5px; }
.job-line .when { flex: none; width: var(--years); margin-left: auto; padding-left: 16px; box-sizing: content-box; }
.job-about { display: block; margin-top: 4px; line-height: 24.5px; text-wrap: pretty; }
@media (hover: hover) {
  .job-card:hover::before { opacity: 1; }
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) and (min-resolution: 1.5dppx) {
  .job-card:hover { --lift: 1.006; }
  .job-card:hover .job-art, .job-card:hover .job-art img { transition: transform 150ms ease-out; }
}
.job-card:focus-visible { outline-color: var(--name); outline-offset: 10px; border-radius: 16px; }
@media (prefers-reduced-motion: reduce) {
  .job-art, .job-art img, .job-card::before { transition: none; }
}



/* The case study: the way back in the top-left corner, where the home page
   says where Eugene is, and set like the Appearance switch: grey words on the sky that turn the
   name's colour, with a soft fill, when pointed at. Then the text in the home page's column, and the work in a wider
   column, one piece under another. */
.case-side { position: absolute; z-index: 3; top: 24px; left: 24px; }
.case-back {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 32px;
  padding: 0 13px 0 10px;
  border-radius: 999px;
  color: var(--text);
  font-weight: 500;
  line-height: 20px;
  text-decoration: none;
  white-space: nowrap;
  transition: color 200ms, background-color 200ms;
}
.case-back svg { flex: none; }
.case-back:focus-visible { color: var(--name); border-radius: 999px; }
@media (hover: hover) {
  .case-back:hover { color: var(--name); background: color-mix(in srgb, var(--paper) 70%, transparent); }
}

/* Positioned so it paints over the film's glow, which reaches up behind it, as .case-more does. */
.case-head { position: relative; z-index: 1; width: min(var(--column), 100% - 48px); margin: 0 auto; padding-top: 96px; }
/* Hyperbound's logo, where the home page has Eugene's photo, in the same space. */
.case-logo { display: block; width: auto; height: 26px; margin: 11px 0 35px; color: var(--name); }
.case-head h1, .case-head p, .case > .case-more { color: var(--on-sky); text-wrap: pretty; }
/* The name, set like the home page's greeting. */
.case-head h1 {
  color: var(--name);
  font-family: "Geist Serif", Georgia, "Times New Roman", serif;
  font-size: clamp(34px, 8.5vw, 44px);
  font-weight: 400;
  line-height: 1.04;
  letter-spacing: -0.02em;
}
/* The batch in brackets, in the grey of the text. */
.case-head h1 .case-batch { color: var(--text); }
/* Like the home page: the dash in the heading and links in the text are no lighter than the text. */
.case-head h1 .dash { color: var(--on-sky); }
.case-head p .chip, .case > .case-more .chip { color: var(--name); }
/* The same size as the home page's introduction. */
.case-head h1 + p { margin-top: 20px; }
.case-head p + p { margin-top: 14px; }

/* The film, in a wider column under the text. */
.shots { width: min(920px, 100% - 48px); margin: 56px auto 0; }
/* The outcome comes after the film. */
.case > .case-more { position: relative; width: min(var(--column), 100% - 48px); margin: 56px auto 0; }
.case ~ .foot { margin-top: 40px; }

/* The film: Eugene's own copy of the video in the X post. film.js gives it a quiet player of its
   own; without JavaScript it's the browser's. */
/* No taller than the window, so on landscape phones, short laptop windows and when zoomed the bar
   (pause, full screen) is on screen whenever the film is. */
.film-figure {
  position: relative;
  isolation: isolate;
  max-width: calc((100vh - 48px) * 1570 / 1080);
  max-width: calc((100svh - 48px) * 1570 / 1080);
  margin-inline: auto;
}
.film-figure figcaption { margin: 10px 0 8px; line-height: 20px; text-align: center; text-wrap: balance; }
/* A soft glow behind the film takes its colours from the picture, the way YouTube's ambient mode
   does: fainter in light mode, where it tints the white page, fuller in dark mode. film.js draws it,
   already soft, into a small canvas a quarter of the film's width wider on each side and 30% of its
   height taller above and below (the margin-top is a share of the width, which is how 30% of the
   film's height can be written). */
.film-glow {
  position: absolute;
  left: -25%;
  top: 0;
  z-index: -1;
  display: block;
  width: 150%;
  margin-top: -20.64%;
  aspect-ratio: 1.3628;
  opacity: 0.45;
  pointer-events: none;
  /* It fades out before the text around the film, so that keeps its contrast: above the film, below
     it before the caption, and at its outer sides. In light mode the grey text has almost no contrast
     to spare against white, so the glow is gone by the film's bottom edge and a little sooner at the
     sides; dark mode (below) lets it reach further. */
  --glow-fade: linear-gradient(transparent 11%, #000 21%, #000 74%, transparent 81.25%), linear-gradient(90deg, transparent 8%, #000 18%, #000 82%, transparent 92%);
  -webkit-mask-image: var(--glow-fade);
  -webkit-mask-composite: source-in;
  mask-image: var(--glow-fade);
  mask-composite: intersect;
}
/* Browsers that can't soften inside a canvas blur it here instead. */
.film-glow.is-plain { filter: blur(44px); }
/* The glow may reach past the window's sides on phones; it's cut there rather than widening the page. */
.case { overflow-x: clip; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .film-glow {
    opacity: 0.7;
    --glow-fade: linear-gradient(transparent 11%, #000 21%, #000 75%, transparent 87%), linear-gradient(90deg, transparent 4%, #000 16%, #000 84%, transparent 96%);
  }
}
:root[data-theme="dark"] .film-glow {
  opacity: 0.7;
  --glow-fade: linear-gradient(transparent 11%, #000 21%, #000 75%, transparent 87%), linear-gradient(90deg, transparent 4%, #000 16%, #000 84%, transparent 96%);
}
.film-figure figcaption a { white-space: nowrap; }
.film {
  position: relative;
  isolation: isolate;
  /* Clipped but not scrollable, so a control taking the keyboard can't scroll the picture inside
     it (the preview reaches past the edges); older browsers fall back to hidden. */
  overflow: hidden;
  overflow: clip;
  aspect-ratio: 1570 / 1080;
  border-radius: 12px;
  /* The poster again behind the video, for when Safari paints neither (after Back or Forward). */
  background: #2a87c8 url("/work/hyperbound/film/poster.webp") center / cover;
  color: #fff;
  -webkit-tap-highlight-color: transparent;
  /* Its controls are laid out by the film's own width (the @container rules below). */
  container-type: inline-size;
}
.film::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px var(--hairline);
  pointer-events: none;
}
.film video { display: block; width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
.film.is-playing:not(.is-awake) { cursor: none; }
.film :focus-visible { outline-color: #fff; }
/* The Play button's white ring has a dark one just inside it, so it shows over bright frames too. */
.film .film-play:focus-visible { box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.3), 0 0 0 3px rgb(0 0 0 / 0.55); }

/* Before it starts: a Play button in the middle of the poster, between its two names, in frosted
   glass over the picture, as on attio.com's video. The glass also dims what's behind it a little,
   so the white words read over the bright poster as well as the softened preview. */
.film-play {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 44px;
  padding: 0 20px 0 17px;
  border-radius: 999px;
  background: rgb(255 255 255 / 0.12);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.3);
  -webkit-backdrop-filter: blur(20px) brightness(0.72) saturate(1.3);
  backdrop-filter: blur(20px) brightness(0.72) saturate(1.3);
  color: #fff;
  font-size: 15px;
  font-weight: 500;
  line-height: 20px;
  text-decoration: none;
  transform: translate(-50%, -50%);
  transition: transform 200ms, opacity 200ms, visibility 0s, background-color 200ms;
}
.film-play svg { width: 15px; height: 15px; }
@media (hover: hover) {
  .film:hover .film-play { transform: translate(-50%, -50%) scale(1.04); }
  /* The words stay white: the site's link hover would turn the link to X dark in light mode. */
  .film-play:hover { background: rgb(255 255 255 / 0.2); color: #fff; }
}
.film:not(.is-idle) .film-play, .film-out, .film.is-failed .film-play:not(.film-out) {
  opacity: 0;
  visibility: hidden;
  transition: transform 200ms, opacity 200ms, visibility 0s 200ms;
}
.film.is-failed .film-out { opacity: 1; visibility: visible; transition: opacity 200ms; }
/* While it fades, the link to X no longer takes the clicks meant for Play. A film that can't play
   shows its poster behind the link, wherever it stopped. */
.film:not(.is-failed) .film-out { pointer-events: none; }
.film.is-failed video { visibility: hidden; }

/* Until the film is played, a ten-second silent stretch of it loops over the poster while it's on
   screen (film.js), as skale.solutions does. With a mouse, the Play button comes up over a softened
   picture only when the film is pointed at; on a touch screen it stays. */
/* It reaches 20px past every edge, out of sight, so that softening it leaves no pale rim where the
   blur runs out of picture. */
.film .film-preview {
  position: absolute;
  left: -20px;
  top: -20px;
  width: calc(100% + 40px);
  height: calc(100% + 40px);
  border-radius: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 500ms, filter 300ms;
}
.film.is-previewing .film-preview { opacity: 1; }
.film:not(.is-idle) .film-preview { visibility: hidden; opacity: 0; transition: none; }
@media (hover: hover) {
  .film.is-previewing.is-idle .film-play:not(.film-out) { opacity: 0; }
  .film.is-previewing.is-idle:hover .film-play:not(.film-out),
  .film.is-previewing.is-idle .film-play:not(.film-out):focus-visible { opacity: 1; }
  .film.is-previewing.is-idle:hover .film-preview { filter: blur(8px) brightness(0.7); }
}

/* While it plays: a bar that comes up with the pointer, or a tap. */
.film-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 56px 10px 6px;
  background: linear-gradient(rgb(0 0 0 / 0), rgb(0 0 0 / 0.45) 45%, rgb(0 0 0 / 0.7));
  text-shadow: 0 1px 3px rgb(0 0 0 / 0.5);
  font-size: 13px;
  line-height: 20px;
  /* A double click on the times doesn't select them. */
  -webkit-user-select: none;
  user-select: none;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 250ms;
}
/* Faded out while it plays, but still there for the keyboard: focus brings it back. */
.film:not(.is-idle):not(.is-failed) .film-bar { visibility: visible; }
.film.is-awake:not(.is-idle):not(.is-failed) .film-bar { opacity: 1; }
/* Only the controls take clicks; the shade behind them lets clicks through to the picture. */
.film.is-awake:not(.is-idle):not(.is-failed) .film-bar > * { pointer-events: auto; }
.film-bar button { width: 36px; height: 36px; border-radius: 8px; color: #fff; }
/* The icons are swapped as they change, so the pointer is always over the button itself. */
.film-bar button svg { width: 16px; height: 16px; filter: drop-shadow(0 1px 2px rgb(0 0 0 / 0.4)); pointer-events: none; }
.film-bar button:focus-visible { outline-offset: -2px; }
.film-time { min-width: 36px; text-align: center; font-variant-numeric: tabular-nums; }
.film-scrub { position: relative; flex: 1; min-width: 0; height: 36px; margin: 0 6px; }
.film-track {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 3px;
  margin-top: -1.5px;
  overflow: hidden;
  border-radius: 2px;
  background: rgb(255 255 255 / 0.28);
  pointer-events: none;
}
.film-loaded, .film-played { position: absolute; top: 0; bottom: 0; left: 0; }
.film-loaded { width: var(--loaded, 0%); background: rgb(255 255 255 / 0.3); }
.film-played { width: var(--played, 0%); background: #fff; }
.film-seek {
  position: relative;
  display: block;
  width: 100%;
  height: 36px;
  margin: 0;
  background: transparent;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
.film-seek::-webkit-slider-runnable-track { height: 3px; background: transparent; }
.film-seek::-moz-range-track { height: 3px; background: transparent; }
.film-seek::-webkit-slider-thumb {
  width: 12px;
  height: 12px;
  margin-top: -4.5px;
  border-radius: 50%;
  background: #fff;
  transform: scale(0);
  transition: transform 150ms;
  -webkit-appearance: none;
  appearance: none;
}
.film-seek::-moz-range-thumb { width: 12px; height: 12px; border: 0; border-radius: 50%; background: #fff; transform: scale(0); transition: transform 150ms; }
.film-seek:hover::-webkit-slider-thumb, .film-seek:active::-webkit-slider-thumb, .film-seek:focus-visible::-webkit-slider-thumb { transform: scale(1); }
.film-seek:hover::-moz-range-thumb, .film-seek:active::-moz-range-thumb, .film-seek:focus-visible::-moz-range-thumb { transform: scale(1); }
.film-seek:focus-visible { outline-offset: -6px; }
@media (hover: none) {
  .film-seek::-webkit-slider-thumb { transform: scale(1); }
  .film-seek::-moz-range-thumb { transform: scale(1); }
}
/* Shown only if the film is slow to come, so a quick start doesn't flash it. */
.film-wait {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 28px;
  height: 28px;
  margin: -14px 0 0 -14px;
  border: 2px solid rgb(255 255 255 / 0.3);
  border-top-color: #fff;
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms;
  animation: film-wait 800ms linear infinite;
}
.film.is-waiting .film-wait { opacity: 1; }
@keyframes film-wait { to { transform: rotate(1turn); } }
@media (prefers-reduced-motion: reduce) {
  .film-wait { animation-duration: 2400ms; }
}
.film:fullscreen { border-radius: 0; background: #000; }
.film:fullscreen video { object-fit: contain; }
.film:-webkit-full-screen { width: 100%; height: 100%; border-radius: 0; background: #000; }
.film:-webkit-full-screen video { object-fit: contain; }

@media (max-width: 640px) {
  .case-head { padding-top: 72px; }
}
/* A small film (on a phone, a phone on its side, a short or zoomed-in window): a slimmer bar, and
   the poster's names leave no room in the middle, so the Play button sits at the bottom, under them. */
@container (max-width: 640px) {
  .film-bar { padding: 44px 4px 2px; }
  .film-time.film-end { display: none; }
  .film-play { top: auto; bottom: 12px; height: 40px; padding: 0 16px 0 14px; font-size: 14px; transform: translateX(-50%); }
}
@media (hover: hover) {
  @container (max-width: 640px) {
    .film:hover .film-play { transform: translateX(-50%) scale(1.04); }
  }
}
/* Windows high contrast: keep the player's own white-on-shade controls, which the system colours
   would otherwise lose against the picture, and give the Play button the system's focus colour
   between rings of the page colour, so it shows over any frame. The rings drawn as shadows (the
   plain links, Copy email, the job rows, the menu items) would vanish, so those get an outline in
   the system's text colour; the small print on the footer photo keeps its own colours and ring.
   The glow behind the film is only decoration, so it goes. */
@media (forced-colors: active) {
  .film-bar, .film-play, .film-wait { forced-color-adjust: none; }
  .film-glow { display: none; }
  .film .film-play:focus-visible { outline-color: Highlight; box-shadow: 0 0 0 7px Canvas; }
  :is(.film-figure figcaption a, .hero-link, .job):focus-visible { outline: 2px solid CanvasText; outline-offset: 4px; }
  .theme-menu button:focus-visible { outline: 2px solid CanvasText; outline-offset: -2px; }
  .foot-small { forced-color-adjust: none; }
}

/* The footer: contact details in the text column, then a photograph of a Highland viaduct
   that comes up out of the page through its own sky. */
.foot { margin-top: 96px; }
/* Laid out like Plait's footer, on the page's own column: the name and year where the companies
   start, the contact links ending where the years do. */
.foot-top {
  position: relative;
  z-index: 1;
  width: min(var(--column), 100% - 48px);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr auto;
  column-gap: 16px;
  line-height: 20px;
}
/* One heading over two columns of links, the block against the grid's right edge. */
.foot-contact { grid-column: 2; }
.foot-contact ul { grid-template-rows: repeat(2, auto); grid-auto-flow: column; column-gap: 40px; }
/* Email, with a button beside it that copies the address. It shows on hover, on keyboard focus,
   and always on touch screens, which have no hover. */
.foot-email { display: flex; align-items: center; gap: 8px; }
.copy { width: 24px; height: 24px; margin-block: -2px; border-radius: 6px; color: var(--text); opacity: 0; transition: opacity 150ms, color 150ms, background-color 150ms; }
.foot-email:hover .copy, .copy:focus-visible, .copy.done { opacity: 1; }
@media (hover: hover) {
  .copy:hover { color: var(--ink); background: color-mix(in srgb, var(--ink) 7%, transparent); }
}
@media (hover: none) {
  .copy { opacity: 1; }
}
.copy-done { display: none; }
.copy.done .copy-idle { display: none; }
.copy.done .copy-done { display: block; }
.foot-top h2 { margin-bottom: 12px; line-height: 24.5px; }
.foot-top ul { display: grid; row-gap: 8px; }

.foot-art {
  position: relative;
  z-index: 0;
  margin-top: -32px;
  aspect-ratio: 5504 / 3072;
  max-height: 100vh;
  width: 100%;
  overflow: hidden;
  /* Dark low down, so the white small print reads before the picture has arrived. */
  background: linear-gradient(var(--paper) 40%, #2f3a2c);
}
.foot-art > img, .foot-art canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--foot-x) 100%;
}
.foot-art { --foot-x: 50%; }

.foot-art canvas { opacity: 0; transition: opacity 800ms; }
.foot-art canvas.on { opacity: 1; }

/* The empty viaduct by day, and at blue hour in dark mode. */
.foot-art .dusk { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .foot-art .day { display: none; }
  :root:not([data-theme="light"]) .foot-art .dusk { display: block; }
}
:root[data-theme="dark"] .foot-art .day { display: none; }
:root[data-theme="dark"] .foot-art .dusk { display: block; }

/* The sky fades into the page along the mountains rather than along a straight line: as before at
   the sides, and deeper in the valley between them. The mask (scripts/footer-fade.mjs) has the
   picture's own shape and is placed exactly as the picture is, so it lands on the same mountains
   at every size, light and dark. Its second layer keeps the top edge soft when a wide window crops
   the picture's top. */
.foot-art {
  -webkit-mask: var(--foot-fade, url(/footer/sky-fade.png)) var(--foot-x) 100% / cover no-repeat, linear-gradient(transparent, #000 90px);
  -webkit-mask-composite: source-in;
  mask: var(--foot-fade, url(/footer/sky-fade.png)) var(--foot-x) 100% / cover no-repeat, linear-gradient(transparent, #000 90px);
  mask-composite: intersect;
}

/* Over the picture and the train, under the signature: the look Eugene picked from five tried.
   Fine scanlines and a vignette are drawn by ::after below; a faint colour
   grille and moving grain are layers of their own, since they blend with the picture. All of it
   is inside the mask, so it goes with the sky. The grain moves only while the footer is in view. */
.foot-grille, .foot-grain { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.foot-grille {
  opacity: 0.45;
  mix-blend-mode: multiply;
  background: repeating-linear-gradient(to right, #ff7a7a 0 1px, #7aff7a 1px 2px, #7a9bff 2px 3px);
}
.foot-grain { overflow: hidden; opacity: 0.4; mix-blend-mode: overlay; }
.foot-grain::before {
  content: "";
  position: absolute;
  inset: -50%;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='256'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' seed='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E") 0 0 / 180px 180px;
  animation: foot-grain 0.9s steps(1) infinite paused;
}
.at-foot .foot-grain::before { animation-play-state: running; }
@keyframes foot-grain {
  0%, 100% { transform: translate(0, 0); }
  12% { transform: translate(-7%, 4%); }
  25% { transform: translate(5%, -9%); }
  37% { transform: translate(-3%, 8%); }
  50% { transform: translate(9%, 2%); }
  62% { transform: translate(-8%, -6%); }
  75% { transform: translate(3%, 9%); }
  87% { transform: translate(-5%, -3%); }
}
@media (prefers-reduced-motion: reduce) {
  .foot-grain::before { animation: none; }
}

/* The scanlines and the vignette, and a little shade at the bottom for the signature. */
.foot-art::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(to top, rgb(0 0 0 / 0.5), rgb(0 0 0 / 0.24) 90px, transparent 190px),
    radial-gradient(ellipse 75% 85% at 50% 60%, transparent 55%, rgb(0 0 0 / 0.8) 100%),
    repeating-linear-gradient(to bottom, rgb(0 0 0 / 0.28) 0 1px, transparent 1px 4px);
  pointer-events: none;
}

/* The signature, centred on the picture. */
/* Along the bottom of the picture: the name and year on the left, the signature in the middle and
   LinkedIn and X on the right, all in the signature's light grey. On a phone the signature sits
   above the other two. */
.foot-small {
  position: absolute;
  z-index: 2;
  left: 24px;
  right: 24px;
  bottom: 20px;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: end;
  column-gap: 16px;
  row-gap: 10px;
  color: #d1d1d1;
  line-height: 20px;
  text-shadow: 0 1px 10px rgb(0 0 0 / 0.4);
}
.foot-credit { justify-self: start; }
.foot-social { display: flex; justify-self: end; gap: 20px; }
.foot-social a { position: relative; z-index: 0; display: inline-block; color: inherit; transition: color 150ms; }
.foot-social a::before {
  content: '';
  position: absolute;
  inset: -2px -6px;
  z-index: -1;
  border-radius: 6px;
  background: rgb(255 255 255 / 0.14);
  opacity: 0;
  transform: scale(0.94);
  transition: opacity 150ms, transform 220ms cubic-bezier(0.3, 1.25, 0.5, 1);
}
.foot-social a:active::before { opacity: 1; transform: none; }
@media (hover: hover) {
  .foot-social a:hover { color: #fff; }
  .foot-social a:hover::before { opacity: 1; transform: none; }
}
.foot-social a:focus-visible { outline: none; }
.foot-social a:focus-visible::before { opacity: 1; transform: none; box-shadow: 0 0 0 2px currentColor; }
@media (max-width: 640px) {
  .foot-small { grid-template-columns: 1fr auto; }
  .foot-signature { grid-column: 1 / -1; grid-row: 1; justify-self: center; }
}
/* A light grey rather than white, at Eugene's request. */
.foot-signature {
  width: clamp(115px, 11.9vw, 165px);
  filter: brightness(0.82) drop-shadow(0 1px 6px rgb(0 0 0 / 0.35));
}

/* Below 1000 wide the picture is cropped at the sides instead, around the train and the loch. */
@media (max-width: 1000px) {
  .foot-art { --foot-x: 60%; }
}
@media (min-width: 641px) and (max-width: 1000px) {
  .foot-art { aspect-ratio: 4 / 3; }
}

@media (max-width: 640px) {
  .text { padding-top: 72px; }
  .jobs li:not(.job-feature), .job-line { display: grid; grid-template-columns: 1fr var(--years); column-gap: 16px; }
  .jobs .role { grid-column: 1 / -1; grid-row: 2; padding-left: 28px; }
  .jobs .job-note { grid-row: 3; }
  .job-line .dash { display: none; }
  .job-line .when { width: auto; margin-left: 0; padding-left: 0; grid-column: 2; grid-row: 1; }

  .foot { margin-top: 80px; }
  .foot-art { margin-top: -16px; aspect-ratio: 4 / 5; }
}

@media print {
  :root, :root:not([data-theme="light"]), :root[data-theme="dark"] {
    --paper: #fff;
    --ink: #000;
    --name: #000;
    --text: #333;
    --on-sky: #333;
    --dash: #6f7778;
    --chip: transparent;
    --chip-text: #000;
    --hairline: rgb(0 0 0 / 0.08);
    --card-sky: none;
    --under: #fff;
    color-scheme: light;
  }
  .sky, .theme, .case-side, .film-figure, .foot-art, .copy { display: none; }
  .jobs { display: block; }
  .jobs > li { margin-top: 12px; }
  .chip { margin: 0; padding: 0; }
  .job-feature { break-inside: avoid; }
}
