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

/* ===== Modern CSS Animations ===== */
/* Typewriter - Types a single line of monospace text letter by letter with a blinking caret; set --fx-ch to the character count. */
.fx-typewriter {
  display: inline-block; max-width: 100%; overflow: hidden; white-space: nowrap; vertical-align: bottom;
  font-family: var(--ui-font-monospace, monospace);
  width: calc(var(--fx-ch, 20) * 1ch + .15em);
  border-right: .12em solid var(--wt-primary);
  animation: fx-typewriter-type 4.5s steps(var(--fx-ch, 20)) infinite, fx-typewriter-caret .8s step-end infinite;
}
@keyframes fx-typewriter-type { 0% { width: 0; } 65%, 100% { width: calc(var(--fx-ch, 20) * 1ch + .15em); } }
@keyframes fx-typewriter-caret { 50% { border-color: transparent; } }
@media (prefers-reduced-motion: reduce) {
  .fx-typewriter, .fx-typewriter::before, .fx-typewriter::after, .fx-typewriter *, .fx-typewriter *::before, .fx-typewriter *::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 ===== */
/* Circle Reveal - Shows a circular window of an image that opens to the full picture on hover or keyboard focus. */
.fx-circle-reveal { -webkit-clip-path: circle(36% at 50% 50%); clip-path: circle(36% at 50% 50%); transition: clip-path .7s cubic-bezier(.6, 0, .2, 1); }
.fx-circle-reveal:hover, .fx-circle-reveal:focus-visible, :focus-visible > .fx-circle-reveal { -webkit-clip-path: circle(75% at 50% 50%); clip-path: circle(75% at 50% 50%); }
@media (prefers-reduced-motion: reduce) {
  .fx-circle-reveal, .fx-circle-reveal::before, .fx-circle-reveal::after, .fx-circle-reveal *, .fx-circle-reveal *::before, .fx-circle-reveal *::after { animation: none !important; transition: none !important; }
}
/* Star Rotate - A five-point star cut-out that turns slowly and speeds up on hover; use it for ratings or promo badges. */
.fx-star-rotate { -webkit-clip-path: polygon(50% 0, 62.3% 33%, 97.6% 34.5%, 70% 56.5%, 79.4% 90.5%, 50% 71%, 20.6% 90.5%, 30% 56.5%, 2.4% 34.5%, 37.7% 33%); clip-path: polygon(50% 0, 62.3% 33%, 97.6% 34.5%, 70% 56.5%, 79.4% 90.5%, 50% 71%, 20.6% 90.5%, 30% 56.5%, 2.4% 34.5%, 37.7% 33%); animation: fx-star-rotate-turn 14s linear infinite; }
.fx-star-rotate:hover { animation-duration: 3s; }
@keyframes fx-star-rotate-turn { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .fx-star-rotate, .fx-star-rotate::before, .fx-star-rotate::after, .fx-star-rotate *, .fx-star-rotate *::before, .fx-star-rotate *::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; }
}
/* Multiple Filters - Stacks contrast, saturation and a drop shadow, then swaps to a warmer combination on hover. */
.fx-multiple-filters { filter: contrast(1.15) saturate(1.3) drop-shadow(0 10px 14px rgba(var(--wt-primary-rgb), .35)); transition: filter .5s ease; }
.fx-multiple-filters:hover { filter: contrast(1.25) saturate(1.6) sepia(.25) drop-shadow(0 16px 22px rgba(var(--wt-accent-rgb), .45)); }
@media (prefers-reduced-motion: reduce) {
  .fx-multiple-filters, .fx-multiple-filters::before, .fx-multiple-filters::after, .fx-multiple-filters *, .fx-multiple-filters *::before, .fx-multiple-filters *::after { animation: none !important; transition: none !important; }
}
/* Saturation Boost - Desaturated at rest, vivid on hover - draws attention to the product the visitor is looking at. */
.fx-saturation-boost { filter: saturate(.6); transition: filter .4s ease, transform .4s ease; }
.fx-saturation-boost:hover, .fx-saturation-boost:focus-visible { filter: saturate(1.8); transform: scale(1.03); }
@media (prefers-reduced-motion: reduce) {
  .fx-saturation-boost, .fx-saturation-boost::before, .fx-saturation-boost::after, .fx-saturation-boost *, .fx-saturation-boost *::before, .fx-saturation-boost *::after { animation: none !important; transition: none !important; }
}

/* ===== Modern CSS Transform Effects ===== */
/* Skew Parallax - On hover the card skews one way and its image drifts the other, creating a quick sense of depth. */
.fx-skew-parallax { overflow: hidden; transition: transform .5s cubic-bezier(.2, .8, .2, 1); }
.fx-skew-parallax img { transform: scale(1.12); transition: transform .6s cubic-bezier(.2, .8, .2, 1); }
.fx-skew-parallax:hover { transform: skewY(-2deg) translateY(-3px); }
.fx-skew-parallax:hover img { transform: scale(1.18) skewY(2deg) translateY(-6px); }
@media (prefers-reduced-motion: reduce) {
  .fx-skew-parallax, .fx-skew-parallax::before, .fx-skew-parallax::after, .fx-skew-parallax *, .fx-skew-parallax *::before, .fx-skew-parallax *::after { animation: none !important; transition: none !important; }
}
/* Scale & Rotate - A springy scale-and-twist on hover for icons, avatars, logos and small buttons. */
.fx-scale-rotate { transition: transform .45s cubic-bezier(.34, 1.8, .64, 1); }
.fx-scale-rotate:hover, .fx-scale-rotate:focus-visible { transform: scale(1.15) rotate(-8deg); }
@media (prefers-reduced-motion: reduce) {
  .fx-scale-rotate, .fx-scale-rotate::before, .fx-scale-rotate::after, .fx-scale-rotate *, .fx-scale-rotate *::before, .fx-scale-rotate *::after { animation: none !important; transition: none !important; }
}
/* Transform Chain - Chains translate, rotate and scale as separate properties with staggered timing for a lively hover. */
.fx-transform-chain { transition: translate .3s ease, rotate .5s cubic-bezier(.34, 1.56, .64, 1) .08s, scale .4s ease .16s; }
.fx-transform-chain:hover, .fx-transform-chain:focus-visible { translate: 0 -8px; rotate: -3deg; scale: 1.06; }
@supports not (translate: 0) {
  .fx-transform-chain { transition: transform .4s cubic-bezier(.34, 1.56, .64, 1); }
  .fx-transform-chain:hover, .fx-transform-chain:focus-visible { transform: translateY(-8px) rotate(-3deg) scale(1.06); }
}
@media (prefers-reduced-motion: reduce) {
  .fx-transform-chain, .fx-transform-chain::before, .fx-transform-chain::after, .fx-transform-chain *, .fx-transform-chain *::before, .fx-transform-chain *::after { animation: none !important; transition: none !important; }
}

/* ===== Modern CSS Transitions ===== */
/* Neon Fill Button - An outline button that fills with colour from the left and glows; works on any .btn or link. */
.fx-neon-fill-button, .btn.fx-neon-fill-button {
  position: relative; isolation: isolate; overflow: hidden; z-index: 0;
  color: var(--wt-primary-ink); background: transparent; border: 2px solid var(--wt-primary);
  transition: color .35s ease, box-shadow .35s ease;
}
.fx-neon-fill-button::before {
  content: ""; position: absolute; inset: 0; z-index: -1; background: var(--wt-primary);
  transform: scaleX(0); transform-origin: left center; transition: transform .4s cubic-bezier(.7, 0, .3, 1);
}
.fx-neon-fill-button:hover, .fx-neon-fill-button:focus-visible, .btn.fx-neon-fill-button:hover, .btn.fx-neon-fill-button:focus-visible {
  color: var(--wt-on-primary, #fff); border-color: var(--wt-primary);
  box-shadow: 0 0 12px rgba(var(--wt-primary-rgb), .6), 0 0 32px rgba(var(--wt-primary-rgb), .35);
}
.fx-neon-fill-button:hover::before, .fx-neon-fill-button:focus-visible::before { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
  .fx-neon-fill-button, .fx-neon-fill-button::before, .fx-neon-fill-button::after, .fx-neon-fill-button *, .fx-neon-fill-button *::before, .fx-neon-fill-button *::after { animation: none !important; transition: none !important; }
}
/* 3D Flip Card - Flips a card over in 3D on hover or focus to show its back; use the -inner, -front and -back child classes. */
.fx-3d-flip-card { perspective: 1000px; }
.fx-3d-flip-card .fx-3d-flip-card-inner {
  position: relative; width: 100%; height: 100%; transform-style: preserve-3d;
  transition: transform .7s cubic-bezier(.4, .2, .2, 1);
}
.fx-3d-flip-card:hover .fx-3d-flip-card-inner, .fx-3d-flip-card:focus-within .fx-3d-flip-card-inner { transform: rotateY(180deg); }
.fx-3d-flip-card .fx-3d-flip-card-front, .fx-3d-flip-card .fx-3d-flip-card-back {
  position: absolute; inset: 0; -webkit-backface-visibility: hidden; backface-visibility: hidden;
  border-radius: var(--wt-radius-lg, 1rem); overflow: hidden;
}
.fx-3d-flip-card .fx-3d-flip-card-back {
  transform: rotateY(180deg); display: flex; flex-direction: column; justify-content: center; padding: 1rem;
  color: var(--wt-on-primary, #fff); background: linear-gradient(135deg, var(--wt-primary), var(--wt-secondary));
}
@media (prefers-reduced-motion: reduce) {
  .fx-3d-flip-card, .fx-3d-flip-card::before, .fx-3d-flip-card::after, .fx-3d-flip-card *, .fx-3d-flip-card *::before, .fx-3d-flip-card *::after { animation: none !important; transition: none !important; }
}

/* ===== Modern CSS Gradient Effects ===== */
/* Animated Rainbow - A full-spectrum gradient that flows endlessly across banners, buttons and progress bars. */
.fx-animated-rainbow {
  color: #fff;
  background: linear-gradient(90deg, #ff3d7f, #ff9f1c, #ffd23f, #3bce73, #2ec4ff, #7b5cff, #ff3d7f);
  background-size: 300% 100%;
  animation: fx-animated-rainbow-flow 8s linear infinite;
}
@keyframes fx-animated-rainbow-flow { to { background-position: -150% 0; } }
@media (prefers-reduced-motion: reduce) {
  .fx-animated-rainbow, .fx-animated-rainbow::before, .fx-animated-rainbow::after, .fx-animated-rainbow *, .fx-animated-rainbow *::before, .fx-animated-rainbow *::after { animation: none !important; transition: none !important; }
}
/* Text Mask - Large text that works as a window onto a moving gradient - or onto an image set with an inline background-image. */
.fx-text-mask {
  color: var(--wt-primary-ink);
  background-image: var(--fx-mask-img, linear-gradient(135deg, var(--wt-primary) 0%, var(--wt-accent) 30%, var(--wt-secondary) 60%, var(--wt-primary) 100%));
  background-size: cover; background-position: 0% 50%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: fx-text-mask-pan 10s ease-in-out infinite alternate;
}
.fx-text-mask:not([style*="--fx-mask-img"]) { background-size: 300% 300%; }
@keyframes fx-text-mask-pan { to { background-position: 100% 50%; } }
@media (prefers-reduced-motion: reduce) {
  .fx-text-mask, .fx-text-mask::before, .fx-text-mask::after, .fx-text-mask *, .fx-text-mask *::before, .fx-text-mask *::after { animation: none !important; transition: none !important; }
}

/* ===== Modern Shadow Effects ===== */
/* 3D Text Shadow - Stacks hard shadows under a heading so the letters look extruded, with a soft ambient shadow below. */
.fx-3d-text-shadow {
  color: var(--wt-primary-ink);
  --fx-depth: rgba(0, 0, 0, .35);
  text-shadow: 0 1px 0 var(--fx-depth), 0 2px 0 var(--fx-depth), 0 3px 0 var(--fx-depth), 0 4px 0 var(--fx-depth), 0 5px 0 var(--fx-depth), 0 6px 0 var(--fx-depth),
    0 8px 6px rgba(0, 0, 0, .2), 0 14px 18px rgba(0, 0, 0, .18);
}
@supports (color: color-mix(in srgb, red 50%, blue)) {
  .fx-3d-text-shadow { --fx-depth: color-mix(in srgb, var(--wt-primary) 60%, #000); }
}
@media (prefers-reduced-motion: reduce) {
  .fx-3d-text-shadow, .fx-3d-text-shadow::before, .fx-3d-text-shadow::after, .fx-3d-text-shadow *, .fx-3d-text-shadow *::before, .fx-3d-text-shadow *::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; }
}
/* Retro Style - Hard offset shadows in two theme colours for a retro poster look; on .card or .btn it becomes a bold offset box. */
.fx-retro-style { text-shadow: 3px 3px 0 var(--wt-accent), 6px 6px 0 var(--wt-secondary); }
.fx-retro-style.card, .fx-retro-style.btn {
  text-shadow: none; border: 2px solid var(--wt-text, #212529);
  box-shadow: 6px 6px 0 var(--wt-text, #212529);
  transition: transform .2s ease, box-shadow .2s ease;
}
.fx-retro-style.card:hover, .fx-retro-style.btn:hover, .fx-retro-style.btn:focus-visible { transform: translate(-2px, -2px); box-shadow: 8px 8px 0 var(--wt-text, #212529); }
.fx-retro-style.btn:active { transform: translate(4px, 4px); box-shadow: 2px 2px 0 var(--wt-text, #212529); }
@media (prefers-reduced-motion: reduce) {
  .fx-retro-style, .fx-retro-style::before, .fx-retro-style::after, .fx-retro-style *, .fx-retro-style *::before, .fx-retro-style *::after { animation: none !important; transition: none !important; }
}

/* ===== Advanced Animated Backgrounds ===== */
/* Scrolling - A fine blueprint grid that scrolls diagonally forever and fades out towards the edges. */
.fx-bg-scrolling { position: relative; isolation: isolate; overflow: hidden; }
.fx-bg-scrolling::before, .fx-bg-scrolling::after { content: ""; position: absolute; pointer-events: none; z-index: -1; }
.fx-bg-scrolling::before {
  inset: 0;
  background-image:
    linear-gradient(rgba(var(--wt-primary-rgb), .16) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--wt-primary-rgb), .16) 1px, transparent 1px);
  background-size: 36px 36px;
  -webkit-mask-image: radial-gradient(ellipse at center, #000 30%, transparent 78%); mask-image: radial-gradient(ellipse at center, #000 30%, transparent 78%);
  animation: fx-bg-scrolling-scroll 6s linear infinite;
}
@keyframes fx-bg-scrolling-scroll { to { background-position: 36px 36px; } }
@media (prefers-reduced-motion: reduce) {
  .fx-bg-scrolling, .fx-bg-scrolling::before, .fx-bg-scrolling::after, .fx-bg-scrolling *, .fx-bg-scrolling *::before, .fx-bg-scrolling *::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; }
}
