/* Kingdom Advisors Elementor Widgets — Focus Mesh
   A geometric line mesh that sits behind hero content, soft and out of focus, with a lens of
   clarity that follows the cursor.

   THE WHOLE EFFECT IS CSS. The script's only job is writing four custom properties on one element
   per frame (--kaw-mesh-px/py/dx/dy); everything below reads them. That is what keeps it on the
   compositor instead of rasterising a new mask every frame.

   ONE MESH, DRAWN THREE TIMES, AT THREE FOCUS DEPTHS:
     soft   fully blurred, always visible, low opacity — the resting state
     halo   ~40% of the blur, revealed by a WIDE, very soft radial mask that tracks the cursor
     sharp  no blur at all, revealed by a TIGHTER mask tracking the same point
   Stacked in that order, with the halo mask much wider than the sharp one, they read as a
   continuous depth-of-field falloff rather than a circle with an edge.

   Controlled values arrive as `--kaw-mesh-*` variables this stylesheet reads, never as properties
   a control writes onto an element this file also styles — see the "Elementor specificity trap"
   note in the rundown for why that distinction has bitten this plugin three times. */

.kaw-mesh {
  /* ---- placement ---- */
  --kaw-mesh-size: 1180px;      /* rendered HEIGHT of the mesh */
  --kaw-mesh-ar: 0.5511;        /* its width ÷ height, measured from the SVG server-side */
  --kaw-mesh-right: -60px;      /* offset from the right edge; negative bleeds off */
  --kaw-mesh-anchor-w: 1200px;  /* content column to measure that offset from (see [data-anchor]) */
  /* Vertical part of the position (see [data-valign]).
     `top 50%`, NOT `center`, and this is not a stylistic choice. The composed value below is
     consumed by BOTH `background-position` and — in tint mode — `mask-position`, and those take
     different grammars: `background-position` is <bg-position>, which allows the three-value form
     `right 160px center`; `mask-position` is <position>, which does NOT. With `center` here the
     mask silently goes invalid-at-computed-value-time and resolves to `0% 0%`, so the stencil sits
     in the top-left corner while the gradient it is supposed to be masking is over on the right —
     the tinted mesh appears in the wrong place entirely. `top 50%` is identical rendering and makes
     every variant a legal four-value <position>. Measured in Chromium:
     CSS.supports('background-position','right 160px center') -> true
     CSS.supports('mask-position',      'right 160px center') -> false */
  --kaw-mesh-vpos: top 50%;
  --kaw-mesh-fade: 42%;         /* where the mesh dissolves, so it clears the headline */
  --kaw-mesh-feather: 0px;      /* softens the OTHER three edges — see the note on clipping below */
  --kaw-mesh-flip: 1;           /* -1 mirrors the mesh for left-side layouts */
  --kaw-mesh-pad: 220px;        /* overhang, so blur does not fade at the edges */

  /* ---- focus ---- */
  --kaw-mesh-radius: 420px;     /* diameter of the fully sharp lens */
  --kaw-mesh-core: 16%;         /* flat sharp centre before the falloff begins */
  --kaw-mesh-halo: 2.4;         /* how much wider the half-focus halo is */
  --kaw-mesh-blur: 9px;         /* blur on the fully defocused layer */
  --kaw-mesh-base: 0.3;         /* opacity at rest */
  --kaw-mesh-sharp: 0.95;       /* opacity inside the lens */

  /* ---- motion ---- */
  --kaw-mesh-parallax: 1;       /* 0 disables */
  --kaw-mesh-travel: 22px;      /* how far the mesh drifts against the cursor at full strength */

  /* ---- where the lens rests (read by the SCRIPT only: at build, per debounced resize, and once at window load) ----
     Unitless percentages of the field. Declared here so a CLEARED control falls back to the
     original numbers rather than to nothing; nothing in this stylesheet reads them. */
  --kaw-mesh-lens-x: 78;        /* resting point, % of the width from the left (mirrored under Flip) */
  --kaw-mesh-lens-y: 50;        /* resting point, % of the height from the top */
  --kaw-mesh-drift-x: 16;       /* idle drift range either side of the resting point, % of the width */
  --kaw-mesh-drift-y: 32;       /* ... and % of the height */

  /* ---- tint (only used when the colour override is on) ---- */
  --kaw-mesh-c1: #147BD1;
  --kaw-mesh-c2: #48D597;
  --kaw-mesh-angle: 43deg;

  /* ---- written by the script ---- */
  --kaw-mesh-px: -1500px;
  --kaw-mesh-py: -1500px;
  --kaw-mesh-dx: 0;
  --kaw-mesh-dy: 0;

  /* Composed once, consumed by both the background and (in tint mode) the mask, so the painted
     gradient and the mesh that masks it can never drift out of register. */
  --kaw-mesh-pos: right calc(var(--kaw-mesh-right) + var(--kaw-mesh-pad)) var(--kaw-mesh-vpos);
  --kaw-mesh-box: calc(var(--kaw-mesh-size) * var(--kaw-mesh-ar)) var(--kaw-mesh-size);

  position: absolute;
  inset: 0;
  pointer-events: none;

  /* CLIPPING LIVES HERE, NOT ON THE HERO CONTAINER. The layers below overhang by --kaw-mesh-pad
     on all four sides, so something has to clip them or the page gets horizontal scroll. Doing it
     on this element is visually identical to doing it on the host — this element already covers
     the host exactly — and it avoids forcing `overflow: hidden` onto someone else's container,
     which would silently kill `position: sticky` for anything inside the hero and clip their
     dropdowns and tooltips. */
  overflow: hidden;

  /* The dissolve on the content side (fade), plus a feather on the OUTER side.
     WHY NOT JUST `overflow: visible` when the clip is unwanted? Three reasons, all of them bite:
       1. CSS will not let you clip one axis only. If either axis is not `visible` the other
          computes to `auto`, so you cannot clip sideways to avoid a page scrollbar while letting
          the mesh spill vertically. It is all or nothing.
       2. The layers deliberately overhang by --kaw-mesh-pad (220px) on every side, so unclipping
          spills that much blurred mesh over whatever sits above and below, and past the right of
          the viewport — a horizontal page scrollbar.
       3. It breaks this very mask. A mask is sized to the element's box; anything outside is either
          masked away entirely or, with the default `repeat`, painted with the gradient TILED, which
          puts repeating fade bands across the spilled area.
     Feathering the edge instead keeps everything contained and removes the hard cut, which is the
     thing that actually looks wrong. At feather 0 the last two stops collapse onto 100% and this is
     byte-for-byte the old hard edge. */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--kaw-mesh-fade), #000 calc(100% - var(--kaw-mesh-feather)), transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 var(--kaw-mesh-fade), #000 calc(100% - var(--kaw-mesh-feather)), transparent 100%);
}

/* Top and bottom feather.
   A SEPARATE ELEMENT rather than a second mask layer on the field, on purpose: two mask layers
   would need `mask-composite: intersect` / `-webkit-mask-composite: source-in` to AND them
   together, and the default compositing unions them, which is the opposite of what is wanted. One
   extra div with one single-layer mask needs no compositing keyword and behaves identically in
   every browser. It is only masked when the control is actually in use, so the common case pays
   nothing for the extra layer. */
.kaw-mesh__inner {
  position: absolute;
  inset: 0;
}
.kaw-mesh[data-feather="on"] .kaw-mesh__inner {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 var(--kaw-mesh-feather), #000 calc(100% - var(--kaw-mesh-feather)), transparent 100%);
          mask-image: linear-gradient(180deg, transparent 0, #000 var(--kaw-mesh-feather), #000 calc(100% - var(--kaw-mesh-feather)), transparent 100%);
}

/* Mirrored: the mesh flips AND the dissolve moves to the other edge with it. Flipping only the
   mesh leaves it fading out on the side it is now sitting on. */
.kaw-mesh[data-flip="yes"] {
  --kaw-mesh-flip: -1;
  -webkit-mask-image: linear-gradient(270deg, transparent 0, #000 var(--kaw-mesh-fade), #000 calc(100% - var(--kaw-mesh-feather)), transparent 100%);
          mask-image: linear-gradient(270deg, transparent 0, #000 var(--kaw-mesh-fade), #000 calc(100% - var(--kaw-mesh-feather)), transparent 100%);
}

/* `top`/`bottom` MUST carry a length here — see the note on --kaw-mesh-vpos above. The pad is the
   right value anyway: it cancels the layer's overhang, so "top" means the top of the hero rather
   than the top of the padded plane. */
.kaw-mesh[data-valign="top"]    { --kaw-mesh-vpos: top var(--kaw-mesh-pad); }
.kaw-mesh[data-valign="bottom"] { --kaw-mesh-vpos: bottom var(--kaw-mesh-pad); }

.kaw-mesh__stack {
  position: absolute;
  inset: 0;
}

/* ALL THREE PLANES SHARE ONE IDENTICAL TRANSFORM. Give them different parallax multipliers and you
   see doubled strokes at the focus boundary, which is precisely the illusion this is selling. */
.kaw-mesh__plane {
  position: absolute;
  top: calc(var(--kaw-mesh-pad) * -1);
  right: calc(var(--kaw-mesh-pad) * -1);
  bottom: calc(var(--kaw-mesh-pad) * -1);
  left: calc(var(--kaw-mesh-pad) * -1);

  background-image: var(--kaw-mesh-image, none);
  background-repeat: no-repeat;                /* ONE mesh, never tiled */
  background-position: var(--kaw-mesh-pos);
  background-size: var(--kaw-mesh-box);

  /* translate first, then mirror: transform functions apply right-to-left, so scaleX() is the
     inner one and the parallax offset is NOT flipped along with the artwork. */
  transform:
    translate3d(
      calc(var(--kaw-mesh-dx) * var(--kaw-mesh-travel) * -1 * var(--kaw-mesh-parallax)),
      calc(var(--kaw-mesh-dy) * var(--kaw-mesh-travel) * -1 * var(--kaw-mesh-parallax)),
      0)
    scaleX(var(--kaw-mesh-flip));
  -webkit-backface-visibility: hidden;
          backface-visibility: hidden;
}

/* WILL-CHANGE IS ON ONLY WHILE SOMETHING MOVES. `is-animating` is added by the script when the loop
   starts and dropped a second after it settles.

   Leaving it on permanently — which is what the reference implementation did — pins three
   hero-sized layers in GPU memory for the life of the page, two of them carrying a blur. That is
   expensive at rest, and it is worse on the way back from a backgrounded tab: browsers release a
   hidden tab's compositor resources, so every one of those layers has to be re-rasterised at once
   when you return, while the loop is already invalidating them again each frame. The result is a
   few seconds of dropped frames that read as flicker before it settles.

   MDN is explicit that will-change is a last resort and should not be left on speculatively; this
   is the shape it is meant to be used in. */
.kaw-mesh.is-animating .kaw-mesh__plane {
  will-change: transform;
}
.kaw-mesh.is-animating .kaw-mesh__stack--halo,
.kaw-mesh.is-animating .kaw-mesh__stack--sharp {
  will-change: mask-position;
}

/* --------------------------------------------------------------------- anchor to a content column
   Horizontal Offset is measured from the plane's right edge, and the plane spans the whole hero — so
   on a very wide monitor the mesh keeps marching outward with the screen edge and walks away from the
   content. Anchoring pulls the plane's right edge in to where a centred content column of
   --kaw-mesh-anchor-w would end, so the offset is measured from the CONTENT edge instead. The mesh
   stays put next to the headline at any width, while still being painted across the full hero — full
   height, nothing clipped, nothing moved into a narrower container.

   `100%` works here where it would NOT work in `background-position`: a percentage in `right` on an
   absolutely positioned element resolves against its containing block's width (the stack, i.e. the
   hero), which is exactly what is wanted. In `background-position` a percentage resolves against
   (positioning area − image size), which is a different number entirely and would silently mis-place
   the mesh. That is why this is done by insetting the LAYER rather than by shifting the background.

   `max(0px, …)` so a hero narrower than the content column just falls back to the old behaviour
   rather than pushing the mesh off the wrong side. */
.kaw-mesh[data-anchor="on"] .kaw-mesh__plane {
  right: calc(var(--kaw-mesh-pad) * -1 + max(0px, (100% - var(--kaw-mesh-anchor-w)) / 2));
}

/* Mirrored, the mesh lives on the left, so the inset has to move to the left edge. Without this the
   plane still narrows on the right, `scaleX(-1)` puts the narrowed side under the mesh, and the
   anchoring silently does nothing on flipped layouts. */
.kaw-mesh[data-anchor="on"][data-flip="yes"] .kaw-mesh__plane {
  right: calc(var(--kaw-mesh-pad) * -1);
  left: calc(var(--kaw-mesh-pad) * -1 + max(0px, (100% - var(--kaw-mesh-anchor-w)) / 2));
}

/* THE BLUR GOES ON THE PLANE, NOT ON THE STACK — and this is a performance fix, not a style choice.
   It renders identically; putting it on the stack made the browser redo it sixty times a second.

   The plane is what MOVES (the parallax transform is on it). With the filter on the stack, the
   filter's input is the already-transformed plane, so every frame changes the input and the blurred
   result cannot be reused — a 9px Gaussian re-run over a hero-sized surface, every frame, twice
   (soft and halo). With the filter on the plane, `filter` is applied to the element's own content
   and `transform` then positions the RESULT, so the blur input never changes: the browser blurs
   once and moves a cached texture.

   Why it is safe to swap the order: a Gaussian blur is a convolution, so it is linear and
   translation-invariant — blurring then translating is exactly translating then blurring, and the
   same holds for the `scaleX(-1)` flip because the kernel is symmetric. The `opacity` staying up on
   the stack is fine for the same reason: scaling alpha by a constant is linear, so it commutes with
   the convolution. And the filter region is unchanged, because the plane's own box IS the padded box
   the stack's subtree occupied. The mask on the halo stack still applies AFTER the blur, exactly as
   before, because it is still on the parent.

   In TINT mode the same rules blur the same element. The mesh stencil (mask-image) and the fill are
   on the plane's ::before rather than on the plane itself — see "colour override" below for why —
   so the plane's filter blurs the finished, already-stencilled lines and its transform still moves
   the cached result. */
.kaw-mesh__stack--soft {
  opacity: var(--kaw-mesh-base);
}
.kaw-mesh__stack--soft .kaw-mesh__plane {
  filter: blur(var(--kaw-mesh-blur));
}

/* ---------------------------------------------------------------- depth 2: half focus, wide mask
   EIGHT STOPS, NOT TWO. A plain opaque→transparent gradient reads as a detectable ring however
   wide you make it, because the eye finds the linear ramp. These approximate a gaussian. */
.kaw-mesh__stack--halo {
  opacity: calc((var(--kaw-mesh-base) + var(--kaw-mesh-sharp)) / 2);

  -webkit-mask-image: radial-gradient(circle closest-side,
    rgba(0, 0, 0, .95) 0%, rgba(0, 0, 0, .80) 26%, rgba(0, 0, 0, .55) 44%, rgba(0, 0, 0, .32) 60%,
    rgba(0, 0, 0, .15) 74%, rgba(0, 0, 0, .05) 87%, rgba(0, 0, 0, 0) 100%);
          mask-image: radial-gradient(circle closest-side,
    rgba(0, 0, 0, .95) 0%, rgba(0, 0, 0, .80) 26%, rgba(0, 0, 0, .55) 44%, rgba(0, 0, 0, .32) 60%,
    rgba(0, 0, 0, .15) 74%, rgba(0, 0, 0, .05) 87%, rgba(0, 0, 0, 0) 100%);
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-size: calc(var(--kaw-mesh-radius) * var(--kaw-mesh-halo)) calc(var(--kaw-mesh-radius) * var(--kaw-mesh-halo));
          mask-size: calc(var(--kaw-mesh-radius) * var(--kaw-mesh-halo)) calc(var(--kaw-mesh-radius) * var(--kaw-mesh-halo));

  /* CORRECTION — READ THIS BEFORE TRUSTING THE PARAGRAPH BELOW.
     The claim that repositioning a fixed-size gradient "is a compositor job" is WRONG. Blink only
     composites transform, opacity, filter and backdrop-filter; `mask-position` is paint-invalidating,
     so every write here re-records and re-rasters this hero-sized layer on the main thread. Moving
     the mask is still much better than rebuilding the gradient — that part holds — but this is not
     free, and it is the largest remaining per-frame cost in the widget.
     The real fix is to leave `mask-position` static and translate the STACK instead, with the plane
     inside counter-translating so the artwork stays put. That is a visual-risk change and has not
     been done yet; see the flicker section in the rundown. Do not "optimise" this by regenerating
     the gradient — that is worse, and is what the paragraph below is actually about.

     MOVE THE MASK, DO NOT REBUILD IT. Regenerating the gradient string every frame forces the
     browser to rasterise a fresh mask each time and it visibly stutters at hero size. A fixed-size
     gradient that is repositioned is a compositor job. */
  -webkit-mask-position:
    calc(var(--kaw-mesh-px) - (var(--kaw-mesh-radius) * var(--kaw-mesh-halo)) / 2)
    calc(var(--kaw-mesh-py) - (var(--kaw-mesh-radius) * var(--kaw-mesh-halo)) / 2);
          mask-position:
    calc(var(--kaw-mesh-px) - (var(--kaw-mesh-radius) * var(--kaw-mesh-halo)) / 2)
    calc(var(--kaw-mesh-py) - (var(--kaw-mesh-radius) * var(--kaw-mesh-halo)) / 2);
}

/* Same move as the soft layer — see the note there. */
.kaw-mesh__stack--halo .kaw-mesh__plane {
  filter: blur(calc(var(--kaw-mesh-blur) * 0.4));
}

/* ---------------------------------------------------------------- depth 3: sharp, tight mask */
.kaw-mesh__stack--sharp {
  opacity: var(--kaw-mesh-sharp);

  -webkit-mask-image: radial-gradient(circle closest-side,
    #000 0%, #000 var(--kaw-mesh-core), rgba(0, 0, 0, .82) 42%, rgba(0, 0, 0, .56) 56%,
    rgba(0, 0, 0, .31) 69%, rgba(0, 0, 0, .13) 81%, rgba(0, 0, 0, .04) 91%, rgba(0, 0, 0, 0) 100%);
          mask-image: radial-gradient(circle closest-side,
    #000 0%, #000 var(--kaw-mesh-core), rgba(0, 0, 0, .82) 42%, rgba(0, 0, 0, .56) 56%,
    rgba(0, 0, 0, .31) 69%, rgba(0, 0, 0, .13) 81%, rgba(0, 0, 0, .04) 91%, rgba(0, 0, 0, 0) 100%);
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-size: var(--kaw-mesh-radius) var(--kaw-mesh-radius);
          mask-size: var(--kaw-mesh-radius) var(--kaw-mesh-radius);
  -webkit-mask-position:
    calc(var(--kaw-mesh-px) - var(--kaw-mesh-radius) / 2)
    calc(var(--kaw-mesh-py) - var(--kaw-mesh-radius) / 2);
          mask-position:
    calc(var(--kaw-mesh-px) - var(--kaw-mesh-radius) / 2)
    calc(var(--kaw-mesh-py) - var(--kaw-mesh-radius) / 2);
}

/* ------------------------------------------------------------------------------ colour override
   The mesh stops being the IMAGE and becomes the MASK, with a flat colour or gradient painted
   behind it. That is what makes the colour controls work on any SVG shape, whatever colours are
   baked into the file — no re-export from Figma to change a section's palette.

   No conflict with the lens masks above: those are on the STACK, this is on the PLANE's ::before
   inside it.

   The gradient is sized and positioned with the same two variables as the mask, so it lands in the
   mesh's own box rather than spanning the padded plane — otherwise the gradient would run at a
   visibly different angle and extent than the un-overridden version.

   THE STENCIL LIVES ON THE PLANE'S ::before, NOT ON THE PLANE (v1.43.0). On one element CSS always
   applies `filter` FIRST and the mask AFTER it (CSS Masking: filter, then clip, then mask, then
   opacity). Up to 1.42.0 the fill, the mesh mask and the soft/halo blur were all on the plane, so
   the blur ran over a flat fill — which has nothing to blur — and the mask then cut crisp lines out
   of the result: Background Blur did nothing at all in tint mode. Moving the fill and the mask one
   element down puts them in the order the effect needs:
     ::before   fill + mesh mask    -> crisp coloured lines, static inside the plane
     plane      filter: blur()      -> blurs those lines            (the soft / halo rules above)
     plane      transform           -> moves the blurred result     (parallax, flip)
     stack      opacity, lens mask  -> unchanged
   The filter stays on the element that MOVES, so the per-frame model is exactly the untinted one:
   the filter's input (the ::before) never changes, and the browser blurs once and moves a cached
   texture. Do NOT "simplify" this by putting the blur on the stack instead: that renders the same
   picture, but the stack's input is the moving plane, so the blur is re-run on every frame (the
   cost v1.17.3 removed — see the note above the soft layer).
   Every rule here is scoped to [data-tint="on"], so an untinted mesh generates no ::before and its
   cascade is byte-for-byte the 1.42.0 one (tools/test-focus-mesh-render.php row H). The plane keeps
   its background-repeat / -position / -size from the shared rule; they are inert once its own
   background-image is none. */
.kaw-mesh[data-tint="on"] .kaw-mesh__plane {
  background-image: none;
}
.kaw-mesh[data-tint="on"] .kaw-mesh__plane::before {
  content: "";
  position: absolute;
  inset: 0;

  background-image: linear-gradient(var(--kaw-mesh-angle), var(--kaw-mesh-c1), var(--kaw-mesh-c2));
  background-repeat: no-repeat;
  background-position: var(--kaw-mesh-pos);
  background-size: var(--kaw-mesh-box);

  -webkit-mask-image: var(--kaw-mesh-image, none);
          mask-image: var(--kaw-mesh-image, none);
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-size: var(--kaw-mesh-box);
          mask-size: var(--kaw-mesh-box);
  -webkit-mask-position: var(--kaw-mesh-pos);
          mask-position: var(--kaw-mesh-pos);
}

/* A one-colour gradient rather than `background-color`: it has to stay a background IMAGE so that
   background-size and background-position keep sizing it to the mesh box. A background colour
   would flood the whole layer and the mask would be doing all the work — same picture, but the
   gradient/solid switch would then behave differently from one another under the size controls. */
.kaw-mesh[data-tint="on"][data-tint-type="solid"] .kaw-mesh__plane::before {
  background-image: linear-gradient(var(--kaw-mesh-c1), var(--kaw-mesh-c1));
}

/* ------------------------------------------------------------------------------------ the host
   The widget renders inside an Elementor widget wrapper, but the mesh has to fill the HERO. These
   rules do that from the outside — `kaw-mesh-host` is put on the resolved container by the script,
   so nothing has to be hand-classed in the editor.

   `.kaw-mesh-wrap` carries the same rule WITHOUT waiting for the script, because the class is put on
   the wrapper by PHP. That is what keeps the widget out of the layout at first paint — see
   get_html_wrapper_class() in the widget. The host-scoped selectors stay for the case where the
   markup is reproduced by hand. */
.kaw-mesh-wrap,
.kaw-mesh-host > .elementor-widget-kaw_focus_mesh,
.kaw-mesh-host > .e-con-inner > .elementor-widget-kaw_focus_mesh {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  pointer-events: none;
}

/* The inner container Elementor puts between the widget and its output is a normal block with no
   height of its own, so without this the mesh would have nothing to be `inset: 0` against. */
.kaw-mesh-wrap > .elementor-widget-container,
.kaw-mesh-host > .elementor-widget-kaw_focus_mesh > .elementor-widget-container,
.kaw-mesh-host > .e-con-inner > .elementor-widget-kaw_focus_mesh > .elementor-widget-container {
  position: absolute;
  inset: 0;
}

/* Lift the siblings above the mesh.
   Why not simply give the mesh `z-index: -1`? Because a negative z-index child paints BELOW its
   parent's own background unless that parent is a stacking context — and an Elementor container
   with a background usually is not one. The mesh would vanish behind the hero's gradient. Raising
   the siblings is the boring option that always works.
   Both shapes are covered because a BOXED container inserts `.e-con-inner` between itself and its
   children, and a full-width one does not.

   `:not(.e-con-inner)` IS LOAD-BEARING. Without it this rule positions the inner wrapper, the
   inner wrapper becomes the containing block for the widget inside it, and the mesh gets boxed to
   the content width — so it stops at the edge of the text instead of bleeding off the side of the
   hero, and the negative Horizontal Offset appears to do nothing. Boxed is Elementor's DEFAULT
   container type, so this is the common case, not the exotic one. The inner is not a sibling of
   the mesh anyway; its CHILDREN are, and the second selector is what raises those.

   TARGET `.elementor-element`, NOT `*`. A universal child selector also matches the non-widget
   decoration divs Elementor puts directly inside a container or section — `.elementor-background-
   overlay`, `.elementor-shape` (shape dividers), `.elementor-background-video-container`,
   `.elementor-background-slideshow`, `.elementor-motion-effects-container`. Every one of those is
   `position: absolute` by design, styled by Elementor with a single-class rule; this selector is
   more specific, so `position: relative` would win and drop them into normal flow — an overlay with
   `height: 100%` against an auto-height hero then computes to nothing and paints nothing, and a
   shape divider becomes a block sitting in the middle of the hero. Widgets and nested containers
   all carry `.elementor-element`; none of the decoration divs do.

   `:not(.elementor-sticky)` for the same family of reason: forcing `position: relative` onto a
   sticky child would un-stick it, which is the exact failure this widget went out of its way to
   avoid by keeping `overflow: hidden` off the host. */
.kaw-mesh-host--contain > .elementor-element:not(.elementor-widget-kaw_focus_mesh):not(.elementor-sticky),
.kaw-mesh-host--contain > .e-con-inner > .elementor-element:not(.elementor-widget-kaw_focus_mesh):not(.elementor-sticky) {
  position: relative;
  z-index: 1;
}

/* Safety net for the same failure arriving from somewhere else: if a theme or a container setting
   has positioned the inner wrapper, it boxes the mesh exactly as above. Scoped with :has() so it
   can only ever touch an inner wrapper that actually contains a Focus Mesh — no other container on
   the site is affected. Browsers without :has() simply drop the rule and get the boxed mesh. */
.kaw-mesh-host--contain > .e-con-inner:has(> .elementor-widget-kaw_focus_mesh) {
  position: static;
}

/* ------------------------------------------------------------------------- mobile and fallbacks
   Set by the script from the Mobile Behaviour control. `static` keeps the resting mesh — the thing
   the design actually shows — and drops the two tracking layers, which are the expensive ones and
   the ones a phone has no cursor to drive. */
.kaw-mesh.is-static .kaw-mesh__stack--halo,
.kaw-mesh.is-static .kaw-mesh__stack--sharp {
  display: none;
}
.kaw-mesh.is-static .kaw-mesh__plane {
  transform: scaleX(var(--kaw-mesh-flip));
}

.kaw-mesh.is-hidden {
  display: none;
}

/* Reduced motion: no parallax and no ambient drift (the script stops the drift; this stops the
   drift's effect on the artwork). The lens itself still tracks the cursor, because responding
   directly to a pointer is not the kind of motion the setting is asking us to stop. */
@media (prefers-reduced-motion: reduce) {
  .kaw-mesh__plane {
    transform: scaleX(var(--kaw-mesh-flip));
  }
}
