/* ============================================================
   WORK — V3

   Two supplied CodeGrid components, adapted to this site and stitched
   into one page:
     · header  — "Circular Image Gallery" (Slider-24): a tilted ellipse of
       posters orbiting the mark, spun by the wheel. Its GSAP tweens are
       CSS transitions here, so no new dependency came with it.
     · projects — "ThreeJS Infinite Slider" (Slider-20): an endless vertical
       stack of planes that bend with scroll velocity.
   Scrolling hands over from one to the other and back.

   Adapted: the site's own dotted paper instead of #000/#141414, Roc Grotesk
   instead of PP Neue Montreal, the real project posters instead of the
   sample images, brand colours throughout.

   Namespaced under .wk5, loads AFTER style.css.
   ============================================================ */

/* No `background` here. This page used to paint itself flat #fff while the
   rest of the site sat on the dotted paper, which is the single biggest reason
   Work read as a different site. It now inherits the paper like everything
   else. */
body.wk5-page {
  overflow: hidden; overscroll-behavior: none;
  height: 100svh; scrollbar-width: none;
}
body.wk5-page::-webkit-scrollbar { display: none; }
body.wk5-page::before { content: none; }

.wk5 {
  position: fixed; inset: 0; overflow: hidden;
  color: var(--ink);
  font-family: var(--roc);
  touch-action: none;
}

/* ============ HEADER — the orbiting ring (Slider-24) ============ */
.wk5-ring {
  position: absolute; inset: 0; overflow: hidden;
  z-index: 2;
  transform-origin: 50% 50%;
  will-change: transform, opacity;
}
.wk5-ring-item {
  position: absolute; top: 50%; left: 50%;
  width: clamp(120px, 15vw, 240px);
  aspect-ratio: 3 / 2;
  margin-left: calc(clamp(120px, 15vw, 240px) / -2);
  margin-top: calc(clamp(120px, 15vw, 240px) / 3 * -1);
  /* the dim-the-others treatment, as a transition rather than a GSAP tween */
  filter: saturate(1) brightness(1);
  transition: filter 1s cubic-bezier(.16, 1, .3, 1);
  cursor: pointer;
}
.wk5-ring-item.dim { filter: saturate(.15) brightness(.86); }
.wk5-ring-frame {
  width: 100%; height: 100%; overflow: hidden;
  border-radius: clamp(8px, .9vw, 14px);
  /* white, not #f1f0f8: on the paper that near-grey all but vanished, so a
     poster that had not loaded left a hole. A white plate reads as a card. */
  background: #fff;
  box-shadow: 0 14px 38px rgba(20, 20, 80, .16);
  transform: scale(1);
  transition: transform 1s cubic-bezier(.16, 1, .3, 1);
}
.wk5-ring-item.hot .wk5-ring-frame { transform: scale(1.1); }
.wk5-ring-frame img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transform: scale(1.1);                       /* idle zoom, pulls back on hover */
  transition: transform 1s cubic-bezier(.16, 1, .3, 1);
}
.wk5-ring-item.hot .wk5-ring-frame img { transform: scale(1); }

/* the mark at the centre of the ring */
.wk5-mark {
  position: absolute; top: 50%; left: 50%;
  translate: -50% -50%;
  z-index: 10; text-align: center; pointer-events: none;
}
.wk5-mark h1 {
  margin: 0;
  font-family: var(--roc); font-weight: 700;
  font-size: clamp(38px, 6.6vw, 104px);
  letter-spacing: -.055em; line-height: .9;
  text-transform: lowercase;
}
.wk5-mark h1 em { font-style: normal; color: var(--blue); }
/* one span per letter (work.js), so the word can dissolve where it stands */
.wk5-ch { display: inline-block; will-change: opacity, filter, transform; }
/* (the "scroll to browse" cue under the mark was removed on request) */

/* ============ PROJECTS — the infinite slider (Slider-20) ============ */
.wk5-slider {
  position: absolute; inset: 0; z-index: 1;
  opacity: 0; pointer-events: none;
  will-change: opacity;
}
.wk5-slider canvas {
  position: absolute; inset: 0; width: 100%; height: 100%; display: block;
  /* the swap between categories: out fast, back in with a small lift */
  transition: opacity .32s ease, transform .5s var(--ease);
}
.wk5-slider canvas.wk5-swap {
  opacity: 0; transform: translateY(22px);
  transition: opacity .2s ease, transform .2s ease;
}

/* the title / counter that ride the active slide */
.wk5-slide-info {
  position: absolute; top: 50%; left: 0; right: 0;
  translate: 0 -50%;
  padding: 0 clamp(20px, 4vw, 56px);
  display: flex; align-items: baseline; justify-content: space-between; gap: 1.5em;
  z-index: 3; pointer-events: none;
  /* The planes are centred and about a third of the width, so the type sits in
     the clear columns either side. A difference blend was legible but turned
     inside-out wherever a title ran across a poster. */
  color: var(--ink);
  opacity: 0; transition: opacity .4s ease;     /* belongs to the slider, not the ring */
}
.wk5.on-slider .wk5-slide-info { opacity: 1; }
.wk5-slide-title {
  margin: 0; max-width: 30%;
  font-family: var(--roc); font-weight: 700;
  font-size: clamp(18px, 2.4vw, 38px); letter-spacing: -.035em; line-height: 1.05;
}
.wk5-slide-count {
  margin: 0;
  font-family: var(--helv); font-weight: 700;
  font-size: clamp(16px, 2vw, 30px); letter-spacing: .04em;
}

/* (the brand · category caption that sat bottom-left is replaced by the
   category filter below) */

/* a progress rail down the right edge */
.wk5-rail {
  position: absolute; right: clamp(16px, 2.4vw, 34px); top: 24%; bottom: 24%;
  width: 2px; border-radius: 2px; background: rgba(27, 21, 51, .12);
  z-index: 3; pointer-events: none;
  opacity: 0; transition: opacity .4s ease;
}
.wk5.on-slider .wk5-rail { opacity: 1; }
.wk5-rail i {
  position: absolute; left: -2px; width: 6px; height: 34px;
  border-radius: 3px; background: var(--blue);
  will-change: transform;
}

/* back to the ring */
.wk5-back {
  position: absolute; left: clamp(20px, 4vw, 56px); top: clamp(92px, 13vh, 128px);
  z-index: 4;
  font-family: var(--helv); font-weight: 700; letter-spacing: -.04em;
  font-size: clamp(12px, 1.05vw, 15px);
  background: none; border: 0; padding: 0; cursor: pointer; color: var(--ink);
  opacity: 0; pointer-events: none; transition: opacity .4s ease;
}
.wk5.on-slider .wk5-back { opacity: 1; pointer-events: auto; }
.wk5-back:hover { color: var(--blue); }

/* ============ CATEGORY FILTER ============
   One button in the bottom-left corner, where the brand · category caption
   used to be, opening a menu upwards. The panel is the Contact page's —
   white, the same soft drop shadow and inset hairline — and the chosen
   category is the brand blue, the same as every other "on" state here.
   It belongs to the slider, so it arrives and leaves with it. */
.wk5-filter {
  position: absolute; z-index: 6;
  left: clamp(20px, 4vw, 56px);
  bottom: clamp(24px, 4vh, 44px);
  opacity: 0; pointer-events: none;
  transition: opacity .4s ease;
}
.wk5.on-slider .wk5-filter { opacity: 1; pointer-events: auto; }

.wk5-filter-btn {
  display: inline-flex; align-items: center; gap: .55em;
  font-family: var(--roc); font-weight: 700;
  font-size: clamp(13px, 1vw, 15px); letter-spacing: -.01em; line-height: 1;
  color: var(--ink); background: #fff;
  border: 0; border-radius: 999px;
  padding: .78em 1em .78em 1.15em;
  box-shadow: 0 10px 28px rgba(20, 20, 80, .1), inset 0 0 0 1px #e6e4f2;
  cursor: pointer;
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
.wk5-filter-btn:hover { transform: translateY(-2px); box-shadow: 0 14px 32px rgba(20, 20, 80, .14), inset 0 0 0 1px #e6e4f2; }
.wk5-filter-btn:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
/* the kicker says what the control is before it says what it is set to */
.wk5-filter-k {
  font-family: var(--mono); font-weight: 500;
  font-size: .74em; letter-spacing: .18em; text-transform: uppercase;
  color: #6d6884;
  padding-right: .8em; margin-right: .1em;
  border-right: 1px solid #e6e4f2;
  align-self: stretch; display: inline-flex; align-items: center;
}
.wk5-filter-n {
  font-size: .72em; font-weight: 500; color: #6d6884;
  position: relative; top: -.45em; margin-left: -.3em;
}
.wk5-filter-chev {
  width: .85em; height: .85em; margin-left: .15em; color: var(--blue);
  transition: transform .3s var(--ease);
}
.wk5-filter.open .wk5-filter-chev { transform: rotate(180deg); }
/* the menu opens up into the project title — step the title back while it is
   there, rather than let the two touch */
.wk5.on-slider.filter-open .wk5-slide-info { opacity: .12; }

.wk5-filter-menu {
  position: absolute; left: 0; bottom: calc(100% + 10px);
  min-width: 100%; width: max-content;
  max-width: min(340px, calc(100vw - 40px));
  max-height: min(62vh, 470px); overflow-y: auto;
  overscroll-behavior: contain;
  padding: 8px;
  background: #fff;
  border-radius: clamp(16px, 1.6vw, 22px);
  box-shadow: 0 18px 50px rgba(20, 20, 80, .16), inset 0 0 0 1px #eceaf6;
  transform-origin: 0% 100%;
  opacity: 0; transform: translateY(10px) scale(.96);
  transition: opacity .2s ease, transform .28s var(--ease);
  scrollbar-width: thin;
}
.wk5-filter.open .wk5-filter-menu { opacity: 1; transform: none; }

.wk5-filter-item {
  display: flex; align-items: center; justify-content: space-between; gap: 2.4em;
  width: 100%; text-align: left;
  font-family: var(--roc); font-weight: 700;
  font-size: clamp(14px, 1.05vw, 16px); letter-spacing: -.01em;
  color: var(--ink); background: none;
  border: 0; border-radius: 12px;
  padding: .74em .95em;
  cursor: pointer;
  transition: background .18s ease, color .18s ease;
}
/* the rows arrive one after another as the panel opens */
.wk5-filter.open .wk5-filter-item { animation: wk5fi .34s var(--ease) both; animation-delay: calc(var(--i, 0) * 22ms); }
@keyframes wk5fi { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.wk5-filter-item:hover, .wk5-filter-item:focus-visible { background: #f1f0f8; outline: none; }
.wk5-fi-n {
  font-family: var(--mono); font-weight: 500;
  font-size: .78em; letter-spacing: .06em; color: #6d6884;
}
.wk5-filter-item[aria-checked="true"] { background: var(--blue); color: #fff; }
.wk5-filter-item[aria-checked="true"] .wk5-fi-n { color: rgba(255, 255, 255, .78); }

/* ============ SOUND — the button, bottom-right ============
   Shown, not said: a round white button (the filter's material) holding
   four bars that dance while sound is on, breathe while the browser is
   holding sound back (tap to let it out), and give way to a muted speaker
   when it is off. The name is for screen readers and the tooltip. */
.wk5-sound {
  position: absolute; z-index: 6;
  right: clamp(20px, 4vw, 56px);
  bottom: clamp(24px, 4vh, 44px);
  display: grid; place-items: center;
  width: clamp(42px, 3.2vw, 48px); aspect-ratio: 1;
  padding: 0;
  color: var(--ink); background: #fff;
  border: 0; border-radius: 50%;
  box-shadow: 0 10px 28px rgba(20, 20, 80, .1), inset 0 0 0 1px #e6e4f2;
  cursor: pointer;
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
.wk5-sound:hover { transform: translateY(-2px); box-shadow: 0 14px 32px rgba(20, 20, 80, .14), inset 0 0 0 1px #e6e4f2; }
.wk5-sound:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
.wk5-sound > * { grid-area: 1 / 1; }
.wk5-eq { display: flex; align-items: center; gap: 2.5px; height: 16px; }
.wk5-eq i { display: block; width: 2.5px; height: 30%; border-radius: 2px; background: var(--blue); }
.wk5-mute { width: 20px; height: 20px; opacity: 0; transition: opacity .2s ease; }
.wk5-sound.is-on .wk5-eq i { animation: wk5eq .8s ease-in-out infinite alternate; }
.wk5-sound.is-on .wk5-eq i:nth-child(2) { animation-duration: .62s; animation-delay: -.2s; }
.wk5-sound.is-on .wk5-eq i:nth-child(3) { animation-duration: .9s;  animation-delay: -.45s; }
.wk5-sound.is-on .wk5-eq i:nth-child(4) { animation-duration: .7s;  animation-delay: -.1s; }
@keyframes wk5eq { from { height: 22%; } to { height: 100%; } }
/* held back by the browser: the bars stand and breathe — a nudge to tap */
.wk5-sound.is-held .wk5-eq i:nth-child(1) { height: 40%; }
.wk5-sound.is-held .wk5-eq i:nth-child(2) { height: 75%; }
.wk5-sound.is-held .wk5-eq i:nth-child(3) { height: 55%; }
.wk5-sound.is-held .wk5-eq i:nth-child(4) { height: 30%; }
.wk5-sound.is-held .wk5-eq { animation: wk5breathe 1.6s ease-in-out infinite; }
@keyframes wk5breathe { 0%, 100% { opacity: .45; } 50% { opacity: 1; } }
/* off: the muted speaker */
.wk5-sound.is-off .wk5-eq { opacity: 0; }
.wk5-sound.is-off .wk5-mute { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .wk5-sound { transition: none; }
  .wk5-sound.is-on .wk5-eq i, .wk5-sound.is-held .wk5-eq { animation: none; }
  .wk5-sound.is-on .wk5-eq i:nth-child(1) { height: 45%; }
  .wk5-sound.is-on .wk5-eq i:nth-child(2) { height: 90%; }
  .wk5-sound.is-on .wk5-eq i:nth-child(3) { height: 65%; }
  .wk5-sound.is-on .wk5-eq i:nth-child(4) { height: 35%; }
  .wk5-filter-btn, .wk5-filter-menu, .wk5-filter-chev, .wk5-slider canvas { transition: none; }
  .wk5-filter-btn:hover { transform: none; }
  .wk5-filter.open .wk5-filter-item { animation: none; }
}

@media (max-width: 760px) {
  .wk5-ring-item { width: clamp(84px, 26vw, 140px); margin-left: calc(clamp(84px, 26vw, 140px) / -2); margin-top: calc(clamp(84px, 26vw, 140px) / 3 * -1); }
  .wk5-slide-title { font-size: clamp(14px, 4vw, 20px); max-width: 44%; }
  /* On a phone the oval is narrower than the title, so posters orbit straight
     through "the work." and the cue. Same device as the home page's making
     headline: a wash of the paper under the words only, above the ring. */
  .wk5-mark::before {
    content: ""; position: absolute; inset: -34px -30px; z-index: -1;
    background: radial-gradient(closest-side, rgba(237, 236, 248, .94), rgba(237, 236, 248, .7) 55%, rgba(237, 236, 248, 0));
    pointer-events: none;
    opacity: var(--wk5-wash, 1);         /* leaves with the word */
  }
}

@media (prefers-reduced-motion: reduce) {
  .wk5-ring-item, .wk5-ring-frame, .wk5-ring-frame img { transition: none; }
}
