///|
// Nested element node construction with pre-computed selector context.

///|
fn element_to_node_with_styles_internal(
  elem : @html.Element,
  selector_elem : @css.Element,
  ctx : RenderContext,
  stylesheets : Array[@css.Stylesheet],
  indexed_stylesheets : Array[@css.IndexedStylesheet],
  parent_style : @style.Style?,
  css_vars : Map[String, String],
  incoming_counters : Map[String, CounterEntry],
  owner_id : String,
) -> @node.Node {
  let below_viewport = should_use_viewport_skeleton()
  if below_viewport {
    return build_viewport_skeleton_node(
      elem, selector_elem, ctx, stylesheets, indexed_stylesheets, parent_style, css_vars,
      incoming_counters, owner_id,
    )
  }
  // Incremental cascade (Phase 1): when a reuse pass is active and this element
  // is clean (unchanged inputs + clean ancestors under a reuse-safe stylesheet),
  // reuse its prior computed style instead of re-running the cascade. `owner_id`
  // is the structural key; downstream adjustments re-run identically for a clean
  // node. See docs/incremental-cascade-design.md.
  let computed_style = match cascade_reuse_try(owner_id, elem) {
    Some(reused) => reused
    None => {
      let s = compute_element_style_indexed(
        selector_elem,
        elem.style,
        indexed_stylesheets,
        false,
        ctx,
        parent_style,
        css_vars,
      )
      cascade_reuse_record(owner_id, s)
      s
    }
  }
  viewport_full_node_count.val += 1
  let tag_lower = elem.tag.to_lower()
  let computed_style = apply_element_visibility_attributes(
    computed_style,
    elem.attributes,
    tag_lower,
  )
  if computed_style.display == @types.Display::None {
    return attach_dom_id(
      @node.Node::leaf(make_node_id(elem), computed_style),
      elem,
    )
  }
  if should_advance_viewport_estimate(computed_style) {
    viewport_estimated_y.val += computed_style.line_height
  }
  let style = adjust_nested_element_style(
    elem, selector_elem, tag_lower, computed_style, stylesheets, indexed_stylesheets,
    ctx, css_vars,
  )

  let element_css_vars = compute_element_css_vars_indexed(
    selector_elem,
    elem.style,
    indexed_stylesheets,
    ctx,
    css_vars,
  )
  let (own_counters, before_pseudo, after_pseudo, style) = resolve_element_counter_pseudos(
    incoming_counters,
    selector_elem,
    style,
    stylesheets,
    ctx,
    owner_id,
    below_viewport,
    element_css_vars,
    elem.attributes,
  )
  let children = build_styled_element_children(
    elem, selector_elem, tag_lower, style, ctx, stylesheets, indexed_stylesheets,
    element_css_vars, own_counters, owner_id, before_pseudo, after_pseudo,
  )

  let children = if tag_lower == "details" && !elem.attributes.contains("open") {
    prune_closed_details_children(children)
  } else {
    children
  }
  attach_dom_id(
    finalize_special_element_node(
      elem, tag_lower, style, children, element_css_vars,
    ),
    elem,
  )
}