/* ------------------------------------------------------------------
   Good People Agency: transitions to try (preview only)
   Each effect is switched on by a class on <html> (fx-lobby-zoom, fx-intro,
   fx-reveal, fx-expand, fx-stack, fx-roll, fx-cursor, fx-menu, fx-pagewipe),
   set before first paint from the choices saved in the Transitions panel.
   Reduced motion switches every effect off.
   ------------------------------------------------------------------ */

/* ---------- 1. the lobby: the lit door, then the site ---------- */

.lobby { display: none; }
html.lobby-on .lobby {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: #000;
  overflow: hidden;
}
html.lobby-on body { overflow: hidden; }
.lobby__enter {
  position: absolute;
  left: 50%;
  bottom: calc(40px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  z-index: 1;
  background: transparent;
  color: #fff;
  border: 1px solid #fff;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  padding: 16px 40px;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.8s var(--ease) 0.7s, background-color 0.25s var(--ease), color 0.25s var(--ease);
}
html.lobby-on .lobby.is-in .lobby__enter { opacity: 1; }
/* while the cookie banner is open, the Enter button sits just above it */
html.consent-open .lobby__enter { bottom: calc(24px + var(--consent-h, 0px)); }
.lobby__enter:hover, .lobby__enter:focus-visible { background: #fff; color: #000; }
.lobby__enter:focus-visible { outline: 2px solid #fff; outline-offset: 4px; }
.lobby__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  transform-origin: 50% 52%;
  opacity: 0;
  transform: scale(1.06);
  transition: opacity 1.1s var(--ease), transform 2.2s var(--ease);
}
html.lobby-on .lobby.is-in .lobby__img { opacity: 1; transform: scale(1); }

/* exit: walk through the door */
html.fx-lobby-zoom .lobby.is-out { pointer-events: none; transition: opacity 0.7s var(--ease) 0.55s; opacity: 0; }
html.fx-lobby-zoom .lobby.is-out .lobby__img { transform: scale(4.2); transition: transform 1.25s cubic-bezier(0.7, 0, 0.84, 0); }
/* exit: fade */
html.fx-lobby-fade .lobby.is-out { pointer-events: none; opacity: 0; transition: opacity 1s var(--ease); }
/* exit: the image lifts away like a blind */
html.fx-lobby-lift .lobby { clip-path: inset(0 0 0 0); }
html.fx-lobby-lift .lobby.is-out { pointer-events: none; clip-path: inset(0 0 100% 0); transition: clip-path 1s cubic-bezier(0.76, 0, 0.24, 1); }

/* ---------- 2. intro: first screen settles in ---------- */

html.fx-intro.intro-wait [data-intro] { opacity: 0; }
html.fx-intro [data-intro] { transition: opacity 1s var(--ease), transform 1.2s var(--ease), clip-path 1.3s cubic-bezier(0.76, 0, 0.24, 1); }
html.fx-intro.intro-wait .hero-split__h1 { transform: translateY(24px); }
html.fx-intro.intro-wait .hero-split__photo { opacity: 1; clip-path: inset(100% 0 0 0); }
html.fx-intro .hero-split__photo { clip-path: inset(0 0 0 0); }
html.fx-intro .opener .wrap > * { transition: opacity 1s var(--ease), transform 1.2s var(--ease); }
html.fx-intro.intro-wait .opener .wrap > * { opacity: 0; transform: translateY(28px); }
html.fx-intro .opener .wrap > :nth-child(2) { transition-delay: 0.18s; }
html.fx-intro .opener .wrap > :nth-child(3) { transition-delay: 0.32s; }
html.fx-intro [data-intro="2"] { transition-delay: 0.18s; }
html.fx-intro [data-intro="3"] { transition-delay: 0.32s; }
html.fx-intro [data-intro="4"] { transition-delay: 0.46s; }
/* The intro now plays as CSS animations from first paint instead of waiting
   for fx.js to load, so the first screen shows sooner and never depends on a
   script. Same movements, durations, easing and stagger as the transitions
   above. On the homepage it waits for the lobby (runs once lobby-on is gone). */
@keyframes gp-in-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes gp-in-rise24 { from { transform: translateY(24px); } to { transform: none; } }
@keyframes gp-in-rise28 { from { transform: translateY(28px); } to { transform: none; } }
@keyframes gp-in-wipe { from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0 0 0 0); } }
html.fx-intro:not(.lobby-on) [data-intro] { animation: gp-in-fade 1s var(--ease) var(--gp-d, 0s) both; }
html.fx-intro:not(.lobby-on) .hero-split__h1 { animation: gp-in-fade 1s var(--ease) var(--gp-d, 0s) both, gp-in-rise24 1.2s var(--ease) var(--gp-d, 0s) both; }
html.fx-intro:not(.lobby-on) .hero-split__photo { animation: gp-in-wipe 1.3s cubic-bezier(0.76, 0, 0.24, 1) var(--gp-d, 0s) both; }
html.fx-intro:not(.lobby-on) .opener .wrap > * { animation: gp-in-fade 1s var(--ease) var(--gp-d, 0s) both, gp-in-rise28 1.2s var(--ease) var(--gp-d, 0s) both; }
html.fx-intro [data-intro="2"], html.fx-intro .opener .wrap > :nth-child(2) { --gp-d: 0.18s; }
html.fx-intro [data-intro="3"], html.fx-intro .opener .wrap > :nth-child(3) { --gp-d: 0.32s; }
html.fx-intro [data-intro="4"] { --gp-d: 0.46s; }

/* ---------- 3. headings rise from behind a mask as they arrive ---------- */

html.fx-reveal .rv { display: block; overflow: hidden; padding-bottom: 0.06em; margin-bottom: -0.06em; }
html.fx-reveal .rv > .rv__in { display: block; transform: translateY(105%); transition: transform 0.9s cubic-bezier(0.22, 1, 0.36, 1); }
html.fx-reveal .rv.is-in > .rv__in { transform: none; }
/* the opener's heading and lead are wrapped in the HTML, so they rise from first paint without waiting for fx.js */
@keyframes gp-rv { from { transform: translateY(105%); } to { transform: none; } }
html.fx-reveal .opener .rv > .rv__in { animation: gp-rv 0.9s cubic-bezier(0.22, 1, 0.36, 1) var(--gp-d, 0s) both; }

/* ---------- 4. photographs open out from an inset frame as you scroll ---------- */

html.fx-expand .fx-x { clip-path: inset(var(--xi, 0%) var(--xi, 0%) var(--xi, 0%) var(--xi, 0%)); will-change: clip-path; }

/* ---------- 5. sections stack: each new one slides over the last ---------- */

html.fx-stack .stackable { position: sticky; top: 0; background: var(--paper); transform-origin: 50% 0; }
html.fx-stack .stackable.band--bone { background: var(--bone); }
html.fx-stack .stackable.is-covering { transform: scale(calc(1 - var(--cover, 0) * 0.06)); filter: brightness(calc(1 - var(--cover, 0) * 0.4)) blur(calc(var(--cover, 0) * 3px)); }

/* ---------- 6. rolling text on hover ---------- */

html.fx-roll .roll { display: inline-block; position: relative; overflow: hidden; vertical-align: top; line-height: 1.25; }
html.fx-roll .roll__a, html.fx-roll .roll__b { display: block; transition: transform 0.42s cubic-bezier(0.76, 0, 0.24, 1); }
html.fx-roll .roll__b { position: absolute; left: 0; top: 100%; }
html.fx-roll a:hover .roll__a, html.fx-roll button:hover .roll__a, html.fx-roll a:focus-visible .roll__a { transform: translateY(-100%); }
html.fx-roll a:hover .roll__b, html.fx-roll button:hover .roll__b, html.fx-roll a:focus-visible .roll__b { transform: translateY(-100%); }

/* ---------- 7. cursor ring ---------- */

.gpcursor { display: none; }
@media (hover: hover) and (pointer: fine) {
  html.fx-cursor .gpcursor {
    display: block;
    position: fixed;
    left: 0; top: 0;
    z-index: 900;
    width: 14px; height: 14px;
    margin: -7px 0 0 -7px;
    border-radius: 50%;
    background: #fff;
    mix-blend-mode: difference;
    pointer-events: none;
    transition: width 0.3s var(--ease), height 0.3s var(--ease), margin 0.3s var(--ease), opacity 0.3s;
    opacity: 0;
  }
  html.fx-cursor .gpcursor.is-on { opacity: 1; }
  html.fx-cursor .gpcursor.is-link { width: 56px; height: 56px; margin: -28px 0 0 -28px; }
}

/* ---------- 8. full-screen menu: drops like a curtain, lines rise ---------- */

.gpmenu { display: none; }
html.fx-menu .nav { display: none !important; }
html.fx-menu .burger { display: flex !important; }
html.fx-menu .header__spacer { display: block !important; }
html.fx-menu .gpmenu {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  position: fixed;
  inset: 0;
  z-index: 250;
  background: var(--ink);
  color: var(--paper);
  padding: calc(var(--header-h) + 24px) var(--gutter) 32px;
  clip-path: inset(0 0 100% 0);
  visibility: hidden;
  transition: clip-path 0.75s cubic-bezier(0.76, 0, 0.24, 1), visibility 0s linear 0.75s;
}
html.fx-menu .gpmenu.is-open { clip-path: inset(0 0 0 0); visibility: visible; transition: clip-path 0.75s cubic-bezier(0.76, 0, 0.24, 1), visibility 0s; }
.gpmenu__close {
  position: absolute; top: 0; right: var(--gutter);
  height: var(--header-h);
  background: none; border: 0; color: inherit; cursor: pointer;
  font-family: inherit; font-size: 11px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
}
.gpmenu__links { display: flex; flex-direction: column; }
.gpmenu__links a {
  display: block;
  overflow: hidden;
  font-size: clamp(44px, 8vw, 104px);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: -0.025em;
  line-height: 0.98;
}
.gpmenu__links a:hover { color: var(--bone); }
.gpmenu__links a > span { display: block; transform: translateY(105%); transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1); }
.gpmenu.is-open .gpmenu__links a > span { transform: none; }
.gpmenu.is-open .gpmenu__links a:nth-child(1) > span { transition-delay: 0.28s; }
.gpmenu.is-open .gpmenu__links a:nth-child(2) > span { transition-delay: 0.34s; }
.gpmenu.is-open .gpmenu__links a:nth-child(3) > span { transition-delay: 0.40s; }
.gpmenu.is-open .gpmenu__links a:nth-child(4) > span { transition-delay: 0.46s; }
.gpmenu.is-open .gpmenu__links a:nth-child(5) > span { transition-delay: 0.52s; }
.gpmenu.is-open .gpmenu__links a:nth-child(6) > span { transition-delay: 0.58s; }
.gpmenu__foot { display: flex; flex-wrap: wrap; gap: 8px 28px; font-size: 13px; color: rgba(255,255,255,0.72); opacity: 0; transition: opacity 0.5s var(--ease); }
.gpmenu.is-open .gpmenu__foot { opacity: 1; transition-delay: 0.6s; }

/* ---------- 9. page to page: an ink panel wipes across ---------- */

.fx-wipe { position: fixed; inset: 0; z-index: 1100; background: var(--ink); pointer-events: none; transform: translateY(100%); }
html.fx-pagewipe.is-leaving .fx-wipe { transform: translateY(0); transition: transform 0.55s cubic-bezier(0.76, 0, 0.24, 1); }
html.fx-pagewipe.is-arriving body::after {
  content: '';
  position: fixed; inset: 0; z-index: 1100;
  background: var(--ink);
  pointer-events: none;
}
html.fx-pagewipe.is-arrived body::after {
  content: '';
  position: fixed; inset: 0; z-index: 1100;
  background: var(--ink);
  pointer-events: none;
  animation: gpWipeUp 0.7s cubic-bezier(0.76, 0, 0.24, 1) forwards;
}
@keyframes gpWipeUp { to { transform: translateY(-100%); } }

/* ---------- reduced motion: everything off ---------- */

@media (prefers-reduced-motion: reduce) {
  html.lobby-on .lobby { display: none; }
  html.lobby-on body { overflow: auto; }
  html.fx-intro.intro-wait [data-intro], html.fx-intro.intro-wait .opener .wrap > * { opacity: 1; transform: none; clip-path: none; }
  html.fx-intro [data-intro], html.fx-intro .hero-split__h1, html.fx-intro .hero-split__photo, html.fx-intro .opener .wrap > *, html.fx-reveal .opener .rv > .rv__in { animation: none !important; }
  html.fx-reveal .rv > .rv__in { transform: none; }
  html.fx-expand .fx-x { clip-path: none; }
  html.fx-stack .stackable { position: static; }
  html.fx-stack .stackable.is-covering { transform: none; filter: none; }
  html.fx-pagewipe.is-arriving body::after, html.fx-pagewipe.is-arrived body::after { display: none; }
}
