get_aspect_ratio_property, get_direction_property, get_display_property, get_writing_mode, get_position, MultiValue,
// +spec:positioning:94ef0f - position property: static|relative|absolute|sticky|fixed, initial static, applies to all elements except table-column-group/table-column
pub fn get_position_type(styled_dom: &StyledDom, dom_id: Option<NodeId>) -> LayoutPosition {
// +spec:positioning:bda1d5 - resolves inset properties (top/right/bottom/left) as inward offsets per CSS Position 3 ยง3.1
// +spec:positioning:bf9168 - resolves inset properties (top/right/bottom/left) to control positioned box location
// +spec:positioning:f8e0a1 - inset properties (top/right/bottom/left) resolved for positioned elements; auto = unconstrained
// +spec:positioning:7ec143 - top/right/bottom/left offset resolution with percentage against containing block
// +spec:containing-block:d4b3b9 - percentage offsets resolve against CB width (left/right) or height (top/bottom)
MultiValue::Exact(pv) => Some(pv.resolve_with_context(&resolution_context, PropertyContext::Height)),
MultiValue::Exact(pv) => Some(pv.resolve_with_context(&resolution_context, PropertyContext::Height)),
MultiValue::Exact(pv) => Some(pv.resolve_with_context(&resolution_context, PropertyContext::Width)),
MultiValue::Exact(pv) => Some(pv.resolve_with_context(&resolution_context, PropertyContext::Width)),
// +spec:block-formatting-context:f5f992 - Out-of-flow: floated or absolutely positioned boxes laid out outside normal flow
// +spec:positioning:bb19f8 - absolute/fixed positioning: out-of-flow, positioned relative to containing block/viewport
// +spec:positioning:5bfef3 - abspos elements use static position for auto offsets, resolve against nearest positioned ancestor CB
// +spec:positioning:7fff75 - Absolute positioning: removed from flow, offset relative to containing block, establishes new CB
// +spec:positioning:839cbb - absolute elements positioned/sized solely relative to their containing block, modified by inset properties
// +spec:positioning:898590 - absolute positioning takes elements out of flow and positions them relative to containing block
// +spec:positioning:c37c1b - abspos boxes laid out in containing block after its final size is determined
// +spec:positioning:cbe481 - absolute positioning removes elements from flow and positions them relative to containing block
// +spec:positioning:3b3ba4 - Absolute positioning: box offset from containing block, removed from normal flow; fixed positioning: CB = viewport
// +spec:positioning:1d87f6 - Fixed/absolute positioning schemes with box offset resolution (top/right/bottom/left)
// +spec:positioning:c11be9 - absolute positioning: effect of box offsets depends on which properties are auto (non-replaced) or intrinsic dimensions (replaced)
// +spec:containing-block:83a32a - fixed positioning: containing block is viewport; absolute: nearest positioned ancestor or initial CB
// +spec:containing-block:faa9a3 - fixed positioning falls back to initial containing block (viewport) when no ancestor establishes one
// +spec:containing-block:faa9a3 - fixed positioning CB falls back to initial containing block (viewport) when no ancestor establishes one
// +spec:positioning:067eab - CB for fixed = viewport, for absolute = nearest positioned ancestor
// +spec:positioning:067eab - fixed CB is viewport; absolute CB is nearest positioned ancestor's padding-box
// +spec:positioning:9ccf9a - fixed-position CB is viewport (transform/will-change/contain could override, not yet implemented)
// +spec:positioning:f0ad47 - fixed elements use viewport as containing block; content outside viewport cannot be scrolled to
// +spec:positioning:623e45 - inset properties reduce the containing block into the inset-modified containing block
// +spec:positioning:9a90a3 - static position: the position the element would have had in normal flow
// +spec:positioning:ca3e89 - static-position rectangle uses block-start inline-start alignment (CSS2.1 hypothetical box)
// +spec:positioning:16d82c - vertical dimension constraint for abs-positioned non-replaced elements
// +spec:positioning:8f474b - ยง10.6.4 vertical constraint for absolutely positioned non-replaced elements
// +spec:positioning:d730e5 - CB height is independent of the abspos element, so percentage heights always resolve
// +spec:overflow:941a06 - resolve auto inset properties: if only one is auto, solved to zero via constraint; if both auto, use static position
// +spec:height-calculation:2f6e10 - if bottom is auto, replace auto margin-top/margin-bottom with 0
// +spec:box-model:3a9c2a - resolving auto insets: static position fallback when insets are auto
// +spec:box-model:bd442c - weaker inset resolves to align margin box with inset-modified CB edge
// +spec:height-calculation:93e91c - abs non-replaced height: auto margin centering, single auto margin solve, over-constrained ignore bottom
// +spec:positioning:6e7732 - ยง10.6.4 vertical constraint equation for abspos non-replaced elements
// +spec:positioning:b63d0f - absolute positioning with top:auto uses static position (change bars example)
// +spec:positioning:da8a0c - resolving auto insets: normal alignment treated as start, so auto insets resolve to static position
// +spec:positioning:820b22 - 10.6.4: absolutely positioned non-replaced elements vertical constraint equation and 6 rules
// +spec:positioning:08e0ac - absolute element with top:auto uses static position (current line)
// +spec:positioning:d9bb3c - hypothetical position: UA may guess static position rather than fully computing hypothetical box
// +spec:height-calculation:51627d - auto margins to 0, top = static position, height from content (rule 3)
// +spec:positioning:460f2f - All three auto: set top to static position, height from content, solve for bottom
// +spec:overflow:fc0c9e - over-constrained abspos: auto margins minimize overflow (CSS2.1 equivalent of Box Alignment 3 safe alignment)
// +spec:height-calculation:03c071 - none auto: equal auto margins, solve single auto margin, or ignore bottom if over-constrained
// +spec:height-calculation:909b50 - top and height auto, bottom not auto: height from BFC auto heights, solve for top
// +spec:positioning:64e1ba - top+bottom auto, height not auto: set top to static position, solve for bottom
// +spec:intrinsic-sizing:c7227f - except: if box has aspect-ratio, ratio-dependent axis uses max-content
// +spec:containing-block:b3f0dd - clamp effective CB size to zero when insets exceed it (weaker inset reduced)
used_height = (cb_height - top_val - used_margin_top - used_margin_bottom - bottom_val).max(0.0);
// +spec:width-calculation:1661b4 - constraint equation and six rules for abs-pos horizontal (ยง10.3.7)
// +spec:replaced-elements:7d8ba8 - ยง10.3.8: for absolutely positioned replaced elements, width is determined
let width_is_auto = get_css_width(ctx.styled_dom, dom_id, node_state).is_auto() && !is_replaced;
// +spec:width-calculation:942c77 - abs-pos non-replaced width: auto margins, over-constrained resolution
// +spec:width-calculation:dff69d - ยง10.3.7 abs-pos non-replaced: none auto โ equal auto margins, solve single auto margin, or over-constrained
// +spec:writing-modes:9c3b40 - abspos auto margins: if negative remaining in inline axis, start margin=0, end margin gets remainder
// +spec:overflow:f323cb - auto inset: align margin box to stronger inset edge (may overflow CB)
// +spec:width-calculation:bbf97a - set auto margins to 0 for abspos when left/width/right has auto
// +spec:width-calculation:0c29ce - set auto margins to 0, then apply six rules for abs pos width
// +spec:width-calculation:2b2852 - all three auto: set auto margins to 0, use static position for left (LTR)
// +spec:width-calculation:c120b3 - all three of left/width/right auto: set auto margins to 0, then use direction to pick static position
// +spec:intrinsic-sizing:c7227f - except: if box has aspect-ratio, ratio-dependent axis uses max-content
// +spec:positioning:5b0d7f - relative positioning: offset from normal flow position, siblings unaffected
// +spec:positioning:8afbe2 - Relative positioning preserves normal flow size and space; only visual offset applied after layout
// +spec:positioning:b22222 - relative positioning: offset from static position, purely visual effect
// +spec:positioning:b814b6 - relative/absolute/fixed positioning scheme (CSS Positioned Layout Module Level 3)
// +spec:block-formatting-context:60ccf9 - relative positioning shifts inline boxes as a unit after normal flow
// +spec:display-property:17239f - relative positioning offsets element after normal flow; abspos elements taken out of flow
// +spec:positioning:2d8e15 - relative positioning shifts elements as a unit after normal flow without affecting surrounding content
// +spec:overflow:cfb09a - Sticky positioning uses relative-like offsets, clamped to nearest scrollport at scroll time
// +spec:table-layout:6cb73b - position:relative effect on table elements is undefined; skip them
// +spec:positioning:4614dd - position does not apply to table-column-group or table-column boxes
// +spec:positioning:418c74 - inset percentages resolve against containing block size per axis; auto is unconstrained
// +spec:positioning:a2e5f1 - relative positioning shifts element from static position (vs absolute/float)
// +spec:positioning:218b50 - Relative positioning: top=-bottom, left=-right, direction-dependent resolution, top wins over bottom
// +spec:overflow:53dffd - both left/right auto โ used values are 0, boxes stay in original position
// +spec:positioning:d189de - bottom offset for relative positioning is with respect to the box's own bottom edge
// +spec:positioning:d80f47 - opposing inset values are negations: top wins over bottom, left/right per direction
// +spec:positioning:ecc27c - relative positioning: left/right move box horizontally without changing size, left = -right
// +spec:positioning:ac768b - relative positioning: both autoโ0, one autoโneg of other, neitherโtop wins; direction-aware left/right
// +spec:positioning:e3727e - top/bottom: both autoโ0, one autoโnegative of other, neither autoโbottom ignored
// +spec:positioning:1732e8 - left/right for relatively positioned elements determined by 9.4.3 rules
// Spec: "If the 'direction' property of the containing block is 'ltr', the value of 'left' wins"
// +spec:containing-block:6d4fb1 - over-constrained relative positioning: ltrโleft wins, rtlโright wins
// +spec:overflow:f1e1ce - relative positioning may cause overflow:auto/scroll boxes to need scrollbars
// +spec:table-layout:ec2600 - For table-row-group, table-header-group, table-footer-group, or table-row,
// +spec:overflow:bac4e5 - sticky view rectangle from inset properties relative to nearest scrollport
/// +spec:position-sticky:9449f1 - for sticky positioning, insets represent offsets from scrollport edge
/// +spec:box-model:af9af8 - sticky positioning: shift element to stay within sticky view rectangle, margin box constrained to containing block
/// +spec:overflow:bac4e5 - compute sticky view rectangle, clamp end-edge insets to border box size
let sticky_edge = scrollport.origin.y + scroll_offset.y + scrollport.size.height - bottom_inset;
// +spec:positioning:22f165 - absolute/fixed containing block: nearest positioned ancestor's padding-box, or initial CB
// +spec:containing-block:10af51 - absolutely positioned element's CB is nearest positioned ancestor
// +spec:positioning:2d0dbb - containing block for abspos is padding-box of nearest positioned ancestor, or initial CB
// +spec:positioning:3ac06c - abspos positioned relative to containing block ignoring fragmentation breaks
// +spec:positioning:d7e4b4 - containing block of abspos element is always definite (returns concrete LogicalRect)
// +spec:containing-block:18ae8e - Absolute positioning: abs-pos box establishes new CB for normal flow and abs-pos (but not fixed) descendants
// +spec:display-property:5a39bc - containing block for abspos is nearest positioned ancestor or initial containing block
// +spec:positioning:09a0fa - Absolute positioning: CB is padding-box of nearest positioned ancestor
// +spec:positioning:467cb1 - Containing block for abs pos = nearest positioned ancestor or initial CB
// +spec:positioning:99d0bb - containing block for absolute elements is nearest positioned ancestor
// +spec:positioning:92e099 - containing block for abs pos is nearest positioned ancestor or initial CB
// +spec:positioning:f57523 - containing block of abspos element is always definite (returns concrete LogicalRect)
// +spec:positioning:8f50de - relatively positioned parent serves as containing block for abspos descendants
// +spec:containing-block:6bcb0c - containing block is padding edge of nearest positioned ancestor, or initial containing block if none
// +spec:containing-block:bf17e5 - containing block for abspos is padding box of nearest positioned ancestor, or initial CB
// +spec:containing-block:d0f92d - containing block for positioned box is nearest positioned ancestor, or initial containing block
// +spec:containing-block:d7e013 - containing block for positioned box is nearest positioned ancestor or initial CB
// +spec:containing-block:05bc0d - positioning an element changes which ancestor establishes the CB for its descendants
// +spec:positioning:355ee4 - CB for abspos is padding edge of nearest positioned ancestor, or initial CB
// +spec:positioning:383794 - Containing block for abspos is nearest positioned ancestor, or initial containing block if none
// +spec:positioning:5b3e43 - Containing block for abs-pos is padding box of nearest positioned ancestor, or initial CB
// +spec:positioning:882e67 - containing block for abs pos is nearest positioned ancestor or initial CB
// +spec:positioning:292c5c - relative parent serves as containing block for absolute descendants
// +spec:positioning:aa361e - values other than static make a box positioned and establish an abspos containing block
// +spec:containing-block:6bcb0c - containing block formed by padding edge of nearest positioned ancestor
// +spec:positioning:df1921 - abs-pos percentage widths resolve against padding box of containing block
// +spec:positioning:3d88c9 - abspos available space is always definite (viewport or positioned ancestor padding box)
// +spec:containing-block:141dcc - absolute element with no positioned ancestor uses initial containing block
// +spec:containing-block:657f2f - containing block becomes initial containing block when no positioned ancestors
// +spec:containing-block:7f5090 - if no ancestor establishes one, absolute positioning CB is initial containing block
// +spec:containing-block:7f5090 - fallback to initial containing block when no positioned ancestor
// +spec:containing-block:ad5ebc - no positioned ancestor: containing block becomes the initial containing block
// +spec:display-property:813192 - abspos containing block falls back to initial containing block (viewport) when no positioned ancestor