/* Lumenan Studio - modern CSS effects used by this template. Each effect is one class: fx-NAME. */

/* ===== Modern CSS Animations ===== */
/* Glitch Text - Splits a heading into offset colour slices that jitter like a broken screen; repeat the text in data-text. */
.fx-glitch-text { position: relative; display: inline-block; }
.fx-glitch-text::before, .fx-glitch-text::after {
  content: attr(data-text); position: absolute; inset: 0; pointer-events: none;
  -webkit-clip-path: inset(50% 0 50% 0); clip-path: inset(50% 0 50% 0);
}
.fx-glitch-text::before { color: var(--wt-accent); left: 2px; text-shadow: -1px 0 var(--wt-primary); animation: fx-glitch-text-a 2.6s steps(1) infinite; }
.fx-glitch-text::after { color: var(--wt-secondary); left: -2px; text-shadow: 1px 0 var(--wt-accent); animation: fx-glitch-text-b 3.1s steps(1) infinite; }
@keyframes fx-glitch-text-a {
  0% { -webkit-clip-path: inset(0 0 82% 0); clip-path: inset(0 0 82% 0); transform: translate(-3px, -1px); }
  15% { -webkit-clip-path: inset(30% 0 52% 0); clip-path: inset(30% 0 52% 0); transform: translate(3px, 1px); }
  30% { -webkit-clip-path: inset(62% 0 20% 0); clip-path: inset(62% 0 20% 0); transform: translate(-2px, 0); }
  45% { -webkit-clip-path: inset(50% 0 50% 0); clip-path: inset(50% 0 50% 0); }
  80% { -webkit-clip-path: inset(12% 0 70% 0); clip-path: inset(12% 0 70% 0); transform: translate(2px, -1px); }
  90% { -webkit-clip-path: inset(50% 0 50% 0); clip-path: inset(50% 0 50% 0); }
}
@keyframes fx-glitch-text-b {
  0% { -webkit-clip-path: inset(70% 0 8% 0); clip-path: inset(70% 0 8% 0); transform: translate(2px, 1px); }
  20% { -webkit-clip-path: inset(8% 0 76% 0); clip-path: inset(8% 0 76% 0); transform: translate(-3px, 0); }
  35% { -webkit-clip-path: inset(50% 0 50% 0); clip-path: inset(50% 0 50% 0); }
  70% { -webkit-clip-path: inset(40% 0 38% 0); clip-path: inset(40% 0 38% 0); transform: translate(3px, -1px); }
  85% { -webkit-clip-path: inset(50% 0 50% 0); clip-path: inset(50% 0 50% 0); }
}
@media (prefers-reduced-motion: reduce) {
  .fx-glitch-text, .fx-glitch-text::before, .fx-glitch-text::after, .fx-glitch-text *, .fx-glitch-text *::before, .fx-glitch-text *::after { animation: none !important; transition: none !important; }
}
/* Shimmer Skeleton - Loading placeholders with a light sweep; add the class to every grey block of a skeleton card. */
.fx-shimmer-skeleton {
  display: block; min-height: .9rem; border-radius: var(--wt-radius, .5rem);
  background: linear-gradient(90deg, rgba(var(--wt-primary-rgb), .08) 25%, rgba(var(--wt-primary-rgb), .22) 37%, rgba(var(--wt-primary-rgb), .08) 63%);
  background-size: 400% 100%;
  animation: fx-shimmer-skeleton-shine 1.4s ease infinite;
}
@keyframes fx-shimmer-skeleton-shine { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
@media (prefers-reduced-motion: reduce) {
  .fx-shimmer-skeleton, .fx-shimmer-skeleton::before, .fx-shimmer-skeleton::after, .fx-shimmer-skeleton *, .fx-shimmer-skeleton *::before, .fx-shimmer-skeleton *::after { animation: none !important; transition: none !important; }
}

/* ===== Modern CSS Clip-path Effects ===== */
/* Hexagon Scale - Crops avatars or product shots to a hexagon that grows and tilts slightly on hover. */
.fx-hexagon-scale {
  -webkit-clip-path: polygon(25% 3%, 75% 3%, 100% 50%, 75% 97%, 25% 97%, 0 50%); clip-path: polygon(25% 3%, 75% 3%, 100% 50%, 75% 97%, 25% 97%, 0 50%);
  transition: transform .45s cubic-bezier(.34, 1.56, .64, 1), filter .45s;
}
.fx-hexagon-scale:hover { transform: scale(1.1) rotate(4deg); filter: saturate(1.3); }
@media (prefers-reduced-motion: reduce) {
  .fx-hexagon-scale, .fx-hexagon-scale::before, .fx-hexagon-scale::after, .fx-hexagon-scale *, .fx-hexagon-scale *::before, .fx-hexagon-scale *::after { animation: none !important; transition: none !important; }
}
/* Slide Reveal - Wipes an image or banner in from the left, holds it, then wipes it out to the right. */
.fx-slide-reveal { -webkit-clip-path: inset(0 0 0 0); clip-path: inset(0 0 0 0); animation: fx-slide-reveal-wipe 5s cubic-bezier(.7, 0, .3, 1) infinite; }
@keyframes fx-slide-reveal-wipe {
  0% { -webkit-clip-path: inset(0 100% 0 0); clip-path: inset(0 100% 0 0); }
  25%, 75% { -webkit-clip-path: inset(0 0 0 0); clip-path: inset(0 0 0 0); }
  100% { -webkit-clip-path: inset(0 0 0 100%); clip-path: inset(0 0 0 100%); }
}
@media (prefers-reduced-motion: reduce) {
  .fx-slide-reveal, .fx-slide-reveal::before, .fx-slide-reveal::after, .fx-slide-reveal *, .fx-slide-reveal *::before, .fx-slide-reveal *::after { animation: none !important; transition: none !important; }
}

/* ===== Modern CSS Filter Effects ===== */
/* Grayscale to Color - Keeps images black and white until they are hovered or focused - ideal for logo walls and team grids. */
.fx-grayscale-to-color { filter: grayscale(1); transition: filter .5s ease; }
.fx-grayscale-to-color:hover, .fx-grayscale-to-color:focus-visible, :focus-visible > .fx-grayscale-to-color { filter: grayscale(0); }
@media (prefers-reduced-motion: reduce) {
  .fx-grayscale-to-color, .fx-grayscale-to-color::before, .fx-grayscale-to-color::after, .fx-grayscale-to-color *, .fx-grayscale-to-color *::before, .fx-grayscale-to-color *::after { animation: none !important; transition: none !important; }
}
/* Blur Focus - Put it on a row of cards or images: the hovered item stays sharp while its siblings blur and fade. */
.fx-blur-focus > * { transition: filter .4s ease, opacity .4s ease, transform .4s ease; }
.fx-blur-focus:hover > :not(:hover) { filter: blur(3px) saturate(.6); opacity: .65; }
.fx-blur-focus > :hover { transform: translateY(-4px); }
@media (prefers-reduced-motion: reduce) {
  .fx-blur-focus, .fx-blur-focus::before, .fx-blur-focus::after, .fx-blur-focus *, .fx-blur-focus *::before, .fx-blur-focus *::after { animation: none !important; transition: none !important; }
}
/* Glitch Filter - Short bursts of hue, contrast and position jumps make an image look like a corrupted signal. */
.fx-glitch-filter { animation: fx-glitch-filter-glitch 3.5s steps(1) infinite; }
@keyframes fx-glitch-filter-glitch {
  0%, 86%, 100% { filter: none; transform: none; }
  88% { filter: hue-rotate(90deg) saturate(3) contrast(1.6); transform: translate(-4px, 1px); }
  90% { filter: invert(.15) contrast(2); transform: translate(4px, -2px) skewX(6deg); }
  92% { filter: hue-rotate(-70deg) saturate(2); transform: translate(-2px, 0); }
  94% { filter: brightness(1.6); transform: translate(2px, 1px); }
}
@media (prefers-reduced-motion: reduce) {
  .fx-glitch-filter, .fx-glitch-filter::before, .fx-glitch-filter::after, .fx-glitch-filter *, .fx-glitch-filter *::before, .fx-glitch-filter *::after { animation: none !important; transition: none !important; }
}

/* ===== Modern CSS Transform Effects ===== */
/* 3D Card Tilt - Tilts a card in 3D with a moving glare on hover - a pure CSS take on the mouse-follow tilt. */
.fx-3d-card-tilt {
  position: relative; overflow: hidden; transform-style: preserve-3d;
  transform: perspective(900px) rotateX(0deg) rotateY(0deg);
  transition: transform .55s cubic-bezier(.2, .8, .2, 1), box-shadow .55s;
}
.fx-3d-card-tilt::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: linear-gradient(115deg, transparent 30%, rgba(255, 255, 255, .45) 48%, transparent 62%);
  transform: translateX(-60%); transition: transform .7s ease, opacity .4s;
}
.fx-3d-card-tilt:hover, .fx-3d-card-tilt:focus-within {
  transform: perspective(900px) rotateX(8deg) rotateY(-12deg) translateY(-4px);
  box-shadow: 18px 22px 40px -18px rgba(var(--wt-primary-rgb), .55);
}
.fx-3d-card-tilt:hover::after, .fx-3d-card-tilt:focus-within::after { opacity: 1; transform: translateX(60%); }
@media (prefers-reduced-motion: reduce) {
  .fx-3d-card-tilt, .fx-3d-card-tilt::before, .fx-3d-card-tilt::after, .fx-3d-card-tilt *, .fx-3d-card-tilt *::before, .fx-3d-card-tilt *::after { animation: none !important; transition: none !important; }
}
/* Perspective Text - Lays a heading back in 3D perspective with depth layers; it stands up straight on hover. */
.fx-perspective-text {
  display: inline-block; transform: perspective(500px) rotateX(28deg); transform-origin: 50% 100%;
  text-shadow: 0 1px 0 rgba(var(--wt-primary-rgb), .6), 0 2px 0 rgba(var(--wt-primary-rgb), .5), 0 3px 0 rgba(var(--wt-primary-rgb), .4), 0 10px 14px rgba(0, 0, 0, .25);
  transition: transform .6s cubic-bezier(.2, .8, .2, 1);
}
.fx-perspective-text:hover { transform: perspective(500px) rotateX(0deg); }
@media (prefers-reduced-motion: reduce) {
  .fx-perspective-text, .fx-perspective-text::before, .fx-perspective-text::after, .fx-perspective-text *, .fx-perspective-text *::before, .fx-perspective-text *::after { animation: none !important; transition: none !important; }
}
/* Matrix Transform - Uses a single matrix() to scale, skew and lift a tile at once on hover. */
.fx-matrix-transform { transition: transform .5s cubic-bezier(.34, 1.56, .64, 1), box-shadow .5s; }
.fx-matrix-transform:hover, .fx-matrix-transform:focus-visible { transform: matrix(1.05, -.08, .12, 1.05, 0, -8); box-shadow: 0 20px 30px -16px rgba(var(--wt-primary-rgb), .5); }
@media (prefers-reduced-motion: reduce) {
  .fx-matrix-transform, .fx-matrix-transform::before, .fx-matrix-transform::after, .fx-matrix-transform *, .fx-matrix-transform *::before, .fx-matrix-transform *::after { animation: none !important; transition: none !important; }
}

/* ===== Modern CSS Transitions ===== */
/* Morphing Gradient - A gradient button that softly changes to a second gradient and morphs into a pill on hover. */
.fx-morphing-gradient, .btn.fx-morphing-gradient {
  position: relative; isolation: isolate; overflow: hidden; z-index: 0; border: 0;
  color: var(--wt-on-primary, #fff); border-radius: .6rem;
  background: linear-gradient(135deg, var(--wt-primary), var(--wt-secondary));
  transition: border-radius .5s ease, transform .5s ease, box-shadow .5s;
}
.fx-morphing-gradient::before {
  content: ""; position: absolute; inset: 0; z-index: -1; opacity: 0;
  background: linear-gradient(135deg, var(--wt-accent), var(--wt-primary));
  transition: opacity .5s ease;
}
.fx-morphing-gradient:hover, .fx-morphing-gradient:focus-visible, .btn.fx-morphing-gradient:hover, .btn.fx-morphing-gradient:focus-visible {
  color: var(--wt-on-primary, #fff); border-radius: 2rem; transform: translateY(-2px);
  box-shadow: 0 12px 24px -10px rgba(var(--wt-accent-rgb), .7);
}
.fx-morphing-gradient:hover::before, .fx-morphing-gradient:focus-visible::before { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .fx-morphing-gradient, .fx-morphing-gradient::before, .fx-morphing-gradient::after, .fx-morphing-gradient *, .fx-morphing-gradient *::before, .fx-morphing-gradient *::after { animation: none !important; transition: none !important; }
}
/* Rainbow Glow - Surrounds a button or card with a glow that cycles through the theme colours while hovered. */
.fx-rainbow-glow { transition: box-shadow .4s ease, transform .4s ease; }
.fx-rainbow-glow:hover, .fx-rainbow-glow:focus-visible { transform: translateY(-2px); animation: fx-rainbow-glow-glow 2.4s linear infinite; }
@keyframes fx-rainbow-glow-glow {
  0%, 100% { box-shadow: 0 0 14px rgba(var(--wt-primary-rgb), .75), 0 0 34px rgba(var(--wt-primary-rgb), .35); }
  33% { box-shadow: 0 0 14px rgba(var(--wt-accent-rgb), .75), 0 0 34px rgba(var(--wt-accent-rgb), .35); }
  66% { box-shadow: 0 0 14px rgba(var(--wt-secondary-rgb), .75), 0 0 34px rgba(var(--wt-secondary-rgb), .35); }
}
@media (prefers-reduced-motion: reduce) {
  .fx-rainbow-glow, .fx-rainbow-glow::before, .fx-rainbow-glow::after, .fx-rainbow-glow *, .fx-rainbow-glow *::before, .fx-rainbow-glow *::after { animation: none !important; transition: none !important; }
}
/* Split Text Fill - Fills a heading or link with the primary colour from both sides at once on hover - top half from the left, bottom half from the right. */
.fx-split-text-fill {
  display: inline-block; text-decoration: none;
  -webkit-text-fill-color: transparent;
  background-image: linear-gradient(var(--wt-primary), var(--wt-primary)), linear-gradient(var(--wt-primary), var(--wt-primary)), linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 0, 100% 100%, 0 0;
  background-size: 0% 50%, 0% 50%, 100% 100%;
  -webkit-background-clip: text; background-clip: text;
  transition: background-size .6s cubic-bezier(.7, 0, .3, 1);
}
.fx-split-text-fill:hover, .fx-split-text-fill:focus-visible { background-size: 100% 50%, 100% 50%, 100% 100%; }
@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .fx-split-text-fill { -webkit-text-fill-color: currentColor; background: none; }
  .fx-split-text-fill:hover { color: var(--wt-primary-ink); }
}
@media (prefers-reduced-motion: reduce) {
  .fx-split-text-fill, .fx-split-text-fill::before, .fx-split-text-fill::after, .fx-split-text-fill *, .fx-split-text-fill *::before, .fx-split-text-fill *::after { animation: none !important; transition: none !important; }
}

/* ===== Modern CSS Gradient Effects ===== */
/* Mesh Gradient - Soft blobs of the theme colours blended into a slowly drifting mesh - perfect for hero panels. */
.fx-mesh-gradient {
  background-color: var(--wt-primary);
  background-image:
    radial-gradient(at 15% 20%, var(--wt-accent) 0, transparent 55%),
    radial-gradient(at 85% 15%, var(--wt-secondary) 0, transparent 50%),
    radial-gradient(at 75% 85%, var(--wt-accent) 0, transparent 50%),
    radial-gradient(at 20% 90%, var(--wt-secondary) 0, transparent 55%);
  background-size: 160% 160%;
  color: var(--wt-on-primary, #fff);
  animation: fx-mesh-gradient-drift 14s ease-in-out infinite alternate;
}
@keyframes fx-mesh-gradient-drift { from { background-position: 0% 0%; } to { background-position: 100% 100%; } }
@media (prefers-reduced-motion: reduce) {
  .fx-mesh-gradient, .fx-mesh-gradient::before, .fx-mesh-gradient::after, .fx-mesh-gradient *, .fx-mesh-gradient *::before, .fx-mesh-gradient *::after { animation: none !important; transition: none !important; }
}
/* Animated Border - A gradient border that rotates around a card or button; browsers without @property show it still. */
@property --fx-animated-border-angle { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
.fx-animated-border {
  border: 3px solid transparent;
  background:
    linear-gradient(var(--wt-surface, #fff), var(--wt-surface, #fff)) padding-box,
    conic-gradient(from var(--fx-animated-border-angle), var(--wt-primary), var(--wt-accent), var(--wt-secondary), var(--wt-primary)) border-box;
  animation: fx-animated-border-turn 4s linear infinite;
}
@keyframes fx-animated-border-turn { to { --fx-animated-border-angle: 360deg; } }
@media (prefers-reduced-motion: reduce) {
  .fx-animated-border, .fx-animated-border::before, .fx-animated-border::after, .fx-animated-border *, .fx-animated-border *::before, .fx-animated-border *::after { animation: none !important; transition: none !important; }
}
/* Iridescent - A holographic, pearly sheen that shifts its colours as the card is hovered. */
.fx-iridescent {
  position: relative; overflow: hidden; color: #1d1d2b;
  background: linear-gradient(120deg, #f6d5f7, #fbe9d7, #d5f2ef, #d7e2fb, #e9d5fb, #f6d5f7);
  background-size: 300% 300%; background-position: 0% 50%;
  transition: background-position 1.2s ease;
}
.fx-iridescent::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; mix-blend-mode: overlay;
  background: linear-gradient(105deg, transparent 35%, rgba(255, 255, 255, .7) 50%, transparent 65%);
  background-size: 250% 100%; background-position: 100% 0; transition: background-position 1.2s ease;
}
.fx-iridescent:hover, .fx-iridescent:focus-within { background-position: 100% 50%; }
.fx-iridescent:hover::after, .fx-iridescent:focus-within::after { background-position: 0 0; }
@media (prefers-reduced-motion: reduce) {
  .fx-iridescent, .fx-iridescent::before, .fx-iridescent::after, .fx-iridescent *, .fx-iridescent *::before, .fx-iridescent *::after { animation: none !important; transition: none !important; }
}

/* ===== Modern Shadow Effects ===== */
/* Neumorphism - Soft extruded surfaces that match the page background; they press in on hover and adapt to dark mode. */
.fx-neumorphism {
  --fx-neu-bg: var(--wt-bg, #e9edf2);
  background: var(--fx-neu-bg); border: 0;
  --fx-neu-dark: rgba(0, 0, 0, .14); --fx-neu-light: rgba(255, 255, 255, .75);
  box-shadow: 8px 8px 18px var(--fx-neu-dark), -8px -8px 18px var(--fx-neu-light);
  transition: box-shadow .35s ease;
}
@supports (color: color-mix(in srgb, red 50%, blue)) {
  .fx-neumorphism {
    --fx-neu-dark: color-mix(in srgb, var(--fx-neu-bg) 78%, #000);
    --fx-neu-light: color-mix(in srgb, var(--fx-neu-bg) 70%, #fff);
  }
}
.fx-neumorphism:hover, .fx-neumorphism:focus-visible, .fx-neumorphism:active { box-shadow: inset 6px 6px 12px var(--fx-neu-dark), inset -6px -6px 12px var(--fx-neu-light); }
@media (prefers-reduced-motion: reduce) {
  .fx-neumorphism, .fx-neumorphism::before, .fx-neumorphism::after, .fx-neumorphism *, .fx-neumorphism *::before, .fx-neumorphism *::after { animation: none !important; transition: none !important; }
}
/* Fire Text - Flickering flame-coloured shadows rise from the letters of a heading. */
.fx-fire-text {
  color: #fff4d6;
  text-shadow: 0 0 4px #fff3c4, 0 -4px 6px #ffd23f, 0 -10px 14px #ff9f1c, 0 -18px 24px #ff5a1f, 0 -26px 36px #c81d25;
  animation: fx-fire-text-burn 1.2s ease-in-out infinite alternate;
}
@keyframes fx-fire-text-burn {
  to { text-shadow: 0 0 4px #fff3c4, 2px -6px 8px #ffd23f, -2px -12px 16px #ff9f1c, 2px -20px 26px #ff5a1f, -2px -30px 40px #c81d25; }
}
@media (prefers-reduced-motion: reduce) {
  .fx-fire-text, .fx-fire-text::before, .fx-fire-text::after, .fx-fire-text *, .fx-fire-text *::before, .fx-fire-text *::after { animation: none !important; transition: none !important; }
}

/* ===== Advanced Animated Backgrounds ===== */
/* Gradient - A slow, breathing wash of the primary, secondary and accent colours flowing behind the section. */
.fx-bg-gradient-flow { position: relative; isolation: isolate; overflow: hidden; }
.fx-bg-gradient-flow::before, .fx-bg-gradient-flow::after { content: ""; position: absolute; pointer-events: none; z-index: -1; }
.fx-bg-gradient-flow::before {
  inset: 0;
  background: linear-gradient(120deg, rgba(var(--wt-primary-rgb), .30), rgba(var(--wt-secondary-rgb), .22), rgba(var(--wt-accent-rgb), .28), rgba(var(--wt-primary-rgb), .30));
  background-size: 300% 300%;
  animation: fx-bg-gradient-flow-flow 16s ease infinite;
}
@keyframes fx-bg-gradient-flow-flow { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }
@media (prefers-reduced-motion: reduce) {
  .fx-bg-gradient-flow, .fx-bg-gradient-flow::before, .fx-bg-gradient-flow::after, .fx-bg-gradient-flow *, .fx-bg-gradient-flow *::before, .fx-bg-gradient-flow *::after { animation: none !important; transition: none !important; }
}
/* Parallax - Three layers of dots and soft orbs drift at different speeds, giving the section a sense of depth. */
.fx-bg-parallax { position: relative; isolation: isolate; overflow: hidden; }
.fx-bg-parallax::before, .fx-bg-parallax::after { content: ""; position: absolute; pointer-events: none; z-index: -1; }
.fx-bg-parallax::before {
  inset: 0;
  background-image:
    radial-gradient(circle, rgba(var(--wt-primary-rgb), .35) 0 1px, transparent 1.5px),
    radial-gradient(circle, rgba(var(--wt-secondary-rgb), .4) 0 2px, transparent 2.5px);
  background-size: 24px 24px, 70px 70px;
  animation: fx-bg-parallax-layers 20s linear infinite;
}
.fx-bg-parallax::after {
  inset: 0;
  background-image:
    radial-gradient(circle, rgba(var(--wt-accent-rgb), .22) 0 18px, transparent 32px),
    radial-gradient(circle, rgba(var(--wt-primary-rgb), .18) 0 26px, transparent 44px);
  background-size: 220px 220px, 340px 340px;
  background-position: 30px 60px, 180px 10px;
  animation: fx-bg-parallax-near 20s linear infinite;
}
@keyframes fx-bg-parallax-layers { to { background-position: -24px 0, -140px 0; } }
@keyframes fx-bg-parallax-near { to { background-position: -410px 60px, -500px 10px; } }
@media (prefers-reduced-motion: reduce) {
  .fx-bg-parallax, .fx-bg-parallax::before, .fx-bg-parallax::after, .fx-bg-parallax *, .fx-bg-parallax *::before, .fx-bg-parallax *::after { animation: none !important; transition: none !important; }
}
