/* Shared behaviour layer: page-load transition, weighted scroll, custom cursor.
   Loaded on every page after the page's own stylesheet. */

/* ===== LENIS (weighted scroll) ===== */
html.lenis, html.lenis body { height: auto; }
html.lenis { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }

/* ===== PAGE ENTRANCE =====
   A soft-edged curtain in the page colour retracts downward, so content is
   revealed top-to-bottom like a stroke pulled down the page. The curtain sits
   only over the content column — the rail is never covered. */
.wipe {
  position: fixed;
  top: 0; right: 0;
  left: var(--rail, 0px);
  /* Taller than the viewport on purpose: the feathered edge lives in the extra
     35vh below the fold, so nothing shows through before the stroke reaches it. */
  height: 135vh;
  z-index: 500;
  pointer-events: none;
  background: var(--bg, #FBFBFC);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 74%, rgba(0,0,0,0.92) 84%, rgba(0,0,0,0.55) 92%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 74%, rgba(0,0,0,0.92) 84%, rgba(0,0,0,0.55) 92%, transparent 100%);
  animation: wipeDown 1.15s cubic-bezier(0.76, 0, 0.24, 1) both;
}
@keyframes wipeDown {
  from { transform: translateY(0); }
  to   { transform: translateY(100vh); }
}

/* Case studies get a quiet fade instead of the curtain. */
@keyframes calmIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.calm-entrance body > .case-hero,
.calm-entrance body > .case-content,
.calm-entrance body > .backbar {
  animation: calmIn 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.calm-entrance body > .case-content { animation-delay: 0.05s; }


/* ===== CURSOR =====
   Position lives on the outer element and is written every frame; the visual
   state lives on an inner element and is transitioned. They must never be the
   same property, or each frame restarts the transition and the cursor lags. */
@media (hover: hover) and (pointer: fine) {
  html.has-cursor,
  html.has-cursor body,
  html.has-cursor a,
  html.has-cursor button,
  html.has-cursor .tile,
  html.has-cursor figure { cursor: none; }

  .cur {
    position: fixed;
    top: 0; left: 0;
    width: 0; height: 0;
    pointer-events: none;
    z-index: 9999;
    will-change: transform;
    contain: layout style;
  }
  .cur i {
    display: block;
    position: absolute;
    top: 0; left: 0;
    border-radius: 50%;
    will-change: transform;
  }

  /* The point: exact, never eased. */
  .cur-dot i {
    width: 6px; height: 6px;
    margin: -3px 0 0 -3px;
    background: var(--black, #111214);
    transition: transform 0.26s cubic-bezier(0.16, 1, 0.3, 1), background 0.2s ease, opacity 0.2s ease;
  }
  /* The ring: trails on a spring, opens over anything clickable. */
  .cur-ring i {
    width: 32px; height: 32px;
    margin: -16px 0 0 -16px;
    border: 1px solid rgba(17, 18, 20, 0.3);
    transition: transform 0.34s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.25s ease, background 0.25s ease, opacity 0.2s ease;
  }

  .cur-ring.is-active i { transform: scale(1.65); border-color: rgba(17, 18, 20, 0.48); background: rgba(17, 18, 20, 0.04); }
  .cur-dot.is-active i { transform: scale(0.4); }

  .cur-ring.is-media i { border-color: rgba(255, 255, 255, 0.88); background: rgba(255, 255, 255, 0.1); }
  .cur-dot.is-media i { background: #FFFFFF; }

  .cur.is-hidden i { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .wipe { display: none; }
  .cur i { transition: none; }
}
