/* Meridian — desktop stylesheet.
 *
 * Structure and numbers reproduce docs/reference-spec.md §4. Identity (faces, palette,
 * wordmark) is ours. Written from the measured token set, not copied.
 *
 * Two rules govern this file:
 *   1. Motion never owns resting state. Every element's correct final appearance is
 *      declared here; the engine animates *to* it. A throttled tab, a paused document or
 *      prefers-reduced-motion must still leave a fully readable page.
 *      => elements that animate in start from a class the engine removes, not from a bare
 *         transform that only JS can undo.
 *   2. Focus is always visible. The reference preventDefaults Tab; we do not.
 */

/* ---------------------------------------------------------------- faces */

@font-face {
  font-family: "Display";
  src: url(/static/font/display.woff2) format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "UI";
  src: url(/static/font/ui.woff2) format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* Metric-matched fallbacks. Without these the swap moves every line.
 * Measured: Display cap 800/1000upm vs fallback Impact ~720; UI cap 711 vs Arial 716. */
@font-face {
  font-family: "Display Fallback";
  src: local("Haettenschweiler"), local("Impact"), local("Arial Narrow Bold");
  size-adjust: 111%;
  ascent-override: 87%;
  descent-override: 13%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "UI Fallback";
  src: local("Helvetica Neue Bold"), local("Arial Bold"), local("Arial");
  size-adjust: 99%;
  ascent-override: 78.5%;
  descent-override: 21.5%;
  line-gap-override: 0%;
}

:root {
  --bg: #141414;
  --txt: #bac4b8;
  --ease: cubic-bezier(0.25, 0.46, 0.45, 0.94); /* easeOutQuad */
  --ease-img: cubic-bezier(0.39, 0.575, 0.565, 1); /* easeOutSine */
  --edge: 50px; /* outer margin */
  --edge-display: 38px; /* the two display-face blocks sit tighter */
  --bottom: 48px;
  /* Display-face compensation, measured (docs/reference-spec.md, brief.md):
   * cap height 733/800 = 0.91625 ; width ratio 0.341/0.458 = 0.7445 */
  --display-cap: 0.91625;
  --display-squeeze: 0.7445;
}

/* ---------------------------------------------------------------- reset */

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

html {
  background-color: var(--bg);
  -webkit-text-size-adjust: none;
  -webkit-font-smoothing: antialiased;
  cursor: default;
  -webkit-tap-highlight-color: transparent;
}
a, body, div, footer, h1, h2, header, html, img, li, nav, p, span, ul {
  margin: 0;
  padding: 0;
  border: 0;
  font: inherit;
  font-size: 100%;
}
ul, li { list-style: none; }
a { color: inherit; text-decoration: none; }
a, img, picture, svg, video { display: block; }
img, svg, video { width: 100%; height: auto; }
svg { height: 100%; }
body {
  font-family: "UI", "UI Fallback", Helvetica, Arial, sans-serif;
  font-feature-settings: "liga" off;
  color: var(--txt);
}

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

/* The reference has no visible focus at all. Ours does, everywhere. */
:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}
.skip {
  position: absolute;
  z-index: 10000;
  top: 8px;
  left: 8px;
  padding: 10px 14px;
  font-size: 11px;
  letter-spacing: 0.04em;
  background: var(--txt);
  color: var(--bg);
  transform: translateY(-200%);
}
.skip:focus { transform: none; }

/* ---------------------------------------------------------------- shell */

#app {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  user-select: none;
}

#gl, #c2d {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* ---------------------------------------------------------------- loader */

#load {
  position: absolute;
  z-index: 9998;
  top: 35px;
  left: var(--edge-display);
  font-family: "Display", "Display Fallback", Impact, sans-serif;
  font-size: calc(50px * var(--display-cap));
  line-height: 44px;
  letter-spacing: -0.01em;
}
#load > span { float: left; overflow: hidden; }
#load > span:not(:first-child) { margin-left: -6px; }
#load span span {
  display: block;
  padding-right: 10px;
  transform: translate3d(var(--rx, 0), var(--ry, 0), 0) scaleX(var(--display-squeeze));
  transform-origin: 0 50%;
  will-change: transform;
}
/* Resting state lives here, in CSS. The engine only writes --rx / --ry. */
#load span span.off { --rx: -110%; }

/* ---------------------------------------------------------------- nav */

#nav { pointer-events: none; }

#n0 {
  position: absolute;
  top: 35px;
  left: var(--edge-display);
  font-family: "Display", "Display Fallback", Impact, sans-serif;
  font-size: calc(50px * var(--display-cap));
  line-height: 44px;
  letter-spacing: -0.02em;
  pointer-events: all;
}
#n0 > span { float: left; overflow: hidden; }
#n0 span span {
  display: block;
  transform: translate3d(var(--rx, 0), var(--ry, 0), 0) scaleX(var(--display-squeeze));
  transform-origin: 0 50%;
  transition: color 500ms var(--ease);
  will-change: color, transform;
}
#n0 span span.off { --rx: -110%; }

.n1 {
  position: absolute;
  top: 40px;
  right: var(--edge);
  overflow: hidden;
}
.n1 a { display: block; pointer-events: all; }
#n1-0, #n1-1 {
  transition: color 500ms var(--ease);
  will-change: transform, color;
  transform: translate3d(var(--rx, 0), var(--ry, 0), 0);
}
.n1 a.off { --ry: 101%; }
/* the underline under ABOUT / CLOSE */
.n1 a > span { position: relative; display: block; font-size: 12px; line-height: 14px; }
.n1 a > span::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -3px;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(1);
  transform-origin: 0 50%;
  transition: transform 400ms var(--ease);
}
.n1 a:hover > span::after { transform: scaleX(0); transform-origin: 100% 50%; }

#n2 {
  position: absolute;
  bottom: var(--bottom);
  left: var(--edge);
  font-size: 10px;
  line-height: 10px;
  overflow: hidden;
  pointer-events: all;
}
#n2 > div { overflow: hidden; }
.n2 {
  display: table;
  position: relative;
  transition: color 500ms var(--ease);
  will-change: transform, color;
  transform: translate3d(var(--rx, 0), var(--ry, 0), 0);
}
.n2.off { --ry: 101%; }
#n2 > div:last-child .n2::after {
  content: "\2197";
  position: absolute;
  top: 0;
  right: 0;
  padding-left: 5px;
  transform: translateX(100%);
  opacity: 0;
  transition: opacity 200ms var(--ease);
}
#n2:hover > div:last-child .n2::after {
  opacity: 1;
  transition: opacity 400ms var(--ease);
}

#n3 {
  position: absolute;
  bottom: 47px;
  right: var(--edge);
  text-align: right;
  font-size: 12px;
  line-height: 14px;
}
#n3 > div { overflow: hidden; padding-left: 20px; }
.n3 {
  display: inline-block;
  position: relative;
  transition: color 500ms var(--ease);
  will-change: transform, color;
  pointer-events: all;
  transform: translate3d(var(--rx, 0), var(--ry, 0), 0);
}
.n3.off { --ry: 101%; }
.n3::after {
  content: "\2197";
  position: absolute;
  top: 0;
  left: 0;
  padding-right: 5px;
  transform: translateX(-100%);
  opacity: 0;
  transition: opacity 200ms var(--ease);
}
.n3:hover::after { opacity: 1; transition: opacity 400ms var(--ease); }

/* ---------------------------------------------------------------- giant titles */

/* The title block spans the full viewport height so the two lines can be placed against
 * it with percentages; the lines themselves are only as tall as one line of type. */
.t {
  position: absolute;
  top: 0;
  left: var(--edge-display);
  width: calc(100vw - var(--edge-display) * 2);
  height: 100%;
  font-family: "Display", "Display Fallback", Impact, sans-serif;
  letter-spacing: -0.024em;
  pointer-events: none;
  /* On a focused project the background is the project's own light colour, so the site's
   * sage would fall to ~1.6:1. The engine sets --title to the project's text colour. */
  color: var(--title, var(--txt));
}
/* One line per title row; each letter is absolutely placed at the x the composition data
 * gives it, and clips its own horizontal wipe. */
.t > div {
  position: absolute;
  left: 0;
  width: 100%;
  overflow: hidden;
}
.t-l {
  position: absolute;
  top: 0;
  display: block;
  overflow: hidden;
  will-change: left;
}
.t-l > span {
  display: block;
  transform: translate3d(var(--rx, 0), var(--ry, 0), 0) scaleX(var(--display-squeeze));
  transform-origin: 0 50%;
  will-change: transform;
}
.t-l > span.off { --rx: -101%; }

/* ---------------------------------------------------------------- info blocks */

.i-l {
  position: absolute;
  bottom: 47px;
  left: 50%;
  font-size: 10px;
  line-height: 12px;
  letter-spacing: 0.02em;
  transform: translateX(-100%);
  pointer-events: none;
}
.i-l > div { display: flex; flex-wrap: wrap; overflow: hidden; }
.i-l div div:nth-child(1) { width: 30px; font-size: 6px; }
.i-l div div:nth-child(2) { width: 130px; }
.i-l div div:nth-child(3) { width: 250px; }

.i-r {
  position: absolute;
  bottom: var(--bottom);
  left: calc(50% + 140px);
  font-size: 10px;
  line-height: 10px;
  letter-spacing: 0.02em;
  pointer-events: none;
}
.i-r > div { overflow: hidden; }

.i-l div div, .i-r div div { will-change: transform; transform: translate3d(var(--rx, 0), var(--ry, 0), 0); }
.i-l div div.off, .i-r div div.off { --ry: -101%; }

/* ---------------------------------------------------------------- explore */

.e {
  position: absolute;
  bottom: 49px;
  left: 50%;
  transform: translateX(-50%);
  pointer-events: none;
  text-align: center;
}
.e-t { overflow: hidden; font-size: 10px; line-height: 12px; letter-spacing: 0.02em; }
.e-t > div { will-change: transform; transform: translate3d(var(--rx, 0), var(--ry, 0), 0); }
.e-t > div.off { --ry: -101%; }
.e-l { position: relative; margin: 9px auto 0; width: 3px; overflow: hidden; }
.e-l div {
  position: absolute;
  left: 0;
  width: 1px;
  height: 100%;
  border-right: 1px solid currentColor;
  will-change: transform;
}
.e-s {
  margin: 13px auto 0;
  width: 14px;
  height: 14px;
  overflow: hidden;
}
.e-s div, .e-l div { will-change: transform; transform: translate3d(var(--rx, 0), var(--ry, 0), 0); }
.e-s div.off, .e-l div.off { --ry: -110%; }
.e-l, .e-s { pointer-events: none; }

/* ---------------------------------------------------------------- pagination
 * The rectangles are drawn on #c2d; these are the DOM number labels that wipe in either
 * side of the expanded tick. Row top/height/font-size are set per-frame by the engine. */

.pgn-w {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.pgn {
  position: absolute;
  left: 0;
  width: 100%;
  margin-top: 1px;
  overflow: hidden;
}
.pgn > div { position: absolute; top: 0; overflow: hidden; }
.pgn div div {
  padding: 0 2px;
  will-change: transform;
  transform: translate3d(var(--rx, 0), var(--ry, 0), 0);
}
.pgn div div.off { --rx: -100%; }

/* ---------------------------------------------------------------- project page chrome */

#p {
  position: absolute;
  top: 49px;
  left: 50%;
  transform: translateX(-50%);
  pointer-events: none;
  text-align: center;
}
#p-s {
  margin: auto;
  width: 14px;
  height: 14px;
  overflow: hidden;
  text-align: center;
}
#p-s div { will-change: transform; transform: translate3d(var(--rx, 0), var(--ry, 0), 0); }
#p-s div.off { --ry: -110%; }
#p-l { position: relative; width: 3px; overflow: hidden; }
#p-l div {
  position: absolute;
  left: 0;
  width: 1px;
  height: 100%;
  border-right: 1px solid currentColor;
  will-change: transform;
  transform: translate3d(var(--rx, 0), var(--ry, 0), 0);
}
#p-l div.off { --ry: -110%; }
#p-t { margin-top: 4px; overflow: hidden; font-size: 10px; line-height: 12px; letter-spacing: 0.02em; }
#p-t > div { will-change: transform; transform: translate3d(var(--rx, 0), var(--ry, 0), 0); }
#p-t > div.off { --ry: -101%; }

#v {
  position: absolute;
  bottom: 44px;
  left: 50%;
  transform: translateX(-50%);
  text-align: center;
  pointer-events: none;
  font-size: 10px;
  line-height: 12px;
  letter-spacing: 0.02em;
}
#v > div { overflow: hidden; }
#v > div > div { will-change: transform; transform: translate3d(var(--rx, 0), var(--ry, 0), 0); }
#v > div > div.off { --ry: -101%; }

/* ---------------------------------------------------------------- media reel */

#w {
  position: absolute;
  z-index: 2;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
#w-l {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
}
#w-l div {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.w-l-bg, .w-l-img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
.w-l-img { opacity: 0; object-fit: cover; will-change: transform; }
.w-l-bg.fx { opacity: 0; transition: opacity 100ms linear 1000ms; }
.w-l-img.fx { opacity: 1; transition: opacity 1000ms var(--ease-img); }

#w-s-w {
  position: absolute;
  top: 50%;
  right: var(--edge);
  width: 8.88889vh;
  height: 65vh;
  transform: translate(0, -50%);
}
.w-s {
  position: relative;
  width: 8.88889vh;
  height: 5vh;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: all;
  cursor: pointer;
}
.w-s:not(:first-child) { margin-top: 1.66667vh; }
.w-s-img {
  position: absolute;
  top: -0.1px;
  left: -0.1px;
  width: calc(100% + 0.2px);
  height: calc(100% + 0.2px);
  object-fit: cover;
  opacity: 0;
  pointer-events: none;
  will-change: transform;
}
.w-s-img.fx { opacity: 1; transition: opacity 1000ms var(--ease-img); }

#w-a {
  position: absolute;
  top: calc(17.5vh - 6px);
  right: 44px;
  width: calc(8.88889vh + 12px);
  height: calc(5vh + 12px);
  border: 1.34px solid currentColor;
  box-sizing: border-box;
  opacity: 0;
  pointer-events: none;
}

/* ---------------------------------------------------------------- about */

#a {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
#a-left { position: absolute; left: var(--edge); top: 49px; width: 100%; }
#a-nif-w { margin-left: 1px; font-family: "Display", "Display Fallback", Impact, sans-serif; }
.a-nif::after { content: ""; display: block; clear: both; }
.a-nif > span { float: left; overflow: hidden; }
.a-nif span span {
  float: left;
  transform: translate3d(var(--rx, 0), var(--ry, 0), 0) scaleX(var(--display-squeeze));
  transform-origin: 0 50%;
  will-change: transform;
}
.a-nif span span.off { --rx: -101%; }

#a-p { padding-top: 7.5vh; font-size: 11px; line-height: 10px; }
#a-p > span { display: block; overflow: hidden; }
#a-p span span { display: block; will-change: transform; transform: translate3d(var(--rx, 0), var(--ry, 0), 0); }
#a-p span span.off { --ry: 110%; }

#a-social {
  position: absolute;
  left: var(--edge);
  bottom: calc(6.66667vh + 50px);
  font-size: 12px;
  line-height: 14px;
}
#a-social div { overflow: hidden; }
#a-social a { display: table; pointer-events: all; will-change: transform; transform: translate3d(var(--rx, 0), var(--ry, 0), 0); }
#a-social a.off { --ry: 110%; }

#a-list {
  position: absolute;
  bottom: calc(10.83333vh + 50px);
  right: 0;
  font-size: 11px;
  line-height: 11px;
}
#a-list > li { float: left; width: 230px; }
.a-li { position: relative; height: 385px; }
/* Rows stay in flow. Taking them out of it collapses every row onto the first one's
 * static position, because each subsequent hypothetical box ignores the ones before it. */
.a-li li { position: relative; padding-left: 12px; overflow: hidden; }
.a-li span { display: inline-block; }
.a-li span:first-child { position: absolute; top: 0; left: -17px; text-align: right; width: 24px; }
.a-li span:last-child { padding-left: 24px; }
.a-li div { will-change: transform; transform: translate3d(var(--rx, 0), var(--ry, 0), 0); }
.a-li div.off { --ry: 110%; }

#a-design {
  position: absolute;
  bottom: var(--bottom);
  right: 0;
  width: 678px;
  font-size: 10px;
  line-height: 10px;
  overflow: hidden;
}
#a-design a { display: table; pointer-events: all; will-change: transform; transform: translate3d(var(--rx, 0), var(--ry, 0), 0); }
#a-design a.off { --ry: 101%; }

#a-rights {
  position: absolute;
  bottom: var(--bottom);
  right: var(--edge);
  font-size: 10px;
  line-height: 10px;
  text-align: right;
}
#a-rights > div { overflow: hidden; }
#a-rights div div { display: inline-block; will-change: transform; transform: translate3d(var(--rx, 0), var(--ry, 0), 0); }
#a-rights div div.off { --ry: 101%; }

/* ---------------------------------------------------------------- 404 */

#p404 {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 18px;
  text-align: center;
}
.p404-big {
  font-family: "Display", "Display Fallback", Impact, sans-serif;
  font-size: calc(120px * var(--display-cap));
  line-height: 1;
}
.p404-big span { display: block; transform: scaleX(var(--display-squeeze)); }
#p404 a { padding: 20px; font-size: 12px; letter-spacing: 0.04em; text-decoration: underline; }

/* ---------------------------------------------------------------- responsive
 * Height- and aspect-driven, because the layout is one non-scrolling viewport.
 * Progressive shedding, not reflow — spec §4. */

@media (max-width: 700px) { #c2d, .pgn-w { display: none; } }

@media (min-height: 850px) {
  #a-nif-w { font-size: calc((17.5vh + 100px) * var(--display-cap)); line-height: calc(13.0725vh + 74.7px); }
  .a-nif > span { margin-left: calc(-0.42vh + -2.4px); }
}
@media (min-height: 750px) and (max-height: 850px) {
  #a-nif-w { font-size: calc((15vh + 100px) * var(--display-cap)); line-height: calc(11.205vh + 74.7px); }
  .a-nif > span { margin-left: calc(-0.36vh + -2.4px); }
}
@media (max-height: 750px) {
  #a-nif-w { font-size: calc((13.33333vh + 100px) * var(--display-cap)); line-height: calc(9.96vh + 74.7px); }
  .a-nif > span { margin-left: calc(-0.32vh + -2.4px); }
}
@media (max-height: 700px) { #a-p { display: none; } }
@media (max-height: 850px) { #a-social div:nth-child(4), #a-social div:nth-child(5) { display: none; } }
@media (max-height: 600px) { #a-list { display: none; } }

@media (min-width: 1800px) { #a-list > li { width: 260px; } #a-design { width: 1028px; } }
@media (min-width: 1550px) and (max-width: 1800px) { #a-design { width: 908px; } }
@media (max-width: 1550px) { #a-list > li:last-child { display: none; } }
@media (max-width: 1250px) { #a-list > li:nth-child(3) { display: none; } #a-design { display: none; } }
@media (max-width: 1050px) { #a-list > li { display: none; } }
@media (max-width: 1350px) { .i-l, .i-r { display: none; } }
@media (max-width: 1150px) { #w-a, #w-s-w { display: none; } }

/* The single aspect breakpoint — switches the giant-title scale between vh and vw. */
@media (min-aspect-ratio: 1660/1200) {
  .t {
    line-height: 28.125vh;
    font-size: calc(37.5vh * var(--display-cap));
  }
  .t > div { height: 28.125vh; }
  .tt { top: calc(50% - 33.125vh); }
  .tb { top: calc(50% - 5vh); }
  .t > div { margin-left: -3.33333vh; }
  .t-l > span { padding-left: 3.33333vh; padding-right: 3.33333vh; }
  #w-l { width: 96.2963vh; height: 54.16667vh; }
}
@media (max-aspect-ratio: 1660/1200) {
  .t {
    line-height: 19.87952vw;
    font-size: calc(26.50602vw * var(--display-cap));
  }
  .t > div { height: 19.87952vw; }
  .tt { top: calc(50% - 23.49398vw); }
  .tb { top: calc(50% - 3.61446vw); }
  .t > div { margin-left: -2.40964vw; }
  .t-l > span { padding-left: 2.40964vw; padding-right: 2.40964vw; }
  #w-l { width: 69.61178vw; height: 39.15663vw; }
}

@media (min-height: 760px) { .e-l { height: 34px; } }
@media (min-height: 700px) and (max-height: 760px) { .e-l { height: 3.4vh; } }
@media (min-height: 660px) and (max-height: 700px) { .e-l { height: 2.5vh; } }
@media (max-height: 660px) { .e-l { height: 2vh; } }

@media (min-height: 870px) { #p-l { margin: 11px auto 0; height: 16px; } }
@media (min-height: 810px) and (max-height: 870px) { #p-l { margin: 11px auto 0; height: 1.2vh; } }
@media (max-height: 810px) { #p-l { height: 0; } }

/* ---------------------------------------------------------------- reduced motion
 * The reference has none. Everything here is motion, so this matters more than usual:
 * kill the transitions, and the engine snaps its damped values straight to target. */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
  /* Resting state is a custom property, so reduced motion is one rule: put everything at
   * its final position and let the engine's snap-to-target do the rest. */
  .off, [style*="--rx"], [style*="--ry"] { --rx: 0 !important; --ry: 0 !important; }
}
