/* ==========================================================================
   ICI — animation engine
   Declarative, attribute-driven. The JS in animations.js only adds
   .is-revealed and sets a few custom properties; everything else is CSS.

     <div data-reveal="up" data-delay="150">…</div>
     <h2 data-split>Heading that staggers by word</h2>
     <img data-parallax="0.18">
     <div data-tilt>…</div>
     <span data-count="1200" data-suffix="+"></span>
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Scroll reveal
   -------------------------------------------------------------------------- */

[data-reveal] {
  --rv-dur: .95s;
  --rv-ease: cubic-bezier(.16, 1, .3, 1);
  --rv-delay: 0ms;
  opacity: 0;
  will-change: transform, opacity;
  transition:
    opacity var(--rv-dur) var(--rv-ease) var(--rv-delay),
    transform var(--rv-dur) var(--rv-ease) var(--rv-delay),
    filter var(--rv-dur) var(--rv-ease) var(--rv-delay),
    clip-path var(--rv-dur) var(--rv-ease) var(--rv-delay);
}

[data-reveal="fade"]   { transform: none; }
[data-reveal="up"]     { transform: translate3d(0, 42px, 0); }
[data-reveal="down"]   { transform: translate3d(0, -42px, 0); }
/* Horizontal offsets are tied to the container gutter. An element sitting
   against the container edge then slides in from exactly the page margin,
   so a waiting element can never extend past the viewport at any width. */
[data-reveal="left"]   { transform: translate3d(calc(-1 * var(--ici-gutter, 24px)), 0, 0); }
[data-reveal="right"]  { transform: translate3d(var(--ici-gutter, 24px), 0, 0); }
[data-reveal="scale"]  { transform: scale(.92); }
[data-reveal="zoom"]   { transform: scale(1.08); }
[data-reveal="blur"]   { filter: blur(14px); transform: translate3d(0, 20px, 0); }
[data-reveal="rise"]   { transform: translate3d(0, 70px, 0) scale(.97); }
[data-reveal="tilt"]   { transform: perspective(1200px) rotateX(12deg) translate3d(0, 40px, 0); transform-origin: bottom; }
[data-reveal="flip"]   { transform: perspective(1200px) rotateY(-24deg) translate3d(30px, 0, 0); transform-origin: left center; }

/* Clip wipes — the element is masked and unmasks in a direction */
[data-reveal="clip"],
[data-reveal="clip-up"]    { opacity: 1; clip-path: inset(100% 0 0 0); }
[data-reveal="clip-down"]  { opacity: 1; clip-path: inset(0 0 100% 0); }
[data-reveal="clip-left"]  { opacity: 1; clip-path: inset(0 100% 0 0); }
[data-reveal="clip-right"] { opacity: 1; clip-path: inset(0 0 0 100%); }

/* Line draw — for hairlines and underlines */
[data-reveal="draw-x"] { opacity: 1; transform: scaleX(0); transform-origin: left; }
[data-reveal="draw-y"] { opacity: 1; transform: scaleY(0); transform-origin: top; }

/* Resting state */
[data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  filter: none;
  clip-path: inset(0 0 0 0);
}

/* --------------------------------------------------------------------------
   2. Stagger
   A parent with [data-stagger] cascades its revealed children.
   -------------------------------------------------------------------------- */

[data-stagger] > * { --rv-step: 90ms; }
[data-stagger] > *:nth-child(1)  { --rv-delay: calc(var(--rv-step) * 0); }
[data-stagger] > *:nth-child(2)  { --rv-delay: calc(var(--rv-step) * 1); }
[data-stagger] > *:nth-child(3)  { --rv-delay: calc(var(--rv-step) * 2); }
[data-stagger] > *:nth-child(4)  { --rv-delay: calc(var(--rv-step) * 3); }
[data-stagger] > *:nth-child(5)  { --rv-delay: calc(var(--rv-step) * 4); }
[data-stagger] > *:nth-child(6)  { --rv-delay: calc(var(--rv-step) * 5); }
[data-stagger] > *:nth-child(7)  { --rv-delay: calc(var(--rv-step) * 6); }
[data-stagger] > *:nth-child(8)  { --rv-delay: calc(var(--rv-step) * 7); }
[data-stagger] > *:nth-child(9)  { --rv-delay: calc(var(--rv-step) * 8); }
[data-stagger] > *:nth-child(10) { --rv-delay: calc(var(--rv-step) * 9); }
[data-stagger] > *:nth-child(11) { --rv-delay: calc(var(--rv-step) * 10); }
[data-stagger] > *:nth-child(12) { --rv-delay: calc(var(--rv-step) * 11); }
[data-stagger="fast"] > *  { --rv-step: 55ms; }
[data-stagger="slow"] > *  { --rv-step: 150ms; }

/* Bootstrap columns wrap the card, so target one level deeper too */
[data-stagger] > [class*="col-"] > [data-reveal] { --rv-delay: inherit; }

/* --------------------------------------------------------------------------
   3. Split-word headings
   Markup comes from the split_words() PHP helper or from JS.
   -------------------------------------------------------------------------- */

.sw-word { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: .08em; margin-bottom: -.08em; }
.sw-inner {
  display: inline-block;
  transform: translate3d(0, 110%, 0) rotate(4deg);
  opacity: 0;
  transition:
    transform 1.05s cubic-bezier(.16, 1, .3, 1) calc(var(--i, 0) * 65ms + var(--sw-base, 0ms)),
    opacity .8s ease calc(var(--i, 0) * 65ms + var(--sw-base, 0ms));
}
.is-revealed .sw-inner,
.sw-run .sw-inner { transform: none; opacity: 1; }

/* Character-level variant for short display text */
.sc-char {
  display: inline-block;
  opacity: 0;
  transform: translate3d(0, 40%, 0) scale(.9);
  transition:
    transform .8s cubic-bezier(.16, 1, .3, 1) calc(var(--i, 0) * 26ms),
    opacity .6s ease calc(var(--i, 0) * 26ms);
}
.is-revealed .sc-char { transform: none; opacity: 1; }

/* --------------------------------------------------------------------------
   4. Parallax
   JS writes --pty (px). Keep transforms on their own layer.
   -------------------------------------------------------------------------- */

[data-parallax] {
  transform: translate3d(0, var(--pty, 0px), 0) scale(var(--psc, 1));
  will-change: transform;
}
[data-parallax-x] { transform: translate3d(var(--ptx, 0px), 0, 0); will-change: transform; }

/* --------------------------------------------------------------------------
   5. Ken Burns
   -------------------------------------------------------------------------- */

.kenburns { animation: kenburns 22s var(--ici-ease-soft, ease) infinite alternate; }
@keyframes kenburns {
  0%   { transform: scale(1)    translate3d(0, 0, 0); }
  100% { transform: scale(1.14) translate3d(-1.5%, -1.5%, 0); }
}
.kenburns-slow { animation-duration: 34s; }

/* Carousel slides get Ken Burns only while active */
.carousel-item .kb-img { transform: scale(1.02); transition: transform 8s linear; }
.carousel-item.active .kb-img { transform: scale(1.14); }

/* --------------------------------------------------------------------------
   6. Tilt (3D hover)
   JS writes --tx / --ty in degrees.

   Tilt and reveal both animate `transform`, so an element carrying both must
   not have its entrance transform overwritten by the resting tilt transform.
   The hover transform is therefore withheld until the element has revealed.
   -------------------------------------------------------------------------- */

[data-tilt] { transform-style: preserve-3d; }

[data-tilt]:not([data-reveal]),
[data-tilt][data-reveal].is-revealed {
  transform: perspective(900px) rotateX(var(--ty, 0deg)) rotateY(var(--tx, 0deg)) translateZ(0);
  transition: transform .35s cubic-bezier(.22, 1, .36, 1);
}

[data-tilt].is-tilting { transition: transform .08s linear; }
[data-tilt-layer] { transform: translateZ(38px); transition: transform .35s cubic-bezier(.22, 1, .36, 1); }

/* --------------------------------------------------------------------------
   7. Magnetic buttons
   Same rule as tilt — the magnet only engages once the element is on screen.
   -------------------------------------------------------------------------- */

[data-magnetic]:not([data-reveal]),
[data-magnetic][data-reveal].is-revealed {
  transform: translate3d(var(--mgx, 0px), var(--mgy, 0px), 0);
  transition: transform .45s cubic-bezier(.22, 1, .36, 1);
}
[data-magnetic].is-magnetic { transition: transform .12s ease-out; }

/* --------------------------------------------------------------------------
   8. Counters
   -------------------------------------------------------------------------- */

[data-count] { font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   9. Marquee direction variants
   -------------------------------------------------------------------------- */

.marquee-reverse .marquee-track { animation-direction: reverse; }
.marquee-slow    .marquee-track { animation-duration: 70s; }

/* --------------------------------------------------------------------------
   10. Ambient / decorative
   -------------------------------------------------------------------------- */

.float-y { animation: float-y 7s ease-in-out infinite; }
@keyframes float-y {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-14px); }
}

.spin-slow { animation: spin-slow 26s linear infinite; }
@keyframes spin-slow { to { transform: rotate(360deg); } }

/* Shimmering gold sweep across text */
.shimmer {
  background: linear-gradient(100deg,
    var(--ici-gold, #c9a227) 0%,
    var(--ici-gold-200, #f0dda2) 42%,
    var(--ici-gold, #c9a227) 60%);
  background-size: 250% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: shimmer 6s linear infinite;
}
@keyframes shimmer { to { background-position: -250% 0; } }

/* Attention pulse for a small badge or dot */
.pulse-dot { position: relative; }
.pulse-dot::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: 0 0 0 0 rgba(201,162,39,.6);
  animation: pulse-dot 2.4s cubic-bezier(.66, 0, 0, 1) infinite;
}
@keyframes pulse-dot { to { box-shadow: 0 0 0 16px rgba(201,162,39,0); } }

/* Underline that draws when its section reveals */
.draw-underline { position: relative; }
.draw-underline::after {
  content: ''; position: absolute; left: 0; bottom: -2px; width: 100%; height: 2px;
  background: var(--ici-gold, #c9a227);
  transform: scaleX(0); transform-origin: left;
  transition: transform 1s cubic-bezier(.16, 1, .3, 1) .35s;
}
.is-revealed .draw-underline::after, .draw-underline.is-revealed::after { transform: scaleX(1); }

/* Image reveal with a gold curtain that slides away */
.curtain { position: relative; overflow: hidden; }
.curtain::after {
  content: ''; position: absolute; inset: 0; z-index: 2;
  background: var(--ici-gold, #c9a227);
  transform-origin: right;
  transition: transform 1.1s cubic-bezier(.76, 0, .24, 1) .1s;
}
.curtain.is-revealed::after { transform: scaleX(0); }
.curtain img { transform: scale(1.15); transition: transform 1.5s cubic-bezier(.16, 1, .3, 1) .25s; }
.curtain.is-revealed img { transform: none; }

/* Row of items that slide in alternately from the sides */
.zip > *:nth-child(odd)  { --rv-delay: 0ms; }
.zip > *:nth-child(even) { --rv-delay: 120ms; }

/* --------------------------------------------------------------------------
   11. Hover micro-interactions
   -------------------------------------------------------------------------- */

.hover-lift { transition: transform .45s cubic-bezier(.22,1,.36,1), box-shadow .45s cubic-bezier(.22,1,.36,1); }
.hover-lift:hover { transform: translateY(-6px); }

.hover-shift i { transition: transform .35s cubic-bezier(.22,1,.36,1); }
.hover-shift:hover i { transform: translateX(5px); }

.hover-grow { overflow: hidden; }
.hover-grow img { transition: transform 1.1s cubic-bezier(.16,1,.3,1); }
.hover-grow:hover img { transform: scale(1.07); }

/* Text swap on hover — the label rolls up and a copy rolls in */
.roll { position: relative; display: inline-block; overflow: hidden; vertical-align: bottom; }
.roll span { display: block; transition: transform .5s cubic-bezier(.22,1,.36,1); }
.roll span:last-child { position: absolute; inset: 0; transform: translateY(105%); }
.roll:hover span:first-child { transform: translateY(-105%); }
.roll:hover span:last-child  { transform: none; }

/* --------------------------------------------------------------------------
   12. Entrance for the header on first paint
   -------------------------------------------------------------------------- */

.ici-header { animation: header-in 1s cubic-bezier(.16,1,.3,1) .2s both; }
@keyframes header-in {
  from { opacity: 0; transform: translateY(-18px); }
  to   { opacity: 1; transform: none; }
}

/* Hero content cascade — runs on load, not on scroll */
.hero-in > * {
  opacity: 0; transform: translate3d(0, 34px, 0);
  animation: hero-in 1.15s cubic-bezier(.16,1,.3,1) forwards;
}
.hero-in > *:nth-child(1) { animation-delay: .35s; }
.hero-in > *:nth-child(2) { animation-delay: .48s; }
.hero-in > *:nth-child(3) { animation-delay: .61s; }
.hero-in > *:nth-child(4) { animation-delay: .74s; }
.hero-in > *:nth-child(5) { animation-delay: .87s; }
.hero-in > *:nth-child(6) { animation-delay: 1s; }
@keyframes hero-in { to { opacity: 1; transform: none; } }

/* --------------------------------------------------------------------------
   13. Reduced motion
   Anyone who asks for less motion gets content, instantly, with no transforms.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }

  [data-reveal],
  .sw-inner,
  .sc-char,
  .hero-in > * {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    clip-path: none !important;
  }

  [data-parallax], [data-parallax-x] { transform: none !important; }
  .curtain::after { transform: scaleX(0) !important; }
  .curtain img { transform: none !important; }
  .marquee-track { animation: none !important; }
  .kenburns, .kenburns-slow, .kb-img { animation: none !important; transform: none !important; }
  .loader { display: none !important; }
}
