/* ==========================================================================
   NEXIFY STUDIO: scroll choreography (js/motion.js, js/crew.js)
   Same palette, type and light as the rest of the site; only motion is new.
   Type rises from behind a baseline the way the giant words sit on the floor
   line, the spotlight comes up as a section arrives, photographs open like a
   curtain and settle out of a slow zoom. Starting states apply only while
   .mo is on <html> (set before first paint, removed again if the engine never
   starts), so nothing can stay hidden.
   ========================================================================== */

:root {
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-io: cubic-bezier(0.7, 0, 0.25, 1);
}

/* ---- reveals: play in on arrival, play back out when scrolled back above --- */
.mo [data-fx] {
  transition-property: opacity, transform, filter, clip-path, background-color, border-color, color;
  transition-duration: 0.9s, 1.2s, 1.1s, 1.3s, 0.25s, 0.25s, 0.25s;
  transition-timing-function: var(--ease-out), var(--ease-out), var(--ease-out), var(--ease-io), var(--ease), var(--ease), var(--ease);
  transition-delay: 0s;
}
.mo [data-fx].is-in { transition-delay: var(--fx-delay, 0s), var(--fx-delay, 0s), var(--fx-delay, 0s), var(--fx-delay, 0s), 0s, 0s, 0s; }
.mo [data-fx]:not(.is-in) { transition-duration: 0.45s, 0.45s, 0.45s, 0.6s, 0.25s, 0.25s, 0.25s; }
.fx-instant, .fx-instant *, .fx-instant::before, .fx-instant *::before { transition: none !important; }

/* rise: lifts into place */
.mo [data-fx="up"]:not(.is-in),
.mo [data-fx="row"]:not(.is-in) { opacity: 0; transform: translate3d(0, 2rem, 0); }
.mo [data-fx="rise"]:not(.is-in) { opacity: 0; transform: translate3d(0, 3rem, 0) scale(0.985); }

/* focus: copy pulls from a soft blur to sharp */
.mo [data-fx="blur"]:not(.is-in) { opacity: 0; filter: blur(14px); transform: translate3d(0, 0.6rem, 0); }

/* wipe: the mono label draws in from its slash */
.mo [data-fx="wipe"] { clip-path: inset(-30% -4% -30% -4%); }
.mo [data-fx="wipe"]:not(.is-in) { clip-path: inset(-30% 100% -30% -4%); }

/* words: each word rises from behind the line it sits on */
.mw {
  display: inline-block;
  vertical-align: top;
  padding-bottom: 0.16em;           /* room for descenders inside the mask */
  margin-bottom: -0.16em;
  clip-path: inset(-0.5em -0.3em 0 -0.3em);
}
.mwi {
  display: inline-block;
  transition: transform 1.15s var(--ease-out), opacity 0.8s var(--ease-out);
  transition-delay: calc(var(--fx-delay, 0s) + var(--wi, 0) * 0.06s);
}
.mo [data-fx="words"]:not(.is-in) .mwi {
  transform: translate3d(0, 115%, 0);
  opacity: 0;
  transition-duration: 0.45s;
  transition-delay: 0s;
}

/* characters: the closing line builds letter by letter out of focus */
.mwr { display: inline-block; white-space: nowrap; }
.mc {
  display: inline-block;
  transition: transform 1s var(--ease-out), opacity 0.8s var(--ease-out), filter 0.9s var(--ease-out);
  transition-delay: calc(var(--fx-delay, 0s) + var(--ci, 0) * 0.034s);
}
.mo [data-fx="chars"]:not(.is-in) .mc {
  opacity: 0;
  transform: translate3d(0, 0.45em, 0);
  filter: blur(10px);
  transition-duration: 0.4s;
  transition-delay: 0s;
}

/* rows: the hairline above each row draws in from the left as the row rises */
.mo .menu__item[data-fx],
.mo .workshop[data-fx] { position: relative; border-top-color: transparent; }
.mo .menu__item[data-fx]::before,
.mo .workshop[data-fx]::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: -1px;
  height: 1px;
  background: var(--line);
  transform-origin: 0 50%;
  transition: transform 1.4s var(--ease-out);
  transition-delay: inherit;
}
.mo .workshop[data-fx]::before { background: var(--line-strong); }
.mo .menu__item[data-fx]:not(.is-in)::before,
.mo .workshop[data-fx]:not(.is-in)::before { transform: scaleX(0); }

/* photographs: a curtain opens, the picture settles out of a slow zoom.
   The curtain is a mask that grows from one edge, not a clip-path: the
   browser's IntersectionObserver measures an element through its own
   clip-path, so a tall photo whose curtain opens from its bottom edge (still
   below the reveal line) counted as off screen the moment it began to open,
   was closed again by js/motion.js, and flickered without ever opening.
   A mask leaves the photo's measured box alone; the look is the same. */
.mo [data-fx="img"] {
  --curtain-at: 50% 100%;
  -webkit-mask-image: linear-gradient(#000, #000);
          mask-image: linear-gradient(#000, #000);
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: var(--curtain-at);
          mask-position: var(--curtain-at);
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  transition: -webkit-mask-size 1.5s var(--ease-io), mask-size 1.5s var(--ease-io);
  transition-delay: 0s;
}
.mo [data-fx="img"].is-in { transition-delay: var(--fx-delay, 0s); }
.mo [data-fx="img"]:not(.is-in) { transition-duration: 0.6s; }
.mo [data-fx="img"][data-dir="up"]    { --curtain-at: 50% 100%; }   /* opens upward from the bottom edge */
.mo [data-fx="img"][data-dir="down"]  { --curtain-at: 50% 0%; }     /* opens downward from the top edge */
.mo [data-fx="img"][data-dir="left"]  { --curtain-at: 0% 50%; }     /* opens from the left edge */
.mo [data-fx="img"][data-dir="right"] { --curtain-at: 100% 50%; }   /* opens from the right edge */
.mo [data-fx="img"][data-dir="up"]:not(.is-in),
.mo [data-fx="img"][data-dir="down"]:not(.is-in)  { -webkit-mask-size: 100% 0%; mask-size: 100% 0%; }
.mo [data-fx="img"][data-dir="left"]:not(.is-in),
.mo [data-fx="img"][data-dir="right"]:not(.is-in) { -webkit-mask-size: 0% 100%; mask-size: 0% 100%; }
.mo [data-fx="img"] img {
  scale: var(--zoom-to, 1);
  transition: scale 2s var(--ease-out), transform 1s var(--ease), opacity 0.4s;
  transition-delay: var(--fx-delay, 0s), 0s, 0s;
}
.mo [data-fx="img"]:not(.is-in) img {
  scale: var(--zoom-from, 1.26);
  transition-duration: 0.6s, 1s, 0.4s;
  transition-delay: 0s;
}
/* parallax photos keep a little zoom so they can drift inside their frame */
.mo .gallery__item, .mo .location__media { --zoom-to: 1.1; --zoom-from: 1.34; }
.mo .about__media img { transition: none; }   /* scrubbed by scroll instead */

.mo .gallery__item[data-fx] .gallery__cap {
  transition: opacity 0.8s var(--ease-out), transform 1s var(--ease-out);
  transition-delay: calc(var(--fx-delay, 0s) + 0.55s);
}
.mo .gallery__item[data-fx]:not(.is-in) .gallery__cap { opacity: 0; transform: translate3d(0, 0.8rem, 0); transition-delay: 0s; }

/* ---- scrubbed: spotlight, giant words ------------------------------------ */
/* each section's spotlight comes up as it arrives (js: --light) */
.mo .sec::before { opacity: var(--light, 1); }

/* the giant word rises from behind its baseline (--gr), then drifts across
   the section as it passes (--gd) */
.mo .sec__giant {
  --gr: 1;
  --gd: 0.5;
  transform: translate3d(calc((0.5 - var(--gd)) * 12vw), calc((1 - var(--gr)) * 100%), 0);
  clip-path: inset(-45% -12% calc((1 - var(--gr)) * 100% - var(--gr) * 45%) -12%);
  will-change: transform;
}

/* ---- About: the photo stays while the steps light in turn (wide screens) --- */
@media (min-width: 961px) {
  .mo .about { align-items: start; }
  .mo .about__media {
    position: sticky;
    top: 12vh;
    height: 76vh;
    width: auto;
    max-width: 100%;
    justify-self: start;
  }
  .mo .principle { position: relative; min-height: 34vh; align-content: start; padding: 2.2rem 0; }
  .mo .principle::after {               /* a bright line runs across the lit step */
    content: "";
    position: absolute;
    left: 0; top: -1px;
    width: 100%; height: 1px;
    background: var(--offwhite);
    transform-origin: 0 50%;
    transform: scaleX(var(--act, 0));
  }
  .mo .principle__num,
  .mo .principle__title,
  .mo .principle__text { opacity: calc(0.3 + 0.7 * var(--act, 1)); }
  .mo .principle__title { font-size: clamp(1.2rem, 1.6vw, 1.7rem); }
}

/* ==========================================================================
   Barber showcase (js/crew.js)
   ========================================================================== */
.sec--team.is-crew { padding: 0; z-index: 1; }
.sec--team.is-crew > .sec__inner { display: none; }   /* the static grid */
.crew { position: relative; }
.crew__pin {
  position: sticky;
  top: 0;
  height: calc(100 * var(--vh-fill));
  overflow: hidden;
  /* the stage recedes into the dark as the gallery slides over it */
  scale: calc(1 - 0.05 * var(--crew-exit, 0));
  transform-origin: 50% 40%;
}
.crew__pin::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 20;
  background: #030303;
  opacity: calc(0.78 * var(--crew-exit, 0));
  pointer-events: none;
}
.crew__pin .sec__giant { z-index: 0; }

/* the stage: a spotlight falls on the centre place */
.crew__stage { position: absolute; inset: 0; z-index: 1; }
.crew__stage::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 24% 72% at 66% 0%, rgba(255, 250, 245, 0.085), rgba(255, 250, 245, 0.02) 50%, transparent 76%);
  pointer-events: none;
}
.crew__deck {
  position: absolute;
  left: 66%;
  top: 53%;
  width: 0;
  height: 0;
  perspective: 1800px;
  perspective-origin: 0 0;
  transform-style: preserve-3d;
}
.crew__card {
  --cw: min(26vw, 52vh);
  position: absolute;
  left: 0;
  top: 0;
  width: var(--cw);
  aspect-ratio: 3 / 4;
  margin: 0;
  background: #0b0b0b;
  transform: translate(-50%, -50%);
  backface-visibility: hidden;
  will-change: transform, opacity, filter;
}
.crew__card img { width: 100%; height: 100%; object-fit: cover; display: block; }
.crew__card::after {      /* falls to black at the foot, like the hero floor */
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 40%;
  background: linear-gradient(to top, rgba(3, 3, 3, 0.92), transparent);
  pointer-events: none;
}
.crew__nophoto { position: absolute; inset: 0; display: grid; place-items: center; color: var(--grey-dim); font-family: var(--font-mono); }
.crew__num {
  position: absolute;
  left: -0.06em;
  bottom: -0.4em;
  z-index: 2;
  font-family: var(--font-display-heavy);
  font-weight: 900;
  font-size: calc(var(--cw) * 0.34);
  line-height: 1;
  letter-spacing: -0.08em;
  color: transparent;
  background: linear-gradient(100deg, #868584 0%, #5d5b5a 40%, #2d2b2a 85%);
  -webkit-background-clip: text;
  background-clip: text;
  pointer-events: none;
}

/* the side column: heading, the barber's details, the stage counter */
.crew__side {
  position: absolute;
  z-index: 3;
  left: var(--gx);
  top: 0;
  bottom: 0;
  width: min(40vw, 46rem);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: clamp(1.5rem, 4vh, 3.5rem);
  padding: 12vh 0 7vh;
}
.crew__side .sec__head { margin: 0; max-width: none; }
.crew__bios { display: grid; margin-top: auto; }
.crew__bio { grid-area: 1 / 1; align-self: end; }
.crew__bio:not(.is-on) { pointer-events: none; }
.crew__part { will-change: opacity, transform; }
.crew__specialty {
  margin: 0 0 1.1em;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--grey-rating);
}
.crew__name {
  margin: 0;
  padding-bottom: 0.14em;
  font-family: var(--font-headline);
  font-weight: 800;
  font-size: clamp(2.2rem, 3.7vw, 4.2rem);
  line-height: 1;
  letter-spacing: -0.09em;
  color: #fff;
  overflow: hidden;
  overflow: clip;
}
.crew__namei { display: inline-block; }
.crew__intro {
  margin: 0.9em 0 0;
  max-width: 28em;
  font-family: var(--font-ui);
  font-size: clamp(1rem, 1.1vw, 1.12rem);
  line-height: 1.5;
  color: var(--grey-body);
}
.crew__where {
  margin: 1.1em 0 0;
  font-family: var(--font-mono);
  font-size: 0.76rem;
  letter-spacing: 0.06em;
  color: var(--grey-dim);
}
.crew__actions { margin: 0; }
.crew__actions .pill { margin-top: 1.8rem; }

.crew__count {
  display: flex;
  align-items: center;
  gap: 0.9em;
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.86rem;
  letter-spacing: 0.1em;
  color: var(--grey-dim);
}
.crew__win { display: block; height: 1em; overflow: hidden; line-height: 1; color: #fff; }
.crew__digits { display: flex; flex-direction: column; will-change: transform; }
.crew__digits span { display: block; height: 1em; line-height: 1; }
.crew__rail { position: relative; width: clamp(5rem, 9vw, 9rem); height: 1px; background: var(--line-strong); }
.crew__rail i { position: absolute; inset: 0; background: #fff; transform-origin: 0 50%; transform: scaleX(0); }

/* the gallery slides up over the pinned stage */
.mo-crew .sec--team.is-crew + .sec--gallery {
  margin-top: calc(-100 * var(--vh-fill));
  background: #030303;
  z-index: 2;
}

/* phones and narrow windows: heading on top, the barber centred, details below */
@media (max-width: 960px) {
  .crew__side { left: var(--gx); right: var(--gx); width: auto; padding: 7vh 0 5vh; }
  .crew__side .sec__lede { display: none; }
  .crew__side .sec__title { font-size: clamp(1.8rem, 7vw, 2.6rem); }
  .crew__stage::before { background: radial-gradient(ellipse 50% 60% at 50% 0%, rgba(255, 250, 245, 0.08), transparent 75%); }
  .crew__deck { left: 50%; top: 44%; }
  .crew__card { --cw: min(54vw, 30vh); }
  .crew__name { font-size: clamp(1.8rem, 8vw, 2.6rem); }
  .crew__intro { font-size: 0.95rem; }
  .crew__where { display: none; }
  .crew__actions .pill { margin-top: 1.2rem; }
  .crew__count { position: absolute; right: 0; top: calc(7vh + 0.35rem); }
}
@media (max-height: 760px) and (min-width: 961px) {
  .crew__side .sec__lede { display: none; }
}

/* ==========================================================================
   Reduced motion: nothing travels, turns or zooms; fades, focus pulls,
   wipes and the spotlight stay
   ========================================================================== */
.mo-reduce [data-fx],
.mo-reduce [data-fx] .mwi,
.mo-reduce [data-fx] .mc,
.mo-reduce [data-fx] .gallery__cap { transform: none !important; }
.mo-reduce [data-fx] img { scale: none !important; translate: none !important; }
.mo-reduce .sec__giant { transform: none; clip-path: none; opacity: calc(0.8 * var(--gr, 1)); }
.mo-reduce .crew__pin { scale: none; }
