/**
 * WellMade Axis Effects - New Hover effects stylesheet (no-build).
 *
 * Nine hover effects in three families, each scoped under a .wma-nh--<effect>
 * class so nothing collides with theme or GenerateBlocks styles:
 *   Border   glow-sweep / glow-edge (arc and follow-cursor), gradient
 *   Surface  shine-* (4 styles), fill-* (5 styles), ripple, spotlight, glare
 *   Electric electric-border / electric-sparks
 * Plus the universal modifiers: .wma-nh--tilt (3D surface tilt on any effect),
 * .wma-nh--ripple-liquid (liquid surface on ripple) and .wma-nh--parallax
 * (content depth, rides on tilt).
 *
 * The pointer position and per-effect angles arrive as CSS custom properties
 * the engine writes on the element (--wma-nh-active / glowbase and
 * the tilt vars). Colors come from --wma-nh-color / --wma-nh-color2, set from
 * the block's chosen palette colors by the engine, with the indigo / sky
 * defaults below when none are set.
 *
 * @package WellMade_Effects
 */

/* Typed props so gradients/angles can animate smoothly (Baseline: Chrome85+/Safari16.4+/FF128+) */
@property --wma-nh-angle { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
@property --wma-nh-active { syntax: "<number>"; inherits: true; initial-value: 0; }
@property --wma-nh-spin  { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
@property --wma-nh-glowbase { syntax: "<angle>"; inherits: true; initial-value: 0deg; }
/* Pointer position and per-layer opacity for the two pointer-driven surface
   effects (Spotlight, Glare). They inherit so the pseudo-elements can read
   them, and they are registered so the browser interpolates them smoothly
   instead of snapping between values. */
@property --wma-nh-mx { syntax: "<percentage>"; inherits: true; initial-value: 50%; }
@property --wma-nh-my { syntax: "<percentage>"; inherits: true; initial-value: 50%; }
@property --wma-nh-spot-o { syntax: "<number>"; inherits: true; initial-value: 0; }
@property --wma-nh-glare-o { syntax: "<number>"; inherits: true; initial-value: 0; }

/* CSS-first activation: :hover sets active=1 so effects light up even if JS pointer
   binding fails. JS only refines cursor position/angle on top of this. A card on
   the scroll trigger answers to .wma-nh--on, written by the engine's viewport
   observer, and its :hover is inert: one trigger per block, predictable. */
[data-wma-nh]:not([data-wma-nh-trigger="scroll"]):hover,
[data-wma-nh].wma-nh--on { --wma-nh-active: 1 !important; }

[data-wma-nh] {
  --wma-nh-active: 0;
  --wma-nh-color: rgb(99,102,241);   /* indigo default, palette-driven in product */
  --wma-nh-color2: rgb(56,189,248);  /* secondary accent for electric */
  --wma-nh-speed: var(--wma-motion-base, 200ms);
  --wma-nh-travel: var(--wma-motion-travel, 550ms);
}

/* -------------------------------------------------------------------------
   1) BORDER GLOW  (the cursor.com / Aceternity idiom, done right)
   A bright conic-gradient ARC (~110deg of light, rest transparent) sits on the
   border ring via mask cutout. The arc rotates slowly and continuously, and its
   base angle is nudged toward the cursor so the light gathers on the side nearest
   the pointer. Smooth rotation = premium; no jitter. Ref: Aceternity Glowing
   Effect (Cursor Enterprise page), css-tip Temani Afif rotating-arc border.
   ------------------------------------------------------------------------- */
.wma-nh--glow-sweep,
.wma-nh--glow-edge { position: relative; isolation: isolate; transition: border-color var(--wma-nh-speed) var(--wma-ease-out, ease-out); }
/* The effect IS the border, so the block's own colour steps aside while the arc
   is lit rather than sitting behind it as a second frame. */
.wma-nh--glow-sweep:not([data-wma-nh-trigger="scroll"]):hover,
.wma-nh--glow-sweep.wma-nh--on,
.wma-nh--glow-sweep:focus-visible,
.wma-nh--glow-edge:hover,
.wma-nh--glow-edge:focus-visible { border-color: transparent !important; }

/* the light arc, shown only on the rim */
.wma-nh--glow-sweep::before,
.wma-nh--glow-edge::before {
  content: ""; position: absolute; border-radius: inherit;
  /* Out onto the border ring, not inside it: an absolutely positioned child is
     laid out against the padding box, so inset:0 would start the arc inside the
     block's own border and leave the border itself unlit. */
  inset: calc(-1 * var(--wma-nh-bd-w, 2px));
  /* rim thickness: the block's own border width, read by the engine */
  padding: var(--wma-nh-bd-w, 2px);
  pointer-events: none; z-index: 2;
  opacity: var(--wma-nh-active);
  transition: opacity var(--wma-nh-speed) var(--wma-ease-out, ease-out);
  /* --wma-nh-glowbase is set by JS toward the cursor; --wma-nh-spin rotates */
  background: conic-gradient(
    from calc(var(--wma-nh-glowbase, 0deg) + var(--wma-nh-spin, 0deg)),
    transparent 0deg,
    color-mix(in srgb, var(--wma-nh-color) 40%, transparent) 20deg,
    var(--wma-nh-color) 55deg,
    #fff 90deg,
    var(--wma-nh-color2) 125deg,
    color-mix(in srgb, var(--wma-nh-color2) 40%, transparent) 160deg,
    transparent 190deg,
    transparent 360deg);
  -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, linear-gradient(#000 0 0);
          mask-composite: exclude;
  filter: drop-shadow(0 0 5px var(--wma-nh-color)) drop-shadow(0 0 9px var(--wma-nh-color2));
}
/* Sweep: the arc travels round the rim on its own, and the pointer only sets
   where it starts from. */
.wma-nh--glow-sweep::before { animation: wma-nh-glowspin 5s linear infinite; }
@keyframes wma-nh-glowspin { from { --wma-nh-spin: 0deg; } to { --wma-nh-spin: 360deg; } }

/* Edge-follow: the light does not travel. It is drawn where the pointer is, and
   it answers to how close the pointer is to the rim: full at the edge, gone at
   the centre.
   The shape is the one Linear, Cursor's enterprise page and the Aceternity
   component built from it all use: the whole rim carries the colour, and a
   RADIAL mask centred on the pointer's own position reveals only the part near
   it. A conic cone swung from the centre knows the direction of the pointer but
   not how far along a side it sits, so it spills across a whole quadrant however
   narrow it is; a radial mask lights what is near the pointer, which is why a
   corner picks up half of each side meeting there on its own.
   Fading toward the centre is the component's own default (its inactiveZone is
   0.7, not the 0.01 its demo passes): the glow belongs to the edge, so walking
   inward should put it out. */
.wma-nh--glow-edge::before {
  animation: none;
  opacity: calc(var(--wma-nh-active) * var(--wma-nh-edge, 0));
  transition: opacity var(--wma-nh-speed) var(--wma-ease-out, ease-out);
  /* whole rim lit, in the block's own colours */
  background: linear-gradient(
    var(--wma-nh-glowbase, 135deg),
    var(--wma-nh-color), var(--wma-nh-color2));
  /* Two masks that have to intersect: the radial pool around the pointer, and
     the ring cutout the sweep also uses. */
  -webkit-mask:
    radial-gradient(var(--wma-nh-reach, 120%) var(--wma-nh-reach, 120%) at var(--wma-nh-x, 50%) var(--wma-nh-y, 50%),
      #000 10%, rgba(0,0,0,.35) 45%, transparent 70%),
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: source-in, xor;
          mask:
    radial-gradient(var(--wma-nh-reach, 120%) var(--wma-nh-reach, 120%) at var(--wma-nh-x, 50%) var(--wma-nh-y, 50%),
      #000 10%, rgba(0,0,0,.35) 45%, transparent 70%),
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
          mask-composite: intersect, exclude;
}

/* soft outer bloom that follows the same arc, blurred, for depth */
.wma-nh--glow-sweep::after,
.wma-nh--glow-edge::after {
  content: ""; position: absolute; inset: calc(-1 * var(--wma-nh-bd-w, 2px)); border-radius: inherit;
  pointer-events: none; z-index: -1;
  opacity: calc(var(--wma-nh-active) * .6);
  transition: opacity var(--wma-nh-speed) var(--wma-ease-out, ease-out);
  background: conic-gradient(
    from calc(var(--wma-nh-glowbase, 0deg) + var(--wma-nh-spin, 0deg)),
    transparent 0deg, var(--wma-nh-color) 70deg, var(--wma-nh-color2) 120deg, transparent 180deg, transparent 360deg);
  filter: blur(13px);
}
.wma-nh--glow-sweep::after { animation: wma-nh-glowspin 5s linear infinite; }
/* Edge-follow lights the border and nothing else, so its bloom is cut back to
   the rim. The sweep's bloom is a full blurred disc sitting behind the block,
   which reads as depth while the arc travels; here it would just tint the middle
   of the box (measured: it lifted the interior from the bare 18 to 46, brighter
   than the border it was meant to be lighting). Blurring is done with a drop
   shadow rather than filter:blur, because a mask clips what blur has already
   spread, which would leave a hard edge exactly where the glow should fade. */
.wma-nh--glow-edge::after {
  animation: none;
  opacity: calc(var(--wma-nh-active) * .6 * var(--wma-nh-edge, 0));
  padding: var(--wma-nh-bd-w, 2px);
  /* Same shape as the arc. Left on a different mask it lit sides the pointer was
     nowhere near and dragged the light off its anchor (measured once already:
     with the pointer top-right it put 45 on the bottom edge while the arc had it
     at 15). */
  background: linear-gradient(
    var(--wma-nh-glowbase, 135deg),
    var(--wma-nh-color), var(--wma-nh-color2));
  -webkit-mask:
    radial-gradient(var(--wma-nh-reach, 120%) var(--wma-nh-reach, 120%) at var(--wma-nh-x, 50%) var(--wma-nh-y, 50%),
      #000 10%, rgba(0,0,0,.35) 45%, transparent 70%),
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: source-in, xor;
          mask:
    radial-gradient(var(--wma-nh-reach, 120%) var(--wma-nh-reach, 120%) at var(--wma-nh-x, 50%) var(--wma-nh-y, 50%),
      #000 10%, rgba(0,0,0,.35) 45%, transparent 70%),
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
          mask-composite: intersect, exclude;
  /* Blur with a drop shadow, not filter:blur: a mask clips what blur has already
     spread, leaving a hard edge exactly where the glow should be fading out. */
  filter: drop-shadow(0 0 6px var(--wma-nh-color)) drop-shadow(0 0 12px var(--wma-nh-color2));
}
/* @supports fallback: static box-shadow rim if mask-composite missing */
@supports not ((mask-composite: exclude) or (-webkit-mask-composite: xor)) {
  [class*="wma-nh--glow-"]::before {
    padding: 0; background: none; animation: none;
    box-shadow: inset 0 0 0 2px var(--wma-nh-color), 0 0 14px var(--wma-nh-color);
  }
}

/* -------------------------------------------------------------------------
   2) RIPPLE  (concentric rings spawned at cursor point on enter)
   pure CSS rings, scale+opacity, JS only stamps position + triggers.
   ------------------------------------------------------------------------- */
/* The ripple rings are clipped to the block so they never spill outside a small
   element like a button. A ring layer holds them, matching the block's own
   rounded corners so the clip follows the shape. */
.wma-nh--ripple { position: relative; }
.wma-nh--ripple > .wma-nh-ripple-layer {
  position: absolute; inset: 0; border-radius: inherit; overflow: hidden;
  pointer-events: none; z-index: 2;
}
/* liquid surface: the block content warps gently like water while hovered. The
   feDisplacementMap scale is driven by JS (0 at rest, up while active) so the
   surface only ripples when the pointer is inside. Toggled by .wma-nh--ripple-liquid. */
.wma-nh--ripple-liquid .wma-nh-liquid-inner {
  filter: url(#wma-nh-liquid);
  transition: filter var(--wma-motion-gentle, 300ms) var(--wma-ease-out, ease-out);
}
/* When the ripple+liquid effect is on an image, the engine has wrapped the img
   and then moved it into the liquid inner. Keep both boxes shrink-wrapped to the
   image so the displacement warps the picture itself, not an empty box. */
.wma-nh-wrap .wma-nh-liquid-inner { display: block; line-height: 0; border-radius: inherit; }
.wma-nh-wrap .wma-nh-liquid-inner > img { display: block; max-width: 100%; height: auto; border-radius: inherit; }
/* optional real 3D surface tilt: the block tilts smoothly and continuously in
   perspective toward the cursor while it moves across the surface, like a soft
   liquid sheet leaning under your finger. Driven by --tiltx/--tilty, eased by a
   transition so movement is fluid (never restarts, never jerks). Returns flat on
   leave. UNIVERSAL modifier: add .wma-nh--tilt to ANY effect block. The value is
   marked important so it wins over a transform the block or theme already sets
   (a GB Button hover transform, for example), which would otherwise cancel it. */
.wma-nh--tilt {
  transform: perspective(900px) rotateX(var(--tiltx, 0deg)) rotateY(var(--tilty, 0deg)) !important;
  transition: transform var(--wma-nh-tilt-speed, var(--wma-nh-travel, 550ms)) var(--wma-ease-soft, cubic-bezier(0.22, 0.61, 0.36, 1));
  transform-style: preserve-3d;
  will-change: transform;
}
.wma-nh--ripple .wma-nh-ring {
  position: absolute; left: var(--rx, 50%); top: var(--ry, 50%);
  width: 0; height: 0; border-radius: 50%;
  pointer-events: none;
  /* thin ring that STAYS thin as it grows (we animate width/height, not scale,
     so the 1.5px border never thickens). A real wave is a thin expanding line.
     This is a wave, not the block's rim, so it keeps its own weight and does
     not follow the block's border width. */
  border: 1.5px solid var(--wma-nh-color);
  transform: translate(-50%, -50%);
  opacity: 0;
  /* Slow, decelerating expansion reads as water, not a click ripple. Awwwards
     water ripples run well over two seconds per ring with a soft ease-out. */
  animation: wma-nh-ripple 2400ms cubic-bezier(0, 0, 0.2, 1) forwards;
}
/* three staggered waves like a real drop, each thinner and fainter as it expands.
   A wider stagger gives the calm, spaced rhythm of drops on a pond. */
.wma-nh--ripple .wma-nh-ring.r2 { animation-delay: 320ms; border-color: var(--wma-nh-color2); }
.wma-nh--ripple .wma-nh-ring.r3 { animation-delay: 640ms; border-color: var(--wma-nh-color); }
@keyframes wma-nh-ripple {
  0%   { width: 0;     height: 0;     opacity: .5;  border-width: 1.5px; }
  30%  {               opacity: .38; }
  100% { width: 440px; height: 440px; opacity: 0;   border-width: .5px; }
}


/* -------------------------------------------------------------------------
   GRADIENT BORDER  (a true multi-color gradient border, native-aware)
   Native-First: the effect respects the block's own border and radius. The
   engine reads the block's existing border width, so the gradient becomes that
   border: same width, same place, one border rather than two. The fill is
   painted with background-clip so it lives exactly in the border ring and the
   center stays the block's own background: no inner glow, no z-index trick,
   correct rounded corners inherited from the block.
   ------------------------------------------------------------------------- */
.wma-nh--gradient {
  position: relative;
  transition: border-color var(--wma-nh-speed) var(--wma-ease-out, ease-out);
}
/* The block's own border colour steps aside while the gradient is lit, the same
   way the other border effects behave. At rest the block keeps the border it
   was given: an effect that erased it even when idle would be changing the
   design rather than adding to it. */
.wma-nh--gradient:not([data-wma-nh-trigger="scroll"]):hover,
.wma-nh--gradient.wma-nh--on,
.wma-nh--gradient:focus-visible { border-color: transparent !important; }
/* The gradient lives on a ::before, not on the block itself, so an inline
   background on the block (some GB setups add one) cannot reset our
   background-size and stop the drift. The ::before sits in the border ring via
   background-clip and drifts continuously. */
.wma-nh--gradient::before {
  content: ""; position: absolute; pointer-events: none;
  inset: calc(-1 * var(--wma-nh-bd-w, 2px));
  border: var(--wma-nh-bd-w, 2px) solid transparent;
  border-radius: inherit;
  background-image: linear-gradient( var(--wma-nh-gradient-angle, 60deg),
    hsl(224, 85%, 66%), hsl(269, 85%, 66%), hsl(314, 85%, 66%),
    hsl(359, 85%, 66%), hsl(44, 85%, 66%), hsl(89, 85%, 66%),
    hsl(134, 85%, 66%), hsl(179, 85%, 66%) );
  background-origin: border-box;
  background-clip: border-box;
  -webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
  mask-composite: exclude;
  background-size: 300% 300%;
  background-position: 0 50%;
  /* Hidden at rest; the border reveals and the gradient starts drifting on
     hover, since this is a hover effect. */
  opacity: 0;
  transition: opacity var(--wma-nh-speed, var(--wma-motion-base, 200ms)) var(--wma-ease-out, ease-out);
}
.wma-nh--gradient:not([data-wma-nh-trigger="scroll"]):hover::before,
.wma-nh--gradient.wma-nh--on::before {
  opacity: 1;
  animation: wma-nh-gradient-move 4s ease infinite alternate;
}
/* Chosen colors switch the rainbow to the two picked colors (with an auto mid). */
.wma-nh--gradient.wma-nh--gradient-custom::before {
  background-image: linear-gradient( var(--wma-nh-gradient-angle, 60deg),
    var(--wma-nh-color),
    color-mix(in oklab, var(--wma-nh-color), var(--wma-nh-color2)),
    var(--wma-nh-color2) );
}
@keyframes wma-nh-gradient-move {
  0%   { background-position: 0 50%; }
  100% { background-position: 100% 50%; }
}
@media (prefers-reduced-motion: reduce) {
  .wma-nh--gradient::before { animation: none; }
}

/* -------------------------------------------------------------------------
   3a) ELECTRIC - BORDER ONLY (animated conic border, zero SVG, safe)
   ------------------------------------------------------------------------- */
/* electric border, BalintFerenczy technique: a real border line is run through a
   multi-layer feTurbulence + feDisplacementMap filter so the edge crackles like a
   live wire, plus blurred glow layers. Ref: codepen BalintFerenczy/KwdoyEN. */
.wma-nh--electric-border { position: relative; isolation: isolate; }
/* The effect IS the border, so the layers cover the border ring rather than
   sitting inside it. An absolutely positioned child is laid out against the
   padding box, so inset:0 would start it inside the block's own border and the
   two would read as two separate frames, one grey and one lit. Pulling the
   layers out by the border width puts them exactly over the ring, at exactly
   the width the block was given, which is what the reference does: one border,
   and the electricity is it. */
.wma-nh--electric-border .eb-layers {
  position: absolute; inset: calc(-1 * var(--wma-nh-bd-w, 2px)); border-radius: inherit; pointer-events: none;
  opacity: var(--wma-nh-active); transition: opacity var(--wma-nh-speed) var(--wma-ease-out, ease-out);
}
/* The block's own border colour steps aside while the effect is lit, so the
   ring shows the electricity instead of showing both. */
.wma-nh--electric-border {
  transition: border-color var(--wma-nh-speed) var(--wma-ease-out, ease-out);
}
.wma-nh--electric-border:not([data-wma-nh-trigger="scroll"]):hover,
.wma-nh--electric-border.wma-nh--on,
.wma-nh--electric-border:focus-visible {
  border-color: transparent !important;
}
/* steady lit border: always on under the crackle, so there is a real glowing edge
   and the electricity runs ON it (not instead of it). Ref: user image 3.
   Slightly under the block's own width so the crackling line reads as sitting on
   top of it rather than the two cancelling into one flat band. */
.wma-nh--electric-border .eb-steady {
  position: absolute; inset: 0; border-radius: inherit; box-sizing: border-box;
  border: max(1px, calc(var(--wma-nh-bd-w, 2px) * 0.75)) solid var(--wma-nh-color);
  box-shadow: 0 0 6px color-mix(in srgb, var(--wma-nh-color) 70%, transparent),
              inset 0 0 4px color-mix(in srgb, var(--wma-nh-color) 45%, transparent);
}
.wma-nh--electric-border .eb-line {
  position: absolute; inset: 0; border-radius: inherit; box-sizing: border-box;
  border: var(--wma-nh-bd-w, 2px) solid var(--wma-nh-color);
  filter: var(--wma-nh-eb-filter, url(#wma-nh-eb-filter));
}
.wma-nh--electric-border .eb-glow-1 {
  position: absolute; inset: 0; border-radius: inherit; box-sizing: border-box;
  border: var(--wma-nh-bd-w, 2px) solid color-mix(in srgb, var(--wma-nh-color2) 60%, transparent);
  filter: var(--wma-nh-eb-filter, url(#wma-nh-eb-filter)) blur(2px);
}
/* Outer bloom. The offset scales with the border: pinned at a flat 1px it gets
   swallowed as the border thickens (measured: the bloom reaches 7px past the
   edge on a 2px border, nothing at all on an 8px one, and sits inside the edge
   by 16px), so the thicker the border the more the glow has to start outside
   it. */
.wma-nh--electric-border .eb-glow-2 {
  position: absolute; inset: calc(-1 * var(--wma-nh-bd-w, 2px)); border-radius: inherit; box-sizing: border-box;
  border: var(--wma-nh-bd-w, 2px) solid var(--wma-nh-color2);
  filter: var(--wma-nh-eb-filter, url(#wma-nh-eb-filter)) blur(6px); opacity: .7;
}
.wma-nh--electric-border .eb-bg {
  position: absolute; inset: 0; border-radius: inherit; z-index: -1;
  transform: scale(1.02); filter: blur(16px); opacity: .24;
  background: linear-gradient(-30deg, var(--wma-nh-color2), transparent, var(--wma-nh-color));
}


/* -------------------------------------------------------------------------
   3b) ELECTRIC - SPARKS (canvas sparks off the pointer)
   The lively electric style: small sparks fly off the cursor and fade. Drawn on
   a canvas by the engine, which fades every particle with the hover amount, so
   the canvas itself carries no opacity gate.
   ------------------------------------------------------------------------- */
.wma-nh--electric-sparks { position: relative; }
.wma-nh--electric-sparks .wma-nh-sparks-canvas {
  position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; display: block; opacity: 1;
}

/* -------------------------------------------------------------------------
   4) SHINE  (a light sweeps across the face)
   Pure CSS, compositor-only: a gradient streak on a pseudo-element slides
   across on hover. The classic premium gloss, at home on buttons and cards.
   Four styles, one class each.
   ------------------------------------------------------------------------- */
/* The effect needs a positioning context and needs to clip the streak to the
   block. GeneratePress and GenerateBlocks write overflow-x and overflow-y
   separately (and a block's own global class may set either), so both axes are
   set here explicitly rather than through the shorthand, and marked important so
   a global class on the block cannot leave the streak unclipped. */
.wma-nh--shine-diagonal, .wma-nh--shine-colored,
.wma-nh--shine-gleam, .wma-nh--shine-double {
  position: relative !important;
  overflow-x: hidden !important;
  overflow-y: hidden !important;
  isolation: isolate;
}

/* white diagonal gloss */
.wma-nh--shine-diagonal::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: 0;
  width: 60%; min-width: 60px;
  pointer-events: none; z-index: 2;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.35), transparent);
  transform: skewX(-20deg) translateX(-180%);
  transition: transform var(--wma-nh-shine-speed, var(--wma-nh-travel, 550ms)) var(--wma-ease-standard, ease) !important;
}
.wma-nh--shine-diagonal:not([data-wma-nh-trigger="scroll"]):hover::before,
.wma-nh--shine-diagonal.wma-nh--on::before { transform: skewX(-20deg) translateX(320%); }

/* the same streak, tinted with the chosen color */
.wma-nh--shine-colored::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: 0;
  width: 55%; min-width: 55px;
  pointer-events: none; z-index: 2;
  background: linear-gradient(90deg, transparent,
    color-mix(in oklab, var(--wma-nh-color, #6366f1), transparent 35%), transparent);
  transform: skewX(-20deg) translateX(-180%);
  transition: transform var(--wma-nh-shine-speed, var(--wma-nh-travel, 550ms)) var(--wma-ease-standard, ease) !important;
}
.wma-nh--shine-colored:not([data-wma-nh-trigger="scroll"]):hover::before,
.wma-nh--shine-colored.wma-nh--on::before { transform: skewX(-20deg) translateX(340%); }

/* soft angled glass gleam */
.wma-nh--shine-gleam::after {
  content: ""; position: absolute; top: -50%; left: -50%; right: -50%; bottom: -50%;
  pointer-events: none; z-index: 2;
  background: linear-gradient(to bottom, transparent, rgba(255,255,255,.28) 50%, transparent);
  transform: rotateZ(60deg) translate(-6em, 9em);
}
.wma-nh--shine-gleam:not([data-wma-nh-trigger="scroll"]):hover::after,
.wma-nh--shine-gleam.wma-nh--on::after { animation: wma-nh-gleam var(--wma-nh-shine-speed, var(--wma-nh-travel, 550ms)) forwards; }
@keyframes wma-nh-gleam { 100% { transform: rotateZ(60deg) translate(2em, -11em); } }

/* two offset streaks, the second in the accent color */
.wma-nh--shine-double::before, .wma-nh--shine-double::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: 0;
  width: 40%; min-width: 40px;
  pointer-events: none; z-index: 2;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.28), transparent);
  transform: skewX(-20deg) translateX(-220%);
  transition: transform var(--wma-nh-shine-speed, var(--wma-nh-travel, 550ms)) var(--wma-ease-standard, ease) !important;
}
.wma-nh--shine-double::after {
  background: linear-gradient(90deg, transparent,
    color-mix(in oklab, var(--wma-nh-color2, #a855f7), transparent 40%), transparent);
  transition-delay: 90ms !important;
}
.wma-nh--shine-double:not([data-wma-nh-trigger="scroll"]):hover::before,
.wma-nh--shine-double:not([data-wma-nh-trigger="scroll"]):hover::after,
.wma-nh--shine-double.wma-nh--on::before,
.wma-nh--shine-double.wma-nh--on::after {
  transform: skewX(-20deg) translateX(360%);
}

/* -------------------------------------------------------------------------
   5) FILL  (a color wipes in, and the text inverts with it)
   The point of a fill is not the colour: it is that the block visibly changes
   state, the way a ghost button does. A wipe that slides under the label while
   the label stays the same colour just paints over the block and says nothing.
   So the fill carries a matching text colour: the label flips as the colour
   arrives, which is what makes the interaction readable (the Allbirds pattern:
   light button with dark text turns dark button with light text on hover).

   The fill sits at z-index -1 rather than lifting the children, because a
   GenerateBlocks button holds a bare text node, and a text node cannot be given
   a z-index. Negative z-index puts the fill behind the block's own text without
   needing any wrapper element to exist.
   ------------------------------------------------------------------------- */
.wma-nh--fill-left, .wma-nh--fill-radial, .wma-nh--fill-corner,
.wma-nh--fill-split, .wma-nh--fill-up {
  position: relative !important;
  overflow-x: hidden !important;
  overflow-y: hidden !important;
  /* isolation is deliberately not set here: it would trap the -1 pseudo behind
     the block's own background. The overflow already clips the fill. */
  transition: color var(--wma-nh-fill-speed, var(--wma-nh-travel, 550ms)) var(--wma-ease-standard, cubic-bezier(.4,0,.2,1)) !important;
}
/* The label flips to the paired colour as the fill lands. */
.wma-nh--fill-left:not([data-wma-nh-trigger="scroll"]):hover, .wma-nh--fill-radial:not([data-wma-nh-trigger="scroll"]):hover,
.wma-nh--fill-corner:not([data-wma-nh-trigger="scroll"]):hover, .wma-nh--fill-split:not([data-wma-nh-trigger="scroll"]):hover,
.wma-nh--fill-up:not([data-wma-nh-trigger="scroll"]):hover,
[class*="wma-nh--fill-"].wma-nh--on {
  color: var(--wma-nh-fill-text, #fff) !important;
}
/* Any child that carries its own colour (icons, spans) follows the label. */
.wma-nh--fill-left:not([data-wma-nh-trigger="scroll"]):hover *, .wma-nh--fill-radial:not([data-wma-nh-trigger="scroll"]):hover *,
.wma-nh--fill-corner:not([data-wma-nh-trigger="scroll"]):hover *, .wma-nh--fill-split:not([data-wma-nh-trigger="scroll"]):hover *,
.wma-nh--fill-up:not([data-wma-nh-trigger="scroll"]):hover *,
[class*="wma-nh--fill-"].wma-nh--on * { color: inherit !important; fill: currentColor; }

.wma-nh--fill-left::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  background: linear-gradient(90deg, var(--wma-nh-color, #6366f1), var(--wma-nh-color2, #a855f7));
  transform: scaleX(0); transform-origin: left center;
  transition: transform var(--wma-nh-fill-speed, var(--wma-nh-travel, 550ms)) var(--wma-ease-standard, cubic-bezier(.4,0,.2,1)) !important;
}
.wma-nh--fill-left:not([data-wma-nh-trigger="scroll"]):hover::before,
.wma-nh--fill-left.wma-nh--on::before { transform: scaleX(1); }

.wma-nh--fill-radial::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  background: radial-gradient(circle at center, var(--wma-nh-color, #6366f1), var(--wma-nh-color2, #a855f7));
  clip-path: circle(0% at 50% 50%);
  transition: clip-path var(--wma-nh-fill-speed, var(--wma-nh-travel, 550ms)) var(--wma-ease-standard, ease) !important;
}
.wma-nh--fill-radial:not([data-wma-nh-trigger="scroll"]):hover::before,
.wma-nh--fill-radial.wma-nh--on::before { clip-path: circle(75% at 50% 50%); }

.wma-nh--fill-corner::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  background: linear-gradient(135deg, var(--wma-nh-color, #6366f1), var(--wma-nh-color2, #a855f7));
  clip-path: polygon(0 0, 0 0, 0 0);
  transition: clip-path var(--wma-nh-fill-speed, var(--wma-nh-travel, 550ms)) var(--wma-ease-standard, ease) !important;
}
.wma-nh--fill-corner:not([data-wma-nh-trigger="scroll"]):hover::before,
.wma-nh--fill-corner.wma-nh--on::before { clip-path: polygon(0 0, 200% 0, 0 200%); }

.wma-nh--fill-split::before, .wma-nh--fill-split::after {
  content: ""; position: absolute; top: 0; height: 100%; width: 50%; z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, var(--wma-nh-color, #6366f1), var(--wma-nh-color2, #a855f7));
  transform: scaleX(0);
  transition: transform var(--wma-nh-fill-speed, var(--wma-nh-travel, 550ms)) var(--wma-ease-standard, cubic-bezier(.4,0,.2,1)) !important;
}
.wma-nh--fill-split::before { left: 0; transform-origin: left; }
.wma-nh--fill-split::after { right: 0; transform-origin: right; }
.wma-nh--fill-split:not([data-wma-nh-trigger="scroll"]):hover::before, .wma-nh--fill-split:not([data-wma-nh-trigger="scroll"]):hover::after,
.wma-nh--fill-split.wma-nh--on::before, .wma-nh--fill-split.wma-nh--on::after { transform: scaleX(1); }

.wma-nh--fill-up::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  background: linear-gradient(0deg, var(--wma-nh-color, #6366f1), var(--wma-nh-color2, #a855f7));
  transform: scaleY(0); transform-origin: bottom center;
  transition: transform var(--wma-nh-fill-speed, var(--wma-nh-travel, 550ms)) var(--wma-ease-standard, cubic-bezier(.4,0,.2,1)) !important;
}
.wma-nh--fill-up:not([data-wma-nh-trigger="scroll"]):hover::before,
.wma-nh--fill-up.wma-nh--on::before { transform: scaleY(1); }

/* Wrapper the engine inserts around a void element (a bare img) so effects that
   need pseudo-elements or child layers have a host. It shrink-wraps the element
   and provides the positioning context. */
.wma-nh-wrap { position: relative; display: inline-block; line-height: 0; max-width: 100%; }
/* A void element (an image, say) cannot host the effect layers, so it gets a
   wrapper and its border travels here. The values arrive as custom properties
   rather than inline border declarations: GenerateBlocks matches
   [style*=border-width] on substring and answers with a forced solid border, so
   an inline width would pull a stray frame onto every wrapped element. */
.wma-nh-wrap--carried {
  border-width: var(--wma-nh-carry-w, 0);
  border-style: var(--wma-nh-carry-style, none);
  border-color: var(--wma-nh-carry-color, transparent);
  box-sizing: border-box;
}
.wma-nh-wrap > img { display: block; max-width: 100%; height: auto; position: relative; z-index: 0; border-radius: inherit; }
/* Every effect layer must paint above the wrapped image, or the image hides it
   and only the tilt (a transform on the wrapper) shows. The image is z-index 0,
   so lift the pseudo-element and injected layers above it. */
.wma-nh-wrap[class*="wma-nh--glow-"]::before,
.wma-nh-wrap[class*="wma-nh--glow-"]::after,
.wma-nh-wrap.wma-nh--ripple::before,
.wma-nh-wrap .eb-layers,
.wma-nh-wrap .wma-nh-sparks-canvas,
.wma-nh-wrap.wma-nh--gradient::before,
.wma-nh-wrap[class*="wma-nh--shine-"]::before,
.wma-nh-wrap[class*="wma-nh--shine-"]::after,
.wma-nh-wrap[class*="wma-nh--fill-"]::before,
.wma-nh-wrap[class*="wma-nh--fill-"]::after,
.wma-nh-wrap .wma-nh-ripple-layer { z-index: 3; }

/* reduced motion: kill continuous motion everywhere, keep a static resting look */
@media (prefers-reduced-motion: reduce) {
  [class*="wma-nh--glow-"]::before,
  [class*="wma-nh--glow-"]::after { animation: none !important; }
  .wma-nh--ripple .wma-nh-ring { display: none !important; }
  [class*="wma-nh--shine-"]::before,
  [class*="wma-nh--shine-"]::after { transition: none !important; animation: none !important; }
  [class*="wma-nh--fill-"]::before,
  [class*="wma-nh--fill-"]::after { transition: none !important; }
}

/* -------------------------------------------------------------------------
   Surface: Spotlight and Glare. Both follow the pointer, so both read
   --wma-nh-mx / --wma-nh-my, which the engine writes. Unlike the other surface
   effects these do not run on a keyframe: the pointer is the timeline.
   ------------------------------------------------------------------------- */

/* Spotlight: a soft radial pool of light centred on the pointer. The overlay
   sits on top of the block without touching layout. */
.wma-nh--spotlight::before {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	pointer-events: none;
	opacity: var(--wma-nh-spot-o);
	background: radial-gradient(
		ellipse var(--wma-nh-spot-size, 70%) var(--wma-nh-spot-size, 70%) at var(--wma-nh-mx) var(--wma-nh-my),
		var(--wma-nh-color, rgb(99,102,241)),
		transparent 65%
	);
	transition: opacity var(--wma-nh-speed, var(--wma-motion-base, 200ms)) var(--wma-ease-out, ease-out);
	z-index: 1;
}

/* Glare: a narrow diagonal streak that sweeps across the surface as the pointer
   travels, the way a sheen slides over glossy card stock. Distinct from the
   spotlight, which pools rather than sweeps. */
.wma-nh--glare::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	pointer-events: none;
	opacity: var(--wma-nh-glare-o);
	background: linear-gradient(
		115deg,
		transparent calc(var(--wma-nh-mx) - 22%),
		var(--wma-nh-color, rgb(99,102,241)) var(--wma-nh-mx),
		transparent calc(var(--wma-nh-mx) + 22%)
	);
	transition: opacity var(--wma-nh-speed, var(--wma-motion-base, 200ms)) var(--wma-ease-out, ease-out);
	z-index: 2;
}

/* Blend per surface, decided by the engine from the block's own background. On
   a dark surface 'screen' lifts the color as light; on a light surface it would
   wash out, so 'multiply' deepens the color into the surface instead. Before
   the engine measures (first hover) no class is present and the overlay is a
   plain colored wash, which still reads. The author never sees a blend control.
   ------------------------------------------------------------------------- */
.wma-nh--ondark.wma-nh--spotlight::before,
.wma-nh--ondark.wma-nh--glare::after { mix-blend-mode: screen; }
.wma-nh--onlight.wma-nh--spotlight::before,
.wma-nh--onlight.wma-nh--glare::after { mix-blend-mode: multiply; }

/* Parallax: with tilt on, lift the block's own content onto a nearer plane so it
   separates from the surface as the block turns, instead of the whole thing
   moving as one flat card. Only direct children move, so a block with no inner
   wrapper simply shows no parallax rather than breaking. */
.wma-nh--tilt.wma-nh--parallax { transform-style: preserve-3d; }
.wma-nh--tilt.wma-nh--parallax > * {
	transform: translateZ( 18px ) scale( 0.97 );
	transform-style: preserve-3d;
}
@media ( prefers-reduced-motion: reduce ) {
	.wma-nh--tilt.wma-nh--parallax > * { transform: none; }
}

/* Keep the overlays inside rounded corners. */
.wma-nh--spotlight,
.wma-nh--glare { overflow: hidden; }

/* Reduced motion: the engine already bails, this is the CSS safety net. */
@media ( prefers-reduced-motion: reduce ) {
	.wma-nh--spotlight::before,
	.wma-nh--glare::after { transition: none; opacity: 0; }
}

/* -------------------------------------------------------------------------
   Cross-block robustness. These effects are added to arbitrary blocks (a GB
   Button, an Image, a Container), not only the cards they were designed on.
   The rules below make them behave on any block.
   ------------------------------------------------------------------------- */

/* Every effect block needs a positioning context and its own stacking context
   so the absolute layers sit correctly, even if the block did not set one. */
[data-wma-nh] { position: relative; }

/* On an Image block the effect lives on the <figure>, which wraps the <img>.
   The figure must take the image's own size (it is inline-ish by default) and
   the effect layers must sit above the image, or only the tilt (a transform on
   the figure) would show. Make the figure shrink-wrap the image and lift every
   effect layer above it. */
figure[data-wma-nh] { display: inline-block; position: relative; overflow: visible; line-height: 0; }
figure[data-wma-nh] > img { position: relative; z-index: 0; border-radius: inherit; display: block; }
[class*="wma-nh--glow-"]::before,
[class*="wma-nh--glow-"]::after { z-index: 2; }
figure[class*="wma-nh--glow-"]::before,
figure[class*="wma-nh--glow-"]::after,
figure.wma-nh--electric-border .eb-layers,
figure.wma-nh--electric-sparks .wma-nh-sparks-canvas,
figure.wma-nh--gradient::before,
figure.wma-nh--ripple .wma-nh-ripple-layer,
figure.wma-nh--spotlight::before,
figure.wma-nh--glare::after { z-index: 2; }

/* -------------------------------------------------------------------------
   SHAPE-AWARE RENDERING
   A border effect landing on a block made of a single inline SVG (a
   GenerateBlocks Shape, an SVG inlined by Core) is drawn on the shape itself.
   The engine swaps the box effect class for .wma-nh--shape + a mode class, so
   none of the rectangle layers above ever apply here. Overlay strokes use
   vector-effect: non-scaling-stroke, so the widths below are screen pixels at
   any viewBox scale.
   ------------------------------------------------------------------------- */
.wma-nh--shape { position: relative; }
.wma-nh--shape .wma-nh-shape-svg { overflow: visible; }

/* Silhouette glow: a tight inner light and a wider halo, both following the
   alpha silhouette. Small blur radii on the inner layer keep the edge crisp;
   the halo's reach and strength come from Intensity via the engine. */
.wma-nh--shape-glow .wma-nh-shape-svg {
  filter: drop-shadow(0 0 3px transparent) drop-shadow(0 0 var(--wma-nh-sh-b2, 18px) transparent);
  transition: filter var(--wma-nh-speed, var(--wma-motion-base, 200ms)) var(--wma-ease-out, cubic-bezier(0, 0, 0.3, 1));
}
.wma-nh--shape-glow:hover .wma-nh-shape-svg,
.wma-nh--shape-glow:focus-visible .wma-nh-shape-svg {
  filter: drop-shadow(0 0 3px var(--wma-nh-color, rgb(99, 102, 241))) drop-shadow(0 0 var(--wma-nh-sh-b2, 18px) var(--wma-nh-sh-c2, rgba(99, 102, 241, 0.55)));
}

/* The overlay groups fade in over the base timing and out the same way. */
.wma-nh-shape-run,
.wma-nh-shape-grad,
.wma-nh-shape-el {
  opacity: 0;
  transition: opacity var(--wma-motion-base, 200ms) var(--wma-ease-out, cubic-bezier(0, 0, 0.3, 1));
}
.wma-nh--shape:not([data-wma-nh-trigger="scroll"]):hover .wma-nh-shape-run,
.wma-nh--shape.wma-nh--on .wma-nh-shape-run,
.wma-nh--shape:focus-visible .wma-nh-shape-run,
.wma-nh--shape:not([data-wma-nh-trigger="scroll"]):hover .wma-nh-shape-grad,
.wma-nh--shape.wma-nh--on .wma-nh-shape-grad,
.wma-nh--shape:focus-visible .wma-nh-shape-grad,
.wma-nh--shape:not([data-wma-nh-trigger="scroll"]):hover .wma-nh-shape-el,
.wma-nh--shape.wma-nh--on .wma-nh-shape-el,
.wma-nh--shape:focus-visible .wma-nh-shape-el {
  opacity: var(--wma-nh-sh-o, 1);
}

/* Running light: the dash pattern is normalised (pathLength=100) so the same
   26/74 split reads on any shape; the engine writes each outline's own loop
   duration so the perceived speed is constant across sizes. */
.wma-nh-shape-run path,
.wma-nh-shape-run circle,
.wma-nh-shape-run rect,
.wma-nh-shape-run ellipse,
.wma-nh-shape-run polygon,
.wma-nh-shape-run polyline,
.wma-nh-shape-run line {
  fill: none;
  stroke: var(--wma-nh-color, rgb(99, 102, 241));
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-dasharray: 26 74;
  stroke-dashoffset: 0;
  animation: wma-nh-shape-run 1800ms linear infinite;
  animation-play-state: paused;
  filter: drop-shadow(0 0 5px var(--wma-nh-color, rgb(99, 102, 241)));
}
.wma-nh--shape-light:not([data-wma-nh-trigger="scroll"]):hover .wma-nh-shape-run path,
.wma-nh--shape-light:not([data-wma-nh-trigger="scroll"]):hover .wma-nh-shape-run circle,
.wma-nh--shape-light:not([data-wma-nh-trigger="scroll"]):hover .wma-nh-shape-run rect,
.wma-nh--shape-light:not([data-wma-nh-trigger="scroll"]):hover .wma-nh-shape-run ellipse,
.wma-nh--shape-light:not([data-wma-nh-trigger="scroll"]):hover .wma-nh-shape-run polygon,
.wma-nh--shape-light:not([data-wma-nh-trigger="scroll"]):hover .wma-nh-shape-run polyline,
.wma-nh--shape-light:not([data-wma-nh-trigger="scroll"]):hover .wma-nh-shape-run line,
.wma-nh--shape-light.wma-nh--on .wma-nh-shape-run path,
.wma-nh--shape-light.wma-nh--on .wma-nh-shape-run circle,
.wma-nh--shape-light.wma-nh--on .wma-nh-shape-run rect,
.wma-nh--shape-light.wma-nh--on .wma-nh-shape-run ellipse,
.wma-nh--shape-light.wma-nh--on .wma-nh-shape-run polygon,
.wma-nh--shape-light.wma-nh--on .wma-nh-shape-run polyline,
.wma-nh--shape-light.wma-nh--on .wma-nh-shape-run line,
.wma-nh--shape-light:focus-visible .wma-nh-shape-run path {
  animation-play-state: running;
}
@keyframes wma-nh-shape-run {
  to { stroke-dashoffset: -100; }
}

/* Gradient stroke: paint comes from the per-card linearGradient the engine
   builds; only the geometry of the stroke lives here. */
.wma-nh-shape-grad path,
.wma-nh-shape-grad circle,
.wma-nh-shape-grad rect,
.wma-nh-shape-grad ellipse,
.wma-nh-shape-grad polygon,
.wma-nh-shape-grad polyline,
.wma-nh-shape-grad line {
  fill: none;
  stroke-width: 3;
  stroke-linejoin: round;
}

/* Path electric: a colored halo under a thin bright core, both displaced by
   the card's own drifting-noise filter. The core flips dark on light
   surfaces, from the same surface tag Spotlight and Glare use. */
.wma-nh-shape-el .wma-nh-sh-halo {
  fill: none;
  stroke: var(--wma-nh-color, rgb(99, 102, 241));
  stroke-width: 2.4;
  stroke-linejoin: round;
  opacity: 0.6;
}
.wma-nh-shape-el .wma-nh-sh-core {
  fill: none;
  stroke: #ffffff;
  stroke-width: 1;
  stroke-linejoin: round;
  opacity: 0.9;
}
.wma-nh--onlight .wma-nh-shape-el .wma-nh-sh-core { stroke: #111111; }

@media (prefers-reduced-motion: reduce) {
  .wma-nh-shape-run path,
  .wma-nh-shape-run circle,
  .wma-nh-shape-run rect,
  .wma-nh-shape-run ellipse,
  .wma-nh-shape-run polygon,
  .wma-nh-shape-run polyline,
  .wma-nh-shape-run line {
    animation: none;
    stroke-dasharray: none;
    opacity: 0.7;
  }
}

/* Surface effect on a shape: the wrapper shrink-wraps the SVG and carries the
   whole box machinery, clipped by the engine to the shape's silhouette. */
.wma-nh-shape-surface {
  position: relative;
  display: inline-block;
  line-height: 0;
}
.wma-nh-shape-surface > svg,
.wma-nh-shape-surface .wma-nh-liquid-inner > svg {
  display: block;
}

/* On a shape the fill wipe must ride above the SVG: the box version paints
   behind the block's children so text stays legible, but here the child is
   the shape itself and the wipe is the recolouring. Clipped to the
   silhouette, so lifting it turns the shape the fill color. */
.wma-nh-shape-surface[class*="wma-nh--fill-"]::before,
.wma-nh-shape-surface[class*="wma-nh--fill-"]::after {
  z-index: 2;
}
