/* ==========================================================================
   Blob Decorations (v3.2 — outline variant + refactored)
   --------------------------------------------------------------------------
   Three blob decoration types share the same anchor / shape / size / color
   system:

     1) Background blob   .has-blob-bg   (inline SVG injected by JS, fill)
     2) Image mask        .blob-mask     (figure with clip-path)
     3) Outline blob      .blob-outline  (inline SVG injected by JS, stroke)

   Shapes are generated as SVG paths by /js/applari-js/blob-decorations.js.
   This file handles positioning, color, sizing, and the "breathing" pulse.

   USAGE
   -----
   A) Background blob on a .color-section
      <div class="color-section gb-container alignfull
                  has-blob-bg blob-pink blob-anchor-l blob-shape-1">
        ...
      </div>

   B) Image blob mask — TWO MODES
      Mode B1: Flow mode (no anchor → block flow with shape's aspect-ratio)
        <figure class="wp-block-image blob-mask blob-shape-2">
          <img src="..." />
        </figure>

      Mode B2: Anchor mode (any .blob-anchor-* → positioned absolutely)
        <figure class="blob-mask blob-anchor-r blob-shape-7 blob-size-md">
          <img src="..." />
        </figure>

      Anchor mode requires the parent to have .has-blob-bg or .has-blob-decor
      (positioning context).

   C) Outline blob (transparent fill, stroked border, always on top)
      <div class="color-section has-blob-decor">
        <div class="blob-outline blob-anchor-r blob-shape-7 blob-size-lg"></div>
        <h1>...</h1>
      </div>

      Outline always renders on top (z-index: 2) above .has-blob-bg blobs and
      .blob-mask elements. Always anchored. pointer-events: none.

   D) Marker class for sections that have only positioned masks/outlines
      (no background blob):
        <div class="color-section has-blob-decor">...</div>

   Shared modifiers:
     Color    : .blob-pink (default), .blob-green, .blob-blue, .blob-light-blue
     Anchor   : .blob-anchor-l (default), .blob-anchor-r, .blob-anchor-t,
                .blob-anchor-b, .blob-anchor-tl, .blob-anchor-tr,
                .blob-anchor-bl, .blob-anchor-br
     Shape    : .blob-shape-1 (default) … .blob-shape-7
     Size     : .blob-size-md (default, 110%), .blob-size-sm (70%),
                .blob-size-lg (150%), .blob-size-xl (200%)

   Per-section overrides (CSS variables, set inline via style="..."):
     --blob-bg-height     : background blob height %
     --blob-mask-height   : image mask height % (anchor mode only)
     --blob-mask-fill     : image mask scale (default 1 — values > 1 push the
                            mask edges closer to the image edges so more of
                            the image is visible). Convenience classes:
                            .blob-mask-fill-md/lg/xl
     --blob-outline-height: outline blob height %
     --blob-outline-width : outline stroke width in CSS px (default 2)
     --blob-overflow      : overhang past anchored edge (default 30%)
     --blob-aspect        : per-shape aspect ratio (auto-set by shape class)

   ARCHITECTURE NOTES
   ------------------
   - Single source of truth for anchor positioning, per-shape aspect ratio,
     color variants, and size presets — all consumed by 3 blob types via
     CSS custom properties.
   - JS injects <svg class="blob-bg-svg"> for backgrounds and
     <svg class="blob-outline-svg"> for outlines. Image masks use a global
     <svg><defs><clipPath> referenced via clip-path: url(#id).
   - Path morphing is interpolated in JS (rAF loop) instead of CSS
     `transition: d`, because Safari does not yet support transitions on
     the SVG `d` attribute in stable releases.
   - 12s morph + 24s pulse, intentionally calm.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. Positioning context (parent of any blob decoration)
   --------------------------------------------------------------------------
   .has-blob-bg always provides this context (it has its own background blob).
   .has-blob-decor is the marker for sections that have only positioned
   masks or outlines — no background blob.
   -------------------------------------------------------------------------- */

.has-blob-bg,
.has-blob-decor {
    position: relative;
    isolation: isolate;

    --blob-overflow: 15%;
    overflow-x: clip;
}


/* --------------------------------------------------------------------------
   2. Shared variables — single source of truth
   --------------------------------------------------------------------------
   These CSS custom properties are unscoped, so they can live on either the
   parent (.has-blob-bg) or the consumer itself (.blob-mask, .blob-outline)
   and inherit to wherever the consumer reads them. Setting them on a
   non-blob element has no side effects.
   -------------------------------------------------------------------------- */

/* Color variants */
.blob-pink       { --blob-color: var(--pink); }
.blob-green      { --blob-color: var(--green); }
.blob-blue       { --blob-color: var(--blue); }
.blob-light-blue { --blob-color: var(--light-blue); }

/* Per-shape aspect ratios — width = height × aspect */
.blob-shape-1 { --blob-aspect: 1.10 / 1; }
.blob-shape-2 { --blob-aspect: 1.40 / 1; }
.blob-shape-3 { --blob-aspect: 1.00 / 1; }
.blob-shape-4 { --blob-aspect: 0.85 / 1; }
.blob-shape-5 { --blob-aspect: 1.05 / 1; }
.blob-shape-6 { --blob-aspect: 1.05 / 1; }
.blob-shape-7 { --blob-aspect: 1.45 / 1; }

/* Size presets — height as % of parent section. Per-blob-type overrides
   (--blob-bg-height etc.) take precedence as inline styles. */
.blob-size-sm { --blob-h: 70%; }
.blob-size-md { --blob-h: 110%; }
.blob-size-lg { --blob-h: 150%; }
.blob-size-xl { --blob-h: 200%; --blob-overflow: 35%; }

/* Image mask fill — scales the clip-path outward from the center so the
   mask edges sit closer to the image edges (more of the image is visible).
   Default 1 = no scaling. Read by JS via getComputedStyle.
   Max safe value is ~1.25: image masks use baseRadiusFactor 0.40 in the path
   generator, so 0.40 × 1.25 = 0.50 = box edge. Values above 1.25 will cause
   the clip-path to clamp to the figure's bounding box → straight edges. */
.blob-mask-fill-md { --blob-mask-fill: 1.10; }
.blob-mask-fill-lg { --blob-mask-fill: 1.18; }
.blob-mask-fill-xl { --blob-mask-fill: 1.25; }


/* --------------------------------------------------------------------------
   3. A) Background blob — inline SVG injected by JS into .has-blob-bg
   -------------------------------------------------------------------------- */

.has-blob-bg .blob-bg-svg {
    position: absolute;
    z-index: -1;
    pointer-events: none;

    height: var(--blob-bg-height, var(--blob-h, 110%));
    width: auto;
    aspect-ratio: var(--blob-aspect, 1.10 / 1);

    color: var(--blob-color, var(--grey));

    /* Default position equivalent to .blob-anchor-l. Anchor classes below
       override this. */
    top: 50%;
    left: 0;
    translate: calc(-1 * var(--blob-overflow)) -50%;
}


/* --------------------------------------------------------------------------
   4. B) Image blob mask — applies to <figure> wrapping an <img>
   --------------------------------------------------------------------------
   JS sets clip-path: url(#blob-clip-N) and morphs the underlying <path> d
   attribute. Two modes:
   - Flow mode (no anchor class): figure adopts the shape's aspect-ratio and
     crops the image via object-fit: cover.
   - Anchor mode (any .blob-anchor-*): figure becomes positioned absolutely
     inside its parent, like a background blob.
   -------------------------------------------------------------------------- */

.blob-mask {
    aspect-ratio: var(--blob-aspect, auto);
}

.blob-mask img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Anchor mode — pulls the figure out of flow */
.blob-mask:is(.blob-anchor-l, .blob-anchor-r, .blob-anchor-t, .blob-anchor-b,
              .blob-anchor-tl, .blob-anchor-tr, .blob-anchor-bl, .blob-anchor-br) {
    position: absolute;
    z-index: -1;
    pointer-events: none;
    margin: 0;

    height: var(--blob-mask-height, var(--blob-h, 110%));
    width: auto;
}


/* --------------------------------------------------------------------------
   5. C) Outline blob — inline SVG injected by JS into .blob-outline
   --------------------------------------------------------------------------
   Transparent fill, stroked path. Always positioned absolutely (anchor
   class required), always on top of other blobs (z-index: 2). Click events
   pass through (pointer-events: none).

   Stroke width is controlled by --blob-outline-width (default 2px). The JS
   sets vector-effect="non-scaling-stroke" so the stroke stays a constant
   pixel width regardless of the SVG viewBox scaling.
   -------------------------------------------------------------------------- */

.blob-outline {
    position: absolute;
    z-index: 1;
    pointer-events: none;
    margin: 0;

    height: var(--blob-outline-height, var(--blob-h, 110%));
    width: auto;
    aspect-ratio: var(--blob-aspect, 1.10 / 1);

    color: var(--blob-color, var(--pink));

    /* Default position equivalent to .blob-anchor-l. Anchor classes below
       override this. */
    top: 50%;
    left: 0;
    translate: calc(-1 * var(--blob-overflow)) -50%;
}

.blob-outline .blob-outline-svg {
    width: 100%;
    height: 100%;
    display: block;
}


/* --------------------------------------------------------------------------
   6. Shared anchor positioning — single source of truth
   --------------------------------------------------------------------------
   Each anchor pins the blob to one edge or corner of the parent and pushes
   it `--blob-overflow` past that edge. Translate percentages refer to the
   blob's own width/height, so overhang scales with blob size.
   -------------------------------------------------------------------------- */

/* Edge: left */
.has-blob-bg.blob-anchor-l .blob-bg-svg,
.blob-mask.blob-anchor-l,
.blob-outline.blob-anchor-l {
    top: 50%;    bottom: auto;
    left: 0;     right: auto;
    translate: calc(-1 * var(--blob-overflow)) -50%;
}

/* Edge: right */
.has-blob-bg.blob-anchor-r .blob-bg-svg,
.blob-mask.blob-anchor-r,
.blob-outline.blob-anchor-r {
    top: 50%;    bottom: auto;
    left: auto;  right: 0;
    translate: var(--blob-overflow) -50%;
}

/* Edge: top */
.has-blob-bg.blob-anchor-t .blob-bg-svg,
.blob-mask.blob-anchor-t,
.blob-outline.blob-anchor-t {
    top: 0;      bottom: auto;
    left: 50%;   right: auto;
    translate: -50% calc(-1 * var(--blob-overflow));
}

/* Edge: bottom */
.has-blob-bg.blob-anchor-b .blob-bg-svg,
.blob-mask.blob-anchor-b,
.blob-outline.blob-anchor-b {
    top: auto;   bottom: 0;
    left: 50%;   right: auto;
    translate: -50% var(--blob-overflow);
}

/* Corner: top-left */
.has-blob-bg.blob-anchor-tl .blob-bg-svg,
.blob-mask.blob-anchor-tl,
.blob-outline.blob-anchor-tl {
    top: 0;      bottom: auto;
    left: 0;     right: auto;
    translate: calc(-1 * var(--blob-overflow)) calc(-1 * var(--blob-overflow));
}

/* Corner: top-right */
.has-blob-bg.blob-anchor-tr .blob-bg-svg,
.blob-mask.blob-anchor-tr,
.blob-outline.blob-anchor-tr {
    top: 0;      bottom: auto;
    left: auto;  right: 0;
    translate: var(--blob-overflow) calc(-1 * var(--blob-overflow));
}

/* Corner: bottom-left */
.has-blob-bg.blob-anchor-bl .blob-bg-svg,
.blob-mask.blob-anchor-bl,
.blob-outline.blob-anchor-bl {
    top: auto;   bottom: 0;
    left: 0;     right: auto;
    translate: calc(-1 * var(--blob-overflow)) var(--blob-overflow);
}

/* Corner: bottom-right */
.has-blob-bg.blob-anchor-br .blob-bg-svg,
.blob-mask.blob-anchor-br,
.blob-outline.blob-anchor-br {
    top: auto;   bottom: 0;
    left: auto;  right: 0;
    translate: var(--blob-overflow) var(--blob-overflow);
}
/*Centered blob*/
.has-blob-bg.blob-anchor-center .blob-bg-svg,
.blob-mask.blob-anchor-center,
.blob-outline.blob-anchor-center {
    --blob-overflow: 0%;
    top: 50%;
    left: 50%;
    translate: -50% -50%;
}
/*Centered bottom blob*/
.has-blob-bg.blob-anchor-center-bottom .blob-bg-svg,
.blob-mask.blob-anchor-center-bottom,
.blob-outline.blob-anchor-center-bottom {
    top: auto;
    bottom: 0;
    left: 50%;
    translate: -50% 0;
}


/* --------------------------------------------------------------------------
   7. Animations — pulse only (path morph is handled in JS)
   --------------------------------------------------------------------------
   The blob path `d` attribute is interpolated in JavaScript (rAF loop) by
   blob-decorations.js. CSS `transition: d` is not used because Safari
   does not yet support it in stable releases.
   Pulse is intentionally subtle (4% scale) and slow.
   -------------------------------------------------------------------------- */

.blob-bg-svg,
.blob-mask,
.blob-outline {
    animation: blob-pulse 24s ease-in-out infinite alternate;
}

@keyframes blob-pulse {
    from { scale: 1; }
    to   { scale: 1.04; }
}




/* --------------------------------------------------------------------------
   8. Mobile responsiveness — cap blob dimensions on small viewports
   --------------------------------------------------------------------------
   On narrow viewports a tall mobile section makes the height-based blob
   grow much taller than the viewport, and with wide aspect-ratio shapes
   the resulting width can be several times the viewport width — leaving
   only a thin vertical slice visible after the anchor's overhang.

   These caps prevent the blob from outgrowing reasonable viewport bounds.
   With aspect-ratio set, the unbound dimension shrinks to maintain shape
   proportions, so the blob stays recognizable.
   -------------------------------------------------------------------------- */

@media (max-width: 768px) {
    .has-blob-bg .blob-bg-svg,
    .blob-mask:is(.blob-anchor-l, .blob-anchor-r, .blob-anchor-t, .blob-anchor-b,
                  .blob-anchor-tl, .blob-anchor-tr, .blob-anchor-bl, .blob-anchor-br),
    .blob-outline {
        max-width: 170vw;
    }
    /*Wider blob in mobile*/
    .has-blob-bg.wider-blob-in-mobile .blob-bg-svg,
    .has-blob-bg .wider-blob-in-mobile.blob-mask,
    .has-blob-bg .wider-blob-in-mobile.blob-outline{
        max-width: 250vw;
    }
}


/* --------------------------------------------------------------------------
   9. Reduced motion — disable pulse (JS skips path morph on its own)
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    .blob-bg-svg,
    .blob-mask,
    .blob-outline {
        animation: none;
    }
}
/* --------------------------------------------------------------------------
   10. Fade-in on scroll — opacity 0 → 1 when blob enters the viewport
   --------------------------------------------------------------------------
   JS adds .is-blob-visible to .has-blob-bg / .has-blob-decor / .blob-mask
   via IntersectionObserver. Above-the-fold elements become visible on load;
   below-the-fold elements fade in as they scroll into view.

   Only active for users who have no motion preference — reduced-motion users
   always see blobs at full opacity.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
    .blob-bg-svg,
    .blob-mask,
    .blob-outline {
        opacity: 0;
        transition: opacity 0.8s ease;
    }

    .is-blob-visible .blob-bg-svg,
    .is-blob-visible .blob-mask,
    .is-blob-visible .blob-outline,
    .blob-mask.is-blob-visible {
        opacity: 1;
    }
}
.editor-styles-wrapper .blob-bg-svg,
.editor-styles-wrapper .blob-mask,
.editor-styles-wrapper .blob-outline,
.editor-styles-wrapper .blob-mask.is-blob-visible {
    opacity: 1;
}
.editor-styles-wrapper .is-blob-visible .blob-bg-svg,
.editor-styles-wrapper .is-blob-visible .blob-mask,
.editor-styles-wrapper .is-blob-visible .blob-outline,
.editor-styles-wrapper .blob-mask.is-blob-visible {
    opacity: 1;
}


/*Helper classes*/
.has-blob-bg.offset-blob-left .blob-bg-svg,
.has-blob-bg.offset-blob-left .blob-mask,
.has-blob-bg .offset-blob-left.blob-outline{
    left:-25%;
}
.has-blob-bg.offset-blob-right .blob-bg-svg,
.has-blob-bg.offset-blob-right .blob-mask,
.has-blob-bg .offset-blob-right .blob-outline{
    right:-25%;
}
.has-blob-bg.offset-blob-top .blob-bg-svg,
.has-blob-bg.offset-blob-top .blob-mask,
.has-blob-bg .offset-blob-top .blob-outline{
    top:-50%;
}
.has-blob-bg.offset-blob-bottom .blob-bg-svg,
.has-blob-bg.offset-blob-bottom .blob-mask,
.has-blob-bg .offset-blob-bottom .blob-outline{
    translate:-50% 50%;
}