/* Press Enter. A dark page around one darker, louder window.
   Two voices: the grotesque says what a thing is (names, buttons, facts);
   the slab, a typewriter's descendant, says what you get from it (slogans and promises),
   and those lines are typed in.
   One yellow, the enter key's, used only on keys, the caret and the dot of a button.
   The light palette this replaced: ground #eceef1, ink #000, mute #5b6068, line #d2d6dd,
   soft #dde1e7, error #b42318. */

:root {
  color-scheme: dark;
  --ground: #111216;
  --ink: #f2f3f5;
  --mute: #a1a7b0;
  --line: #2b2e35;
  --soft: #1e2026;
  --dark: #0d0e11;
  --go: #ffcc00;
  --error: #ff6b5b;

  --sans: "Host Grotesk", "Helvetica Neue", Arial, sans-serif;
  --slab: "Zilla Slab", Rockwell, "Roboto Slab", Georgia, serif;
  --mono: "JetBrains Mono", ui-monospace, Menlo, monospace;
  /* The arrow on every square button: up and to the right. */
  --arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 9.5 9.5 2.5M3.5 2.5h6v6' fill='none' stroke='black' stroke-width='1.6'/%3E%3C/svg%3E");

  --pad: clamp(1.25rem, 4.6vw, 4.5rem);
  --gap: clamp(0.75rem, 2vw, 2rem);
  --radius: 4px;
  --settle: cubic-bezier(0.2, 0.75, 0.1, 1);
  /* Room a page leaves at its top for the fixed header. */
  --clear: clamp(7.5rem, 11vw, 10.5rem);
}

/* Going from one page to the next, the header stays put and the rest cross-fades. A project's
   small preview and its full frame share a name, so one grows into the other. */
@view-transition {
  navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 320ms;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: 5.5rem;
}

html.is-intro {
  overflow: hidden;
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.0625rem;
  font-weight: 400;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection {
  background: var(--go);
  color: var(--dark);
}

img,
canvas {
  max-width: none;
}

a {
  color: inherit;
}

:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 4px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip {
  position: fixed;
  left: var(--pad);
  top: -5rem;
  z-index: 200;
  padding: 0.7rem 1.1rem;
  background: var(--ink);
  color: var(--dark);
  border-radius: 999px;
}

.skip:focus {
  top: 0.75rem;
}

/* The slab voice, upright and light like something just typed, now lives only in the hero. */

.hero__line,
.stage__title {
  font-family: var(--slab);
  font-weight: 300;
}

/* Everywhere else the display voice is the grotesque, set bold and tight. */

.lede__line,
.about__lead,
.me__title,
.services__title,
.service__line,
.lost__title {
  font-family: var(--sans);
  font-weight: 600;
}

.project__say,
.card__line,
.lead__line {
  font-family: var(--sans);
  font-weight: 500;
}

/* Buttons: a dark pill whose dot swells when you reach for it */

.pill {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  height: 3rem;
  padding: 0 1.15rem 0 1.45rem;
  border: 0;
  border-radius: 999px;
  background: #fff;
  color: var(--dark);
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 400ms var(--settle), color 400ms var(--settle);
  -webkit-tap-highlight-color: transparent;
}

.pill::after {
  content: "";
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--go);
  transition: transform 500ms var(--settle);
}

.pill:hover::after {
  transform: scale(2.1);
}

.pill:active {
  transform: scale(0.97);
}

.pill--light {
  background: var(--soft);
  color: var(--ink);
}

/* Header */

.top {
  position: fixed;
  inset: 0 0 auto;
  z-index: 40;
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: clamp(1rem, 2.4vw, 2.4rem) var(--pad) 0;
  pointer-events: none;
  transition: color 400ms linear;
  view-transition-name: top;
}

.top > * {
  pointer-events: auto;
}

.top__name {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-right: auto;
  padding: 0.3rem 1rem 0.3rem 0.3rem;
  border-radius: 999px;
  transition: background-color 400ms linear;
  font-size: clamp(1.15rem, 1.5vw, 1.5rem);
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
}

/* The logo: the yellow enter key. It dips when pressed, like the real thing. */
.brand__key {
  width: 2.4rem;
  height: 2.4rem;
  flex: none;
  transition: transform 180ms var(--settle);
}

.brand__key rect {
  fill: var(--go);
}

.brand__key path {
  fill: none;
  stroke: var(--dark);
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.top__name:hover .brand__key {
  transform: translateY(2px) scale(0.96);
}

.lang,
.tabs {
  gap: 0.15rem;
  padding: 0 0.35rem;
}

.lang::after,
.tabs::after {
  content: none;
}

/* The tabs: one per page. The page you are on is the lit one. */
.tabs a {
  display: inline-flex;
  align-items: center;
  height: 2.3rem;
  padding: 0 0.85rem;
  border-radius: 999px;
  color: inherit;
  text-decoration: none;
  opacity: 0.72;
  transition: opacity 300ms linear, background-color 300ms linear;
}

.tabs a:hover,
.tabs a[aria-current] {
  opacity: 1;
}

.tabs a[aria-current] {
  background: rgba(255, 255, 255, 0.14);
}

.lang button {
  appearance: none;
  height: 2.3rem;
  min-width: 2.6rem;
  padding: 0 0.6rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
  opacity: 0.66;
  transition: opacity 300ms linear, background-color 300ms linear;
}

.lang button[aria-pressed="true"] {
  background: rgba(255, 255, 255, 0.14);
  opacity: 1;
}

.js.is-ready .top.is-away > * {
  opacity: 0;
  transform: translateY(-9rem);
  pointer-events: none;
}

/* Over the dark window the header turns light */

.top.is-dark {
  color: #fff;
}

.top.is-dark .pill {
  background: #fff;
  color: var(--dark);
}

/* Over bright keys a see-through chip would vanish, so the light controls get a dark backing. */
.top.is-dark .pill--light,
.top.is-dark .top__name {
  background: rgba(13, 14, 17, 0.72);
  color: #fff;
}

.top.is-dark .top__name {
  padding: 0.3rem 1rem 0.3rem 0.3rem;
  border-radius: 999px;
}

.top.is-dark .lang button[aria-pressed="true"],
.top.is-dark .tabs a[aria-current] {
  background: rgba(255, 255, 255, 0.2);
}

/* Typed text: letters appear one by one behind a yellow caret, in time or with the scroll */

.tw {
  white-space: nowrap;
}

.js [data-type] .c {
  position: relative;
  opacity: 0;
}

.js [data-type] .c.is-on {
  opacity: 1;
}

.js [data-type] .c.is-last::after {
  content: "";
  position: absolute;
  left: calc(100% + 0.08em);
  bottom: 0.1em;
  width: 0.42em;
  height: 0.78em;
  background: var(--go);
}

.js [data-type].is-typed .c.is-last::after {
  animation: caret 1.05s steps(1) infinite;
}

@keyframes caret {
  50% {
    opacity: 0;
  }
}

/* Hero: the 3D window fills the screen from the very top, edge to edge, with the slogan and
   the work index in a bar under it. It is pinned while the window grows over that bar and
   the camera dives into the keys. */

.hero {
  height: 275vh;
}

.hero__pin {
  position: sticky;
  top: 0;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
}

.hero__slot {
  min-height: 12rem;
}

.hero__bar {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gap);
  align-items: end;
  padding: clamp(0.9rem, 1.7vw, 1.6rem) var(--pad) clamp(0.9rem, 1.6vw, 1.5rem);
  opacity: calc(1 - var(--e, 0) * 2.4);
  transform: translateY(calc(var(--e, 0) * 2.5rem));
}

.hero__line {
  grid-column: 1 / span 7;
  margin: 0;
  font-size: clamp(1.7rem, 3.1vw, 3.3rem);
  line-height: 1.08;
  letter-spacing: -0.022em;
}

.index {
  grid-column: 9 / -1;
  font-size: 0.9375rem;
}

.index a {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.32rem 0;
  border-top: 1px solid var(--line);
  text-decoration: none;
}

.index a span:first-child {
  font-weight: 500;
}

.index a span:last-child {
  color: var(--mute);
}

.index a:hover span:first-child {
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

.index__hint {
  margin: 0;
  padding-top: 0.4rem;
  border-top: 1px solid var(--line);
  color: var(--mute);
}

/* The window. Its position and size are set from the script; the canvas inside always
   covers the whole viewport, so growing the window only reveals more of the same picture. */

.stage,
.stage-end {
  margin: 0;
  overflow: hidden;
  background: #0a0b0e;
}

.stage-end {
  border-radius: var(--radius);
}

.stage {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 5;
  width: 100%;
  height: 80%;
}

.scene {
  position: absolute;
  left: 0;
  top: 0;
  display: block;
  visibility: hidden;
}

.has-gl .scene {
  visibility: visible;
}

.stage__poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.has-gl .stage__poster {
  visibility: hidden;
}

/* The slogan inside the dive is written by the scroll. It types "Proof, not", tries two words,
   backspaces each, and settles on "promises." Every new letter lands like a pressed key, and
   the two lines slide past each other as you go by. Scroll back up and it un-types itself. */
.stage__title {
  position: absolute;
  left: var(--pad);
  right: var(--pad);
  bottom: 9vh;
  margin: 0;
  color: #fff;
  font-size: clamp(1.9rem, 6.2vw, 6.6rem);
  line-height: 1;
  letter-spacing: -0.035em;
  pointer-events: none;
  opacity: var(--title-o, 0);
  transform: translateY(var(--title-y, 0));
}

.slogan__line {
  display: block;
  min-height: 1em;
  white-space: pre;
  transform: translateX(var(--title-x, 0));
}

.slogan__line + .slogan__line {
  transform: translateX(calc(var(--title-x, 0) * -1));
}

.slogan__new {
  display: inline-block;
  animation: keystroke 240ms var(--settle);
}

@keyframes keystroke {
  from {
    opacity: 0.2;
    transform: translateY(0.24em) scale(0.88);
  }
}

.slogan__caret {
  display: inline-block;
  width: 0.42em;
  height: 0.78em;
  margin-left: 0.08em;
  background: var(--go);
  transform: translateY(0.06em);
}

.stage__title.is-typed .slogan__caret {
  animation: caret 1.05s steps(1) infinite;
}

/* Words and letters arrive from below, tilted, and settle */

.cw {
  display: inline-block;
  overflow: hidden;
  padding: 0.1em 0.06em 0.14em 0;
  margin: -0.1em -0.06em -0.14em 0;
  vertical-align: top;
}

.js [data-chars] .c {
  display: inline-block;
  transform: translateY(112%) rotate(9deg);
  transform-origin: 0 100%;
  transition: transform 900ms var(--settle);
  transition-delay: calc(var(--i) * 24ms);
}

.js [data-chars].is-in .c {
  transform: none;
}

.js [data-rise] .w {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.9em) rotate(5deg);
  transform-origin: 0 100%;
  transition: transform 800ms var(--settle), opacity 300ms linear;
  transition-delay: calc(var(--i) * 34ms);
}

.js [data-rise].is-in .w {
  opacity: 1;
  transform: none;
}

.js .top > *,
.js .index > * {
  opacity: 0;
  transform: translateY(1.5rem);
  transition: transform 800ms var(--settle), opacity 400ms linear;
}

.js .top > *:nth-child(2),
.js .index > *:nth-child(2) {
  transition-delay: 80ms;
}

.js .top > *:nth-child(3),
.js .index > *:nth-child(3) {
  transition-delay: 160ms;
}

.js .index > *:nth-child(4) {
  transition-delay: 240ms;
}

.js.is-ready .top > *,
.js.is-ready .index > * {
  opacity: 1;
  transform: none;
}

.js [data-scrub] .s {
  opacity: 0.16;
  transition: opacity 350ms linear;
}

.js [data-scrub] .s.is-on {
  opacity: 1;
}

/* Intro */

.intro {
  display: none;
}

.js .intro {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: block;
}

.js .intro.is-done,
.js.no-intro .intro {
  display: none;
}

.intro__mask {
  position: absolute;
  inset: 0;
  display: block;
}

.intro__shade {
  fill: #0a0b0e;
}

.intro__key {
  fill: var(--go);
}

.intro__arrow {
  fill: none;
  stroke: var(--dark);
  stroke-width: 8.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.intro__count,
.intro__bar {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  transition: opacity 150ms linear;
}

.intro__count {
  top: calc(50% + 11vmin);
  margin: 0;
  padding: 0.1em 0.5em;
  /* Same colour as the shade behind it, so the white digits never depend on the SVG alone. */
  background: #0a0b0e;
  color: #fff;
  font-size: 0.9375rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.08em;
}

.intro__bar {
  top: calc(50% + 11vmin + 2rem);
  width: 6rem;
  height: 2px;
  background: rgba(255, 255, 255, 0.18);
}

.intro__bar span {
  display: block;
  height: 100%;
  background: var(--go);
  transform: scaleX(0);
  transform-origin: 0 50%;
}

.intro.is-opening .intro__count,
.intro.is-opening .intro__bar {
  opacity: 0;
}

/* Big link lines: a keycap and a plain promise, each one a way into another page. */

.lede__intro {
  margin: 0 0 clamp(1.25rem, 2.4vw, 2.4rem);
  color: var(--mute);
  font-size: clamp(1.0625rem, 1.45vw, 1.45rem);
  font-weight: 400;
}

.lede__line {
  display: flex;
  align-items: center;
  gap: 0.3em;
  width: fit-content;
  max-width: 100%;
  padding-block: 0.1em;
  font-size: clamp(1.7rem, 5.3vw, 5.7rem);
  line-height: 1.04;
  letter-spacing: -0.035em;
  text-decoration: none;
  transition: transform 500ms var(--settle);
}

.lede__line:hover {
  transform: translateX(0.22em);
}

/* A keycap drawn in type, in the three colours of the 3D keys. */
.cap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 1.8em;
  height: 1.68em;
  border-radius: 0.4em;
  background: #fff;
  box-shadow: 0 0.15em 0 #c4c8cf;
  color: var(--dark);
  font-family: var(--sans);
  font-size: 0.48em;
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1;
  transform: translateY(-0.08em);
  transition: transform 120ms ease-out, box-shadow 120ms ease-out;
}

/* On the dark ground the black key is lifted a little, so it still reads as a key. */
.cap--black {
  background: #2a2d34;
  box-shadow: 0 0.15em 0 #000;
  color: #fff;
}

.cap--go {
  background: var(--go);
  box-shadow: 0 0.15em 0 #c79f00;
}

.lede__line:hover .cap,
.lede__line:active .cap,
.card:hover .cap,
.card:active .cap,
.service:hover .cap {
  box-shadow: 0 0 0 transparent;
  transform: translateY(0.07em);
}

/* A project: its site fills the screen edge to edge, from the very top, and is pinned there while
   the scroll runs it from first screen to footer. The track's extra height (set from the script)
   is the distance that takes. A slim bar underneath names the project and says what it does. */

.project {
  padding-bottom: clamp(2rem, 5vw, 5rem);
}

.project__track {
  height: calc(100vh + var(--tour, 0px));
  height: calc(100svh + var(--tour, 0px));
}

.project__pin {
  position: sticky;
  top: 0;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  height: 100vh;
  height: 100svh;
}

.shot {
  position: relative;
  min-height: 0;
  overflow: hidden;
  background: #0a0b0e;
  clip-path: inset(
    calc((1 - var(--in, 1)) * 8%) calc((1 - var(--in, 1)) * 5%) round calc(var(--radius) * (1 - var(--in, 1)) * 4)
  );
}

.shot.is-open {
  clip-path: none;
}

/* The still capture shows until the live site or the recording is ready, and stays if neither loads. */
.shot__page {
  position: absolute;
  left: 0;
  top: 0;
  display: block;
  width: 100%;
  height: auto;
  will-change: transform;
}

.shot__live,
.shot__film {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  background: #fff;
  opacity: 0;
  transition: opacity 400ms linear;
}

/* The page's own scroll drives the site inside, so the frame itself does not take the pointer. */
.shot__live {
  pointer-events: none;
}

.shot__film {
  object-fit: cover;
  object-position: 50% 0;
}

.shot.is-live .shot__live,
.shot.is-film .shot__film {
  opacity: 1;
}

.shot__hint {
  position: absolute;
  left: var(--pad);
  bottom: 1rem;
  margin: 0;
  padding: 0.55rem 0.95rem;
  border-radius: 999px;
  background: rgba(13, 14, 17, 0.86);
  color: #fff;
  font-size: 0.875rem;
  opacity: calc(1 - var(--tour-p, 0) * 9);
  pointer-events: none;
}

/* How far through the site you are */
.shot__rail {
  position: absolute;
  top: 0.9rem;
  right: 0.6rem;
  bottom: 0.9rem;
  width: 4px;
  overflow: hidden;
  background: rgba(13, 14, 17, 0.3);
  border-radius: 4px;
}

.shot__rail span {
  display: block;
  height: 100%;
  background: var(--go);
  transform: scaleY(var(--tour-p, 0));
  transform-origin: 50% 0;
}

.project__bar {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gap);
  align-items: start;
  padding: clamp(0.85rem, 1.5vw, 1.4rem) var(--pad) clamp(0.9rem, 1.6vw, 1.5rem);
  background: var(--ground);
}

.project__head {
  grid-column: 1 / span 3;
}

.project__name {
  margin: 0;
  font-size: clamp(1.6rem, 2.5vw, 3rem);
  font-weight: 400;
  line-height: 0.95;
  letter-spacing: -0.045em;
  /* Long names wrap inside their column instead of running into the description. */
  overflow-wrap: break-word;
}

.project__kind {
  margin: 0.4rem 0 0;
  color: var(--mute);
  font-size: 0.9375rem;
  line-height: 1.2;
}

.project__say {
  grid-column: 4 / span 5;
  margin: 0;
  font-size: clamp(1.0625rem, 1.5vw, 1.6rem);
  font-weight: 400;
  line-height: 1.38;
  letter-spacing: -0.012em;
}

.facts {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gap);
  margin: 1.5rem var(--pad) 0;
}

.facts div {
  grid-column: span 6;
  padding-top: 0.7rem;
  border-top: 1px solid var(--line);
}

.facts dt {
  color: var(--mute);
  font-size: 0.875rem;
}

.facts dd {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.3;
}

.project__bar .facts {
  grid-column: 10 / -1;
  display: block;
  margin: 0;
}

.project__bar .facts div {
  padding: 0;
  border: 0;
}

.project__bar .facts div + div {
  margin-top: 0.6rem;
}

/* About */

.about {
  padding: var(--clear) var(--pad) clamp(4rem, 8vw, 8rem);
}

.about__lead {
  margin: 0 0 clamp(3rem, 7vw, 7rem);
  font-size: clamp(1.95rem, 5.1vw, 5.5rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
}

.about__grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gap);
  row-gap: 2.5rem;
}

.about__body {
  grid-column: 1 / span 5;
  font-size: clamp(1.0625rem, 1.45vw, 1.45rem);
  line-height: 1.42;
}

.about__body p {
  margin: 0 0 1em;
  max-width: 34ch;
}

.builds {
  grid-column: 8 / -1;
  margin: 0;
  padding: 0;
  list-style: none;
  border-bottom: 1px solid var(--line);
}

.builds li {
  display: flex;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1rem 0;
  border-top: 1px solid var(--line);
}

.builds li span:last-child {
  color: var(--mute);
  text-align: right;
}

.builds a {
  text-underline-offset: 0.25em;
}

/* Services rows, on the about page: each a key, a promise, a few lines on what it is and
   what comes with it. */

.services {
  padding: clamp(4rem, 9vw, 9rem) var(--pad) clamp(2rem, 5vw, 5rem);
}

.services__title {
  margin: 0;
  font-size: clamp(1.95rem, 5.1vw, 5.5rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
}

.services__intro {
  margin: 1.1rem 0 clamp(2.5rem, 6vw, 6rem);
  color: var(--mute);
  font-size: clamp(1.0625rem, 1.45vw, 1.45rem);
}

.service {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gap);
  row-gap: clamp(1rem, 1.6vw, 1.6rem);
  padding: clamp(1.75rem, 3.4vw, 3.4rem) 0;
  border-top: 1px solid var(--line);
}

.service__name {
  grid-column: 1 / span 3;
  grid-row: 1 / span 2;
  display: flex;
  align-items: center;
  align-self: start;
  gap: 0.75rem;
  margin: 0;
  font-size: 1rem;
  font-weight: 500;
}

.service__name .cap {
  width: 2.7rem;
  height: 2.5rem;
  border-radius: 0.6rem;
  box-shadow: 0 0.24rem 0 #c4c8cf;
  font-size: 1.0625rem;
  transform: none;
}

.service__name .cap--black {
  box-shadow: 0 0.24rem 0 #000;
}

.service__name .cap--go {
  box-shadow: 0 0.24rem 0 #c79f00;
}

.service:hover .service__name .cap {
  box-shadow: 0 0 0 transparent;
  transform: translateY(0.2rem);
}

.service__line {
  grid-column: 4 / -1;
  margin: 0;
  font-size: clamp(1.6rem, 3.7vw, 4rem);
  line-height: 1.04;
  letter-spacing: -0.03em;
}

.service__body {
  grid-column: 4 / span 5;
  margin: 0;
  max-width: 46ch;
  font-size: clamp(1.0625rem, 1.3vw, 1.3rem);
  line-height: 1.45;
}

.service__gets {
  grid-column: 10 / -1;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.9375rem;
}

.service__gets li {
  padding: 0.5rem 0;
  border-top: 1px solid var(--line);
}

.service__gets li:first-child {
  padding-top: 0.2rem;
  border-top: 0;
}

/* Where to go next: the closing links of a page. */

.next {
  padding: clamp(2.5rem, 6vw, 6rem) var(--pad) clamp(4rem, 9vw, 9rem);
}

.next__links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: clamp(1.5rem, 3vw, 3rem);
}

/* The projects page: a small window onto each site, drifting slowly down its page. */

.projects {
  padding: var(--clear) var(--pad) clamp(4rem, 9vw, 9rem);
}

.projects .display {
  margin-bottom: clamp(1.5rem, 3.2vw, 3.4rem);
}

.projects__intro {
  margin: 0 0 clamp(2.5rem, 6vw, 6rem);
  max-width: 44ch;
  color: var(--mute);
  font-size: clamp(1.0625rem, 1.45vw, 1.45rem);
}

.cards {
  display: grid;
  row-gap: clamp(3rem, 7vw, 7rem);
}

.card {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gap);
  align-items: center;
  text-decoration: none;
}

.card__window {
  grid-column: 1 / span 7;
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: var(--radius);
  background: #0a0b0e;
  transition: transform 600ms var(--settle);
}

.card__window img {
  position: absolute;
  left: 0;
  top: 0;
  display: block;
  width: 100%;
  height: auto;
}

.js .card__window.is-in img {
  animation: drift 22s ease-in-out infinite alternate;
}

.js .card:nth-child(2) .card__window.is-in img {
  animation-duration: 27s;
}

.js .card:nth-child(3) .card__window.is-in img {
  animation-duration: 24s;
}

.js .card:nth-child(4) .card__window.is-in img {
  animation-duration: 29s;
}

.js .card:nth-child(5) .card__window.is-in img {
  animation-duration: 25s;
}

@keyframes drift {
  to {
    transform: translate3d(0, var(--drift, 0), 0);
  }
}

.card:hover .card__window {
  transform: translateY(-0.4rem);
}

.card__text {
  grid-column: 9 / -1;
}

.card:nth-child(even) .card__window {
  grid-column: 6 / -1;
  order: 2;
}

.card:nth-child(even) .card__text {
  grid-column: 1 / span 4;
}

.card__name {
  display: flex;
  align-items: center;
  gap: 0.3em;
  margin: 0;
  font-size: clamp(1.9rem, 3.4vw, 3.7rem);
  font-weight: 400;
  line-height: 0.95;
  letter-spacing: -0.045em;
}

.card__kind {
  margin: 0.6rem 0 0;
  color: var(--mute);
  font-size: 0.9375rem;
}

.card__line {
  margin: 1.1rem 0 1.5rem;
  max-width: 20ch;
  font-size: clamp(1.3rem, 1.9vw, 2rem);
  line-height: 1.15;
  letter-spacing: -0.015em;
}

.card:hover .pill::after {
  transform: scale(2.1);
}

/* A project's own page opens on its name, with the top of its site showing underneath. */

.lead {
  padding: var(--clear) var(--pad) clamp(1.5rem, 3vw, 3rem);
}

.lead__crumb {
  margin: 0 0 clamp(1rem, 2vw, 2rem);
  color: var(--mute);
  font-size: 0.9375rem;
}

.lead__crumb a {
  text-underline-offset: 0.25em;
}

.lead .display {
  margin-bottom: clamp(1.4rem, 3vw, 3.2rem);
}

.lead__line {
  margin: 0;
  font-size: clamp(1.3rem, 2.3vw, 2.5rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
}

/* How a project runs: four steps, in order, so they are numbered. */

.process {
  padding: 0 var(--pad) clamp(3rem, 7vw, 7rem);
}

.process__title {
  margin: 0 0 clamp(1.25rem, 2.4vw, 2.4rem);
  color: var(--mute);
  font-size: clamp(1.0625rem, 1.45vw, 1.45rem);
  font-weight: 400;
}

.steps {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: var(--gap);
  row-gap: 2.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
}

.steps li {
  padding-top: 1.1rem;
  border-top: 1px solid var(--ink);
  counter-increment: step;
}

.steps li::before {
  content: counter(step);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.7rem;
  height: 2.5rem;
  border-radius: 0.6rem;
  background: #fff;
  box-shadow: 0 0.24rem 0 #c4c8cf;
  color: var(--dark);
  font-size: 1.0625rem;
  font-weight: 600;
}

.steps li:last-child::before {
  background: var(--go);
  box-shadow: 0 0.24rem 0 #c79f00;
}

.step__name {
  margin: 1.1rem 0 0.5rem;
  font-size: clamp(1.4rem, 2vw, 2.1rem);
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.035em;
}

.step__body {
  margin: 0;
  max-width: 30ch;
  line-height: 1.45;
}

/* No page at this address. */

.lost {
  min-height: 80vh;
  padding: var(--clear) var(--pad) clamp(4rem, 8vw, 8rem);
}

.lost__title {
  margin: 0 0 1rem;
  font-size: clamp(1.95rem, 5.1vw, 5.5rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
}

.lost p {
  margin: 0 0 2rem;
  color: var(--mute);
  font-size: clamp(1.0625rem, 1.45vw, 1.45rem);
}

/* Contact */

.contact {
  padding: var(--clear) var(--pad) clamp(4rem, 8vw, 8rem);
}

.display {
  margin: 0 0 clamp(2rem, 4.5vw, 4.5rem);
  font-size: clamp(3.25rem, 13.2vw, 14.5rem);
  font-weight: 600;
  line-height: 0.86;
  letter-spacing: -0.045em;
}

.contact__grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gap);
  align-items: start;
}

.contact__left {
  grid-column: 1 / span 5;
}

.contact__note {
  margin: 0 0 2.5rem;
  max-width: 34ch;
  font-size: clamp(1.0625rem, 1.45vw, 1.45rem);
  line-height: 1.42;
}

.stage-end {
  grid-column: 7 / -1;
  position: sticky;
  clip-path: inset(0 round var(--radius));
  top: 6.5rem;
  height: min(74vh, 48rem);
}

.portrait {
  max-width: 14rem;
  aspect-ratio: 4 / 5;
  margin: 0 0 2rem;
  overflow: hidden;
  background: var(--soft);
  border-radius: var(--radius);
}

.portrait img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.form {
  display: grid;
  gap: 1.75rem;
}

.field {
  display: grid;
  gap: 0.35rem;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.field label,
.field legend {
  padding: 0;
  color: var(--mute);
  font-size: 0.9375rem;
}

.field input[type="text"],
.field textarea {
  width: 100%;
  padding: 0.45rem 0 0.6rem;
  border: 0;
  border-bottom: 1.5px solid var(--ink);
  border-radius: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 1.25rem;
}

.field textarea {
  min-height: 6.5rem;
  resize: vertical;
}

.field input[type="text"]:focus-visible,
.field textarea:focus-visible {
  outline: 0;
  padding-bottom: calc(0.6rem - 1.5px);
  border-bottom-width: 3px;
}

.field [aria-invalid="true"] {
  border-bottom-color: var(--error);
}

.field__help,
.field__error {
  margin: 0.2rem 0 0;
  color: var(--mute);
  font-size: 0.9375rem;
}

.field__error {
  color: var(--error);
}

.field--choices {
  display: block;
}

.field--choices legend {
  margin-bottom: 0.7rem;
}

.choice {
  display: inline-block;
  margin: 0 0.4rem 0.4rem 0;
}

.choice input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.choice span {
  display: inline-flex;
  align-items: center;
  height: 2.75rem;
  padding: 0 1.2rem;
  border-radius: 999px;
  background: var(--soft);
  color: var(--ink);
  font-size: 1rem;
  cursor: pointer;
  transition: background-color 300ms var(--settle), color 300ms var(--settle);
}

.choice input:checked + span {
  background: #fff;
  color: var(--dark);
}

.choice input:focus-visible + span {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

.form__end {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
}

.form__status {
  margin: 0;
  max-width: 32ch;
}

/* Footer */

.foot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 2rem;
  padding: 1.5rem var(--pad) 2rem;
  border-top: 1px solid var(--line);
  font-size: 0.9375rem;
}

.foot p {
  margin: 0;
}

.foot__name {
  font-weight: 500;
}

.foot a {
  text-underline-offset: 0.25em;
}

.foot__nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.25rem;
}

/* Narrow screens */

@media (max-width: 900px) {
  :root {
    --clear: 10rem;
  }

  /* The tabs take a row of their own under the logo. */
  .top {
    flex-wrap: wrap;
    row-gap: 0.5rem;
  }

  .top::after {
    content: "";
    order: 2;
    flex-basis: 100%;
  }

  .lang {
    order: 1;
  }

  .tabs {
    order: 3;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .tabs::-webkit-scrollbar {
    display: none;
  }

  .tabs a {
    padding: 0 0.7rem;
  }

  .hero {
    height: 235vh;
  }

  .service__name,
  .service__line,
  .service__body,
  .service__gets {
    grid-column: 1 / -1;
    grid-row: auto;
  }

  .card__window,
  .card__text,
  .card:nth-child(even) .card__window,
  .card:nth-child(even) .card__text {
    grid-column: 1 / -1;
    order: 0;
  }

  .card__text {
    margin-top: 1.25rem;
  }

  .steps {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .hero__bar {
    row-gap: 0.9rem;
  }

  .hero__line,
  .index {
    grid-column: 1 / -1;
  }

  /* Four names on one row down to a 360px phone; narrower than that, whole names move to a second row. */
  .index {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem clamp(0.9rem, 4.4vw, 1.4rem);
  }

  .index a {
    padding: 0;
    border: 0;
    white-space: nowrap;
  }

  .index a span:last-child,
  .index__hint {
    display: none;
  }

  .stage__title {
    bottom: 12vh;
  }

  .project__bar {
    row-gap: 0.6rem;
  }

  .project__head {
    grid-column: 1 / -1;
    display: flex;
    align-items: baseline;
    gap: 0.8rem;
  }

  .project__kind {
    margin: 0;
  }

  .project__say {
    grid-column: 1 / -1;
  }

  .about__body,
  .builds,
  .contact__left,
  .stage-end {
    grid-column: 1 / -1;
  }

  .stage-end {
    position: relative;
    top: 0;
    order: -1;
    height: 58vh;
    margin-bottom: 2.5rem;
  }
}

@media (max-width: 520px) {
  .steps {
    grid-template-columns: minmax(0, 1fr);
  }

  .facts div {
    grid-column: 1 / -1;
  }

  .facts div + div {
    margin-top: 1rem;
  }

  .builds li {
    flex-direction: column;
    gap: 0.15rem;
  }

  .builds li span:last-child {
    text-align: left;
  }
}

/* With motion turned off nothing is pinned or typed, and each site scrolls inside its own frame. */

@media (prefers-reduced-motion: reduce) {
  .hero {
    height: auto;
  }

  .js .intro {
    display: none;
  }

  @view-transition {
    navigation: none;
  }

  .js .card__window.is-in img {
    animation: none;
  }

  .card__window,
  .tabs a {
    transition: none;
  }

  .js [data-chars] .c,
  .js [data-type] .c,
  .js [data-rise] .w,
  .js .top > *,
  .js .index > *,
  .js [data-scrub] .s {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .js [data-type] .c.is-last::after {
    content: none;
  }

  .stage__title,
  .index__hint,
  .shot__hint,
  .shot__rail {
    display: none;
  }

  .project__track,
  .project__pin {
    position: static;
    height: auto;
  }

  .shot {
    height: 80vh;
    overflow-y: auto;
  }

  .shot__page {
    position: static;
  }

  .shot__live {
    pointer-events: auto;
  }

  .pill,
  .pill::after {
    transition: none;
  }
}

/* A project that is a film rather than a site: the video sits centred, as tall as the screen allows. */

.reel {
  display: grid;
  justify-items: center;
  gap: clamp(1rem, 2vw, 1.75rem);
  padding: 0 var(--pad);
}

.reel__stage {
  margin: 0;
  max-width: 100%;
}

.reel__stage video {
  display: block;
  height: min(78vh, 900px);
  max-width: 100%;
  aspect-ratio: 9 / 16;
  border-radius: var(--radius);
  background: var(--dark);
  object-fit: cover;
}

.reel__say {
  max-width: 34rem;
  margin: 0;
  font-size: clamp(1.0625rem, 1.5vw, 1.6rem);
  line-height: 1.2;
  letter-spacing: -0.012em;
  text-align: center;
}

/* ------------------------------------------------------------------------------------------
   The studio layout, below the hero: numbered mono labels, two-tone bold titles, square
   buttons with an arrow, thin rules, and yellow corner marks on what you can act on.
   ------------------------------------------------------------------------------------------ */

.project__name,
.card__name {
  font-weight: 600;
  letter-spacing: -0.035em;
}

/* Small mono labels: a section number in yellow, a dash, a name. */
.label {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0 0 clamp(1.5rem, 3vw, 2.75rem);
  color: var(--mute);
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  line-height: 1.2;
  text-transform: uppercase;
}

.label__no {
  color: var(--go);
}

.label__no::after {
  content: "—";
  margin-left: 0.75rem;
  color: var(--mute);
}

.lead__crumb {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.hl {
  color: var(--go);
}

.mute {
  color: var(--mute);
}

/* A yellow dot beside "Taking projects": a plain marker, not a fake live signal. */
.live {
  display: inline-block;
  flex: none;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--go);
}

/* Corner marks: four yellow L's drawn with one element. */
.brackets {
  --b: 1.1rem;
  --t: 2px;
  position: absolute;
  inset: 0.9rem;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(var(--go) 0 0) 0 0 / var(--b) var(--t),
    linear-gradient(var(--go) 0 0) 0 0 / var(--t) var(--b),
    linear-gradient(var(--go) 0 0) 100% 0 / var(--b) var(--t),
    linear-gradient(var(--go) 0 0) 100% 0 / var(--t) var(--b),
    linear-gradient(var(--go) 0 0) 0 100% / var(--b) var(--t),
    linear-gradient(var(--go) 0 0) 0 100% / var(--t) var(--b),
    linear-gradient(var(--go) 0 0) 100% 100% / var(--b) var(--t),
    linear-gradient(var(--go) 0 0) 100% 100% / var(--t) var(--b);
  background-repeat: no-repeat;
}

/* Buttons below the header: square blocks with an arrow. The yellow one is the main action. */
.pill:not(.tabs):not(.lang) {
  justify-content: space-between;
  gap: 2.25rem;
  height: 3.5rem;
  padding: 0 1.35rem;
  border-radius: 0;
  background: var(--go);
  color: var(--dark);
  font-size: 0.9375rem;
  font-weight: 500;
  transition: background-color 300ms linear, color 300ms linear, box-shadow 300ms linear;
}

.pill:not(.tabs):not(.lang)::after {
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 0;
  background: currentColor;
  -webkit-mask: var(--arrow) center / contain no-repeat;
  mask: var(--arrow) center / contain no-repeat;
  transition: transform 400ms var(--settle);
}

.pill:not(.tabs):not(.lang):hover {
  background: #ffe066;
}

.pill:not(.tabs):not(.lang):hover::after,
.card:hover .pill::after {
  transform: translate(2px, -2px);
}

.pill--light:not(.tabs):not(.lang) {
  background: transparent;
  color: var(--ink);
  box-shadow: inset 0 0 0 1px #3a3e47;
}

.pill--light:not(.tabs):not(.lang):hover {
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--ink);
}

.arrow {
  display: inline-block;
  flex: none;
  width: 0.75rem;
  height: 0.75rem;
  background: currentColor;
  -webkit-mask: var(--arrow) center / contain no-repeat;
  mask: var(--arrow) center / contain no-repeat;
  transition: transform 400ms var(--settle);
}

.choice span {
  border-radius: 0;
}

/* Things that rise into place once, the first time they come into view. */
[data-reveal="up"] {
  transition: opacity 700ms linear, transform 1000ms var(--settle), border-color 400ms var(--settle);
}

html[data-booted] [data-reveal="up"]:not(.is-in) {
  opacity: 0;
  transform: translateY(2.5rem);
}

.tiles .tile:nth-child(3n + 2),
.offers .offer:nth-child(2n) {
  transition-delay: 90ms;
}

.tiles .tile:nth-child(3n) {
  transition-delay: 180ms;
}

/* Section heads: a big two-tone title on the left, a short note on the right. */
.sec-head {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gap);
  row-gap: 1.5rem;
  align-items: end;
  margin-bottom: clamp(2.5rem, 5vw, 5rem);
}

.sec-title {
  grid-column: 1 / span 7;
  margin: 0;
  font-size: clamp(2.6rem, 6.4vw, 6.75rem);
  font-weight: 600;
  line-height: 0.98;
  letter-spacing: -0.035em;
}

.sec-title > span,
.me__title > span,
.together__title > span {
  display: block;
}

.sec-intro {
  grid-column: 9 / -1;
  margin: 0;
  max-width: 36ch;
  color: var(--mute);
  font-size: clamp(1rem, 1.2vw, 1.2rem);
  line-height: 1.5;
}

.sec-aside {
  grid-column: 9 / -1;
}

.sec-aside .sec-intro {
  margin-bottom: 1.75rem;
}

.sec-nums {
  display: flex;
  gap: 2.75rem;
  margin: 0;
}

.sec-nums dt {
  font-size: clamp(1.8rem, 2.6vw, 2.6rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.04em;
}

.sec-nums dd {
  margin: 0.5rem 0 0;
  color: var(--mute);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* The stats row, right after the hero: four numbers between thin rules. */
.stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin: clamp(3rem, 6vw, 6rem) var(--pad) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.stat {
  padding: clamp(1.4rem, 2.4vw, 2.2rem) clamp(0.75rem, 1.5vw, 1.5rem) clamp(1.6rem, 3vw, 2.8rem);
}

.stat + .stat {
  border-left: 1px solid var(--line);
}

.stat__num {
  margin: 0;
  font-size: clamp(2.6rem, 4.6vw, 4.75rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

.stat__unit {
  margin-left: 0.18em;
  color: var(--go);
  font-size: 0.42em;
  letter-spacing: -0.01em;
}

.stat__what {
  margin: 0.8rem 0 0;
  color: var(--mute);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* The skills ticker: one line of big words sliding left forever. Hover to hold it. */
.ticker {
  overflow: hidden;
  padding: clamp(1.5rem, 3vw, 2.6rem) 0;
  border-bottom: 1px solid var(--line);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}

.ticker__track {
  display: flex;
  width: max-content;
  animation: ticker 48s linear infinite;
}

.ticker:hover .ticker__track {
  animation-play-state: paused;
}

.ticker__set {
  display: flex;
  align-items: center;
  gap: clamp(1.75rem, 3.2vw, 3.5rem);
  margin: 0;
  padding-right: clamp(1.75rem, 3.2vw, 3.5rem);
  color: #d7dadf;
  font-size: clamp(2.2rem, 5.2vw, 5.4rem);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.03em;
  white-space: nowrap;
}

.ticker__set i {
  flex: none;
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  background: var(--go);
}

@keyframes ticker {
  to {
    transform: translateX(-50%);
  }
}

/* 001 About: the portrait with corner marks on the left, the introduction and facts on the right.
   The portrait opens upward once, the first time it comes into view. */
.me {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gap);
  row-gap: 2.5rem;
  align-items: start;
  padding: clamp(5rem, 10vw, 10rem) var(--pad) 0;
}

.me > .label {
  grid-column: 1 / -1;
  margin-bottom: 0;
}

.me__photo {
  grid-column: 1 / span 5;
  margin: 0;
}

.me__frame {
  position: relative;
  overflow: hidden;
  background: var(--dark);
}

.me__frame img {
  display: block;
  width: 100%;
  height: auto;
  clip-path: inset(0);
  transition: clip-path 1200ms var(--settle), transform 1400ms var(--settle);
}

html[data-booted] [data-reveal="photo"]:not(.is-in) img {
  clip-path: inset(18% 0 0 0);
  transform: scale(1.06);
}

.me__cap {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 0.9rem;
  color: var(--mute);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.me__cap span:last-child {
  text-align: right;
}

.me__text {
  grid-column: 7 / -1;
  font-size: clamp(1rem, 1.15vw, 1.15rem);
  line-height: 1.55;
}

.me__title {
  margin: 0 0 clamp(1.5rem, 3vw, 2.75rem);
  font-size: clamp(2.6rem, 5.4vw, 5.75rem);
  line-height: 0.98;
  letter-spacing: -0.035em;
}

.me__text p {
  margin: 0 0 1em;
  max-width: 52ch;
  color: var(--mute);
}

.me__text .me__lead {
  max-width: 34ch;
  color: var(--ink);
  font-size: clamp(1.15rem, 1.6vw, 1.6rem);
  line-height: 1.35;
  letter-spacing: -0.01em;
}

.me__facts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: var(--gap);
  margin: clamp(2rem, 3.5vw, 3rem) 0 0;
  border-top: 1px solid var(--line);
}

.me__facts div {
  padding: 1.1rem 0 1.25rem;
  border-bottom: 1px solid var(--line);
}

.me__facts dt {
  color: var(--mute);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.me__facts dd {
  margin: 0.45rem 0 0;
  font-size: 0.9375rem;
  line-height: 1.35;
}

.me__open {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.me__links,
.together__links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: clamp(2rem, 3.5vw, 3rem);
}

/* 002 Services: four cards. Corner marks close in on the one you point at. */
.services .sec-head + .offers {
  margin-top: 0;
}

.offers {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap);
}

.offer {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: clamp(1.75rem, 3vw, 2.75rem);
  border: 1px solid var(--line);
  background: #15171c;
}

.offer:hover {
  border-color: #3d414a;
}

.offer .brackets {
  inset: 0.7rem;
  opacity: 0;
  transform: scale(1.03);
  transition: opacity 300ms linear, transform 500ms var(--settle);
}

.offer:hover .brackets {
  opacity: 1;
  transform: none;
}

.offer__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: clamp(2rem, 4vw, 3.5rem);
}

.offer__top .cap {
  width: 2.7rem;
  height: 2.5rem;
  border-radius: 0.6rem;
  box-shadow: 0 0.24rem 0 #c4c8cf;
  font-size: 1.0625rem;
  transform: none;
}

.offer__top .cap--black {
  box-shadow: 0 0.24rem 0 #000;
}

.offer__top .cap--go {
  box-shadow: 0 0.24rem 0 #c79f00;
}

.offer:hover .offer__top .cap {
  box-shadow: 0 0 0 transparent;
  transform: translateY(0.2rem);
}

.offer__no {
  color: var(--mute);
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
}

.offer__name {
  margin: 0;
  font-size: clamp(1.6rem, 2.4vw, 2.4rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.04em;
}

.offer__line {
  margin: 0.6rem 0 0;
  font-size: clamp(1.05rem, 1.25vw, 1.25rem);
  font-weight: 500;
}

.offer__body {
  margin: 1rem 0 0;
  max-width: 48ch;
  color: var(--mute);
  line-height: 1.55;
}

.offer__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin: 1.5rem 0 clamp(2rem, 4vw, 3rem);
  padding: 0;
  list-style: none;
}

.offer__tags li {
  padding: 0.45rem 0.7rem;
  border: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.offer__go {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: auto;
  padding-top: 1.1rem;
  border-top: 1px solid var(--line);
  font-weight: 500;
  text-decoration: none;
  transition: color 300ms linear;
}

.offer__go:hover {
  color: var(--go);
}

.offer:hover .arrow {
  transform: translate(2px, -2px);
}

/* 003 Work: every project as a window onto the top of its site. Point at one and it scrolls. */
.work {
  padding: clamp(5rem, 10vw, 10rem) var(--pad) 0;
}

.tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(2rem, 3.5vw, 3.5rem) var(--gap);
}

.tile {
  display: block;
  text-decoration: none;
}

.tile__window {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border: 1px solid var(--line);
  background: #0a0b0e;
}

.tile__window img {
  position: absolute;
  left: 0;
  top: 0;
  display: block;
  width: 100%;
  height: auto;
  transition: transform 5s cubic-bezier(0.45, 0, 0.2, 1);
}

.tile:hover .tile__window img,
.tile:focus-visible .tile__window img {
  transform: translateY(var(--travel, -50%));
}

.tile__tag {
  position: absolute;
  top: 0.8rem;
  right: 0.8rem;
  padding: 0.3rem 0.5rem;
  background: rgba(13, 14, 17, 0.85);
  color: #fff;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
}

.tile__text {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding-top: 1rem;
}

.tile__name {
  margin: 0;
  font-size: clamp(1.15rem, 1.5vw, 1.5rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  transition: color 300ms linear;
}

.tile:hover .tile__name {
  color: var(--go);
}

.tile__kind {
  margin: 0;
  color: var(--mute);
  font-size: 0.8125rem;
  text-align: right;
}

.work__end {
  display: flex;
  justify-content: center;
  margin-top: clamp(2.5rem, 5vw, 4rem);
}

/* 004 The closing panel: a framed invitation with the studio's name written large behind it. */
.together {
  padding: clamp(5rem, 10vw, 10rem) var(--pad) clamp(4rem, 8vw, 8rem);
}

.together__box {
  position: relative;
  overflow: hidden;
  padding: clamp(4.25rem, 7vw, 7rem) clamp(1.5rem, 5vw, 5rem);
  border: 1px solid var(--line);
  background: #14151a;
}

.together__box .brackets {
  --b: 1.6rem;
  inset: 1.1rem;
}

.together__ghost {
  position: absolute;
  right: -0.03em;
  bottom: -0.2em;
  margin: 0;
  color: transparent;
  font-size: clamp(5rem, 17vw, 18rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.06em;
  white-space: nowrap;
  -webkit-text-stroke: 1px rgba(255, 255, 255, 0.08);
  pointer-events: none;
}

.together .label,
.together__title,
.together__body,
.together__links,
.together__note {
  position: relative;
}

.together__title {
  margin: 0;
  font-size: clamp(2.8rem, 7.5vw, 8rem);
  font-weight: 600;
  line-height: 0.95;
  letter-spacing: -0.04em;
}

.together__body {
  margin: clamp(1.5rem, 3vw, 2.5rem) 0 0;
  max-width: 40ch;
  color: var(--mute);
  font-size: clamp(1.05rem, 1.3vw, 1.3rem);
  line-height: 1.5;
}

.together__note {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: clamp(2rem, 4vw, 3rem) 0 0;
  color: var(--mute);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

@media (max-width: 900px) {
  .stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .stat:nth-child(3) {
    border-left: 0;
  }

  .stat:nth-child(n + 3) {
    border-top: 1px solid var(--line);
  }

  .me__photo,
  .me__text,
  .sec-title,
  .sec-intro,
  .sec-aside {
    grid-column: 1 / -1;
  }

  .me__photo {
    max-width: 28rem;
  }

  .offers {
    grid-template-columns: minmax(0, 1fr);
  }

  .tiles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 520px) {
  .me__facts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .tile__text {
    flex-direction: column;
    gap: 0.2rem;
  }

  .tile__kind {
    text-align: left;
  }

  .pill:not(.tabs):not(.lang) {
    gap: 1.25rem;
  }

  .me__links .pill,
  .together__links .pill {
    flex: 1 1 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ticker__track {
    animation: none;
  }

  .tile__window img,
  [data-reveal="up"],
  .me__frame img {
    transition: none;
  }
}

/* The flying Enter key's landing spots: beside each section title on wide screens, at the end of
   the section label on phones. They stay empty while the 3D key flies (flyer.js); where it cannot
   fly, a still key sits in each one. */
:root {
  --key: clamp(34px, 3.4vw, 60px);
}

.me__title,
.sec-title,
.label {
  position: relative;
}

.perch {
  position: absolute;
  width: var(--key);
  height: var(--key);
  pointer-events: none;
}

.perch--side {
  left: calc(-1 * var(--key) - 0.6rem);
  top: 0.49em;
  transform: translateY(-50%);
}

.perch.perch--label {
  display: none;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
}

.perch-still .perch {
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='1' y='1' width='30' height='30' rx='8.5' fill='%23ffcc00'/%3E%3Cpath d='M21.5 10v8.5h-11m3.8-3.8-3.8 3.8 3.8 3.8' fill='none' stroke='%230d0e11' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

.flyer {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 35;
  pointer-events: none;
  visibility: hidden;
  will-change: transform;
}

@media (max-width: 900px) {
  .perch.perch--side {
    display: none;
  }

  .perch.perch--label {
    display: block;
  }
}

/* Section text that comes out of the flying key: each section's label and title wait, hidden, in
   the key; when it lands they fly out of it into place, word by word (flyer.js sets --fx/--fy, the
   way back to the key, and --k, the order). */
html.js .spawn-wait .label > span,
html.js .spawn-wait [data-rise] .w {
  opacity: 0;
  transform: translate(var(--fx, 0px), var(--fy, 0px)) scale(0.12) rotate(-30deg);
  transform-origin: 50% 50%;
  transition: none;
}

html.js .spawn-go .label > span.spawn,
html.js .spawn-go [data-rise] .w.spawn {
  opacity: 1;
  transform: none;
  transform-origin: 50% 50%;
  transition: transform 1100ms var(--settle), opacity 200ms linear;
  transition-delay: calc(var(--k, 0) * 45ms);
}

/* The stats row lives in the hero's strip, under the 3D window, from the first screen. It rises
   in with the header when the intro opens, and fades as the window grows over it. */
.hero__bar > .stats {
  grid-column: 1 / -1;
  margin: 0;
}

.js .hero__bar .stat {
  opacity: 0;
  transform: translateY(1.5rem);
  transition: transform 800ms var(--settle), opacity 400ms linear;
}

.js .hero__bar .stat:nth-child(2) {
  transition-delay: 80ms;
}

.js .hero__bar .stat:nth-child(3) {
  transition-delay: 160ms;
}

.js .hero__bar .stat:nth-child(4) {
  transition-delay: 240ms;
}

.js.is-ready .hero__bar .stat {
  opacity: 1;
  transform: none;
}

/* On phones the four sit two by two, kept compact so the keys still fill most of the screen. */
@media (max-width: 900px) {
  .hero__bar .stat {
    padding: 0.85rem 0.75rem 0.95rem;
  }

  .hero__bar .stat__num {
    font-size: 2.1rem;
  }

  .hero__bar .stat__what {
    margin-top: 0.45rem;
    letter-spacing: 0.1em;
  }
}

@media (prefers-reduced-motion: reduce) {
  .js .hero__bar .stat {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Ways to reach me directly: on the contact page under the form, and in every footer. */
.direct {
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
}

.direct__lead {
  margin: 0 0 1rem;
  color: var(--mute);
}

.direct__list {
  margin: 0;
}

.direct__list div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--line);
}

.direct__list dt {
  color: var(--mute);
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.direct__list dd {
  margin: 0;
  text-align: right;
}

.direct__list a,
.foot__reach a {
  text-underline-offset: 0.25em;
}

.foot__reach {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.25rem;
}

/* The contact form's spam trap: a field people never see, which bots fill in (Netlify drops those). */
.form__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
