/* ==========================================================================
   liquid-motion — the animation layer for the liquid-glass page.
   Loaded after liquid.css. Kept separate so the material and the motion can be
   reasoned about (and reverted) independently.

   Two hard rules, both from what the material costs:
   1. Never animate `backdrop-filter` or `filter` on a persistent surface. They
      re-run the blur every frame. Everything here animates transform / opacity /
      background-position / custom properties only.
   2. Nothing may leave content invisible if the animation never runs. A
      backgrounded tab pauses animations, so every entrance state is opt-in via
      a class JS adds only once it is in a position to remove it again.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Ambient caustics — a slow band of light travelling across the page,
      the thing that makes glass look lit rather than painted.
   -------------------------------------------------------------------------- */
.lq-caustics {
  position: fixed;
  inset: -20% -10%;
  z-index: 0;
  pointer-events: none;
  opacity: .55;
  background:
    radial-gradient(38% 26% at 22% 30%, rgba(120, 170, 255, .16), transparent 70%),
    radial-gradient(30% 22% at 74% 62%, rgba(190, 215, 255, .18), transparent 72%),
    radial-gradient(26% 30% at 52% 12%, rgba(255, 255, 255, .55), transparent 70%);
  filter: blur(28px);
  will-change: transform;
}
.on-dark .lq-caustics, .lq-caustics.is-night { opacity: .38; }

@media (prefers-reduced-motion: no-preference) {
  .lq-caustics { animation: lqDrift 42s ease-in-out infinite alternate; }
}
@keyframes lqDrift {
  from { transform: translate3d(-2%, -1%, 0) scale(1); }
  to   { transform: translate3d(3%, 2%, 0) scale(1.08); }
}

/* --------------------------------------------------------------------------
   2. Pointer-tracked rim light on the two deep-glass surfaces.
      A real pane brightens where the light hits it; this follows the cursor.
      Injected by liquid-motion.js so it never collides with liquid.css's
      ::before / ::after (refraction ring and edge ring).
   -------------------------------------------------------------------------- */
.glass-deep { position: relative; }
.lq-sheen {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity .45s ease;
  background: radial-gradient(
    260px circle at var(--mx, 50%) var(--my, 0%),
    rgba(255, 255, 255, .58),
    rgba(255, 255, 255, .12) 42%,
    transparent 68%
  );
  mix-blend-mode: screen;
}
.glass-deep:hover > .lq-sheen,
.glass-deep:focus-within > .lq-sheen { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .lq-sheen { display: none; }
}

/* --------------------------------------------------------------------------
   3. Staggered entrance for panes inside a revealed section.
      liquid.css already reveals sections; this makes the children arrive in
      sequence so a grid of cards assembles instead of popping as one block.
   -------------------------------------------------------------------------- */
.has-reveal .lq-stagger > * {
  opacity: 0;
  transform: translateY(14px) scale(.994);
}
.has-reveal .lq-stagger.in > * {
  opacity: 1;
  transform: none;
  transition:
    opacity .5s cubic-bezier(.2, .7, .3, 1),
    transform .5s cubic-bezier(.2, .7, .3, 1);
  transition-delay: calc(var(--i, 0) * 55ms);
}

/* --------------------------------------------------------------------------
   4. Idle float on the hero card — a few pixels, very slow. Glass should feel
      suspended rather than nailed down.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  .lq-float { animation: lqFloat 13s ease-in-out infinite alternate; }
}
@keyframes lqFloat {
  from { transform: translateY(-4px); }
  to   { transform: translateY(5px); }
}

/* --------------------------------------------------------------------------
   5. Specular travel across a pane on hover — a narrow highlight that crosses
      the surface. Animates background-position, which composites cheaply.
   -------------------------------------------------------------------------- */
.pane, .glass { background-repeat: no-repeat; }
.lq-swipe { position: relative; overflow: hidden; }
.lq-swipe::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: -40%;
  width: 34%;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    transparent,
    rgba(255, 255, 255, .55) 45%,
    rgba(255, 255, 255, .78) 52%,
    transparent
  );
  transform: skewX(-14deg);
  opacity: 0;
  transition: none;
}
@media (prefers-reduced-motion: no-preference) {
  .lq-swipe:hover::before {
    opacity: 1;
    animation: lqSwipe .85s cubic-bezier(.32, .8, .34, 1);
  }
}
@keyframes lqSwipe {
  from { left: -40%; }
  to   { left: 118%; }
}

/* --------------------------------------------------------------------------
   6. Hero variable token — the "Type" treatment Sergio picked.

      No braces. They were here originally so `{{…}}` would read as one variable
      holding a value, but at hero size two glyphs a side stack into a pile of
      parentheses around the word rather than a frame for it. The blinking caret
      already says "this is a slot being filled", so the braces were redundant
      as well as noisy. (index.html keeps its braces — different driver,
      different size, and they work there.)

      Self-contained on purpose — it uses liquid.css's own accent tokens rather
      than importing hero-anims.css, so this page stays standalone and picks up
      the .on-dark palette flip for free.
   -------------------------------------------------------------------------- */
.tok {
  display: inline-flex;
  align-items: baseline;
  gap: 0;
}
/* liquid.css gives .tok a gradient text fill (`background-clip: text` +
   `-webkit-text-fill-color: transparent`). Its child is a flex item — its own
   box — so it inherits the transparent fill with no background to clip against
   and renders INVISIBLE. An explicit colour restores it. Flips under .on-dark. */
.tok-word {
  -webkit-text-fill-color: currentColor;
  background: none;
  color: var(--accent);
  display: inline-block;
  white-space: nowrap;
  vertical-align: bottom;
  /* NO `overflow: hidden` here. It was a holdover from a width-animated version
     of this effect; the typing sets textContent directly, so it clipped nothing
     useful and did clip the descenders — the g in "hiring agents" lost its tail. */
  /* the caret is a border so it inherits nothing from the gradient text fill */
  border-right: 2px solid var(--accent-2);
}

@media (prefers-reduced-motion: no-preference) {
  .tok-word { animation: lqCaret .75s steps(1) infinite; }
}
@keyframes lqCaret { 50% { border-right-color: transparent; } }

@media (prefers-reduced-motion: reduce) {
  .tok-word { animation: none; border-right-color: transparent; }
}

/* --------------------------------------------------------------------------
   7. Parallax — the ground moves slower than the content it sits behind.
      JS writes --par; the transform is declarative so it stays on the
      compositor.
   -------------------------------------------------------------------------- */
.lq-parallax { transform: translate3d(0, var(--par, 0px), 0); will-change: transform; }

@media (prefers-reduced-motion: reduce) {
  .lq-parallax { transform: none !important; }
  .lq-caustics { animation: none !important; }
  .lq-float { animation: none !important; }
  .has-reveal .lq-stagger > *,
  .has-reveal .lq-stagger.in > * {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}
