/* ============================================================
   Motion layer — "the gallery attendant"
   ------------------------------------------------------------
   Everything here is scoped under .js-motion, a class that
   js/motion.js adds to <html>. Without JS (or with JS broken)
   none of these rules apply, so content is never left hidden
   and the native cursor is never removed. Every effect also
   backs off under prefers-reduced-motion.
   ============================================================ */

/* ---------- 1. Brass cursor ----------
   Two parts on purpose. The dot tracks the pointer with zero smoothing, so
   you always know exactly where you are about to click; the ring trails it
   for weight. A single lagging ring was imprecise to aim with, because
   cursor:none means it is the only pointer reference on screen. */
.b4g-dot {
  position: fixed; top: 0; left: 0; z-index: 9999;
  width: 6px; height: 6px; margin: -3px 0 0 -3px;
  border-radius: 50%;
  background: var(--text);
  pointer-events: none;
  opacity: 0;
  /* No transition on transform: the dot must be exactly under the pointer. */
  transition: opacity .25s ease, background-color .25s ease, scale .16s ease;
  will-change: transform;
}
.b4g-dot.on { opacity: 1; }
/* Over a plate the brass disc is the affordance, so the dot steps aside. */
.b4g-dot.hide { opacity: 0; }
.b4g-dot.press { scale: 2.2; }

.b4g-cursor {
  position: fixed; top: 0; left: 0; z-index: 9998;
  width: 34px; height: 34px; margin: -17px 0 0 -17px;
  border: 1px solid var(--brand-ink);
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  display: grid; place-items: center;
  transition: opacity .3s ease, width .34s cubic-bezier(.2,.8,.2,1),
              height .34s cubic-bezier(.2,.8,.2,1), margin .34s cubic-bezier(.2,.8,.2,1),
              background-color .34s ease, border-color .34s ease;
  will-change: transform;
}
.b4g-cursor.on { opacity: 1; }
.b4g-cursor .lbl {
  font: 500 .58rem/1 var(--font);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--bg);
  opacity: 0; transform: scale(.7);
  transition: opacity .26s ease, transform .32s cubic-bezier(.2,.8,.2,1);
  white-space: nowrap;
}
/* Over a game plate the ring becomes a filled brass disc labelled PLAY. */
.b4g-cursor.lg {
  width: 84px; height: 84px; margin: -42px 0 0 -42px;
  background: var(--brand); border-color: var(--brand);
}
.b4g-cursor.lg .lbl { opacity: 1; transform: scale(1); color: var(--on-brand); }
/* Over text links the ring tightens around the dot rather than becoming a
   second dot, which would just double up with the tracking dot. */
.b4g-cursor.sm {
  width: 20px; height: 20px; margin: -10px 0 0 -10px;
  border-color: var(--brand-ink);
}
.js-motion.has-cursor,
.js-motion.has-cursor a,
.js-motion.has-cursor button,
.js-motion.has-cursor .card,
.js-motion.has-cursor .feat-card { cursor: none; }
/* Keep a real cursor for anything you type into. */
.js-motion.has-cursor input,
.js-motion.has-cursor textarea,
.js-motion.has-cursor select { cursor: auto; }

/* ---------- 2. Page transition veil ---------- */
/* A sheet of warm paper sliding over the page, not a blackout. Keeping the
   veil in the parchment family means the transition reads as turning a page
   in the catalogue rather than the screen cutting to black. */
.b4g-veil {
  position: fixed; inset: 0; z-index: 9999;
  background: linear-gradient(180deg, #ece3d0, #ddd2b8);
  pointer-events: none;
  transform: scaleY(0); transform-origin: bottom;
  display: grid; place-items: center;
}
.b4g-veil.in {
  animation: veilIn .66s cubic-bezier(.45,0,.2,1) forwards;
}
.b4g-veil .mark {
  font-family: var(--display); font-style: italic; font-weight: 400;
  font-size: 1.5rem; letter-spacing: -.01em;
  color: var(--brand-ink);
  opacity: 0;
}
.b4g-veil.in .mark { animation: markIn .66s ease forwards .1s; }
@keyframes veilIn { to { transform: scaleY(1); } }
@keyframes markIn { 45% { opacity: .85; } to { opacity: .85; } }

/* Content settles in on arrival. */
.js-motion .main,
.js-motion .content-shell,
.js-motion .catalog,
.js-motion #player { animation: pageIn .7s cubic-bezier(.2,.8,.2,1) both; }
@keyframes pageIn {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: none; }
}

/* ---------- 3. Plates hang themselves in ---------- */
.js-motion [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 26px, 0);
  transition:
    opacity .78s cubic-bezier(.2,.8,.2,1),
    transform .78s cubic-bezier(.2,.8,.2,1);
  transition-delay: calc(var(--i, 0) * 65ms);
  will-change: opacity, transform;
}
.js-motion [data-reveal].in { opacity: 1; transform: none; }

/* ---------- 4. Headline word reveal ---------- */
.js-motion .b4g-line { display: block; overflow: hidden; }
.js-motion .b4g-word {
  display: inline-block;
  transform: translate3d(0, 100%, 0);
  transition: transform .95s cubic-bezier(.16,1,.3,1);
  transition-delay: calc(var(--w, 0) * 55ms);
}
.js-motion .b4g-word.in { transform: none; }

/* ---------- 5. Plate parallax + reveal rule ---------- */
.js-motion .feat-thumb img,
.js-motion .card .thumb img,
.js-motion .catalog img {
  will-change: transform;
}
/* The caption rule draws itself in from the left on hover. */
.js-motion .feat-body h2,
.js-motion .card .title,
.js-motion .catalog strong { position: relative; display: inline-block; }
.js-motion .feat-body h2::after,
.js-motion .card .title::after,
.js-motion .catalog strong::after {
  content: "";
  position: absolute; left: 0; bottom: -3px;
  height: 1px; width: 100%;
  background: var(--brand);
  transform: scaleX(0); transform-origin: left;
  transition: transform .5s cubic-bezier(.2,.8,.2,1);
}
.js-motion .feat-card:hover .feat-body h2::after,
.js-motion .card:hover .title::after,
.js-motion .catalog li:hover strong::after { transform: scaleX(1); }

/* ---------- 6. Magnetic pull ---------- */
.js-motion [data-magnetic] {
  transition: transform .45s cubic-bezier(.2,.8,.2,1);
  will-change: transform;
}

/* ---------- 7. Sidebar index hover ---------- */
.js-motion .nav-item { position: relative; overflow: hidden; }
.js-motion .nav-item::after {
  content: "";
  position: absolute; left: 0; bottom: 0; height: 1px; width: 100%;
  background: var(--line);
  transform: scaleX(0); transform-origin: left;
  transition: transform .45s cubic-bezier(.2,.8,.2,1);
}
.js-motion .nav-item:hover::after { transform: scaleX(1); }

/* ---------- Reduced motion: keep the design, drop the movement ---------- */
@media (prefers-reduced-motion: reduce) {
  .js-motion [data-reveal],
  .js-motion .b4g-word { opacity: 1 !important; transform: none !important; transition: none !important; }
  .js-motion .main, .js-motion .content-shell,
  .js-motion .catalog, .js-motion #player { animation: none; }
  .b4g-veil, .b4g-cursor { display: none !important; }
  .js-motion.has-cursor, .js-motion.has-cursor a,
  .js-motion.has-cursor button, .js-motion.has-cursor .card,
  .js-motion.has-cursor .feat-card { cursor: auto; }
}
