/* ==========================================================================
   AALANKAAR STUDIOS — 04 · MOTION SYSTEM
   Declarative reveals. JS only adds `.is-inview`; every behaviour below is
   chosen by a data attribute so markup stays readable.
   ========================================================================== */

/* --------------------------------------------------------------------------
   SCROLL REVEALS
   [data-reveal] elements start hidden and settle when observed.
   [data-reveal-delay] staggers in 60ms steps.
   -------------------------------------------------------------------------- */

/* Reveals FAIL OPEN.
   The hidden starting state is gated behind .can-reveal on <html>, which the
   motion module only adds once it has actually armed the observer. If
   JavaScript never runs, or IntersectionObserver never delivers a callback —
   a throttled tab, a restored tab, a privacy extension — the class is absent
   and every element simply renders normally.
   The alternative, hiding by default and relying on JS to un-hide, means one
   silent observer failure leaves whole sections looking empty. */

[data-reveal]{
  transition:opacity var(--dur-4) var(--ease),
             transform var(--dur-4) var(--ease),
             clip-path var(--dur-5) var(--ease);
  transition-delay:calc(var(--reveal-delay, 0) * 1ms);
}

.can-reveal [data-reveal]{
  opacity:0;
  will-change:opacity, transform;
}
.can-reveal [data-reveal].is-inview{
  opacity:1;
  transform:none;
  will-change:auto;
}

.can-reveal [data-reveal="up"]{    transform:translateY(38px); }
.can-reveal [data-reveal="down"]{  transform:translateY(-28px); }
.can-reveal [data-reveal="left"]{  transform:translateX(44px); }
.can-reveal [data-reveal="right"]{ transform:translateX(-44px); }
.can-reveal [data-reveal="fade"]{  transform:none; }
.can-reveal [data-reveal="scale"]{ transform:scale(.94); }

/* The image curtain — a mask lifts from the floor of the frame.
   clip-path belongs only to these two variants. Applied to every reveal it
   would crop anything that paints outside its own border box — which, with
   the display face set on a tight line-height, means every descender in an
   animated heading. */
.can-reveal [data-reveal="curtain"]{
  opacity:1;
  clip-path:inset(100% 0 0 0);
  transform:none;
}
.can-reveal [data-reveal="curtain-left"]{
  opacity:1;
  clip-path:inset(0 100% 0 0);
  transform:none;
}
.can-reveal [data-reveal="curtain"].is-inview,
.can-reveal [data-reveal="curtain-left"].is-inview{ clip-path:inset(0 0 0 0); }

/* Curtain paired with a counter-scaling image: the frame opens while the
   photograph settles back to 1:1 — the trick that makes reveals feel filmic. */
[data-reveal="curtain"] > img,
[data-reveal="curtain-left"] > img{
  transform:scale(1.16);
  transition:transform 1.6s var(--ease);
}
[data-reveal="curtain"].is-inview > img,
[data-reveal="curtain-left"].is-inview > img{ transform:scale(1); }

/* Hairline that draws across */
.can-reveal [data-reveal="rule"]{
  opacity:1;
  transform:scaleX(0);
  transform-origin:left center;
  transition:transform var(--dur-5) var(--ease);
}
.can-reveal [data-reveal="rule"].is-inview{ transform:scaleX(1); }

/* --------------------------------------------------------------------------
   SPLIT TEXT
   JS wraps each word in .sw > .sw__i. Words rise out of their own mask,
   which is why the overflow:hidden matters more than the transform.
   -------------------------------------------------------------------------- */

.split{ display:inline; }
.sw{
  display:inline-block;
  overflow:hidden;
  vertical-align:top;
  /* The display face is set on a tight line-height, so descenders fall well
     outside the line box. The mask is padded to clear them — otherwise a
     word like "slowly" loses the tail of its y — and the negative margin
     cancels the padding so line spacing is untouched.
     The travel below is set to clear this padding too, or the incoming word
     would be visible inside it before it starts moving. */
  padding-bottom:0.3em;
  margin-bottom:-0.3em;
}
.sw__i{
  display:inline-block;
  transition:transform 1s var(--ease), opacity .8s var(--ease);
  transition-delay:calc(var(--wi, 0) * 42ms);
}
.can-reveal .sw__i{
  transform:translateY(150%) rotate(3deg);
  opacity:0;
}
.can-reveal .is-inview .sw__i{ transform:translateY(0) rotate(0); opacity:1; }

/* Per-character variant for short display lines */
.sc{
  display:inline-block;
  overflow:hidden;
  vertical-align:top;
  padding-bottom:0.3em;
  margin-bottom:-0.3em;
}
.sc__i{
  display:inline-block;
  transition:transform .85s var(--ease), opacity .6s var(--ease);
  transition-delay:calc(var(--ci, 0) * 26ms);
}
.can-reveal .sc__i{
  transform:translateY(150%);
  opacity:0;
}
.can-reveal .is-inview .sc__i{ transform:translateY(0); opacity:1; }

/* --------------------------------------------------------------------------
   PARALLAX
   JS writes --py (px offset) from scroll position. Depth is authored in
   markup via data-parallax="0.12" etc.
   -------------------------------------------------------------------------- */

[data-parallax]{
  transform:translate3d(0, var(--py, 0px), 0);
  will-change:transform;
}
[data-parallax-scale]{
  transform:translate3d(0, var(--py, 0px), 0) scale(var(--ps, 1));
}

/* --------------------------------------------------------------------------
   MAGNETIC ELEMENTS
   JS writes --mx / --my; CSS owns the easing so release always feels soft.
   -------------------------------------------------------------------------- */

[data-magnetic]{
  transform:translate3d(var(--mx, 0px), var(--my, 0px), 0);
  transition:transform .45s var(--ease-soft);
}
[data-magnetic].is-pulled{ transition:transform .12s linear; }

/* --------------------------------------------------------------------------
   MARQUEE — a seamless ticker. Two identical tracks, one offset by 100%.
   -------------------------------------------------------------------------- */

.marquee{
  position:relative;
  display:flex;
  overflow:hidden;
  user-select:none;
  -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;
  align-items:center;
  flex-shrink:0;
  gap:var(--s-5);
  padding-right:var(--s-5);
  min-width:100%;
  animation:marquee-run var(--marquee-dur, 38s) linear infinite;
  animation-direction:var(--marquee-dir, normal);
}
.marquee:hover .marquee__track{ animation-play-state:paused; }
@keyframes marquee-run{
  from{ transform:translateX(0); }
  to  { transform:translateX(-100%); }
}

.marquee__item{
  display:inline-flex;
  align-items:center;
  gap:var(--s-4);
  font-family:var(--font-display);
  font-size:clamp(1.6rem, 4.6vw, 3.6rem);
  font-weight:500;
  font-style:italic;
  letter-spacing:var(--ls-display);
  white-space:nowrap;
  color:var(--fg);
}
.marquee__item::after{
  content:"✳";
  font-style:normal;
  font-size:.4em;
  color:var(--c-gold);
  transform:translateY(-.35em);
}
.marquee--label .marquee__item{
  font-family:var(--font-sans);
  font-style:normal;
  font-size:var(--fs-label);
  letter-spacing:var(--ls-wide);
  text-transform:uppercase;
  color:var(--fg-muted);
}

/* --------------------------------------------------------------------------
   HOVER MICRO-INTERACTIONS
   -------------------------------------------------------------------------- */

/* Text that swaps itself out on hover — the old line leaves, a clone enters */
.swap{
  position:relative;
  display:inline-block;
  overflow:hidden;
  vertical-align:bottom;
}
.swap__a,
.swap__b{
  display:block;
  transition:transform var(--dur-3) var(--ease), opacity var(--dur-3) var(--ease);
}
.swap__b{
  position:absolute; inset:0;
  transform:translateY(105%);
  opacity:0;
}
.swap:hover .swap__a,
a:hover > .swap .swap__a,
button:hover > .swap .swap__a{ transform:translateY(-105%); opacity:0; }
.swap:hover .swap__b,
a:hover > .swap .swap__b,
button:hover > .swap .swap__b{ transform:translateY(0); opacity:1; }

/* Slow drift for decorative motifs */
@keyframes drift{
  0%,100%{ transform:translate3d(0,0,0) rotate(0deg); }
  50%    { transform:translate3d(0,-14px,0) rotate(2.5deg); }
}
.drift{ animation:drift 9s var(--ease-soft) infinite; }
.drift--slow{ animation-duration:14s; }
.drift--delay{ animation-delay:-4s; }

/* A gentle breathing scale, used on the hero motif */
@keyframes breathe{
  0%,100%{ transform:scale(1); }
  50%    { transform:scale(1.035); }
}
.breathe{ animation:breathe 11s var(--ease-soft) infinite; }

/* Slow rotation for the seal / stamp */
@keyframes spin-slow{ to{ transform:rotate(360deg); } }
.spin-slow{ animation:spin-slow 26s linear infinite; }

/* Shimmer that travels across gold text once on reveal */
.shimmer{
  background:linear-gradient(100deg,
    var(--c-gold) 0%, var(--c-gold) 38%,
    var(--c-gold-soft) 50%,
    var(--c-gold) 62%, var(--c-gold) 100%);
  background-size:220% 100%;
  -webkit-background-clip:text;
          background-clip:text;
  color:transparent;
  background-position:120% 0;
}
.is-inview .shimmer,
.shimmer.is-inview{
  transition:background-position 1.9s var(--ease) .3s;
  background-position:-20% 0;
}

/* --------------------------------------------------------------------------
   SCROLL PROGRESS RAIL — a gold thread down the left edge
   -------------------------------------------------------------------------- */

.scroll-rail{
  position:fixed;
  top:0; left:0;
  width:2px; height:100vh;
  z-index:var(--z-nav);
  pointer-events:none;
  background:transparent;
}
.scroll-rail__fill{
  width:100%;
  height:100%;
  background:linear-gradient(180deg, var(--c-gold), var(--c-vermilion));
  transform:scaleY(var(--progress, 0));
  transform-origin:top center;
}

/* --------------------------------------------------------------------------
   COUNTER — numbers that tick up when observed
   -------------------------------------------------------------------------- */

.counter{ font-variant-numeric:tabular-nums lining-nums; }

/* --------------------------------------------------------------------------
   The Elementor editor must never fight the motion system: everything is
   shown at rest so the author can see what they are editing.
   -------------------------------------------------------------------------- */

body.elementor-editor-active [data-reveal],
body.elementor-editor-active .sw__i,
body.elementor-editor-active .sc__i{
  opacity:1 !important;
  transform:none !important;
  clip-path:none !important;
}
