/* Motion layer. Every hidden/start state is scoped to html.motion, which is only
   set when the visitor hasn't asked for reduced motion, so without JS, or with
   reduced motion on, the site renders fully static and readable. */

:root
{
  --ease-out:cubic-bezier(.16,1,.3,1);
  --ease-in-out:cubic-bezier(.65,0,.35,1)
}

/* ---------- Page transitions (Chrome/Edge/Safari; ignored elsewhere) ---------- */
@media(prefers-reduced-motion:no-preference)
{
  @view-transition
  {
    navigation:auto
  }
  header
  {
    view-transition-name:site-header
  }
  ::view-transition-old(root)
  {
    animation:.35s var(--ease-in-out) both page-out
  }
  ::view-transition-new(root)
  {
    animation:.6s var(--ease-out) both page-in
  }
}
@keyframes page-out
{
  to
  {
    opacity:0;
    transform:translateY(-18px)
  }
}
@keyframes page-in
{
  from
  {
    opacity:0;
    transform:translateY(28px)
  }
}

/* ---------- Scroll progress ---------- */
.progress
{
  position:fixed;
  inset:0 0 auto;
  height:2px;
  background:var(--lime);
  transform-origin:0 50%;
  transform:scaleX(0);
  z-index:50;
  pointer-events:none
}

/* ---------- Line-by-line text reveal ---------- */
.line
{
  display:block;
  overflow:hidden;
  /* Grow the clipping box so tight line-heights don't crop ascenders/descenders. */
  padding:.12em .12em .16em;
  margin:-.12em -.12em -.16em
}
.line>span
{
  display:inline-block;
  vertical-align:top
}
.motion [data-split] .line>span
{
  transform:translateY(125%) rotate(4deg);
  transform-origin:0 100%;
  transition:transform 1.1s var(--ease-out);
  transition-delay:calc(var(--i) * 90ms + var(--delay,0ms))
}
.motion [data-split].is-in .line>span
{
  transform:none
}

/* ---------- Generic reveal ---------- */
.motion [data-reveal]
{
  opacity:0;
  transform:translateY(28px);
  transition:opacity .9s var(--ease-out),transform .9s var(--ease-out);
  transition-delay:var(--delay,0ms)
}
.motion [data-reveal].is-in
{
  opacity:1;
  transform:none
}
.motion [data-reveal="fade"]
{
  transform:none
}

/* Media blocks wipe open from the bottom, with the artwork settling inside. */
.motion [data-reveal="wipe"]
{
  opacity:1;
  transform:none;
  clip-path:inset(100% 0 0 0);
  transition:clip-path 1.2s var(--ease-in-out);
  transition-delay:var(--delay,0ms)
}
.motion [data-reveal="wipe"].is-in
{
  clip-path:inset(0)
}
.motion [data-reveal="wipe"] .media-placeholder
{
  opacity:0;
  transition:opacity .8s ease calc(var(--delay,0ms) + .7s)
}
.motion [data-reveal="wipe"].is-in .media-placeholder
{
  opacity:1
}

/* Rules draw themselves in. */
.motion [data-reveal="rule"]
{
  opacity:1;
  transform:none;
  position:relative;
  border-bottom-color:transparent
}
.motion [data-reveal="rule"]::after
{
  content:'';
  position:absolute;
  left:0;
  right:0;
  bottom:-1px;
  height:1px;
  background:var(--line);
  transform:scaleX(0);
  transform-origin:0 50%;
  transition:transform 1.2s var(--ease-in-out) var(--delay,0ms)
}
.motion [data-reveal="rule"].is-in::after
{
  transform:scaleX(1)
}

/* ---------- Hero intro choreography ---------- */
/* Fill mode "backwards" (not forwards) so the finished animation releases
   transform, otherwise it would override the magnetic hover on .start. */
.page-intro header>*
{
  animation:drop-in .9s var(--ease-out) backwards
}
.page-intro header>:nth-child(2)
{
  animation-delay:.08s
}
.page-intro header>:nth-child(3)
{
  animation-delay:.16s
}
.page-intro header>:nth-child(4)
{
  animation-delay:.16s
}
@keyframes drop-in
{
  from
  {
    opacity:0;
    transform:translateY(-10px)
  }
}
.page-intro .bg-field
{
  animation:field-in 2.4s ease both .2s
}
@keyframes field-in
{
  from
  {
    opacity:0
  }
}
/* Logo cursor types itself in on arrival, then blinks. */
.motion.page-intro .wordmark-cursor
{
  animation:cursor-in .5s steps(1) backwards .9s,cursor-blink 1.1s steps(1) 1.4s infinite
}
.motion .wordmark-cursor
{
  animation:cursor-blink 1.1s steps(1) 1.4s infinite
}
.wordmark:hover .wordmark-cursor
{
  animation:none
}
@keyframes cursor-in
{
  from
  {
    opacity:0
  }
}
@keyframes cursor-blink
{
  50%
  {
    opacity:0
  }
}

/* ---------- Header meta arrow ---------- */
.meta-arrow
{
  display:inline-block;
  margin:0 6px;
  color:var(--lime);
  font-weight:400
}
.motion .meta-arrow
{
  animation:arrow-nudge 2.4s var(--ease-in-out) infinite
}
@keyframes arrow-nudge
{
  50%
  {
    transform:translateX(5px)
  }
}

/* ---------- Services marquee ---------- */
.marquee
{
  position:relative;
  z-index:1;
  overflow:hidden;
  border-bottom:1px solid var(--line);
  padding:26px 0;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent)
}
.marquee-track
{
  display:flex;
  width:max-content
}
.motion .marquee-track
{
  animation:marquee 42s linear infinite
}
.marquee:hover .marquee-track
{
  animation-play-state:paused
}
.marquee ul
{
  display:flex;
  align-items:center;
  gap:44px;
  padding:0 44px 0 0;
  margin:0;
  list-style:none
}
.marquee li
{
  font-size:clamp(28px,3.4vw,52px);
  font-weight:600;
  letter-spacing:-.06em;
  white-space:nowrap
}
.marquee li:nth-child(4n+3)
{
  color:transparent;
  -webkit-text-stroke:1px var(--muted)
}
.marquee li.star
{
  color:var(--lime);
  font-size:clamp(18px,2vw,28px)
}
@keyframes marquee
{
  to
  {
    transform:translateX(-50%)
  }
}

/* ---------- Project cards: parallax artwork ---------- */
.media::before,.media::after
{
  translate:calc(var(--mx,0) * -22px) calc(var(--my,0) * -22px);
  transition:translate .9s var(--ease-out)
}
.media::after
{
  translate:calc(var(--mx,0) * 14px) calc(var(--my,0) * 14px)
}
.media .media-placeholder
{
  translate:calc(var(--mx,0) * 8px) calc(var(--my,0) * 8px);
  transition:translate .9s var(--ease-out),opacity .8s ease
}
/* Transform-only hover; animating letter-spacing would re-run layout every frame. */
.enquire
{
  width:max-content;
  transition:color .25s ease,translate .5s var(--ease-out)
}
.grid article:hover .enquire
{
  color:var(--lime);
  translate:6px 0
}

/* ---------- Underline sweep on text links ---------- */
.big-link,.contact button
{
  position:relative;
  background-image:linear-gradient(var(--lime),var(--lime));
  background-repeat:no-repeat;
  background-size:0 100%;
  background-position:0 0;
  transition:background-size .5s var(--ease-out),color .3s ease
}
.big-link:hover,.contact button:hover
{
  background-size:100% 100%;
  color:var(--bg)
}
.big-link:hover b,.contact button:hover b
{
  color:var(--bg)
}
.big-link,.contact button
{
  padding-left:4px;
  padding-right:4px;
  margin-left:-4px
}

/* ---------- Magnetic elements ---------- */
[data-magnetic]
{
  transition:transform .6s var(--ease-out)
}
[data-magnetic].is-pulling
{
  transition:transform .15s linear
}
.start,.big-link
{
  display:inline-block
}

/* ---------- Cursor ring (fine pointers only) ---------- */
.cursor
{
  position:fixed;
  top:0;
  left:0;
  width:34px;
  height:34px;
  margin:-17px 0 0 -17px;
  border:1px solid rgba(215,243,106,.55);
  border-radius:50%;
  pointer-events:none;
  z-index:60;
  opacity:0;
  will-change:translate,scale;
  /* Position comes from JS via `translate`; size changes use `scale` so nothing
     here triggers layout. */
  transition:opacity .3s ease,scale .45s var(--ease-out),background-color .35s ease,border-color .35s ease
}
.cursor.is-visible
{
  opacity:1
}
.cursor.is-hovering
{
  scale:1.8;
  background-color:rgba(215,243,106,.08);
  border-color:var(--lime)
}
.cursor.is-visible.is-text
{
  opacity:0
}
.cursor.is-pressed
{
  scale:.7
}

/* ---------- Team carousel swap ---------- */
.motion .team-portrait.is-changing
{
  animation:portrait-swap .7s var(--ease-out)
}
@keyframes portrait-swap
{
  from
  {
    transform:scale(.86) rotate(calc(var(--dir,1) * 14deg));
    opacity:.4
  }
}
.motion .team-details.is-changing>*
{
  animation:detail-swap .7s var(--ease-out) both
}
.motion .team-details.is-changing>:nth-child(2)
{
  animation-delay:.05s
}
.motion .team-details.is-changing>:nth-child(3)
{
  animation-delay:.1s
}
@keyframes detail-swap
{
  from
  {
    opacity:0;
    transform:translateX(calc(var(--dir,1) * 36px))
  }
}

@media(max-width:800px)
{
  .marquee
  {
    padding:18px 0
  }
  .marquee ul
  {
    gap:28px;
    padding-right:28px
  }
}
