/* flj-glow.css — pointer-tracking spotlight glow.
 *
 * Vanilla port of the React "spotlight card": a radial highlight follows the
 * cursor across the page and lights up the border of any element marked
 * [data-glow]. The maths lives in CSS custom properties that flj-glow.js keeps
 * up to date on :root, so one pointer listener drives every card on the page.
 *
 *   <div class="flj-glow" data-glow>…</div>
 *   <div class="flj-glow flj-glow--gold" data-glow>…</div>
 *
 * Hue is derived from the cursor's horizontal position (--xp), so the glow
 * shifts through a range as you move — set --glow-base / --glow-spread per
 * variant to keep it inside the site's palette instead of the rainbow the
 * original produced.
 */

:root {
  /* Updated by flj-glow.js on pointermove. Defaults keep the effect sane
     before the first move and on touch devices that never fire it. */
  --glow-x: 50;
  --glow-y: 50;
  --glow-xp: 0.5;
  --glow-yp: 0.5;
}

.flj-glow {
  /* Palette: red → gold sweep, matching the site rather than the demo's blue. */
  --glow-base: 352;          /* site red */
  --glow-spread: 44;         /* travels toward gold, never into green/blue */
  --glow-saturation: 82;
  --glow-lightness: 58;
  --glow-radius: 18;
  --glow-border: 2;
  --glow-size: 320;
  --glow-backdrop: rgba(255, 255, 255, 0.04);
  --glow-spot-opacity: 0.14;
  --glow-border-opacity: 0.95;
  --glow-light-opacity: 0.75;

  --glow-border-size: calc(var(--glow-border) * 1px);
  --glow-spotlight-size: calc(var(--glow-size) * 1px);
  --glow-hue: calc(var(--glow-base) + (var(--glow-xp) * var(--glow-spread)));

  position: relative;
  border-radius: calc(var(--glow-radius) * 1px);
  border: var(--glow-border-size) solid color-mix(in srgb, var(--text) 6%, transparent);
  background-color: var(--glow-backdrop);
  background-image: radial-gradient(
    var(--glow-spotlight-size) var(--glow-spotlight-size) at
    calc(var(--glow-x) * 1px) calc(var(--glow-y) * 1px),
    hsl(var(--glow-hue) calc(var(--glow-saturation) * 1%) calc(var(--glow-lightness) * 1%)
        / var(--glow-spot-opacity)),
    transparent
  );
  /* Fixed attachment puts the gradient in viewport space, so the highlight sits
     under the real cursor no matter where the card is scrolled to. */
  background-attachment: fixed;
  background-size: calc(100% + (2 * var(--glow-border-size)))
                   calc(100% + (2 * var(--glow-border-size)));
  background-position: 50% 50%;
  background-repeat: no-repeat;
}

/* The two pseudo-elements paint the lit border: ::before is the coloured
   spotlight, ::after a tighter white core. Both are masked so only the border
   ring shows, which is what makes the edge glow instead of the whole box. */
.flj-glow::before,
.flj-glow::after {
  content: '';
  position: absolute;
  inset: calc(var(--glow-border-size) * -1);
  border: var(--glow-border-size) solid transparent;
  border-radius: inherit;
  background-attachment: fixed;
  background-repeat: no-repeat;
  background-position: 50% 50%;
  background-size: calc(100% + (2 * var(--glow-border-size)))
                   calc(100% + (2 * var(--glow-border-size)));
  pointer-events: none;
  -webkit-mask: linear-gradient(transparent, transparent), linear-gradient(#fff, #fff);
  mask: linear-gradient(transparent, transparent), linear-gradient(#fff, #fff);
  -webkit-mask-clip: padding-box, border-box;
  mask-clip: padding-box, border-box;
  -webkit-mask-composite: xor;
  mask-composite: intersect;
}

.flj-glow::before {
  background-image: radial-gradient(
    calc(var(--glow-spotlight-size) * 0.75) calc(var(--glow-spotlight-size) * 0.75) at
    calc(var(--glow-x) * 1px) calc(var(--glow-y) * 1px),
    hsl(var(--glow-hue) calc(var(--glow-saturation) * 1%) calc(var(--glow-lightness) * 1%)
        / var(--glow-border-opacity)),
    transparent 100%
  );
  filter: brightness(1.6);
}

.flj-glow::after {
  background-image: radial-gradient(
    calc(var(--glow-spotlight-size) * 0.4) calc(var(--glow-spotlight-size) * 0.4) at
    calc(var(--glow-x) * 1px) calc(var(--glow-y) * 1px),
    hsl(0 0% 100% / var(--glow-light-opacity)),
    transparent 100%
  );
}

/* ---------- variants ---------- */

/* Teal — used for anything already completed. */
.flj-glow--done {
  --glow-base: 168;
  --glow-spread: 14;
  --glow-saturation: 76;
  --glow-lightness: 52;
}

/* Gold — the "to do" accent used by trace and write steps. */
.flj-glow--gold {
  --glow-base: 42;
  --glow-spread: 12;
  --glow-saturation: 78;
  --glow-lightness: 60;
}

/* Stronger edge for hero surfaces like the auth card. */
.flj-glow--strong {
  --glow-border: 2;
  --glow-size: 460;
  --glow-spot-opacity: 0.2;
}

/* Quieter, for dense grids where many cards are on screen at once. */
.flj-glow--soft {
  --glow-size: 240;
  --glow-spot-opacity: 0.1;
  --glow-border-opacity: 0.6;
  --glow-light-opacity: 0.4;
}

/* The pointer highlight is a hover affordance; with no pointer there is nothing
   to track, so fall back to a plain edge rather than a glow frozen mid-screen. */
@media (hover: none) {
  .flj-glow::before,
  .flj-glow::after {
    display: none;
  }
  .flj-glow {
    background-image: none;
    border-color: color-mix(in srgb, var(--text) 12%, transparent);
  }
}

@media (prefers-reduced-motion: reduce) {
  .flj-glow::after {
    display: none;
  }
}

/* ---------- spotlight ----------
 * A single soft light raking across the top of a dark surface. Vanilla port of
 * the React <Spotlight> — it was an animated blurred ellipse, which is one
 * pseudo-element here. Put .flj-spot on any position:relative dark container.
 */

.flj-spot {
  position: relative;
  overflow: hidden;
}
.flj-spot::before {
  content: '';
  position: absolute;
  top: -30%;
  left: -10%;
  width: 70%;
  height: 90%;
  border-radius: 50%;
  background: radial-gradient(closest-side,
    color-mix(in srgb, var(--text) 16%, transparent),
    color-mix(in srgb, var(--text) 6%, transparent) 45%,
    transparent 72%);
  filter: blur(28px);
  pointer-events: none;
  transform: rotate(-14deg);
  animation: fljSpotDrift 11s ease-in-out infinite alternate;
}
@keyframes fljSpotDrift {
  from { transform: rotate(-16deg) translate3d(-3%, -2%, 0) scale(1); opacity: 0.85; }
  to   { transform: rotate(-10deg) translate3d(6%, 3%, 0) scale(1.08); opacity: 1; }
}
/* Warm variant picking up the site's red instead of neutral white. */
.flj-spot--red::before {
  background: radial-gradient(closest-side,
    rgba(230, 57, 70, 0.22),
    rgba(230, 57, 70, 0.08) 45%,
    transparent 72%);
}

/* Gradient-clipped heading, as used on the demo's title. */
.flj-grad-text {
  background: linear-gradient(180deg, var(--text) 0%, var(--text2) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@media (prefers-reduced-motion: reduce) {
  .flj-spot::before { animation: none; }
}
