package d2isometricimg

import (
	

	
)

const hierarchyMaxDescent = .60

// Spend the most visible relief on the first source tier, with progressively
// smaller steps and a fixed bound even for very deep source nesting.
func hierarchyTierHeight( int) float64 {
	return hierarchyMaxDescent * (1 - math.Pow(2./3, float64(max(0, ))))
}

// Each independent visible root gets its own support plan. Deep containers
// never stretch an unrelated shallow diagram. Sequence-containing roots keep
// their existing background planes and semantic group washes.
func hierarchyStrongTerraces( []d2isometric.Board,  map[string]*d2isometric.Node,  map[string]bool,  []bool) {
	 := make(map[string]int, len())
	for ,  := range  {
		[.ID] = 
	}
	,  := make([]int, len()), make([]int, len())
	,  := make([]bool, len()), make([]bool, len())
	 := make([]uint8, len())
	var  func(int)
	 = func( int) {
		if [] != 0 {
			return
		}
		[], [] = 1, 
		 := []
		if ,  := [.ParentID];  && [] != 1 && .Kind != "platform" {
			()
			[], [] = [], []
		}
		 := [.SourceID]
		[] = .Kind == "group" &&  != nil && .SequenceRole == "" && .Opacity > 0 && .StrokeDash == 0 && nativePaint(.Fill, "transparent").A > 0
		if [] {
			[]++
		}
		[] = 2
	}
	for  := range  {
		()
		if [[].ID] || [] {
			[[]] = true
		}
	}
	 := make([]int, len())
	for  := range  {
		[[]] = max([[]], [])
	}
	for  := range  {
		 := []
		if [] || [] == 0 {
			continue
		}
		[].Position.Y = hierarchyTierHeight([]) - hierarchyTierHeight([])
		if [] == [] {
			[].Position.Y = 0
		}
		if [] {
			// A presentation-only kind keeps source paint physical even when
			// floating-point saturation makes a very deep final step zero.
			[].Kind = "terrace"
		}
	}
	for  := range  {
		if [].Kind != "terrace" {
			continue
		}
		 := hierarchyBaseSurfaceY([]) + hierarchyTierHeight([]-1) - hierarchyTierHeight([[]])
		if ,  := [[].ParentID];  {
			 = hierarchySurfaceY([])
		}
		[].Size.Y = max(0, hierarchySurfaceY([])-)
	}
}

func hierarchySupportOffsets( []d2isometric.Board) map[string]float64 {
	var  map[string]float64
	for ,  := range  {
		if .Position.Y < 0 {
			if  == nil {
				 = make(map[string]float64)
			}
			[.ID] = .Position.Y
		}
	}
	return 
}

// Solid contact queries use the same cap-anchored extension as construction.
// The body is taller beneath its original top; labels and route Y stay fixed.
type hierarchyExtension struct{ top, scale float64 }

func hierarchyNodeExtension( d2isometric.Node,  float64) hierarchyExtension {
	 := .Position.Y - .Size.Y/2
	 := nativeCanonicalHeight(, 0)
	if nativeSolidNode() {
		 = nativeSolidHeight()
	}
	 *= hierarchyNodeRelief()
	return hierarchyExtension{ + , 1 - min(0, )/max(.001, )}
}

func ( hierarchyExtension) ( float64) float64 {
	if  >= .top || .scale <= 1 {
		return 
	}
	return .top + (-.top)/.scale
}

func ( hierarchyExtension) ( float64) float64 {
	if  >= .top || .scale <= 1 {
		return 
	}
	return .top + (-.top)*.scale
}