/* DECEMA — motion system
   Timing vocabulary: two easings, two primary durations, and a set of
   staggers. Everything below is built from these. */

:root {
  --cubic: cubic-bezier(0.77, 0, 0.175, 1);
  --cubic-2: cubic-bezier(0.5, 0, 0.5, 1);
  --dur: 0.79s;
  --dur-2: 0.49s;
  --stagger-nav: 0.06s;
  --stagger-line: 0.015s;
}

/* ---------------------------------------------------------------
   1. Nav — three-state machine (opening → open → closing).
   Entry rises from below; exit continues upward rather than
   reversing, so open and close never look like the same move.
   --------------------------------------------------------------- */

/* Closed, this must occupy no space at all. `height: 0` alone is not enough:
   with border-box sizing the vertical padding cannot compress, so the panel
   still painted an opaque, blurred band across the top of every page. Zero the
   padding and take it out of visibility too. */

.c-navscreen {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 0;
  padding-top: 0;
  padding-bottom: 0;
  z-index: 998;
  overflow: hidden;
  pointer-events: none;
  visibility: hidden;
  filter: blur(12px);
  transition: height 0.01s ease, padding 0.01s ease, visibility 0s linear,
    filter var(--dur-2) var(--cubic-2) 0.1s;
}

body.is--navopening .c-navscreen,
body.is--navopen .c-navscreen {
  height: 100%;
  padding-top: var(--header-h);
  padding-bottom: var(--gutter);
  pointer-events: all;
  visibility: visible;
  filter: blur(0);
  transition: height 0.01s ease, padding 0.01s ease, visibility 0s linear,
    filter var(--dur-2) var(--cubic-2);
}

/* Keep it visible through the exit animation, then hide. */
body.is--navclosing .c-navscreen {
  height: 100%;
  padding-top: var(--header-h);
  padding-bottom: var(--gutter);
  visibility: visible;
}

.c-navscreen__menu {
  perspective: 1000px;
}

.c-navscreen__menu li a {
  display: block;
  position: relative;
  line-height: 1;
  transform-style: preserve-3d;
  transform-origin: center center;
  backface-visibility: hidden;
  transform: translateY(30%) rotateX(-40deg);
  opacity: 0;
  transition: transform var(--dur-2) ease, opacity var(--dur-2) ease;
}

body.is--navopening .c-navscreen__menu li a,
body.is--navopen .c-navscreen__menu li a {
  transform: none;
  opacity: 1;
  transition: transform var(--dur) var(--cubic), opacity var(--dur) var(--cubic);
}

body.is--navopening .c-navscreen__menu li:nth-child(1) a,
body.is--navopen .c-navscreen__menu li:nth-child(1) a {
  transition-delay: 0s;
}

body.is--navopening .c-navscreen__menu li:nth-child(2) a,
body.is--navopen .c-navscreen__menu li:nth-child(2) a {
  transition-delay: calc(var(--stagger-nav) * 1);
}

body.is--navopening .c-navscreen__menu li:nth-child(3) a,
body.is--navopen .c-navscreen__menu li:nth-child(3) a {
  transition-delay: calc(var(--stagger-nav) * 2);
}

body.is--navopening .c-navscreen__menu li:nth-child(4) a,
body.is--navopen .c-navscreen__menu li:nth-child(4) a {
  transition-delay: calc(var(--stagger-nav) * 3);
}

body.is--navclosing .c-navscreen__menu li a {
  transform: translateY(-30%) rotateX(40deg);
  opacity: 0;
  transition: transform var(--dur) var(--cubic), opacity var(--dur) var(--cubic);
  transition-delay: 0s !important;
}

/* Supporting blocks fade in just behind the menu and statement. */

.c-navscreen__meta,
.c-navscreen__right,
.c-navscreen__footer {
  opacity: 0;
  transform: translateY(1rem);
  transition: opacity var(--dur-2) var(--cubic),
    transform var(--dur) var(--cubic);
}

body.is--navopening .c-navscreen__meta,
body.is--navopen .c-navscreen__meta,
body.is--navopening .c-navscreen__right,
body.is--navopen .c-navscreen__right,
body.is--navopening .c-navscreen__footer,
body.is--navopen .c-navscreen__footer {
  opacity: 1;
  transform: none;
  transition-delay: 0.13s;
}

body.is--navopening .c-navscreen__right,
body.is--navopen .c-navscreen__right {
  transition-delay: 0.2s;
}

body.is--navclosing .c-navscreen__meta,
body.is--navclosing .c-navscreen__right,
body.is--navclosing .c-navscreen__footer {
  opacity: 0;
  transform: translateY(1rem);
  transition-delay: 0s;
}

/* Opener: two faces on a shared perspective. The plus turns away as the
   cross turns in, so the mark reads as one object flipping. */

.c-navopener__face {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform-origin: center center;
  backface-visibility: hidden;
  transition: transform var(--dur) var(--cubic);
}

.c-navopener__face::before,
.c-navopener__face::after {
  content: "";
  display: block;
  position: absolute;
  width: 100%;
  height: 2px;
  background: currentColor;
  top: 50%;
  left: 50%;
  transform: translateX(-50%) translateY(-50%);
  backface-visibility: hidden;
}

/* second bar upright — together they make a plus */
.c-navopener__face::after {
  transform: translateX(-50%) translateY(-50%) rotate(-90deg);
}

/* the cross face waits edge-on, and its bars sit at 45° */
.c-navopener__close {
  transform: translateY(-40%) rotateX(-90deg);
}

.c-navopener__close::before {
  transform: translateX(-50%) translateY(-50%) rotate(45deg);
}

.c-navopener__close::after {
  transform: translateX(-50%) translateY(-50%) rotate(-45deg);
}

body.is--navopening .c-navopener__open,
body.is--navopen .c-navopener__open {
  transform: translateY(50%) rotateX(-90deg);
}

body.is--navopening .c-navopener__close,
body.is--navopen .c-navopener__close {
  transform: none;
}

/* ---------------------------------------------------------------
   3. Phatlines — text revealed a line at a time, each line hinged
   back in 3D and swinging up to flat.
   --------------------------------------------------------------- */

.js-phatlines {
  perspective: 1000px;
}

.js-phatlines .line {
  display: block;
  overflow: visible;
}

.js-phatlines .line .line__inner {
  display: block;
  transform-style: preserve-3d;
  transform-origin: center center;
  backface-visibility: hidden;
  transform: translateY(50%) rotateX(-40deg);
  opacity: 0;
  transition: all var(--dur) var(--cubic);
}

.js-phatlines.is--revealed .line .line__inner,
body.is--navopening .c-navscreen .js-phatlines .line .line__inner,
body.is--navopen .c-navscreen .js-phatlines .line .line__inner {
  transform: none;
  opacity: 1;
}

.js-phatlines .line:nth-child(1) .line__inner { transition-delay: calc(var(--stagger-line) * 0); }
.js-phatlines .line:nth-child(2) .line__inner { transition-delay: calc(var(--stagger-line) * 1); }
.js-phatlines .line:nth-child(3) .line__inner { transition-delay: calc(var(--stagger-line) * 2); }
.js-phatlines .line:nth-child(4) .line__inner { transition-delay: calc(var(--stagger-line) * 3); }
.js-phatlines .line:nth-child(5) .line__inner { transition-delay: calc(var(--stagger-line) * 4); }
.js-phatlines .line:nth-child(6) .line__inner { transition-delay: calc(var(--stagger-line) * 5); }
.js-phatlines .line:nth-child(7) .line__inner { transition-delay: calc(var(--stagger-line) * 6); }
.js-phatlines .line:nth-child(8) .line__inner { transition-delay: calc(var(--stagger-line) * 7); }
.js-phatlines .line:nth-child(9) .line__inner { transition-delay: calc(var(--stagger-line) * 8); }
.js-phatlines .line:nth-child(10) .line__inner { transition-delay: calc(var(--stagger-line) * 9); }

body.is--navclosing .c-navscreen .js-phatlines .line .line__inner {
  transform: translateY(-50%) rotateX(40deg);
  opacity: 0;
  transition-delay: 0s !important;
}

/* ---------------------------------------------------------------
   4. Overview — 5-column offset grid, three rows to a viewport,
   infinite vertical loop, media parallaxing inside clipped frames.
   --------------------------------------------------------------- */

.c-scroll {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  will-change: transform;
}

/* Touch: the wall scrolls natively inside its container, so the OS supplies
   momentum and deceleration. The grid carries no transform in this mode. */
body.has--nativescroll .c-body--overview {
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-y: none;
}

body.has--nativescroll .c-overview {
  touch-action: auto;
}

/* iOS ignores overflow:hidden on body alone — the root element needs it too,
   or the page rubber-bands behind the wall. */
html.has--infinite,
body.has--infinite {
  overflow: hidden;
  height: 100%;
  overscroll-behavior: none;
}

.c-overview {
  /* svh throughout, to match the item height. Mixing vh and svh makes the
     cycle mis-measure on phones as the address bar shows and hides. */
  --offset-gap: 12svh;
  --col-gap: 6vw;
  --row-gap: 22svh;
  --translate-x: 0px;
  --translate-y: 0px;

  /* On pointer devices JS drives the pan from the wheel, so the browser must
     not also scroll here. Touch hands this back — see .has--nativescroll. */
  touch-action: pinch-zoom;

  position: relative;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  column-gap: var(--col-gap);
  row-gap: var(--row-gap);
  width: 110%;
  left: -5%;
  top: calc(var(--offset-gap) * -1);
}

/* Three rows to a viewport on desktop, two on phones — at three, a phone
   row is barely 100px tall and the photography stops reading. */
.c-overview__item {
  position: relative;
  height: calc((100svh + var(--offset-gap) * 2 - var(--row-gap) * 2) / 3);
  opacity: 0;
}

/* columns 2 and 4 drop half a row — the broken rhythm */
.c-overview__item:nth-child(5n + 2),
.c-overview__item:nth-child(5n + 4) {
  transform: translateY(calc(50% + var(--row-gap) / 2));
}

body.has--loaded .c-overview__item {
  opacity: 1;
}

.c-media {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 110%;
  height: 120%;
  overflow: hidden;
  transform: translate(
    calc(var(--translate-x) + var(--settle-x, 0px) - 50%),
    calc(var(--translate-y) + var(--settle-y, 0px) - 50%)
  );
  transition: none;
}

/* once the intro has run, media settles into frame and stays there,
   parallax continuing to ride on --translate-x/y */
body.has--finished .c-overview__item.is--visible .c-media {
  --settle-x: 0px;
  --settle-y: 0px;
  transition: transform 0.2s var(--cubic);
  transition-delay: calc(var(--delay, 1) * 0.01s);
  transition-duration: var(--duration, 0.2s);
}

/* Intro is over — parallax now tracks directly, smoothed in JS instead. */
body.has--settled .c-overview__item .c-media {
  transition: none;
}

/* Images are contained, not cropped — each keeps its own proportions and
   floats inside a frame larger than itself. That size variation is what
   gives the wall its rhythm. */

.c-media a {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  max-width: 100%;
  max-height: 100%;
  transform: translate(-50%, -50%);
  overflow: hidden;
  line-height: 0;
}

.c-media img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  transform: scale(var(--scale, 1));
  transition: transform 1.2s var(--cubic);
  background: rgba(20, 19, 15, 0.04);
}

.c-media a:hover img {
  --scale: 1.04;
}

/* fixed wordmark over the wall */

.c-markover {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  mix-blend-mode: difference;
  color: #fff;
}

.c-markover h1 {
  margin: 0;
  font-size: var(--fs-display);
  line-height: 0.82;
  letter-spacing: -0.05em;
  font-weight: 400;
  text-align: center;
}

@media (max-width: 1100px) {
  .c-overview {
    grid-template-columns: repeat(3, 1fr);
    --col-gap: 4vw;
  }

  .c-overview__item:nth-child(5n + 2),
  .c-overview__item:nth-child(5n + 4) {
    transform: none;
  }

  .c-overview__item:nth-child(3n + 2) {
    transform: translateY(calc(50% + var(--row-gap) / 2));
  }
}

@media (max-width: 720px) {
  .c-overview {
    grid-template-columns: repeat(2, 1fr);
    --offset-gap: 8svh;
    --row-gap: 14svh;
    --col-gap: 4vw;
    width: 100%;
    left: 0;
  }

  /* two rows to a viewport here, not three */
  .c-overview__item {
    height: calc((100svh + var(--offset-gap) * 2 - var(--row-gap)) / 2);
  }
}

/* ---------------------------------------------------------------
   5. Reduced motion — keep the design, drop the movement.
   --------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .c-navscreen,
  .c-navscreen__menu li a,
  .c-navscreen__bottom,
  .js-phatlines .line .line__inner,
  .c-media,
  .c-media img {
    transition: none !important;
  }

  .c-navscreen__menu li a,
  .js-phatlines .line .line__inner {
    transform: none !important;
    opacity: 1 !important;
  }

  .c-overview__item {
    opacity: 1 !important;
  }
}

/* ---------------------------------------------------------------
   6. No-JS — everything visible, no dependence on class toggles.
   --------------------------------------------------------------- */

.no-js .c-navscreen__menu li a,
.no-js .js-phatlines .line .line__inner {
  transform: none;
  opacity: 1;
}

.no-js .c-overview__item {
  opacity: 1;
}

.no-js .c-scroll {
  position: static;
}
