/* ================================================================ FX === */
/* The CSS half of fx.js: patterns from Aceternity UI, Magic UI, hover.dev,
   Animate UI, React Bits, Inspira UI and Eldora UI, rebuilt without their
   React, Tailwind and Motion. Colours come from --fx-b1/--fx-b2 (a page's two
   accents) and --fx-line (its hairlines), so the same effect wears AZFit's
   green on our site and a coach's own colour on hers. */
@property --fx-a { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
@property --fx-o { syntax: '<angle>'; inherits: false; initial-value: 0deg; }

/* ---- numbers: every digit a wheel (Animate UI SlidingNumber, Magic UI NumberTicker) ---- */
.fx-roll { display: inline-flex; align-items: flex-start; font-variant-numeric: tabular-nums; line-height: 1.1; }
.fx-d { display: inline-block; height: 1.1em; overflow: hidden; }
.fx-d > span { display: flex; flex-direction: column; transform: translateY(calc(var(--n, 0) * -1.1em));
  transition: transform .75s cubic-bezier(.2, .9, .25, 1); }
.fx-d:nth-child(2n) > span { transition-duration: .9s; }
.fx-d i { display: block; height: 1.1em; font-style: normal; text-align: center; }
.fx-c { display: inline-block; }

/* ---- words ---- */
/* Flip words (Aceternity FlipWords): letters leave blurred, the next word arrives the same way. */
.fx-flip { display: inline-block; white-space: nowrap; }
.fx-flip span { display: inline-block; animation: fx-letter-in .55s cubic-bezier(.2, .8, .2, 1) both; animation-delay: calc(var(--k) * 32ms); }
.fx-flip.out span { animation: fx-letter-out .38s cubic-bezier(.4, 0, .2, 1) both; animation-delay: calc(var(--k) * 12ms); }
@keyframes fx-letter-in { from { opacity: 0; filter: blur(8px); transform: translateY(45%); } }
@keyframes fx-letter-out { to { opacity: 0; filter: blur(8px); transform: translateY(-45%) scale(1.06); } }
/* Blur text (React Bits BlurText / SplitText): words come into focus one after another. */
.fx-w { display: inline-block; opacity: 0; filter: blur(12px); transform: translateY(28%);
  transition: opacity .9s, filter .9s, transform .9s cubic-bezier(.2, .8, .2, 1); transition-delay: calc(var(--i) * 70ms + var(--d0, 0ms)); }
.in .fx-w, .fx-w.in { opacity: 1; filter: none; transform: none; }
/* Gradient and shiny text (Magic UI AnimatedGradientText, AnimatedShinyText). */
.fx-grad { background: linear-gradient(92deg, var(--fx-b1, #4ade80), var(--fx-b2, #22d3ee) 55%, var(--fx-b1, #4ade80));
  background-size: 200% auto; -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: fx-grad 7s linear infinite; }
@keyframes fx-grad { to { background-position: -200% center; } }
/* Letters that animate on their own layer escape a parent's clipped gradient and vanish, so a flipping word
   takes its gradient letter by letter instead: green into cyan across the word. */
.fx-flip.fx-grad { background: none; -webkit-background-clip: border-box; background-clip: border-box; color: var(--fx-b1, #4ade80); animation: none; }
.fx-flip.fx-grad span { color: color-mix(in srgb, var(--fx-b2, #22d3ee) calc(min(var(--k), 10) * 8%), var(--fx-b1, #4ade80)); }
.fx-shine { background: linear-gradient(110deg, currentColor 38%, #fff 50%, currentColor 62%) 0 0 / 250% 100%;
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; animation: fx-shine 3.4s linear infinite; }
@keyframes fx-shine { from { background-position: 150% 0; } to { background-position: -100% 0; } }
.fx-typing::after { content: ''; display: inline-block; width: 2px; height: 1em; margin-left: 2px; background: currentColor;
  vertical-align: -.12em; animation: fx-caret .8s steps(1) infinite; }
@keyframes fx-caret { 50% { opacity: 0; } }

/* ---- the animated list (Magic UI AnimatedList) ---- */
.fx-feed { display: flex; flex-direction: column; gap: 10px; margin: 0; padding: 0; list-style: none; }

/* ---- beams (Magic UI AnimatedBeam) ---- */
.fx-beams { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.fx-beam-base { fill: none; stroke: var(--fx-line, rgba(255, 255, 255, .1)); stroke-width: 2; }
.fx-beam-run { fill: none; stroke-width: 2.5; stroke-linecap: round; stroke-dasharray: .2 1; stroke-dashoffset: .2;
  animation: fx-beam var(--t, 3.2s) cubic-bezier(.45, 0, .55, 1) var(--d, 0s) infinite; animation-direction: var(--dir, normal); }
@keyframes fx-beam { to { stroke-dashoffset: -1; } }

/* ---- a light that runs round a border (Magic UI BorderBeam / ShineBorder) ---- */
.fx-rim { position: absolute; inset: 0; z-index: 2; padding: 1.5px; border-radius: inherit; pointer-events: none;
  background: conic-gradient(from var(--fx-a), transparent 0 64%, var(--fx-b1, #4ade80) 78%, var(--fx-b2, #22d3ee) 88%, transparent 96%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); animation: fx-spin var(--t, 6s) linear infinite; }
@keyframes fx-spin { to { --fx-a: 360deg; } }

/* ---- backgrounds ---- */
/* Grid and dot patterns (Magic UI GridPattern / DotPattern), fading out from the middle. */
.fx-grid, .fx-dots { position: absolute; inset: 0; z-index: -1; pointer-events: none;
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 32%, #000 25%, transparent 75%);
  mask-image: radial-gradient(ellipse 70% 60% at 50% 32%, #000 25%, transparent 75%); }
.fx-grid { background-image: linear-gradient(to right, var(--fx-line, rgba(255, 255, 255, .06)) 1px, transparent 1px),
  linear-gradient(to bottom, var(--fx-line, rgba(255, 255, 255, .06)) 1px, transparent 1px); background-size: 56px 56px; }
.fx-dots { background-image: radial-gradient(var(--fx-line, rgba(255, 255, 255, .1)) 1px, transparent 1.2px); background-size: 22px 22px; }
/* Retro grid (Magic UI RetroGrid): a floor of lines running toward you. */
.fx-retro { position: absolute; inset: 0; z-index: -1; overflow: hidden; perspective: 220px; pointer-events: none;
  -webkit-mask-image: linear-gradient(to top, #000 10%, transparent 65%); mask-image: linear-gradient(to top, #000 10%, transparent 65%); }
.fx-retro i { position: absolute; left: -50%; right: -50%; top: 42%; height: 200%; transform: rotateX(68deg); transform-origin: 50% 0;
  background-image: linear-gradient(to right, var(--fx-line, rgba(255, 255, 255, .12)) 1px, transparent 0),
    linear-gradient(to bottom, var(--fx-line, rgba(255, 255, 255, .12)) 1px, transparent 0);
  background-size: 64px 64px; animation: fx-retro 16s linear infinite; }
@keyframes fx-retro { to { background-position: 0 640px; } }
/* Spotlight (Aceternity Spotlight): a long ellipse of light that swings in from the corner. */
.fx-spotlight { position: absolute; top: -32%; left: -18%; z-index: -1; width: 92%; height: 130%; pointer-events: none;
  background: radial-gradient(ellipse 34% 62% at 50% 50%, rgba(255, 255, 255, .13), rgba(255, 255, 255, .04) 45%, transparent 72%);
  transform: rotate(-32deg); filter: blur(18px); animation: fx-spot-in 2.2s .2s cubic-bezier(.2, .8, .2, 1) both; }
.fx-spotlight.r { left: auto; right: -18%; transform: rotate(32deg) scaleX(-1); animation-name: fx-spot-in-r; }
@keyframes fx-spot-in { from { opacity: 0; transform: translate(-8%, -12%) rotate(-32deg) scale(.55); } }
@keyframes fx-spot-in-r { from { opacity: 0; transform: translate(8%, -12%) rotate(32deg) scaleX(-1) scale(.55); } }
/* Aurora (Aceternity AuroraBackground): slow bands of colour under a blur. */
.fx-aurora { position: absolute; inset: -10%; z-index: -1; pointer-events: none; opacity: .45; filter: blur(70px);
  background: repeating-linear-gradient(100deg, var(--fx-b1, #4ade80) 10%, var(--fx-b2, #22d3ee) 16%, #6366f1 22%, var(--fx-b1, #4ade80) 28%);
  background-size: 300% 200%; animation: fx-aurora 40s linear infinite;
  -webkit-mask-image: radial-gradient(ellipse 60% 50% at 50% 0%, #000 10%, transparent 70%); mask-image: radial-gradient(ellipse 60% 50% at 50% 0%, #000 10%, transparent 70%); }
@keyframes fx-aurora { to { background-position: 350% 50%; } }
/* Lamp (Aceternity LampContainer): a bar of light and the cone it throws, brightest straight down. */
.fx-lamp { position: absolute; top: 0; left: 50%; z-index: -1; width: min(60rem, 130%); height: 26rem; translate: -50% 0; pointer-events: none;
  -webkit-mask-image: radial-gradient(52% 100% at 50% 0%, #000 35%, transparent 80%); mask-image: radial-gradient(52% 100% at 50% 0%, #000 35%, transparent 80%); }
.fx-lamp::before, .fx-lamp::after { content: ''; position: absolute; top: 0; width: 50%; height: 100%; opacity: .55; transition: opacity 1.2s; }
.fx-lamp::before { right: 50%; background: conic-gradient(from 180deg at 100% 0%, var(--fx-b1, #4ade80) 0deg, transparent 58deg, transparent 360deg); }
.fx-lamp::after { left: 50%; background: conic-gradient(from 90deg at 0% 0%, transparent 0deg, transparent 32deg, var(--fx-b1, #4ade80) 90deg, transparent 90.5deg); }
.fx-lamp i { position: absolute; top: 0; left: 50%; z-index: 1; width: 40%; height: 2px; translate: -50% 0; border-radius: 2px; background: var(--fx-b1, #4ade80);
  box-shadow: 0 0 24px 6px color-mix(in srgb, var(--fx-b1, #4ade80) 60%, transparent), 0 0 120px 40px color-mix(in srgb, var(--fx-b1, #4ade80) 25%, transparent);
  transition: width 1.2s cubic-bezier(.2, .8, .2, 1); }
.fx-lamp:not(.on) i { width: 14%; }
.fx-lamp:not(.on)::before, .fx-lamp:not(.on)::after { opacity: .15; }
/* Meteors (Magic UI Meteors) and sparkles (Aceternity SparklesCore). */
.fx-meteor { position: absolute; top: var(--y); left: var(--x); width: 2px; height: 2px; border-radius: 50%; background: #fff; opacity: 0;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .08); pointer-events: none; animation: fx-meteor var(--t) linear var(--d) infinite; }
.fx-meteor::before { content: ''; position: absolute; top: 50%; width: 70px; height: 1px; translate: 0 -50%;
  background: linear-gradient(90deg, rgba(255, 255, 255, .7), transparent); }
@keyframes fx-meteor { 0% { opacity: 0; transform: rotate(215deg) translateX(0); } 6%, 60% { opacity: 1; }
  100% { opacity: 0; transform: rotate(215deg) translateX(-520px); } }
.fx-sparkle { position: absolute; top: var(--y); left: var(--x); width: calc(var(--s) * 3px); aspect-ratio: 1; border-radius: 50%; background: #fff;
  opacity: 0; pointer-events: none; animation: fx-twinkle var(--t) ease-in-out var(--d) infinite; }
@keyframes fx-twinkle { 50% { opacity: .85; transform: scale(1.5); } }
/* Ripple (Magic UI Ripple): rings that breathe behind the thing in the middle. */
.fx-ripple { position: absolute; inset: 0; z-index: -1; pointer-events: none; }
.fx-ripple i { position: absolute; top: 50%; left: 50%; width: calc(90px + var(--k) * 74px); aspect-ratio: 1; translate: -50% -50%; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--fx-b1, #4ade80) calc(34% - var(--k) * 6%), transparent);
  background: color-mix(in srgb, var(--fx-b1, #4ade80) calc(6% - var(--k) * 1%), transparent);
  animation: fx-ripple 3.6s ease-in-out infinite; animation-delay: calc(var(--k) * .14s); }
@keyframes fx-ripple { 50% { transform: scale(.93); } }
/* A live dot (every status page ever): a ping that keeps going out. */
.fx-live { position: relative; display: inline-block; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--fx-b1, #4ade80); }
.fx-live::after { content: ''; position: absolute; inset: 0; border-radius: 50%; background: inherit; animation: fx-ping 1.8s cubic-bezier(0, 0, .2, 1) infinite; }
@keyframes fx-ping { 75%, 100% { transform: scale(2.8); opacity: 0; } }

/* ---- marquee (Magic UI Marquee, Aceternity InfiniteMovingCards) ---- */
.fx-marquee { --gap: 14px; display: flex; gap: var(--gap); overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.fx-marquee > div { display: flex; flex: none; gap: var(--gap); min-width: 100%; justify-content: space-around; animation: fx-marq var(--dur, 40s) linear infinite; }
.fx-marquee.rev > div { animation-direction: reverse; }
.fx-marquee:hover > div { animation-play-state: paused; }
@keyframes fx-marq { to { transform: translateX(calc(-100% - var(--gap))); } }

/* ---- orbiting circles (Magic UI OrbitingCircles) ---- */
.fx-orbit { position: absolute; top: 50%; left: 50%; width: calc(var(--r) * 2); aspect-ratio: 1; translate: -50% -50%; border-radius: 50%;
  border: 1px solid var(--fx-line, rgba(255, 255, 255, .08)); pointer-events: none; }
.fx-orb { position: absolute; top: 50%; left: 50%; translate: -50% -50%;
  transform: rotate(calc(var(--fx-o) + var(--a, 0deg))) translateX(var(--r, 120px)) rotate(calc(-1 * (var(--fx-o) + var(--a, 0deg))));
  animation: fx-orbit var(--t, 30s) linear infinite; animation-direction: var(--dir, normal); }
@keyframes fx-orbit { to { --fx-o: 360deg; } }

/* ---- compare (Aceternity Compare) ---- */
.fx-cmp { --pos: 50%; position: relative; overflow: hidden; cursor: ew-resize; touch-action: pan-y; user-select: none; -webkit-user-select: none; }
.fx-cmp-b { position: absolute; inset: 0; clip-path: inset(0 calc(100% - var(--pos)) 0 0); }
.fx-cmp-line { position: absolute; top: 0; bottom: 0; left: var(--pos); z-index: 3; width: 2px; translate: -1px 0; pointer-events: none;
  background: linear-gradient(transparent, var(--fx-b1, #4ade80) 20%, var(--fx-b2, #22d3ee) 80%, transparent);
  box-shadow: 0 0 22px 2px color-mix(in srgb, var(--fx-b1, #4ade80) 50%, transparent); }
.fx-cmp-handle { position: absolute; top: 50%; left: var(--pos); z-index: 4; display: grid; place-items: center; width: 44px; height: 44px; translate: -50% -50%;
  border: 1px solid rgba(255, 255, 255, .25); border-radius: 50%; background: rgba(10, 11, 14, .75); backdrop-filter: blur(8px); color: #fff; cursor: ew-resize;
  box-shadow: 0 10px 30px -8px rgba(0, 0, 0, .8); transition: transform .25s; }
.fx-cmp-handle::before { content: '‹ ›'; font: 700 15px/1 system-ui, sans-serif; letter-spacing: 2px; }
.fx-cmp.drag .fx-cmp-handle, .fx-cmp-handle:focus-visible { transform: scale(1.12); outline: 2px solid var(--fx-b1, #4ade80); outline-offset: 3px; }

/* ---- spotlight cards and tilt (Magic UI MagicCard, Aceternity CardSpotlight / 3D card) ---- */
.spot { position: relative; isolation: isolate; }
.spot::after, .spot::before { content: ''; position: absolute; inset: 0; z-index: 3; border-radius: inherit; pointer-events: none; opacity: 0; transition: opacity .35s; }
.spot::after { background: radial-gradient(440px circle at var(--mx, 50%) var(--my, 50%), color-mix(in srgb, var(--accent, #4ade80) 10%, transparent), transparent 44%); }
.spot::before { padding: 1px; background: radial-gradient(280px circle at var(--mx, 50%) var(--my, 50%), var(--accent, #4ade80), transparent 64%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); }
.spot:hover::after, .spot:hover::before, .spot:focus-visible::before { opacity: 1; }
.tilt { transform: perspective(1100px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)); transition: transform .6s cubic-bezier(.2, .8, .2, 1); }
.mag { transition: transform .45s cubic-bezier(.2, .8, .2, 1); }

/* ---- slide tabs (hover.dev SlideTabs, Animate UI Tabs) ---- */
.fx-pill { position: absolute; top: 0; left: 0; z-index: 0; border-radius: 999px; background: var(--fx-pill, #fff); opacity: 0; pointer-events: none; }
.fx-pill-go { transition: transform .5s cubic-bezier(.3, 1.25, .5, 1), width .5s cubic-bezier(.3, 1.25, .5, 1), opacity .2s; }

/* ---- one-time code (shadcn / Animate UI InputOTP) ---- */
.fx-otp { position: relative; }
.fx-otp input { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; padding: 0; border: 0; outline: none; background: transparent;
  color: transparent; caret-color: transparent; font-size: 16px; letter-spacing: 1em; cursor: text; }
.fx-otp input::selection { background: transparent; }
.fx-otp-cells { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 8px; }
.fx-otp-cells i { position: relative; display: grid; place-items: center; height: 60px; border: 1px solid var(--fx-line2, rgba(255, 255, 255, .16));
  border-radius: 14px; background: rgba(255, 255, 255, .03); font-style: normal; font-size: 26px; font-weight: 600; font-variant-numeric: tabular-nums;
  transition: border-color .2s, box-shadow .2s, background-color .2s; }
.fx-otp-cells i.on { border-color: var(--fx-b1, #4ade80); box-shadow: 0 0 0 4px color-mix(in srgb, var(--fx-b1, #4ade80) 18%, transparent); }
.fx-otp-cells i.on:empty::after { content: ''; width: 2px; height: 26px; background: currentColor; animation: fx-caret 1s steps(1) infinite; }
.fx-otp-cells i.full { animation: fx-pop .28s cubic-bezier(.3, 1.6, .5, 1); background: rgba(255, 255, 255, .06); }
.fx-otp.bad { animation: fx-shake .42s; }
.fx-otp.bad .fx-otp-cells i { border-color: #f87171; }
@keyframes fx-pop { 50% { transform: scale(1.08); } }
@keyframes fx-shake { 20%, 60% { transform: translateX(-7px); } 40%, 80% { transform: translateX(7px); } }

/* ---- bursts ---- */
.fx-spark { position: fixed; z-index: 9999; width: 0; height: 0; color: var(--fx-b1, #4ade80); pointer-events: none; }
.fx-spark i { position: absolute; left: -1px; top: -5px; width: 2px; height: 10px; border-radius: 2px; background: currentColor;
  transform: rotate(var(--a)) translateY(-10px); animation: fx-spark .55s cubic-bezier(.2, .8, .2, 1) forwards; }
@keyframes fx-spark { to { transform: rotate(var(--a)) translateY(-30px) scaleY(.2); opacity: 0; } }
.fx-confetti { position: fixed; inset: 0; z-index: 9999; width: 100vw; height: 100vh; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .fx-flip span, .fx-rim, .fx-retro i, .fx-aurora, .fx-meteor, .fx-sparkle, .fx-ripple i, .fx-live::after, .fx-marquee > div,
  .fx-orb, .fx-grad, .fx-shine, .fx-beam-run, .fx-spotlight { animation: none !important; }
  .fx-w { opacity: 1; filter: none; transform: none; transition: none; }
  .fx-d > span { transition: none; }
}
