;; Feathered blend - blend two same-size frames with distance-based falloff
;; Center shows overlay, edges show background, with smooth transition

(require-primitives "xector")

(define-effect xector_feathered_blend
  :params (
    (inner-radius :type float :default 0.3 :range [0 1] :desc "Radius where overlay is 100% (fraction of size)")
    (fade-width :type float :default 0.2 :range [0 0.5] :desc "Width of fade region (fraction of size)")
    (overlay :type frame :default nil :desc "Frame to blend in center")
  )
  (let* (
         ;; Get normalized distance from center (0 at center, ~1 at corners)
         (dist (dist-from-center frame))
         (max-dist (βmax dist))
         (dist-norm (α/ dist max-dist))

         ;; Calculate blend factor:
         ;; - 1.0 when dist-norm < inner-radius (fully overlay)
         ;; - 0.0 when dist-norm > inner-radius + fade-width (fully background)
         ;; - linear ramp between
         (t (α/ (α- dist-norm inner-radius) fade-width))
         (blend (α- 1 (αclamp t 0 1)))
         (inv-blend (α- 1 blend))

         ;; Background channels
         (bg-r (red frame))
         (bg-g (green frame))
         (bg-b (blue frame)))

    (if (nil? overlay)
        ;; No overlay - visualize the blend mask
        (let ((vis (α* blend 255)))
          (rgb vis vis vis))

        ;; Blend overlay with background using the mask
        (let* ((ov-r (red overlay))
               (ov-g (green overlay))
               (ov-b (blue overlay))
               ;; lerp: bg * (1-blend) + overlay * blend
               (r-out (α+ (α* bg-r inv-blend) (α* ov-r blend)))
               (g-out (α+ (α* bg-g inv-blend) (α* ov-g blend)))
               (b-out (α+ (α* bg-b inv-blend) (α* ov-b blend))))
          (rgb r-out g-out b-out)))))
