; recursive-firebird-se2000.dither
;
; THE RECURSIVE FIREBIRD
; "Five Threads, One Flame"
;
; A no-border 5x7 garment embroidery designed for a single-needle
; Brother SE2000-class workflow.
;
;   art.grammar          recursive, constraint-aware motif growth
;   art.perception       multiscale readability optimization
;   art.negative-space   treats garment color as part of the palette
;   embroidery.sheen     chooses stitch angle from simulated light
;   embroidery.physics   predicts pull, stretch, nesting, and puckering
;   embroidery.routing   global single-needle color-block routing
;   embroidery.lod       stitch-detail budgeting by visual importance
;
; Target:
;   Hoop:          5 x 7 inches
;   Safe artwork:  approximately 4.45 x 6.45 inches
;   Fabric:        black cotton jersey
;   Threads:       five
;   Color blocks:  five global passes
;   Stitch target: 30,000-39,000
;   Hard ceiling:  42,000
;   Style:         running stitch, bean stitch, narrow satin, sparse tatami
;   Export:        PES
;
; IMPORTANT:
; This is a design program, not a substitute for a test stitch. The final
; physics pass must use a calibration swatch for the actual shirt, stabilizer,
; needle, thread, and machine tension.

(module dither://package/user/recursive-firebird
  :title "The Recursive Firebird"
  :version "0.1.0"
  :summary "A five-thread recursive phoenix generated for a 5x7 garment hoop."
  :requires [dither://package/core
             dither://package/math
             dither://package/vector
             dither://package/field
             dither://package/art.grammar
             dither://package/art.perception
             dither://package/art.negative-space
             dither://package/embroidery
             dither://package/embroidery.sheen
             dither://package/embroidery.physics
             dither://package/embroidery.routing
             dither://package/embroidery.lod
             dither://package/render]
  :capabilities [:write-document
                 :modify-workspace
                 :spawn-jobs
                 :write-files])

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 1. Production envelope
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defcustom user/firebird-machine
  {:profile :brother-se2000
   :single-needle true
   :hoop {:width {:inches 5.0}
          :height {:inches 7.0}}
   :safe-area {:width {:inches 4.45}
               :height {:inches 6.45}}
   :center {:x {:inches 0.0}
            :y {:inches 0.0}}
   :export-format :pes
   :thread-block-budget 5
   :manual-thread-changes 4}
  :title "Firebird Machine Profile"
  :type :map)

(defcustom user/firebird-garment
  {:kind :t-shirt
   :fabric :cotton-jersey
   :color "#111111"
   :garment-color-role :negative-space
   :stretch-axis :horizontal
   :nominal-stretch {:x 0.075 :y 0.025}
   :stabilizer :medium-cutaway
   :topper :none
   :placement :center-chest
   :calibration-swatch
     dither://project/current/calibration/black-jersey-medium-cutaway}
  :title "Firebird Garment Profile"
  :summary "The physics solver should replace nominal values with a sewn swatch."
  :type :map)

(defcustom user/firebird-budgets
  {:target-stitches 34000
   :hard-max-stitches 42000
   :target-trims 28
   :hard-max-trims 45
   :target-jumps 36
   :hard-max-jump {:millimeters 18.0}
   :min-stitch {:millimeters 1.15}
   :preferred-running-stitch {:millimeters 2.15}
   :max-running-stitch {:millimeters 3.20}
   :min-satin-width {:millimeters 1.25}
   :max-satin-width {:millimeters 4.20}
   :min-open-gap {:millimeters 0.85}
   :min-parallel-line-gap {:millimeters 1.35}
   :max-layer-count 3
   :max-local-density :medium
   :large-fill-regions false}
  :title "Firebird Stitch and Routing Budgets"
  :type :map)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 2. Five actual threads
;;
;; Black jersey is intentionally used as visible negative space, but it does
;; not count as an upper thread. Every visible stitched color belongs to one
;; of these five global color passes.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defcustom user/firebird-palette
  [{:id :deep-teal
    :name "Deep Teal"
    :rgb "#087A7A"
    :role [:cool-shadow :inner-wing :tail-shadow]}

   {:id :dark-plum
    :name "Dark Plum"
    :rgb "#542044"
    :role [:deep-shadow :wing-depth :eye-motif]}

   {:id :ember-coral
    :name "Ember Coral"
    :rgb "#CB5B48"
    :role [:warm-feather :flame-edge :small-accent]}

   {:id :bone-ivory
    :name "Bone Ivory"
    :rgb "#E8DFC8"
    :role [:body :feather-highlight :beak :eye-glint]}

   {:id :antique-gold
    :name "Antique Gold"
    :rgb "#C99538"
    :role [:solar-core :final-outline :vein :botanical-filigree]}]
  :title "Recursive Firebird Five-Thread Palette"
  :type :vector)

(defcustom user/firebird-thread-order
  [:deep-teal :dark-plum :ember-coral :bone-ivory :antique-gold]
  :title "Single-Needle Color Order"
  :summary "One global pass per color; gold finishes the visual hierarchy."
  :type :vector)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 3. Artistic controls
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defcustom user/firebird-art
  {:seed 208319
   :pose :ascending
   :wing-span {:inches 4.18}
   :body-height {:inches 2.45}
   :tail-height {:inches 3.30}
   :solar-core-radius {:millimeters 7.8}

   ; The left and right sides share a developmental grammar but are not
   ; exact mirrors. This produces biological coherence without clip-art
   ; symmetry.
   :paired-symmetry 0.82
   :independent-mutation 0.18

   ; Detail is concentrated around the head, solar core, inner wings, and
   ; three major tail eyes. Outer curls are deliberately sparse.
   :detail-focus
     [{:kind :radial :center [0.00 0.90] :radius 0.58 :weight 1.00}
      {:kind :radial :center [0.00 0.05] :radius 0.62 :weight 0.92}
      {:kind :radial :center [-1.00 0.25] :radius 0.80 :weight 0.76}
      {:kind :radial :center [ 1.00 0.25] :radius 0.80 :weight 0.76}
      {:kind :radial :center [0.00 -1.85] :radius 1.25 :weight 0.70}]

   ; The stitched bird must read at all three viewing scales.
   :perceptual-scales
     [{:distance {:inches 8}  :goal :micro-feather-craft}
      {:distance {:feet 3}    :goal :clear-phoenix-silhouette}
      {:distance {:feet 8}    :goal :bright-rising-flame-symbol}]

   :negative-space-target 0.59
   :recursive-depth 3
   :primary-wing-feathers 9
   :secondary-wing-feathers 7
   :tail-streamers 11
   :filigree-sprigs 18}
  :title "Recursive Firebird Artistic Controls"
  :type :map)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 4. Small math helpers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define user/clamp
  (fn [x lo hi]
    (min hi (max lo x))))

(define user/lerp
  (fn [a b t]
    (+ a (* (- b a) t))))

(define user/smoothstep
  (fn [a b x]
    (let {:t (user/clamp (/ (- x a) (- b a)) 0.0 1.0)}
      (* t t (- 3.0 (* 2.0 t))))))

(define user/polar
  (fn [radius angle]
    [(* radius (cos angle))
     (* radius (sin angle))]))

(define user/point+
  (fn [a b]
    [(+ (nth a 0) (nth b 0))
     (+ (nth a 1) (nth b 1))]))

(define user/point*
  (fn [p scalar]
    [(* (nth p 0) scalar)
     (* (nth p 1) scalar)]))

(define user/mirror-x
  (fn [p]
    [(* -1.0 (nth p 0))
     (nth p 1)]))

(define user/thread
  (fn [thread-id]
    (first
      (filter
        (fn [entry] (= (get entry :id) thread-id))
        (custom/get user/firebird-palette)))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 5. Deterministic paired variation
;;
;; DESIGN TECHNIQUE:
;; `art/paired-random` gives corresponding left/right structures a shared
;; developmental value plus a controlled independent mutation. The wings
;; feel related like living anatomy but are not exact mirrors.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define user/paired-value
  (fn [label index side lo hi]
    (let {:controls (custom/get user/firebird-art)
          :seed (get controls :seed)
          :shared (art/paired-random
                    {:seed seed
                     :label label
                     :index index
                     :channel :shared})
          :private (art/paired-random
                     {:seed seed
                      :label label
                      :index index
                      :channel side})
          :pairing (get controls :paired-symmetry)
          :unit (+ (* pairing shared)
                   (* (- 1.0 pairing) private))}
      (user/lerp lo hi unit))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 6. Global fields
;;
;; Every feather, stitch direction, accent color, and level of detail is
;; influenced by the same fields. This is why the image feels like one living
;; organism instead of hundreds of unrelated decorative parts.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define user/solar-heat
  (fn [x y]
    (field/radial-value
      {:point [x y]
       :center [0.0 0.08]
       :radius 2.65
       :curve :inverse-square-soft})))

(define user/rising-flow
  (fn [x y]
    (let {:radial-angle (atan2 (- y 0.05) x)
          :curl (field/curl-noise
                  {:point [(* x 0.84) (* y 0.72)]
                   :seed (get (custom/get user/firebird-art) :seed)
                   :octaves 3})
          :rise (* 0.64 (user/smoothstep -2.8 2.5 y))}
      (+ (* 0.48 radial-angle)
         (* 0.33 curl)
         (* 0.19 rise)))))

(define user/light-direction
  (fn [x y]
    ; A virtual light lives in the solar core. Stitch angles later use this
    ; field to produce different thread sheen with the same five colors.
    (atan2 (- y 0.08) x)))

(define user/detail-importance
  (fn [x y]
    (art.perception/importance-at
      {:point [x y]
       :focus (get (custom/get user/firebird-art) :detail-focus)
       :silhouette-weight 0.42
       :curvature-weight 0.28
       :semantic-weight 0.30})))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 7. Parametric bird skeleton
;;
;; The skeleton is not directly stitched. It is a semantic scaffold used by
;; the motif grammar and route solver.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define user/firebird-skeleton
  (fn []
    {:spine
       (vector/bezier
         [[0.00 -1.10]
          [-0.08 -0.45]
          [0.11 0.40]
          [0.02 1.34]])

     :neck
       (vector/bezier
         [[0.02 1.05]
          [0.35 1.20]
          [0.18 1.55]
          [-0.13 1.62]])

     :head
       {:center [-0.20 1.65]
        :radius [0.18 0.15]
        :facing :left}

     :left-wing
       (vector/bezier
         [[-0.05 0.90]
          [-0.68 1.35]
          [-1.62 1.28]
          [-2.02 0.54]])

     :right-wing
       (vector/bezier
         [[0.05 0.90]
          [0.68 1.35]
          [1.62 1.28]
          [2.02 0.54]])

     :left-wing-lower
       (vector/bezier
         [[-0.08 0.60]
          [-0.75 0.36]
          [-1.35 0.18]
          [-1.72 -0.12]])

     :right-wing-lower
       (vector/bezier
         [[0.08 0.60]
          [0.75 0.36]
          [1.35 0.18]
          [1.72 -0.12]])

     :tail-axis
       (vector/bezier
         [[0.00 -0.72]
          [0.12 -1.38]
          [-0.05 -2.28]
          [0.02 -3.04]])

     :solar-core [0.00 0.10]}))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 8. Recursive feather grammar
;;
;; DESIGN TECHNIQUE:
;; This grammar grows stitchable feathers from semantic rules rather than
;; drawing each feather manually.
;;
;; Each feather contains:
;;   - a central rachis
;;   - alternating barbs
;;   - optional nested flame/eye motifs
;;   - recursive micro-leaves only where the detail budget permits
;;
;; The grammar receives stitchability constraints during growth, so it never
;; proposes a barb thinner than the machine can sew or a gap too tight for the
;; shirt/stabilizer profile.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define user/firebird-feather-grammar
  (art.grammar/compile
    {:id dither://registry/motif-grammar/user/firebird-feather

     :parameters
       {:origin :point
        :direction :angle
        :length :distance
        :width :distance
        :rank :integer
        :side :keyword
        :heat :number
        :importance :number
        :accent :keyword
        :eye? :boolean}

     :axiom
       [:feather
        {:origin :origin
         :direction :direction
         :length :length
         :width :width
         :rank :rank
         :side :side
         :heat :heat
         :importance :importance
         :accent :accent
         :eye? :eye?}]

     :rules
       {:feather
          [{:emit :rachis
            :args {:path
                    (grammar/curve
                      {:origin :origin
                       :direction :direction
                       :length :length
                       :bend (* 0.14 (grammar/signed-side :side))})
                   :thread :antique-gold
                   :stitch :bean
                   :width {:millimeters 1.45}}}

           {:repeat
              {:count
                 (grammar/int
                   (user/lerp 7 18
                     (* :importance
                        (user/clamp (/ :length 1.30) 0.0 1.0))))
               :index :i
               :body
                 [:paired-barbs
                  {:position
                    (grammar/along :rachis
                      (/ (+ :i 1)
                         (+ (grammar/repeat-count) 1)))
                   :fraction
                    (/ (+ :i 1)
                       (+ (grammar/repeat-count) 1))
                   :side :side
                   :heat :heat
                   :importance :importance
                   :accent :accent}]}}

           {:when :eye?
            :emit :eye-flame
            :args {:center (grammar/along :rachis 0.68)
                   :direction :direction
                   :scale (* 0.58 :width)
                   :outer-thread :antique-gold
                   :middle-thread :accent
                   :inner-thread :dark-plum}}]

        :paired-barbs
          [{:let
              {:t :fraction
               :falloff (sin (* 3.14159265 :fraction))
               :base-length (* :falloff
                               (user/lerp 0.20 0.52 :importance))
               :tilt (user/lerp 0.48 1.10 :fraction)}

            :emit-many
              [[:barb
                {:origin :position
                 :direction (+ (grammar/tangent :rachis :fraction) :tilt)
                 :length :base-length
                 :thread
                   (grammar/choose-by-field
                     {:field :heat
                      :stops [[0.00 :deep-teal]
                              [0.34 :dark-plum]
                              [0.58 :ember-coral]
                              [0.82 :bone-ivory]]})
                 :stitch :narrow-satin}]

               [:barb
                {:origin :position
                 :direction (- (grammar/tangent :rachis :fraction) :tilt)
                 :length (* 0.94 :base-length)
                 :thread
                   (grammar/choose-by-field
                     {:field :heat
                      :stops [[0.00 :deep-teal]
                              [0.34 :dark-plum]
                              [0.58 :ember-coral]
                              [0.82 :bone-ivory]]})
                 :stitch :narrow-satin}]]}

           ; Add one level of recursive botanical subdivision only when it
           ; remains visible and the global stitch budget allows it.
           {:when '(and (> :importance 0.72)
                        (> :base-length 0.28))
            :repeat
              {:count 3
               :index :j
               :body
                 [:micro-leaf
                  {:origin
                    (grammar/along-last-emission
                      (/ (+ :j 1) 4.0))
                   :direction
                    (+ (grammar/last-direction)
                       (* 0.28 (- :j 1)))
                   :length (* 0.22 :base-length)
                   :thread :antique-gold}]}}]

        :rachis
          [{:stitch-path
            {:path :path
             :stitch :stitch
             :thread :thread
             :passes 2
             :stitch-length {:millimeters 2.05}
             :role :feather-rachis}}]

        :barb
          [{:stitch-path
            {:path
              (grammar/tapered-curve
                {:origin :origin
                 :direction :direction
                 :length :length
                 :root-width {:millimeters 2.40}
                 :tip-width {:millimeters 1.20}
                 :bend 0.11})
             :stitch :stitch
             :thread :thread
             :angle-policy :follow-local-light
             :role :feather-barb}}]

        :micro-leaf
          [{:stitch-path
            {:path
              (grammar/leaf-curve
                {:origin :origin
                 :direction :direction
                 :length :length
                 :width (* 0.33 :length)})
             :stitch :running
             :thread :thread
             :stitch-length {:millimeters 1.65}
             :role :recursive-micro-leaf}}]

        :eye-flame
          [{:emit :closed-teardrop
            :args {:center :center
                   :direction :direction
                   :length (* 1.00 :scale)
                   :width (* 0.58 :scale)
                   :thread :outer-thread
                   :stitch :bean}}

           {:emit :closed-teardrop
            :args {:center :center
                   :direction :direction
                   :length (* 0.68 :scale)
                   :width (* 0.39 :scale)
                   :thread :middle-thread
                   :stitch :narrow-satin}}

           {:emit :closed-teardrop
            :args {:center :center
                   :direction :direction
                   :length (* 0.35 :scale)
                   :width (* 0.19 :scale)
                   :thread :inner-thread
                   :stitch :narrow-satin}}]

        :closed-teardrop
          [{:stitch-shape
            {:shape
              (grammar/teardrop
                {:center :center
                 :direction :direction
                 :length :length
                 :width :width})
             :stitch :stitch
             :thread :thread
             :fill-policy :contour-first
             :role :feather-eye}}]}

     :growth-constraints
       {:minimum-feature {:millimeters 1.10}
        :minimum-gap {:millimeters 0.85}
        :minimum-satin-width {:millimeters 1.25}
        :maximum-satin-width {:millimeters 4.20}
        :maximum-recursion
          (get (custom/get user/firebird-art) :recursive-depth)
        :budget-source user/firebird-budgets}}))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 9. Wing feather placement
;;
;; Primary and secondary feathers are generated from the skeleton. Each side
;; receives corresponding parameters with controlled mutation.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define user/generate-wing
  (fn [design side skeleton]
    (let {:upper-path
            (if (= side :left)
              (get skeleton :left-wing)
              (get skeleton :right-wing))
          :lower-path
            (if (= side :left)
              (get skeleton :left-wing-lower)
              (get skeleton :right-wing-lower))
          :primary-count
            (get (custom/get user/firebird-art) :primary-wing-feathers)
          :secondary-count
            (get (custom/get user/firebird-art) :secondary-wing-feathers)}

      ; Large rising primaries.
      (for [i (range 0 primary-count)]
        (let {:t (/ (+ i 0.65) primary-count)
              :anchor (vector/point-at upper-path t)
              :base-angle (vector/tangent-angle upper-path t)
              :sweep (user/paired-value :primary-sweep i side 0.38 1.00)
              :length (user/paired-value :primary-length i side 0.58 1.18)
              :width (user/paired-value :primary-width i side 0.24 0.42)
              :direction
                (if (= side :left)
                  (+ base-angle sweep)
                  (- base-angle sweep))
              :heat (user/solar-heat (nth anchor 0) (nth anchor 1))
              :importance
                (user/detail-importance (nth anchor 0) (nth anchor 1))
              :accent
                (if (> t 0.58) :deep-teal :ember-coral)}

          (art.grammar/grow design user/firebird-feather-grammar
            {:origin anchor
             :direction direction
             :length length
             :width width
             :rank i
             :side side
             :heat heat
             :importance importance
             :accent accent
             :eye? (and (> i 2) (= 0 (mod i 3)))})))

      ; Smaller lower wing coverts.
      (for [i (range 0 secondary-count)]
        (let {:t (/ (+ i 0.70) secondary-count)
              :anchor (vector/point-at lower-path t)
              :base-angle (vector/tangent-angle lower-path t)
              :sweep (user/paired-value :secondary-sweep i side 0.20 0.64)
              :length (user/paired-value :secondary-length i side 0.38 0.78)
              :width (user/paired-value :secondary-width i side 0.20 0.34)
              :direction
                (if (= side :left)
                  (+ base-angle sweep)
                  (- base-angle sweep))
              :heat (user/solar-heat (nth anchor 0) (nth anchor 1))
              :importance
                (user/detail-importance (nth anchor 0) (nth anchor 1))}

          (art.grammar/grow design user/firebird-feather-grammar
            {:origin anchor
             :direction direction
             :length length
             :width width
             :rank i
             :side side
             :heat heat
             :importance importance
             :accent :dark-plum
             :eye? false}))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 10. Tail streamers
;;
;; Each tail feather is a field-guided curve, not a repeated clip-art shape.
;; Three become eye feathers. The rest remain mostly open linework, allowing
;; the black shirt to carry much of the composition.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define user/tail-origin
  (fn [i count]
    (let {:u (/ i (- count 1))
          :x (user/lerp -0.38 0.38 u)
          :y (user/lerp -0.72 -0.88
               (abs (- (* 2.0 u) 1.0)))}
      [x y])))

(define user/tail-direction
  (fn [i count]
    (let {:u (/ i (- count 1))
          :fan (user/lerp -0.72 0.72 u)}
      (- (* -0.50 3.14159265) fan))))

(define user/generate-tail
  (fn [design]
    (let {:count (get (custom/get user/firebird-art) :tail-streamers)}
      (for [i (range 0 count)]
        (let {:origin (user/tail-origin i count)
              :direction (user/tail-direction i count)
              :center-distance
                (abs (- i (/ (- count 1) 2.0)))
              :length
                (user/lerp 2.18 3.20
                  (- 1.0 (/ center-distance (/ count 2.0))))
              :width
                (user/lerp 0.27 0.48
                  (- 1.0 (/ center-distance (/ count 2.0))))
              :importance
                (user/detail-importance
                  (nth origin 0)
                  (- (nth origin 1) 1.35))
              :eye?
                (or (= i 1)
                    (= i (int (/ count 2)))
                    (= i (- count 2)))
              :accent
                (if (= 0 (mod i 2))
                  :deep-teal
                  :ember-coral)}

          (art.grammar/grow design user/firebird-feather-grammar
            {:origin origin
             :direction direction
             :length length
             :width width
             :rank i
             :side (if (< i (/ count 2)) :left :right)
             :heat (user/solar-heat
                     (nth origin 0)
                     (- (nth origin 1) 1.30))
             :importance importance
             :accent accent
             :eye? eye?}))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 11. Body, head, and solar core
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define user/generate-body
  (fn [design skeleton]
    ; The body is built from open contour lanes, not a single dense fill.
    ; The black shirt remains visible between lanes.
    (let {:spine (get skeleton :spine)
          :body-shape
            (vector/variable-width-stroke
              {:path spine
               :width-profile
                 [[0.00 {:millimeters 4.2}]
                  [0.25 {:millimeters 8.8}]
                  [0.58 {:millimeters 10.2}]
                  [0.82 {:millimeters 7.0}]
                  [1.00 {:millimeters 3.4}]]
               :cap :round})}

      (embroidery/add-shape design
        {:id dither://object/generated/firebird/body-understructure
         :shape body-shape
         :stitch
           {:kind :contour-fill
            :thread :bone-ivory
            :spacing {:millimeters 1.10}
            :stitch-length {:millimeters 1.80}
            :angle-field user/rising-flow
            :negative-space 0.38
            :underlay :edge-run}
         :role :body})

      ; Gold rachis lines tie the body to the tail and wings.
      (embroidery/add-stitch-path design
        {:id dither://object/generated/firebird/body-spine
         :path spine
         :stitch :bean
         :thread :antique-gold
         :passes 2
         :stitch-length {:millimeters 1.90}
         :role :body-spine})

      ; Head and neck.
      (embroidery/add-shape design
        {:id dither://object/generated/firebird/head
         :shape
           (vector/ellipse
             {:center (get-in skeleton [:head :center])
              :radius (get-in skeleton [:head :radius])})
         :stitch
           {:kind :contour-fill
            :thread :bone-ivory
            :spacing {:millimeters 1.0}
            :angle-field user/light-direction
            :negative-space 0.24}
         :role :head})

      (embroidery/add-shape design
        {:id dither://object/generated/firebird/beak
         :shape
           (vector/beak-shape
             {:origin [-0.34 1.67]
              :direction 3.05
              :length {:millimeters 8.0}
              :curve 0.34})
         :stitch
           {:kind :narrow-satin
            :thread :bone-ivory
            :angle :cross-form}
         :role :beak})

      (embroidery/add-shape design
        {:id dither://object/generated/firebird/eye
         :shape
           (vector/circle
             {:center [-0.24 1.70]
              :radius {:millimeters 1.15}})
         :stitch
           {:kind :tiny-satin
            :thread :dark-plum}
         :role :eye})

      (embroidery/add-stitch-path design
        {:id dither://object/generated/firebird/eye-glint
         :path
           (vector/line [-0.25 1.71] [-0.23 1.73])
         :stitch :bean
         :thread :bone-ivory
         :passes 2
         :role :eye-glint})

      ; The solar core is the high-value anchor. It is small enough for
      ; controlled fill and uses radiating stitch angle for metallic-like
      ; thread movement without requiring metallic thread.
      (let {:center (get skeleton :solar-core)
            :radius
              (get (custom/get user/firebird-art) :solar-core-radius)}
        (embroidery/add-shape design
          {:id dither://object/generated/firebird/solar-core
           :shape (vector/circle {:center center :radius radius})
           :stitch
             {:kind :radial-fill
              :thread :antique-gold
              :density :medium
              :underlay :center-cross
              :angle-origin center}
           :role :solar-core})

        (embroidery/add-radial-rays design
          {:id dither://object/generated/firebird/solar-rays
           :center center
           :count 21
           :inner-radius {:millimeters 9.5}
           :outer-radius-field
             (fn [i]
               {:millimeters
                 (user/lerp 13.0 23.0
                   (art/random
                     {:seed
                       (get (custom/get user/firebird-art) :seed)
                      :label :solar-ray
                      :index i}))})
           :thread :antique-gold
           :stitch :running
           :stitch-length {:millimeters 1.75}
           :skip-every 3
           :role :solar-rays})))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 12. Botanical flame filigree
;;
;; DESIGN TECHNIQUE:
;; A second grammar grows sparse fern/flame structures from the outside of
;; the wings and tail. It is clipped by stitch budget and silhouette clarity.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(define user/filigree-grammar
  (art.grammar/compile
    {:id dither://registry/motif-grammar/user/firebird-filigree
     :parameters
       {:origin :point
        :direction :angle
        :length :distance
        :depth :integer
        :side :keyword}

     :axiom
       [:sprig {:origin :origin
                :direction :direction
                :length :length
                :depth :depth
                :side :side}]

     :rules
       {:sprig
          [{:emit :stem
            :args {:origin :origin
                   :direction :direction
                   :length :length}}

           {:when '(> :depth 0)
            :repeat
              {:count 4
               :index :i
               :body
                 [:branch
                  {:origin
                    (grammar/along :stem
                      (/ (+ :i 1) 5.0))
                   :direction
                    (+ :direction
                       (* (grammar/signed-side :side)
                          (user/lerp 0.45 0.90
                            (/ :i 3.0))))
                   :length
                    (* :length
                       (user/lerp 0.28 0.46
                         (- 1.0 (/ :i 4.0))))
                   :depth (- :depth 1)
                   :side
                     (if (= :side :left) :right :left)}]}}]

        :branch
          [[:sprig {:origin :origin
                    :direction :direction
                    :length :length
                    :depth :depth
                    :side :side}]]

        :stem
          [{:stitch-path
            {:path
              (grammar/flame-curve
                {:origin :origin
                 :direction :direction
                 :length :length
                 :curl 0.31})
             :stitch :running
             :thread :antique-gold
             :stitch-length {:millimeters 1.85}
             :role :filigree}}]}

     :growth-constraints
       {:minimum-feature {:millimeters 1.20}
        :minimum-gap {:millimeters 1.05}
        :maximum-recursion 2
        :budget-source user/firebird-budgets}}))

(define user/generate-filigree
  (fn [design]
    (let {:count (get (custom/get user/firebird-art) :filigree-sprigs)}
      (for [i (range 0 count)]
        (let {:side (if (= 0 (mod i 2)) :left :right)
              :band (int (/ i 2))
              :y (user/lerp -2.35 1.65 (/ band 9.0))
              :x (if (= side :left)
                   (user/lerp -1.30 -1.96 (/ band 9.0))
                   (user/lerp 1.30 1.96 (/ band 9.0)))
              :direction
                (if (= side :left)
                  (user/lerp 2.35 1.72 (/ band 9.0))
                  (user/lerp 0.79 1.42 (/ band 9.0)))
              :length
                (user/paired-value
                  :filigree-length band side 0.31 0.66)}

          (art.grammar/grow design user/filigree-grammar
            {:origin [x y]
             :direction direction
             :length length
             :depth (if (= 0 (mod band 3)) 2 1)
             :side side}))))))


; Continue with recursive-firebird-se2000-part-2.dither in this same session.
