/* Projects tab, after Unseen's Selected Projects: the title, the pills, two
   columns of large tiles, a small way to get in touch. The room stays behind it
   all, held down by a scrim so the tiles can read. */

/* The room is the backdrop. It is most present behind the title and falls away
   as the tiles arrive. --depth runs 0 to 1 with the scroll; without the script it
   stays at 1, the safe dark end. */
.work-scrim {
  --depth: 1;
  --shade: linear-gradient(to bottom, rgba(4, 9, 38, .34), rgba(4, 9, 38, .58) 46%, rgba(4, 9, 38, .76));
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: var(--shade);
}
.work-scrim::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--deep);
  opacity: calc(var(--depth) * .62);
}
/* With no canvas, the same room as a still, so the calm page is the same place. */
html.calm .work-scrim {
  background: var(--shade), url("/assets/flight/05.webp") 56% 55% / cover no-repeat;
}

.work {
  position: relative;
  z-index: 1;
  padding: clamp(88px, 6.5vw, 104px) var(--gutter) 148px;
}

/* The nav and the footer stay put while the page moves, so whatever passes under
   them dissolves into haze on the way, instead of running through their text. */
.work::before,
.work::after {
  content: "";
  position: fixed;
  inset-inline: 0;
  z-index: 2;
  pointer-events: none;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
.work::before {
  top: 0;
  height: calc(var(--nav-h) + 22px);
  background: linear-gradient(to bottom, rgba(4, 9, 38, .72), rgba(4, 9, 38, .4) 52%, rgba(4, 9, 38, 0));
  -webkit-mask-image: linear-gradient(to bottom, #000 56%, transparent);
  mask-image: linear-gradient(to bottom, #000 56%, transparent);
}
.work::after {
  bottom: 0;
  height: calc(var(--foot-h) + 26px);
  background: linear-gradient(to top, rgba(4, 9, 38, .78), rgba(4, 9, 38, .46) 52%, rgba(4, 9, 38, 0));
  -webkit-mask-image: linear-gradient(to top, #000 62%, transparent);
  mask-image: linear-gradient(to top, #000 62%, transparent);
}

/* ------------------------------------------------------------- the head -- */
.work-head {
  display: grid;
  justify-items: center;
  gap: clamp(16px, 1.4vw, 22px);
  margin-bottom: clamp(28px, 2.5vw, 40px);
}

.work-title {
  font-size: clamp(56px, min(7.3vw, 12.4vh), 136px);
  font-weight: 400;
  line-height: .98;
  letter-spacing: -.04em;
  text-align: center;
  text-wrap: balance;
}

/* One capsule of dark glass. The filled pill is where you are. */
.work-filters {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  border-radius: 999px;
  background: var(--glass);
  box-shadow: inset 0 0 0 1px var(--glass-edge);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  backdrop-filter: blur(14px) saturate(1.2);
}
.work-filter {
  min-height: 26px;
  padding: 0 11px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font: 400 12.5px / 1 var(--sans);
  letter-spacing: -.012em;
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .2s var(--ease), color .2s var(--ease);
}
.work-filter sup {
  margin-left: 1px;
  font-size: 12px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  line-height: 0;
  letter-spacing: 0;
  vertical-align: .62em;
}
@media (hover: hover) {
  .work-filter:hover { background: rgba(255, 255, 255, .12); }
}
.work-filter[aria-pressed="true"] { background: var(--ink); color: var(--fog-ink); }
.work-filter:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ------------------------------------------------------------ the tiles -- */
.tiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(16px, 1.7vw, 24px);
  margin: 0;
  padding: 0;
  list-style: none;
  transition: opacity .2s ease-out;
}
.tiles.is-changing { opacity: 0; }

/* Each tile takes three rows of the grid, so the lines under neighbouring tiles
   sit level however their sentences wrap. The space between tiles is a margin,
   not a grid gap: a subgrid's rows can never be shorter than the parent's gap. */
.tile {
  display: grid;
  grid-row: span 3;
  grid-template-rows: subgrid;
  row-gap: 0;
  min-width: 0;
  margin-bottom: clamp(56px, 6.4vw, 96px);
}
.tile[hidden] { display: none; }

.tile-link {
  display: block;
  color: inherit;
  text-decoration: none;
  outline: none;
}

.tile-frame {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: 6px;
  background: var(--night);
}
.tile-link:focus-visible .tile-frame { outline: 2px solid var(--ink); outline-offset: 3px; }

.tile-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.8s var(--ease), opacity .8s ease-out;
}
.tile-world { opacity: 0; }

/* The lens, when the browser can draw one. It takes over from the images above
   only while a tile is under the pointer. */
.tile-lens {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.tile-head {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 16px;
  align-items: end;
  padding: 16px 0 13px;
  border-bottom: 1px solid var(--line);
}
.tile-head::after {
  content: "";
  position: absolute;
  inset: auto 0 -1px;
  height: 1px;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform .25s var(--ease);
}
.tile-name {
  grid-column: 1;
  font-size: clamp(24px, 2.05vw, 31px);
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -.028em;
}
.tile-type {
  grid-column: 1;
  margin: 5px 0 0;
  color: var(--ink-2);
  font-size: clamp(15.5px, 1.2vw, 17.5px);
  line-height: 1.25;
  letter-spacing: -.012em;
}
.tile-arrow {
  grid-column: 2;
  grid-row: 1 / span 2;
  width: 15px;
  height: 15px;
  margin-bottom: 4px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.25;
  transition: transform .2s var(--ease);
}

/* Only where hover is real, or a tapped tile stays lit when you come back to it. */
@media (hover: hover) {
  .tile-link:hover .tile-img { transform: scale(1.035); }
  .tile-link:hover .tile-world { opacity: 1; }
  .tile-link:hover .tile-head::after { transform: scaleX(1); }
  .tile-link:hover .tile-arrow { transform: translate(2px, 2px); }
}
.tile-link:focus-visible .tile-img { transform: scale(1.035); }
.tile-link:focus-visible .tile-world { opacity: 1; }
.tile-link:focus-visible .tile-head::after { transform: scaleX(1); }
.tile-link:focus-visible .tile-arrow { transform: translate(2px, 2px); }

/* The credits under the line. --label is wide enough for the longest label. */
.tile-note {
  --label: 9.4em;
  display: grid;
  grid-template-columns: var(--label) minmax(0, 1fr);
  column-gap: 16px;
  margin: 13px 0 0;
  max-width: 44em;
  color: var(--ink-2);
  font-size: 15.5px;
  line-height: 1.42;
  letter-spacing: -.008em;
}
.tile-note dd { margin: 0; }
.tile-note--job { margin-top: 15px; }
.tile-note--job dd { color: var(--ink); }
.tile-note--plain { display: block; padding-left: calc(var(--label) + 16px); }

/* ---------------------------------------------------------- the way out -- */
.work-cta {
  display: grid;
  justify-items: center;
  gap: 14px;
  margin-top: clamp(40px, 4.6vw, 64px);
  text-align: center;
}
.work-cta p {
  color: var(--ink-2);
  font-size: 15.5px;
}

/* -------------------------------------------------------------- arrival -- */
/* The page comes up out of the haze on its own, with no script to wait for. Tiles
   below the fold are held back by projects.js until they are reached. */
@keyframes work-in {
  from { opacity: 0; filter: blur(14px); }
  to { opacity: 1; filter: none; }
}
.work-title { animation: work-in 1.1s var(--ease) both; }
.work-filters { animation: work-in 1.1s .08s var(--ease) both; }
.tile { animation: work-in 1.3s .16s var(--ease) both; }
.tile:nth-child(2) { animation-delay: .26s; }

.tile.is-hazy { opacity: 0; filter: blur(14px); animation: none; }
.tile.is-arriving {
  animation: none;
  transition: opacity 1.1s var(--ease), filter 1.3s var(--ease);
}
/* Coming back from display: none would replay the arrival, and a filter should
   show the grid as one piece, so once the filters are touched it is over. */
.tile.is-settled { animation: none; }

/* ----------------------------------------------------------- the swirl -- */
/* With the mesh running, the title holds still at the top and the tiles travel
   up under it. They start low enough that nothing is curling at rest. Everything
   here only applies once swirl.js has said it can run. */
.has-swirl .work { padding-top: 44vh; padding-bottom: 52vh; }
/* On a short screen the closing line must end up below the fixed title, not under it. */
@media (max-height: 570px) { .has-swirl .work { padding-bottom: 14vh; } }
/* The head reaches the top of the screen, so nothing that has flown away can still be
   clicked behind the title. */
.has-swirl .work-head {
  position: fixed;
  top: 0;
  padding-top: max(68px, 8vh);
  inset-inline: 0;
  z-index: 3;
  margin: 0;
  gap: 14px;
}
.has-swirl .work-filters { pointer-events: auto; }
.has-swirl .work-title { font-size: clamp(40px, 4vw, 76px); letter-spacing: -.02em; }
.has-swirl .tiles { max-width: min(81vw, 130vh); margin-inline: auto; }
.has-swirl .tile { margin-bottom: clamp(28px, 3.2vw, 52px); }
.has-swirl .tile-frame { border-radius: 0; }
.has-swirl .tile-name,
.has-swirl .tile-type { font-size: clamp(15px, 1.18vw, 20px); font-weight: 400; letter-spacing: -.01em; }
.has-swirl .tile-type { margin-top: 1px; white-space: nowrap; }
.has-swirl .tile-head { padding: 11px 0 10px; }

/* Each client has its own section now, so the list stays as clean as the reference. */
.has-swirl .tile-note { display: none; }

/* The nav haze would blur the ribbon as it passes, and the ribbon has its own fade. */
.has-swirl .work::before,
.has-swirl .work::after { display: none; }
.has-swirl .work-cta { margin-top: 40px; }

.work-gl {
  position: fixed;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* The real tiles stay in place for links, focus and layout, unseen. */
.swirl-on .tile { animation: none; }
.swirl-on .tile-frame,
.swirl-on .tile-head { opacity: 0; }
.swirl-on .tile-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; border-radius: 6px; }

/* -------------------------------------------------------------- smaller -- */
@media (max-width: 760px) {
  .has-swirl .work { padding-top: 46vh; }
  .has-swirl .tiles { max-width: none; }
  .has-swirl .work-head { top: 0; padding-top: 76px; }
  .has-swirl .work-title { font-size: clamp(38px, 11vw, 56px); }
}

@media (max-width: 1120px) {
  .tile-note { display: block; }
  .tile-note dd { margin-top: 2px; }
  .tile-note--plain { padding-left: 0; }
}

@media (max-width: 760px) {
  .tiles { grid-template-columns: minmax(0, 1fr); }
  .tile:nth-child(2) { animation-delay: .16s; }
  .work-head { margin-bottom: 28px; }
  .tile-frame { border-radius: 4px; }
}

@media (max-width: 860px), (pointer: coarse) {
  .work-filter { min-height: 44px; padding: 0 14px; }
}

@media (prefers-reduced-motion: reduce) {
  .work *,
  .work *::before,
  .work *::after {
    animation: none !important;
    transition: none !important;
  }
  .work .tile-link .tile-img { transform: none; }
}
