Skip to main content

azul_css/props/
property.rs

1//! Defines the core `CssProperty` enum, which represents any single parsed CSS property,
2//! as well as top-level functions for parsing CSS keys and values.
3
4use alloc::{
5    boxed::Box,
6    collections::btree_map::BTreeMap,
7    string::{String, ToString},
8    vec::Vec,
9};
10use core::fmt;
11
12use crate::{
13    corety::AzString,
14    css::{BoxOrStatic, CssPropertyValue},
15    props::basic::{error::InvalidValueErr, pixel::PixelValueWithAuto},
16};
17// Import all property types from their new locations.
18// wildcard imports: this is the property aggregator module that pulls in every
19// property type from its sub-modules; enumerating them all explicitly would be
20// unmaintainable and defeats the purpose of the per-category modules.
21#[allow(clippy::wildcard_imports)]
22use crate::{
23    codegen::format::FormatAsRustCode,
24    props::{
25        basic::{
26            color::{parse_css_color, ColorU, CssColorParseError, CssColorParseErrorOwned},
27            font::{
28                parse_style_font_family, CssStyleFontFamilyParseError,
29                CssStyleFontFamilyParseErrorOwned, StyleFontFamilyVec, *,
30            },
31            length::{parse_float_value, parse_percentage_value, FloatValue, PercentageValue},
32            pixel::{
33                parse_pixel_value, CssPixelValueParseError, CssPixelValueParseErrorOwned,
34                PixelValue,
35            },
36            DurationParseError, DurationParseErrorOwned, InterpolateResolver, InvalidValueErrOwned,
37            PercentageParseError,
38        },
39        formatter::PrintAsCssValue,
40        layout::{
41            column::*, dimensions::*, display::*, flex::*, flow::*, fragmentation::*, grid::*,
42            overflow::*, position::*, shape::*, spacing::*, table::*, text::*, wrapping::*,
43        },
44        style::{
45            background::*, border::*, border_radius::*, box_shadow::*, content::*, effects::*,
46            exclusion::*, filter::*, lists::*, scrollbar::*, spatial_nav::*, text::*,
47            transform::*, SelectionBackgroundColor, SelectionColor, SelectionRadius,
48        },
49    },
50};
51
52const COMBINED_CSS_PROPERTIES_KEY_MAP: [(CombinedCssPropertyType, &str); 31] = [
53    (CombinedCssPropertyType::BorderRadius, "border-radius"),
54    (CombinedCssPropertyType::Overflow, "overflow"),
55    (
56        CombinedCssPropertyType::OverscrollBehavior,
57        "overscroll-behavior",
58    ),
59    (CombinedCssPropertyType::Padding, "padding"),
60    (CombinedCssPropertyType::Margin, "margin"),
61    (CombinedCssPropertyType::Border, "border"),
62    (CombinedCssPropertyType::BorderLeft, "border-left"),
63    (CombinedCssPropertyType::BorderRight, "border-right"),
64    (CombinedCssPropertyType::BorderTop, "border-top"),
65    (CombinedCssPropertyType::BorderBottom, "border-bottom"),
66    (CombinedCssPropertyType::BorderColor, "border-color"),
67    (CombinedCssPropertyType::BorderStyle, "border-style"),
68    (CombinedCssPropertyType::BorderWidth, "border-width"),
69    (CombinedCssPropertyType::BoxShadow, "box-shadow"),
70    (CombinedCssPropertyType::BackgroundColor, "background-color"),
71    (CombinedCssPropertyType::BackgroundImage, "background-image"),
72    (CombinedCssPropertyType::Background, "background"),
73    (CombinedCssPropertyType::Flex, "flex"),
74    (CombinedCssPropertyType::Grid, "grid"),
75    (CombinedCssPropertyType::Gap, "gap"),
76    (CombinedCssPropertyType::GridGap, "grid-gap"),
77    (CombinedCssPropertyType::Font, "font"),
78    (CombinedCssPropertyType::Columns, "columns"),
79    (CombinedCssPropertyType::GridArea, "grid-area"),
80    (CombinedCssPropertyType::ColumnRule, "column-rule"),
81    (CombinedCssPropertyType::TextBox, "text-box"),
82    // +spec:writing-modes:798cca - inset-block/inset-inline shorthand properties
83    (CombinedCssPropertyType::InsetBlock, "inset-block"),
84    (CombinedCssPropertyType::InsetInline, "inset-inline"),
85    // SVG's `fill` IS a background: an SVG shape's box is clipped to its own
86    // geometry, so filling the box fills the shape. Aliasing it here rather
87    // than adding a parallel paint model is what lets all three spellings -
88    // the presentation attribute, `style="fill:…"`, and a stylesheet rule
89    // matching `class="ColorScheme-Text"` - resolve through the ONE cascade,
90    // and it brings every background feature along: a gradient fill, an image
91    // fill and a `:hover` fill need no further plumbing.
92    //
93    // Placed LAST on purpose: `Display for CombinedCssPropertyType` returns
94    // the first name for a type, so this stays an accepted input spelling
95    // without becoming the printed one.
96    (CombinedCssPropertyType::BackgroundColor, "fill"),
97    // ... and SVG's `stroke` is the BORDER of that same box. An SVG shape's
98    // box is clipped to its geometry and can never show a rectangular border,
99    // so the border slots are free, and reusing them means a stroke is styled
100    // by the same cascade as everything else: `stroke="…"`, `style="stroke:…"`
101    // and a stylesheet rule all land in one place. The display list turns them
102    // into a STROKED PATH rather than a rectangle - a stroke follows the
103    // geometry, which is the whole difference between it and a border.
104    (CombinedCssPropertyType::BorderColor, "stroke"),
105    (CombinedCssPropertyType::BorderWidth, "stroke-width"),
106];
107
108const CSS_PROPERTY_KEY_MAP: [(CssPropertyType, &str); 196] = [
109    (CssPropertyType::Display, "display"),
110    (CssPropertyType::Float, "float"),
111    (CssPropertyType::BoxSizing, "box-sizing"),
112    (CssPropertyType::TextColor, "color"),
113    (CssPropertyType::FontSize, "font-size"),
114    (CssPropertyType::FontFamily, "font-family"),
115    (CssPropertyType::FontWeight, "font-weight"),
116    (CssPropertyType::FontStyle, "font-style"),
117    (CssPropertyType::TextAlign, "text-align"),
118    (CssPropertyType::TextJustify, "text-justify"),
119    (CssPropertyType::VerticalAlign, "vertical-align"),
120    (CssPropertyType::LetterSpacing, "letter-spacing"),
121    (CssPropertyType::LineHeight, "line-height"),
122    (CssPropertyType::WordSpacing, "word-spacing"),
123    (CssPropertyType::TabSize, "tab-size"),
124    (CssPropertyType::WhiteSpace, "white-space"),
125    (CssPropertyType::Hyphens, "hyphens"),
126    (CssPropertyType::WordBreak, "word-break"),
127    (CssPropertyType::OverflowWrap, "overflow-wrap"),
128    (CssPropertyType::OverflowWrap, "word-wrap"), // +spec:line-breaking:45074d - word-wrap is legacy name alias for overflow-wrap
129    (CssPropertyType::LineBreak, "line-break"),
130    (CssPropertyType::TextOverflow, "text-overflow"),
131    (CssPropertyType::ObjectFit, "object-fit"),
132    (CssPropertyType::ObjectPosition, "object-position"),
133    (CssPropertyType::AspectRatio, "aspect-ratio"),
134    (CssPropertyType::TextOrientation, "text-orientation"),
135    (CssPropertyType::TextAlignLast, "text-align-last"),
136    (CssPropertyType::TextTransform, "text-transform"),
137    (CssPropertyType::Direction, "direction"),
138    (CssPropertyType::UserSelect, "user-select"),
139    (CssPropertyType::TextDecoration, "text-decoration"),
140    (CssPropertyType::TextIndent, "text-indent"),
141    (CssPropertyType::InitialLetter, "initial-letter"),
142    (CssPropertyType::LineClamp, "line-clamp"),
143    (CssPropertyType::HangingPunctuation, "hanging-punctuation"),
144    (CssPropertyType::TextCombineUpright, "text-combine-upright"),
145    (CssPropertyType::UnicodeBidi, "unicode-bidi"),
146    (CssPropertyType::TextBoxTrim, "text-box-trim"),
147    (CssPropertyType::TextBoxEdge, "text-box-edge"),
148    (CssPropertyType::DominantBaseline, "dominant-baseline"),
149    (CssPropertyType::AlignmentBaseline, "alignment-baseline"),
150    // +spec:inline-block:939f05 - baseline-source longhand (auto | first | last)
151    (CssPropertyType::BaselineSource, "baseline-source"),
152    // +spec:line-height:cc03df - line-fit-edge longhand (leading | text | cap | ex | ...)
153    (CssPropertyType::LineFitEdge, "line-fit-edge"),
154    (CssPropertyType::InitialLetterAlign, "initial-letter-align"),
155    (CssPropertyType::InitialLetterWrap, "initial-letter-wrap"),
156    (CssPropertyType::ScrollbarGutter, "scrollbar-gutter"),
157    (CssPropertyType::OverflowClipMargin, "overflow-clip-margin"),
158    // +spec:overflow:297dc3 - clip rect() auto values resolve to border box edges
159    (CssPropertyType::Clip, "clip"),
160    (CssPropertyType::ExclusionMargin, "-azul-exclusion-margin"),
161    (
162        CssPropertyType::HyphenationLanguage,
163        "-azul-hyphenation-language",
164    ),
165    (CssPropertyType::Cursor, "cursor"),
166    (CssPropertyType::Width, "width"),
167    (CssPropertyType::Height, "height"),
168    (CssPropertyType::MinWidth, "min-width"),
169    (CssPropertyType::MinHeight, "min-height"),
170    (CssPropertyType::MaxWidth, "max-width"),
171    (CssPropertyType::MaxHeight, "max-height"),
172    (CssPropertyType::Position, "position"),
173    (CssPropertyType::Top, "top"),
174    (CssPropertyType::Right, "right"),
175    (CssPropertyType::Left, "left"),
176    (CssPropertyType::Bottom, "bottom"),
177    (CssPropertyType::ZIndex, "z-index"),
178    (CssPropertyType::FlexWrap, "flex-wrap"),
179    (CssPropertyType::FlexDirection, "flex-direction"),
180    (CssPropertyType::FlexGrow, "flex-grow"),
181    (CssPropertyType::FlexShrink, "flex-shrink"),
182    (CssPropertyType::FlexBasis, "flex-basis"),
183    (CssPropertyType::JustifyContent, "justify-content"),
184    (CssPropertyType::AlignItems, "align-items"),
185    (CssPropertyType::AlignContent, "align-content"),
186    (CssPropertyType::ColumnGap, "column-gap"),
187    (CssPropertyType::RowGap, "row-gap"),
188    (
189        CssPropertyType::GridTemplateColumns,
190        "grid-template-columns",
191    ),
192    (CssPropertyType::GridTemplateRows, "grid-template-rows"),
193    (CssPropertyType::GridAutoColumns, "grid-auto-columns"),
194    (CssPropertyType::GridAutoRows, "grid-auto-rows"),
195    (CssPropertyType::GridColumn, "grid-column"),
196    (CssPropertyType::GridRow, "grid-row"),
197    (CssPropertyType::GridTemplateAreas, "grid-template-areas"),
198    (CssPropertyType::WritingMode, "writing-mode"),
199    (CssPropertyType::Clear, "clear"),
200    (CssPropertyType::OverflowX, "overflow-x"),
201    (CssPropertyType::OverflowY, "overflow-y"),
202    // +spec:overflow:17654b - overflow-block and overflow-inline logical properties
203    (CssPropertyType::OverflowBlock, "overflow-block"),
204    (CssPropertyType::OverflowInline, "overflow-inline"),
205    (CssPropertyType::PaddingTop, "padding-top"),
206    (CssPropertyType::PaddingLeft, "padding-left"),
207    (CssPropertyType::PaddingRight, "padding-right"),
208    (CssPropertyType::PaddingBottom, "padding-bottom"),
209    (CssPropertyType::PaddingInlineStart, "padding-inline-start"),
210    (CssPropertyType::PaddingInlineEnd, "padding-inline-end"),
211    (CssPropertyType::MarginTop, "margin-top"),
212    (CssPropertyType::MarginLeft, "margin-left"),
213    (CssPropertyType::MarginRight, "margin-right"),
214    (CssPropertyType::MarginBottom, "margin-bottom"),
215    (CssPropertyType::BackgroundContent, "background"),
216    (CssPropertyType::BackgroundPosition, "background-position"),
217    (CssPropertyType::BackgroundSize, "background-size"),
218    (CssPropertyType::BackgroundRepeat, "background-repeat"),
219    (
220        CssPropertyType::BorderTopLeftRadius,
221        "border-top-left-radius",
222    ),
223    (
224        CssPropertyType::BorderTopRightRadius,
225        "border-top-right-radius",
226    ),
227    (
228        CssPropertyType::BorderBottomLeftRadius,
229        "border-bottom-left-radius",
230    ),
231    (
232        CssPropertyType::BorderBottomRightRadius,
233        "border-bottom-right-radius",
234    ),
235    (CssPropertyType::BorderTopColor, "border-top-color"),
236    (CssPropertyType::BorderRightColor, "border-right-color"),
237    (CssPropertyType::BorderLeftColor, "border-left-color"),
238    (CssPropertyType::BorderBottomColor, "border-bottom-color"),
239    (CssPropertyType::BorderTopStyle, "border-top-style"),
240    (CssPropertyType::BorderRightStyle, "border-right-style"),
241    (CssPropertyType::BorderLeftStyle, "border-left-style"),
242    (CssPropertyType::BorderBottomStyle, "border-bottom-style"),
243    (CssPropertyType::BorderTopWidth, "border-top-width"),
244    (CssPropertyType::BorderRightWidth, "border-right-width"),
245    (CssPropertyType::BorderLeftWidth, "border-left-width"),
246    (CssPropertyType::BorderBottomWidth, "border-bottom-width"),
247    (CssPropertyType::BoxShadowTop, "-azul-box-shadow-top"),
248    (CssPropertyType::BoxShadowRight, "-azul-box-shadow-right"),
249    (CssPropertyType::BoxShadowLeft, "-azul-box-shadow-left"),
250    (CssPropertyType::BoxShadowBottom, "-azul-box-shadow-bottom"),
251    (CssPropertyType::ScrollbarTrack, "-azul-scrollbar-track"),
252    (CssPropertyType::ScrollbarThumb, "-azul-scrollbar-thumb"),
253    (CssPropertyType::ScrollbarButton, "-azul-scrollbar-button"),
254    (CssPropertyType::ScrollbarCorner, "-azul-scrollbar-corner"),
255    (CssPropertyType::ScrollbarResizer, "-azul-scrollbar-resizer"),
256    (CssPropertyType::CaretColor, "caret-color"),
257    (
258        CssPropertyType::CaretAnimationDuration,
259        "caret-animation-duration",
260    ),
261    (CssPropertyType::CaretWidth, "-azul-caret-width"),
262    (
263        CssPropertyType::SelectionBackgroundColor,
264        "-azul-selection-background-color",
265    ),
266    (CssPropertyType::SelectionColor, "-azul-selection-color"),
267    (CssPropertyType::SelectionRadius, "-azul-selection-radius"),
268    (CssPropertyType::ScrollbarWidth, "scrollbar-width"),
269    (
270        CssPropertyType::OverscrollBehaviorX,
271        "overscroll-behavior-x",
272    ),
273    (
274        CssPropertyType::OverscrollBehaviorY,
275        "overscroll-behavior-y",
276    ),
277    (CssPropertyType::ScrollbarColor, "scrollbar-color"),
278    (
279        CssPropertyType::ScrollbarVisibility,
280        "-azul-scrollbar-visibility",
281    ),
282    (
283        CssPropertyType::ScrollbarFadeDelay,
284        "-azul-scrollbar-fade-delay",
285    ),
286    (
287        CssPropertyType::ScrollbarFadeDuration,
288        "-azul-scrollbar-fade-duration",
289    ),
290    (CssPropertyType::Opacity, "opacity"),
291    (CssPropertyType::Visibility, "visibility"),
292    (CssPropertyType::Transform, "transform"),
293    (CssPropertyType::PerspectiveOrigin, "perspective-origin"),
294    (CssPropertyType::TransformOrigin, "transform-origin"),
295    (CssPropertyType::BackfaceVisibility, "backface-visibility"),
296    (CssPropertyType::AppRegion, "-azul-app-region"),
297    // Electron spells it `-webkit-app-region`; accept that too so existing
298    // CSS ports over without a rewrite.
299    (CssPropertyType::AppRegion, "-webkit-app-region"),
300    // CSS Spatial Navigation Level 1. Unprefixed: these are real spec
301    // properties, not azul extensions.
302    (
303        CssPropertyType::SpatialNavigationAction,
304        "spatial-navigation-action",
305    ),
306    (
307        CssPropertyType::SpatialNavigationContain,
308        "spatial-navigation-contain",
309    ),
310    (CssPropertyType::Animation, "animation"),
311    (CssPropertyType::AnimationIn, "-azul-animation-in"),
312    (CssPropertyType::AnimationOut, "-azul-animation-out"),
313    (CssPropertyType::MixBlendMode, "mix-blend-mode"),
314    (CssPropertyType::Filter, "filter"),
315    (CssPropertyType::BackdropFilter, "backdrop-filter"),
316    (CssPropertyType::TextShadow, "text-shadow"),
317    (CssPropertyType::GridAutoFlow, "grid-auto-flow"),
318    (CssPropertyType::JustifySelf, "justify-self"),
319    (CssPropertyType::JustifyItems, "justify-items"),
320    (CssPropertyType::Gap, "gap"),
321    (CssPropertyType::GridGap, "grid-gap"),
322    (CssPropertyType::AlignSelf, "align-self"),
323    (CssPropertyType::Font, "font"),
324    (CssPropertyType::BreakBefore, "break-before"),
325    (CssPropertyType::BreakAfter, "break-after"),
326    (CssPropertyType::BreakInside, "break-inside"),
327    // CSS 2.1 legacy aliases for page breaking
328    (CssPropertyType::BreakBefore, "page-break-before"),
329    (CssPropertyType::BreakAfter, "page-break-after"),
330    (CssPropertyType::BreakInside, "page-break-inside"),
331    (CssPropertyType::Orphans, "orphans"),
332    (CssPropertyType::Widows, "widows"),
333    (CssPropertyType::BoxDecorationBreak, "box-decoration-break"),
334    (CssPropertyType::ColumnCount, "column-count"),
335    (CssPropertyType::ColumnWidth, "column-width"),
336    (CssPropertyType::ColumnSpan, "column-span"),
337    (CssPropertyType::ColumnFill, "column-fill"),
338    (CssPropertyType::ColumnRuleWidth, "column-rule-width"),
339    (CssPropertyType::ColumnRuleStyle, "column-rule-style"),
340    (CssPropertyType::ColumnRuleColor, "column-rule-color"),
341    (CssPropertyType::FlowInto, "flow-into"),
342    (CssPropertyType::FlowFrom, "flow-from"),
343    (CssPropertyType::ShapeOutside, "shape-outside"),
344    (CssPropertyType::ShapeInside, "shape-inside"),
345    (CssPropertyType::ClipPath, "clip-path"),
346    (CssPropertyType::ShapeMargin, "shape-margin"),
347    (
348        CssPropertyType::ShapeImageThreshold,
349        "shape-image-threshold",
350    ),
351    (CssPropertyType::Content, "content"),
352    (CssPropertyType::CounterReset, "counter-reset"),
353    (CssPropertyType::CounterIncrement, "counter-increment"),
354    (CssPropertyType::ListStyleType, "list-style-type"),
355    (CssPropertyType::ListStylePosition, "list-style-position"),
356    (CssPropertyType::StringSet, "string-set"),
357    // CSS 2.1 table properties (value parsers already exist; these key-map
358    // entries make them reachable from stylesheet text via parser2).
359    (CssPropertyType::TableLayout, "table-layout"),
360    (CssPropertyType::BorderCollapse, "border-collapse"),
361    (CssPropertyType::BorderSpacing, "border-spacing"),
362    (CssPropertyType::CaptionSide, "caption-side"),
363    (CssPropertyType::EmptyCells, "empty-cells"),
364];
365
366// Type aliases for `CssPropertyValue<T>`
367pub type CaretColorValue = CssPropertyValue<CaretColor>;
368pub type CaretAnimationDurationValue = CssPropertyValue<CaretAnimationDuration>;
369pub type StyleAnimationValue = CssPropertyValue<crate::props::basic::animation::StyleAnimation>;
370pub type StyleAnimationVecValue =
371    CssPropertyValue<crate::props::basic::animation::StyleAnimationVec>;
372pub type CaretWidthValue = CssPropertyValue<CaretWidth>;
373pub type SelectionBackgroundColorValue = CssPropertyValue<SelectionBackgroundColor>;
374pub type SelectionColorValue = CssPropertyValue<SelectionColor>;
375pub type SelectionRadiusValue = CssPropertyValue<SelectionRadius>;
376pub type StyleBackgroundContentVecValue = CssPropertyValue<StyleBackgroundContentVec>;
377pub type StyleBackgroundPositionVecValue = CssPropertyValue<StyleBackgroundPositionVec>;
378pub type StyleBackgroundSizeVecValue = CssPropertyValue<StyleBackgroundSizeVec>;
379pub type StyleBackgroundRepeatVecValue = CssPropertyValue<StyleBackgroundRepeatVec>;
380pub type StyleFontSizeValue = CssPropertyValue<StyleFontSize>;
381pub type StyleFontFamilyVecValue = CssPropertyValue<StyleFontFamilyVec>;
382pub type StyleFontWeightValue = CssPropertyValue<StyleFontWeight>;
383pub type StyleFontStyleValue = CssPropertyValue<StyleFontStyle>;
384pub type StyleTextColorValue = CssPropertyValue<StyleTextColor>;
385pub type StyleTextAlignValue = CssPropertyValue<StyleTextAlign>;
386pub type StyleVerticalAlignValue = CssPropertyValue<StyleVerticalAlign>;
387pub type StyleLineHeightValue = CssPropertyValue<StyleLineHeight>;
388pub type StyleLetterSpacingValue = CssPropertyValue<StyleLetterSpacing>;
389pub type StyleTextIndentValue = CssPropertyValue<StyleTextIndent>;
390pub type StyleInitialLetterValue = CssPropertyValue<StyleInitialLetter>;
391pub type StyleLineClampValue = CssPropertyValue<StyleLineClamp>;
392pub type StyleHangingPunctuationValue = CssPropertyValue<StyleHangingPunctuation>;
393pub type StyleTextCombineUprightValue = CssPropertyValue<StyleTextCombineUpright>;
394pub type StyleUnicodeBidiValue = CssPropertyValue<StyleUnicodeBidi>;
395pub type StyleTextBoxTrimValue = CssPropertyValue<StyleTextBoxTrim>;
396pub type StyleTextBoxEdgeValue = CssPropertyValue<StyleTextBoxEdge>;
397pub type StyleDominantBaselineValue = CssPropertyValue<StyleDominantBaseline>;
398pub type StyleAlignmentBaselineValue = CssPropertyValue<StyleAlignmentBaseline>;
399pub type StyleBaselineSourceValue = CssPropertyValue<StyleBaselineSource>;
400pub type StyleLineFitEdgeValue = CssPropertyValue<StyleLineFitEdge>;
401pub type StyleInitialLetterAlignValue = CssPropertyValue<StyleInitialLetterAlign>;
402pub type StyleInitialLetterWrapValue = CssPropertyValue<StyleInitialLetterWrap>;
403pub type StyleScrollbarGutterValue = CssPropertyValue<StyleScrollbarGutter>;
404pub type StyleOverflowClipMarginValue = CssPropertyValue<StyleOverflowClipMargin>;
405pub type StyleClipRectValue = CssPropertyValue<StyleClipRect>;
406pub type StyleExclusionMarginValue = CssPropertyValue<StyleExclusionMargin>;
407pub type StyleHyphenationLanguageValue = CssPropertyValue<StyleHyphenationLanguage>;
408pub type StyleWordSpacingValue = CssPropertyValue<StyleWordSpacing>;
409pub type StyleTabSizeValue = CssPropertyValue<StyleTabSize>;
410pub type StyleCursorValue = CssPropertyValue<StyleCursor>;
411pub type StyleBoxShadowValue = CssPropertyValue<crate::css::BoxOrStaticStyleBoxShadow>;
412pub type StyleBorderTopColorValue = CssPropertyValue<StyleBorderTopColor>;
413pub type StyleBorderLeftColorValue = CssPropertyValue<StyleBorderLeftColor>;
414pub type StyleBorderRightColorValue = CssPropertyValue<StyleBorderRightColor>;
415pub type StyleBorderBottomColorValue = CssPropertyValue<StyleBorderBottomColor>;
416pub type StyleBorderTopStyleValue = CssPropertyValue<StyleBorderTopStyle>;
417pub type StyleBorderLeftStyleValue = CssPropertyValue<StyleBorderLeftStyle>;
418pub type StyleBorderRightStyleValue = CssPropertyValue<StyleBorderRightStyle>;
419pub type StyleBorderBottomStyleValue = CssPropertyValue<StyleBorderBottomStyle>;
420pub type StyleBorderTopLeftRadiusValue = CssPropertyValue<StyleBorderTopLeftRadius>;
421pub type StyleBorderTopRightRadiusValue = CssPropertyValue<StyleBorderTopRightRadius>;
422pub type StyleBorderBottomLeftRadiusValue = CssPropertyValue<StyleBorderBottomLeftRadius>;
423pub type StyleBorderBottomRightRadiusValue = CssPropertyValue<StyleBorderBottomRightRadius>;
424pub type StyleOpacityValue = CssPropertyValue<StyleOpacity>;
425pub type StyleVisibilityValue = CssPropertyValue<StyleVisibility>;
426pub type StyleTransformVecValue = CssPropertyValue<StyleTransformVec>;
427pub type StyleTransformOriginValue = CssPropertyValue<StyleTransformOrigin>;
428pub type StylePerspectiveOriginValue = CssPropertyValue<StylePerspectiveOrigin>;
429pub type StyleBackfaceVisibilityValue = CssPropertyValue<StyleBackfaceVisibility>;
430pub type StyleAppRegionValue = CssPropertyValue<StyleAppRegion>;
431pub type StyleSpatialNavigationActionValue = CssPropertyValue<StyleSpatialNavigationAction>;
432pub type StyleSpatialNavigationContainValue = CssPropertyValue<StyleSpatialNavigationContain>;
433pub type StyleMixBlendModeValue = CssPropertyValue<StyleMixBlendMode>;
434pub type StyleFilterVecValue = CssPropertyValue<StyleFilterVec>;
435pub type StyleBackgroundContentValue = CssPropertyValue<StyleBackgroundContent>;
436pub type LayoutScrollbarWidthValue = CssPropertyValue<LayoutScrollbarWidth>;
437pub type OverscrollBehaviorValue = CssPropertyValue<OverscrollBehavior>;
438pub type StyleScrollbarColorValue = CssPropertyValue<StyleScrollbarColor>;
439pub type ScrollbarVisibilityModeValue = CssPropertyValue<ScrollbarVisibilityMode>;
440pub type ScrollbarFadeDelayValue = CssPropertyValue<ScrollbarFadeDelay>;
441pub type ScrollbarFadeDurationValue = CssPropertyValue<ScrollbarFadeDuration>;
442pub type LayoutDisplayValue = CssPropertyValue<LayoutDisplay>;
443pub type StyleHyphensValue = CssPropertyValue<StyleHyphens>;
444pub type StyleWordBreakValue = CssPropertyValue<StyleWordBreak>;
445pub type StyleOverflowWrapValue = CssPropertyValue<StyleOverflowWrap>;
446pub type StyleLineBreakValue = CssPropertyValue<StyleLineBreak>;
447pub type StyleTextOverflowValue = CssPropertyValue<StyleTextOverflow>;
448pub type StyleObjectFitValue = CssPropertyValue<StyleObjectFit>;
449pub type StyleObjectPositionValue = CssPropertyValue<StyleObjectPosition>;
450pub type StyleAspectRatioValue = CssPropertyValue<StyleAspectRatio>;
451pub type StyleTextOrientationValue = CssPropertyValue<StyleTextOrientation>;
452pub type StyleTextAlignLastValue = CssPropertyValue<StyleTextAlignLast>;
453pub type StyleTextTransformValue = CssPropertyValue<StyleTextTransform>;
454pub type StyleDirectionValue = CssPropertyValue<StyleDirection>;
455pub type StyleUserSelectValue = CssPropertyValue<StyleUserSelect>;
456pub type StyleTextDecorationValue = CssPropertyValue<StyleTextDecoration>;
457pub type StyleWhiteSpaceValue = CssPropertyValue<StyleWhiteSpace>;
458pub type LayoutFloatValue = CssPropertyValue<LayoutFloat>;
459pub type LayoutBoxSizingValue = CssPropertyValue<LayoutBoxSizing>;
460pub type LayoutWidthValue = CssPropertyValue<LayoutWidth>;
461pub type LayoutHeightValue = CssPropertyValue<LayoutHeight>;
462pub type LayoutMinWidthValue = CssPropertyValue<LayoutMinWidth>;
463pub type LayoutMinHeightValue = CssPropertyValue<LayoutMinHeight>;
464pub type LayoutMaxWidthValue = CssPropertyValue<LayoutMaxWidth>;
465pub type LayoutMaxHeightValue = CssPropertyValue<LayoutMaxHeight>;
466pub type LayoutPositionValue = CssPropertyValue<LayoutPosition>;
467pub type LayoutTopValue = CssPropertyValue<LayoutTop>;
468pub type LayoutInsetBottomValue = CssPropertyValue<LayoutInsetBottom>;
469pub type LayoutRightValue = CssPropertyValue<LayoutRight>;
470pub type LayoutLeftValue = CssPropertyValue<LayoutLeft>;
471pub type LayoutZIndexValue = CssPropertyValue<LayoutZIndex>;
472pub type LayoutPaddingTopValue = CssPropertyValue<LayoutPaddingTop>;
473pub type LayoutPaddingBottomValue = CssPropertyValue<LayoutPaddingBottom>;
474pub type LayoutPaddingLeftValue = CssPropertyValue<LayoutPaddingLeft>;
475pub type LayoutPaddingRightValue = CssPropertyValue<LayoutPaddingRight>;
476pub type LayoutPaddingInlineStartValue = CssPropertyValue<LayoutPaddingInlineStart>;
477pub type LayoutPaddingInlineEndValue = CssPropertyValue<LayoutPaddingInlineEnd>;
478pub type LayoutMarginTopValue = CssPropertyValue<LayoutMarginTop>;
479pub type LayoutMarginBottomValue = CssPropertyValue<LayoutMarginBottom>;
480pub type LayoutTextJustifyValue = CssPropertyValue<LayoutTextJustify>;
481pub type LayoutMarginLeftValue = CssPropertyValue<LayoutMarginLeft>;
482pub type LayoutMarginRightValue = CssPropertyValue<LayoutMarginRight>;
483pub type LayoutBorderTopWidthValue = CssPropertyValue<LayoutBorderTopWidth>;
484pub type LayoutBorderLeftWidthValue = CssPropertyValue<LayoutBorderLeftWidth>;
485pub type LayoutBorderRightWidthValue = CssPropertyValue<LayoutBorderRightWidth>;
486pub type LayoutBorderBottomWidthValue = CssPropertyValue<LayoutBorderBottomWidth>;
487pub type LayoutOverflowValue = CssPropertyValue<LayoutOverflow>;
488pub type LayoutFlexDirectionValue = CssPropertyValue<LayoutFlexDirection>;
489pub type LayoutFlexWrapValue = CssPropertyValue<LayoutFlexWrap>;
490pub type LayoutFlexGrowValue = CssPropertyValue<LayoutFlexGrow>;
491pub type LayoutFlexShrinkValue = CssPropertyValue<LayoutFlexShrink>;
492pub type LayoutFlexBasisValue = CssPropertyValue<LayoutFlexBasis>;
493pub type LayoutJustifyContentValue = CssPropertyValue<LayoutJustifyContent>;
494pub type LayoutAlignItemsValue = CssPropertyValue<LayoutAlignItems>;
495pub type LayoutAlignContentValue = CssPropertyValue<LayoutAlignContent>;
496pub type LayoutColumnGapValue = CssPropertyValue<LayoutColumnGap>;
497pub type LayoutRowGapValue = CssPropertyValue<LayoutRowGap>;
498pub type LayoutGridTemplateColumnsValue = CssPropertyValue<GridTemplate>;
499pub type LayoutGridTemplateRowsValue = CssPropertyValue<GridTemplate>;
500pub type LayoutGridAutoColumnsValue = CssPropertyValue<GridAutoTracks>;
501pub type LayoutGridAutoRowsValue = CssPropertyValue<GridAutoTracks>;
502pub type LayoutGridColumnValue = CssPropertyValue<GridPlacement>;
503pub type LayoutGridRowValue = CssPropertyValue<GridPlacement>;
504pub type LayoutGridTemplateAreasValue = CssPropertyValue<GridTemplateAreas>;
505pub type LayoutWritingModeValue = CssPropertyValue<LayoutWritingMode>;
506pub type LayoutClearValue = CssPropertyValue<LayoutClear>;
507pub type LayoutGridAutoFlowValue = CssPropertyValue<LayoutGridAutoFlow>;
508pub type LayoutJustifySelfValue = CssPropertyValue<LayoutJustifySelf>;
509pub type LayoutJustifyItemsValue = CssPropertyValue<LayoutJustifyItems>;
510pub type LayoutGapValue = CssPropertyValue<LayoutGap>;
511pub type LayoutAlignSelfValue = CssPropertyValue<LayoutAlignSelf>;
512pub type StyleFontValue = CssPropertyValue<StyleFontFamilyVec>;
513pub type PageBreakValue = CssPropertyValue<PageBreak>;
514pub type BreakInsideValue = CssPropertyValue<BreakInside>;
515pub type WidowsValue = CssPropertyValue<Widows>;
516pub type OrphansValue = CssPropertyValue<Orphans>;
517pub type BoxDecorationBreakValue = CssPropertyValue<BoxDecorationBreak>;
518pub type ColumnCountValue = CssPropertyValue<ColumnCount>;
519pub type ColumnWidthValue = CssPropertyValue<ColumnWidth>;
520pub type ColumnSpanValue = CssPropertyValue<ColumnSpan>;
521pub type ColumnFillValue = CssPropertyValue<ColumnFill>;
522pub type ColumnRuleWidthValue = CssPropertyValue<ColumnRuleWidth>;
523pub type ColumnRuleStyleValue = CssPropertyValue<ColumnRuleStyle>;
524pub type ColumnRuleColorValue = CssPropertyValue<ColumnRuleColor>;
525pub type FlowIntoValue = CssPropertyValue<FlowInto>;
526pub type FlowFromValue = CssPropertyValue<FlowFrom>;
527pub type ShapeOutsideValue = CssPropertyValue<ShapeOutside>;
528pub type ShapeInsideValue = CssPropertyValue<ShapeInside>;
529pub type ClipPathValue = CssPropertyValue<ClipPath>;
530pub type ShapeMarginValue = CssPropertyValue<ShapeMargin>;
531pub type ShapeImageThresholdValue = CssPropertyValue<ShapeImageThreshold>;
532pub type LayoutTableLayoutValue = CssPropertyValue<LayoutTableLayout>;
533pub type StyleBorderCollapseValue = CssPropertyValue<StyleBorderCollapse>;
534pub type LayoutBorderSpacingValue = CssPropertyValue<LayoutBorderSpacing>;
535pub type StyleCaptionSideValue = CssPropertyValue<StyleCaptionSide>;
536pub type StyleEmptyCellsValue = CssPropertyValue<StyleEmptyCells>;
537pub type ContentValue = CssPropertyValue<Content>;
538pub type CounterResetValue = CssPropertyValue<CounterReset>;
539pub type CounterIncrementValue = CssPropertyValue<CounterIncrement>;
540pub type StyleListStyleTypeValue = CssPropertyValue<StyleListStyleType>;
541pub type StyleListStylePositionValue = CssPropertyValue<StyleListStylePosition>;
542pub type StringSetValue = CssPropertyValue<StringSet>;
543
544#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
545pub struct CssKeyMap {
546    // Contains all keys that have no shorthand
547    pub non_shorthands: BTreeMap<&'static str, CssPropertyType>,
548    // Contains all keys that act as a shorthand for other types
549    pub shorthands: BTreeMap<&'static str, CombinedCssPropertyType>,
550}
551
552impl CssKeyMap {
553    #[must_use]
554    pub fn get() -> Self {
555        get_css_key_map()
556    }
557}
558
559/// Returns a map useful for parsing the keys of CSS stylesheets
560#[must_use]
561pub fn get_css_key_map() -> CssKeyMap {
562    CssKeyMap {
563        non_shorthands: CSS_PROPERTY_KEY_MAP.iter().map(|(v, k)| (*k, *v)).collect(),
564        shorthands: COMBINED_CSS_PROPERTIES_KEY_MAP
565            .iter()
566            .map(|(v, k)| (*k, *v))
567            .collect(),
568    }
569}
570
571#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
572#[repr(C)]
573pub enum CombinedCssPropertyType {
574    BorderRadius,
575    Overflow,
576    OverscrollBehavior,
577    Margin,
578    Border,
579    BorderLeft,
580    BorderRight,
581    BorderTop,
582    BorderBottom,
583    BorderColor,
584    BorderStyle,
585    BorderWidth,
586    Padding,
587    BoxShadow,
588    BackgroundColor, // BackgroundContent::Color
589    BackgroundImage, // BackgroundContent::Image
590    Background,
591    Flex,
592    Grid,
593    Gap,
594    GridGap,
595    Font,
596    Columns,
597    ColumnRule,
598    GridArea,
599    TextBox,
600    /// `inset-block` shorthand: sets `inset-block-start` + `inset-block-end`
601    /// (maps to `top` + `bottom` in horizontal-tb writing mode)
602    InsetBlock,
603    /// `inset-inline` shorthand: sets `inset-inline-start` + `inset-inline-end`
604    /// (maps to `left` + `right` in horizontal-tb writing mode)
605    InsetInline,
606}
607
608impl fmt::Display for CombinedCssPropertyType {
609    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
610        // The map is `[(CombinedCssPropertyType, &str)]`, so the NAME is slot 1.
611        // `.map(|(k, _)| k)` bound slot 0 — the enum itself — and `write!` then called
612        // this very impl on it again, recursing until the stack blew.
613        let key = COMBINED_CSS_PROPERTIES_KEY_MAP
614            .iter()
615            .find(|(v, _)| *v == *self)
616            .map(|(_, k)| k)
617            .unwrap();
618        write!(f, "{key}")
619    }
620}
621
622impl CombinedCssPropertyType {
623    /// Parses a CSS key, such as `width` from a string:
624    ///
625    /// # Example
626    ///
627    /// ```rust
628    /// # use azul_css::props::property::{CombinedCssPropertyType, get_css_key_map};
629    /// let map = get_css_key_map();
630    /// assert_eq!(
631    ///     Some(CombinedCssPropertyType::Border),
632    ///     CombinedCssPropertyType::from_str("border", &map)
633    /// );
634    /// ```
635    #[must_use]
636    pub fn from_str(input: &str, map: &CssKeyMap) -> Option<Self> {
637        let input = input.trim();
638        map.shorthands.get(input).copied()
639    }
640
641    /// Returns the original string that was used to construct this `CssPropertyType`.
642    ///
643    /// # Panics
644    ///
645    /// Panics if `self` is not present in `map` (i.e. `map` is not the
646    /// `CssKeyMap` this property type was constructed from).
647    #[must_use]
648    pub fn to_str(&self, map: &CssKeyMap) -> &'static str {
649        map.shorthands
650            .iter()
651            .find(|(_, v)| *v == self)
652            .map(|(k, _)| k)
653            .unwrap()
654    }
655}
656
657/// Represents one parsed CSS key-value pair, such as `"width: 20px"` =>
658/// `CssProperty::Width(LayoutWidth::px(20.0))`
659#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
660#[repr(C, u8)]
661pub enum CssProperty {
662    CaretColor(CaretColorValue),
663    CaretAnimationDuration(CaretAnimationDurationValue),
664    /// `animation: all 2s [timing]` — diff-driven transitions; the OLD tree's
665    /// value governs (USER spec 2026-08-17).
666    Animation(StyleAnimationVecValue),
667    /// `-azul-animation-in: <name> <duration> [timing]` — runs on mount.
668    AnimationIn(StyleAnimationVecValue),
669    /// `-azul-animation-out: <name> <duration> [timing]` — runs on unmount,
670    /// against the retained (frozen) zombie subtree.
671    AnimationOut(StyleAnimationVecValue),
672    CaretWidth(CaretWidthValue),
673    SelectionBackgroundColor(SelectionBackgroundColorValue),
674    SelectionColor(SelectionColorValue),
675    SelectionRadius(SelectionRadiusValue),
676    TextColor(StyleTextColorValue),
677    FontSize(StyleFontSizeValue),
678    FontFamily(StyleFontFamilyVecValue),
679    FontWeight(StyleFontWeightValue),
680    FontStyle(StyleFontStyleValue),
681    TextAlign(StyleTextAlignValue),
682    TextJustify(LayoutTextJustifyValue),
683    VerticalAlign(StyleVerticalAlignValue),
684    LetterSpacing(StyleLetterSpacingValue),
685    TextIndent(StyleTextIndentValue),
686    InitialLetter(StyleInitialLetterValue),
687    LineClamp(StyleLineClampValue),
688    HangingPunctuation(StyleHangingPunctuationValue),
689    TextCombineUpright(StyleTextCombineUprightValue),
690    UnicodeBidi(StyleUnicodeBidiValue),
691    TextBoxTrim(StyleTextBoxTrimValue),
692    TextBoxEdge(StyleTextBoxEdgeValue),
693    DominantBaseline(StyleDominantBaselineValue),
694    AlignmentBaseline(StyleAlignmentBaselineValue),
695    BaselineSource(StyleBaselineSourceValue),
696    LineFitEdge(StyleLineFitEdgeValue),
697    InitialLetterAlign(StyleInitialLetterAlignValue),
698    InitialLetterWrap(StyleInitialLetterWrapValue),
699    ScrollbarGutter(StyleScrollbarGutterValue),
700    OverflowClipMargin(StyleOverflowClipMarginValue),
701    Clip(StyleClipRectValue),
702    ExclusionMargin(StyleExclusionMarginValue),
703    HyphenationLanguage(StyleHyphenationLanguageValue),
704    LineHeight(StyleLineHeightValue),
705    WordSpacing(StyleWordSpacingValue),
706    TabSize(StyleTabSizeValue),
707    WhiteSpace(StyleWhiteSpaceValue),
708    Hyphens(StyleHyphensValue),
709    WordBreak(StyleWordBreakValue),
710    OverflowWrap(StyleOverflowWrapValue),
711    LineBreak(StyleLineBreakValue),
712    TextOverflow(StyleTextOverflowValue),
713    ObjectFit(StyleObjectFitValue),
714    ObjectPosition(StyleObjectPositionValue),
715    AspectRatio(StyleAspectRatioValue),
716    TextOrientation(StyleTextOrientationValue),
717    TextAlignLast(StyleTextAlignLastValue),
718    TextTransform(StyleTextTransformValue),
719    Direction(StyleDirectionValue),
720    UserSelect(StyleUserSelectValue),
721    TextDecoration(StyleTextDecorationValue),
722    Cursor(StyleCursorValue),
723    Display(LayoutDisplayValue),
724    Float(LayoutFloatValue),
725    BoxSizing(LayoutBoxSizingValue),
726    Width(LayoutWidthValue),
727    Height(LayoutHeightValue),
728    MinWidth(LayoutMinWidthValue),
729    MinHeight(LayoutMinHeightValue),
730    MaxWidth(LayoutMaxWidthValue),
731    MaxHeight(LayoutMaxHeightValue),
732    Position(LayoutPositionValue),
733    Top(LayoutTopValue),
734    Right(LayoutRightValue),
735    Left(LayoutLeftValue),
736    Bottom(LayoutInsetBottomValue),
737    ZIndex(LayoutZIndexValue),
738    FlexWrap(LayoutFlexWrapValue),
739    FlexDirection(LayoutFlexDirectionValue),
740    FlexGrow(LayoutFlexGrowValue),
741    FlexShrink(LayoutFlexShrinkValue),
742    FlexBasis(LayoutFlexBasisValue),
743    JustifyContent(LayoutJustifyContentValue),
744    AlignItems(LayoutAlignItemsValue),
745    AlignContent(LayoutAlignContentValue),
746    ColumnGap(LayoutColumnGapValue),
747    RowGap(LayoutRowGapValue),
748    GridTemplateColumns(LayoutGridTemplateColumnsValue),
749    GridTemplateRows(LayoutGridTemplateRowsValue),
750    GridAutoColumns(LayoutGridAutoColumnsValue),
751    GridAutoRows(LayoutGridAutoRowsValue),
752    GridColumn(LayoutGridColumnValue),
753    GridRow(LayoutGridRowValue),
754    GridTemplateAreas(LayoutGridTemplateAreasValue),
755    WritingMode(LayoutWritingModeValue),
756    Clear(LayoutClearValue),
757    BackgroundContent(StyleBackgroundContentVecValue),
758    BackgroundPosition(StyleBackgroundPositionVecValue),
759    BackgroundSize(StyleBackgroundSizeVecValue),
760    BackgroundRepeat(StyleBackgroundRepeatVecValue),
761    OverflowX(LayoutOverflowValue),
762    OverflowY(LayoutOverflowValue),
763    OverflowBlock(LayoutOverflowValue),
764    OverflowInline(LayoutOverflowValue),
765    GridAutoFlow(LayoutGridAutoFlowValue),
766    JustifySelf(LayoutJustifySelfValue),
767    JustifyItems(LayoutJustifyItemsValue),
768    Gap(LayoutGapValue),
769    GridGap(LayoutGapValue),
770    AlignSelf(LayoutAlignSelfValue),
771    Font(StyleFontValue),
772    PaddingTop(LayoutPaddingTopValue),
773    PaddingLeft(LayoutPaddingLeftValue),
774    PaddingRight(LayoutPaddingRightValue),
775    PaddingBottom(LayoutPaddingBottomValue),
776    PaddingInlineStart(LayoutPaddingInlineStartValue),
777    PaddingInlineEnd(LayoutPaddingInlineEndValue),
778    MarginTop(LayoutMarginTopValue),
779    MarginLeft(LayoutMarginLeftValue),
780    MarginRight(LayoutMarginRightValue),
781    MarginBottom(LayoutMarginBottomValue),
782    BorderTopLeftRadius(StyleBorderTopLeftRadiusValue),
783    BorderTopRightRadius(StyleBorderTopRightRadiusValue),
784    BorderBottomLeftRadius(StyleBorderBottomLeftRadiusValue),
785    BorderBottomRightRadius(StyleBorderBottomRightRadiusValue),
786    BorderTopColor(StyleBorderTopColorValue),
787    BorderRightColor(StyleBorderRightColorValue),
788    BorderLeftColor(StyleBorderLeftColorValue),
789    BorderBottomColor(StyleBorderBottomColorValue),
790    BorderTopStyle(StyleBorderTopStyleValue),
791    BorderRightStyle(StyleBorderRightStyleValue),
792    BorderLeftStyle(StyleBorderLeftStyleValue),
793    BorderBottomStyle(StyleBorderBottomStyleValue),
794    BorderTopWidth(LayoutBorderTopWidthValue),
795    BorderRightWidth(LayoutBorderRightWidthValue),
796    BorderLeftWidth(LayoutBorderLeftWidthValue),
797    BorderBottomWidth(LayoutBorderBottomWidthValue),
798    BoxShadowLeft(StyleBoxShadowValue),
799    BoxShadowRight(StyleBoxShadowValue),
800    BoxShadowTop(StyleBoxShadowValue),
801    BoxShadowBottom(StyleBoxShadowValue),
802    ScrollbarTrack(StyleBackgroundContentValue),
803    ScrollbarThumb(StyleBackgroundContentValue),
804    ScrollbarButton(StyleBackgroundContentValue),
805    ScrollbarCorner(StyleBackgroundContentValue),
806    ScrollbarResizer(StyleBackgroundContentValue),
807    ScrollbarWidth(LayoutScrollbarWidthValue),
808    OverscrollBehaviorX(OverscrollBehaviorValue),
809    OverscrollBehaviorY(OverscrollBehaviorValue),
810    ScrollbarColor(StyleScrollbarColorValue),
811    ScrollbarVisibility(ScrollbarVisibilityModeValue),
812    ScrollbarFadeDelay(ScrollbarFadeDelayValue),
813    ScrollbarFadeDuration(ScrollbarFadeDurationValue),
814    Opacity(StyleOpacityValue),
815    Visibility(StyleVisibilityValue),
816    Transform(StyleTransformVecValue),
817    TransformOrigin(StyleTransformOriginValue),
818    PerspectiveOrigin(StylePerspectiveOriginValue),
819    BackfaceVisibility(StyleBackfaceVisibilityValue),
820    AppRegion(StyleAppRegionValue),
821    SpatialNavigationAction(StyleSpatialNavigationActionValue),
822    SpatialNavigationContain(StyleSpatialNavigationContainValue),
823    MixBlendMode(StyleMixBlendModeValue),
824    Filter(StyleFilterVecValue),
825    BackdropFilter(StyleFilterVecValue),
826    TextShadow(StyleBoxShadowValue),
827    BreakBefore(PageBreakValue),
828    BreakAfter(PageBreakValue),
829    BreakInside(BreakInsideValue),
830    Orphans(OrphansValue),
831    Widows(WidowsValue),
832    BoxDecorationBreak(BoxDecorationBreakValue),
833    ColumnCount(ColumnCountValue),
834    ColumnWidth(ColumnWidthValue),
835    ColumnSpan(ColumnSpanValue),
836    ColumnFill(ColumnFillValue),
837    ColumnRuleWidth(ColumnRuleWidthValue),
838    ColumnRuleStyle(ColumnRuleStyleValue),
839    ColumnRuleColor(ColumnRuleColorValue),
840    FlowInto(FlowIntoValue),
841    FlowFrom(FlowFromValue),
842    ShapeOutside(ShapeOutsideValue),
843    ShapeInside(ShapeInsideValue),
844    ClipPath(ClipPathValue),
845    ShapeMargin(ShapeMarginValue),
846    ShapeImageThreshold(ShapeImageThresholdValue),
847    TableLayout(LayoutTableLayoutValue),
848    BorderCollapse(StyleBorderCollapseValue),
849    BorderSpacing(LayoutBorderSpacingValue),
850    CaptionSide(StyleCaptionSideValue),
851    EmptyCells(StyleEmptyCellsValue),
852    Content(ContentValue),
853    CounterReset(CounterResetValue),
854    CounterIncrement(CounterIncrementValue),
855    ListStyleType(StyleListStyleTypeValue),
856    ListStylePosition(StyleListStylePositionValue),
857    StringSet(StringSetValue),
858}
859
860impl_option!(
861    CssProperty,
862    OptionCssProperty,
863    copy = false,
864    [Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord]
865);
866
867crate::impl_vec!(
868    CssProperty,
869    CssPropertyVec,
870    CssPropertyVecDestructor,
871    CssPropertyVecDestructorType,
872    CssPropertyVecSlice,
873    OptionCssProperty
874);
875crate::impl_vec_clone!(CssProperty, CssPropertyVec, CssPropertyVecDestructor);
876crate::impl_vec_debug!(CssProperty, CssPropertyVec);
877crate::impl_vec_partialeq!(CssProperty, CssPropertyVec);
878crate::impl_vec_eq!(CssProperty, CssPropertyVec);
879crate::impl_vec_partialord!(CssProperty, CssPropertyVec);
880crate::impl_vec_ord!(CssProperty, CssPropertyVec);
881crate::impl_vec_hash!(CssProperty, CssPropertyVec);
882
883/// Categorizes a CSS property by its effect on the layout pipeline.
884#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
885pub enum CssPropertyCategory {
886    GpuOnly,
887    /// Affects geometry (width, height, margin, padding, font-size, etc.)
888    Layout,
889    /// Affects only appearance (color, background-color, etc.)
890    Paint,
891    /// A layout-affecting property that also requires children to be re-evaluated.
892    InheritedLayout,
893    /// A paint-affecting property that also requires children to be re-evaluated.
894    InheritedPaint,
895}
896
897/// Fine-grained dirty classification for CSS property changes.
898///
899/// Inspired by Taffy's binary dirty flag but extended to 4 levels for CSS-specific
900/// optimizations. Instead of "clean vs dirty", we classify property changes by their
901/// actual layout impact, enabling the engine to skip unnecessary work.
902///
903/// Reference: Taffy (<https://github.com/DioxusLabs/taffy>) uses a binary dirty flag
904/// (clean/dirty). Our improvement: 4-level classification enables IFC-only reflow,
905/// sizing-only recomputation, and paint-only updates without full subtree relayout.
906#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
907#[repr(C)]
908#[derive(Default)]
909pub enum RelayoutScope {
910    /// No relayout needed — repaint only (e.g., color, background, opacity, transform).
911    /// The node's size and position are unchanged.
912    #[default]
913    None,
914    /// Only the IFC (Inline Formatting Context) containing this node needs re-shaping.
915    /// Block-level siblings are unaffected unless the IFC height changes,
916    /// in which case this auto-upgrades to `SizingOnly`.
917    IfcOnly,
918    /// This node's sizing needs recomputation. Parent may need repositioning
919    /// of subsequent siblings but doesn't need full recursive relayout.
920    SizingOnly,
921    /// Full subtree relayout required (e.g., display, position, float change).
922    Full,
923}
924
925/// Represents a CSS key (for example `"border-radius"` => `BorderRadius`).
926/// You can also derive this key from a `CssProperty` by calling `CssProperty::get_type()`.
927#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
928#[repr(C)]
929pub enum CssPropertyType {
930    CaretColor,
931    CaretAnimationDuration,
932    Animation,
933    AnimationIn,
934    AnimationOut,
935    CaretWidth,
936    SelectionBackgroundColor,
937    SelectionColor,
938    SelectionRadius,
939    TextColor,
940    FontSize,
941    FontFamily,
942    FontWeight,
943    FontStyle,
944    TextAlign,
945    TextJustify,
946    VerticalAlign,
947    LetterSpacing,
948    TextIndent,
949    InitialLetter,
950    LineClamp,
951    HangingPunctuation,
952    TextCombineUpright,
953    UnicodeBidi,
954    TextBoxTrim,
955    TextBoxEdge,
956    DominantBaseline,
957    AlignmentBaseline,
958    BaselineSource,
959    LineFitEdge,
960    InitialLetterAlign,
961    InitialLetterWrap,
962    ScrollbarGutter,
963    OverflowClipMargin,
964    Clip,
965    ExclusionMargin,
966    HyphenationLanguage,
967    LineHeight,
968    WordSpacing,
969    TabSize,
970    WhiteSpace,
971    Hyphens,
972    WordBreak,
973    OverflowWrap,
974    LineBreak,
975    TextOverflow,
976    ObjectFit,
977    ObjectPosition,
978    AspectRatio,
979    TextOrientation,
980    TextAlignLast,
981    TextTransform,
982    Direction,
983    UserSelect,
984    TextDecoration,
985    Cursor,
986    Display,
987    Float,
988    BoxSizing,
989    Width,
990    Height,
991    MinWidth,
992    MinHeight,
993    MaxWidth,
994    MaxHeight,
995    Position,
996    Top,
997    Right,
998    Left,
999    Bottom,
1000    ZIndex,
1001    FlexWrap,
1002    FlexDirection,
1003    FlexGrow,
1004    FlexShrink,
1005    FlexBasis,
1006    JustifyContent,
1007    AlignItems,
1008    AlignContent,
1009    ColumnGap,
1010    RowGap,
1011    GridTemplateColumns,
1012    GridTemplateRows,
1013    GridAutoColumns,
1014    GridAutoRows,
1015    GridColumn,
1016    GridRow,
1017    GridTemplateAreas,
1018    GridAutoFlow,
1019    JustifySelf,
1020    JustifyItems,
1021    Gap,
1022    GridGap,
1023    AlignSelf,
1024    Font,
1025    WritingMode,
1026    Clear,
1027    BackgroundContent,
1028    BackgroundPosition,
1029    BackgroundSize,
1030    BackgroundRepeat,
1031    OverflowX,
1032    OverflowY,
1033    OverflowBlock,
1034    OverflowInline,
1035    PaddingTop,
1036    PaddingLeft,
1037    PaddingRight,
1038    PaddingBottom,
1039    PaddingInlineStart,
1040    PaddingInlineEnd,
1041    MarginTop,
1042    MarginLeft,
1043    MarginRight,
1044    MarginBottom,
1045    BorderTopLeftRadius,
1046    BorderTopRightRadius,
1047    BorderBottomLeftRadius,
1048    BorderBottomRightRadius,
1049    BorderTopColor,
1050    BorderRightColor,
1051    BorderLeftColor,
1052    BorderBottomColor,
1053    BorderTopStyle,
1054    BorderRightStyle,
1055    BorderLeftStyle,
1056    BorderBottomStyle,
1057    BorderTopWidth,
1058    BorderRightWidth,
1059    BorderLeftWidth,
1060    BorderBottomWidth,
1061    BoxShadowLeft,
1062    BoxShadowRight,
1063    BoxShadowTop,
1064    BoxShadowBottom,
1065    ScrollbarTrack,
1066    ScrollbarThumb,
1067    ScrollbarButton,
1068    ScrollbarCorner,
1069    ScrollbarResizer,
1070    ScrollbarWidth,
1071    OverscrollBehaviorX,
1072    OverscrollBehaviorY,
1073    ScrollbarColor,
1074    ScrollbarVisibility,
1075    ScrollbarFadeDelay,
1076    ScrollbarFadeDuration,
1077    Opacity,
1078    Visibility,
1079    Transform,
1080    TransformOrigin,
1081    PerspectiveOrigin,
1082    BackfaceVisibility,
1083    AppRegion,
1084    SpatialNavigationAction,
1085    SpatialNavigationContain,
1086    MixBlendMode,
1087    Filter,
1088    BackdropFilter,
1089    TextShadow,
1090    BreakBefore,
1091    BreakAfter,
1092    BreakInside,
1093    Orphans,
1094    Widows,
1095    BoxDecorationBreak,
1096    ColumnCount,
1097    ColumnWidth,
1098    ColumnSpan,
1099    ColumnFill,
1100    ColumnRuleWidth,
1101    ColumnRuleStyle,
1102    ColumnRuleColor,
1103    FlowInto,
1104    FlowFrom,
1105    ShapeOutside,
1106    ShapeInside,
1107    ClipPath,
1108    ShapeMargin,
1109    ShapeImageThreshold,
1110    TableLayout,
1111    BorderCollapse,
1112    BorderSpacing,
1113    CaptionSide,
1114    EmptyCells,
1115    Content,
1116    CounterReset,
1117    CounterIncrement,
1118    ListStyleType,
1119    ListStylePosition,
1120    StringSet,
1121}
1122
1123impl CssPropertyType {
1124    /// All CSS property types, in declaration order.
1125    ///
1126    /// Use this instead of strum's `EnumIter` — ensures a compile error
1127    /// if a variant is added to the enum but not to this array.
1128    pub const ALL: &[Self] = &[
1129        Self::CaretColor,
1130        Self::CaretAnimationDuration,
1131        Self::Animation,
1132        Self::AnimationIn,
1133        Self::AnimationOut,
1134        Self::CaretWidth,
1135        Self::SelectionBackgroundColor,
1136        Self::SelectionColor,
1137        Self::SelectionRadius,
1138        Self::TextColor,
1139        Self::FontSize,
1140        Self::FontFamily,
1141        Self::FontWeight,
1142        Self::FontStyle,
1143        Self::TextAlign,
1144        Self::TextJustify,
1145        Self::VerticalAlign,
1146        Self::LetterSpacing,
1147        Self::TextIndent,
1148        Self::InitialLetter,
1149        Self::LineClamp,
1150        Self::HangingPunctuation,
1151        Self::TextCombineUpright,
1152        Self::UnicodeBidi,
1153        Self::TextBoxTrim,
1154        Self::TextBoxEdge,
1155        Self::DominantBaseline,
1156        Self::AlignmentBaseline,
1157        Self::BaselineSource,
1158        Self::LineFitEdge,
1159        Self::InitialLetterAlign,
1160        Self::InitialLetterWrap,
1161        Self::ScrollbarGutter,
1162        Self::OverflowClipMargin,
1163        Self::Clip,
1164        Self::ExclusionMargin,
1165        Self::HyphenationLanguage,
1166        Self::LineHeight,
1167        Self::WordSpacing,
1168        Self::TabSize,
1169        Self::WhiteSpace,
1170        Self::Hyphens,
1171        Self::WordBreak,
1172        Self::OverflowWrap,
1173        Self::LineBreak,
1174        Self::TextOverflow,
1175        Self::ObjectFit,
1176        Self::ObjectPosition,
1177        Self::AspectRatio,
1178        Self::TextOrientation,
1179        Self::TextAlignLast,
1180        Self::TextTransform,
1181        Self::Direction,
1182        Self::UserSelect,
1183        Self::TextDecoration,
1184        Self::Cursor,
1185        Self::Display,
1186        Self::Float,
1187        Self::BoxSizing,
1188        Self::Width,
1189        Self::Height,
1190        Self::MinWidth,
1191        Self::MinHeight,
1192        Self::MaxWidth,
1193        Self::MaxHeight,
1194        Self::Position,
1195        Self::Top,
1196        Self::Right,
1197        Self::Left,
1198        Self::Bottom,
1199        Self::ZIndex,
1200        Self::FlexWrap,
1201        Self::FlexDirection,
1202        Self::FlexGrow,
1203        Self::FlexShrink,
1204        Self::FlexBasis,
1205        Self::JustifyContent,
1206        Self::AlignItems,
1207        Self::AlignContent,
1208        Self::ColumnGap,
1209        Self::RowGap,
1210        Self::GridTemplateColumns,
1211        Self::GridTemplateRows,
1212        Self::GridAutoColumns,
1213        Self::GridAutoRows,
1214        Self::GridColumn,
1215        Self::GridRow,
1216        Self::GridTemplateAreas,
1217        Self::GridAutoFlow,
1218        Self::JustifySelf,
1219        Self::JustifyItems,
1220        Self::Gap,
1221        Self::GridGap,
1222        Self::AlignSelf,
1223        Self::Font,
1224        Self::WritingMode,
1225        Self::Clear,
1226        Self::BackgroundContent,
1227        Self::BackgroundPosition,
1228        Self::BackgroundSize,
1229        Self::BackgroundRepeat,
1230        Self::OverflowX,
1231        Self::OverflowY,
1232        Self::OverflowBlock,
1233        Self::OverflowInline,
1234        Self::PaddingTop,
1235        Self::PaddingLeft,
1236        Self::PaddingRight,
1237        Self::PaddingBottom,
1238        Self::PaddingInlineStart,
1239        Self::PaddingInlineEnd,
1240        Self::MarginTop,
1241        Self::MarginLeft,
1242        Self::MarginRight,
1243        Self::MarginBottom,
1244        Self::BorderTopLeftRadius,
1245        Self::BorderTopRightRadius,
1246        Self::BorderBottomLeftRadius,
1247        Self::BorderBottomRightRadius,
1248        Self::BorderTopColor,
1249        Self::BorderRightColor,
1250        Self::BorderLeftColor,
1251        Self::BorderBottomColor,
1252        Self::BorderTopStyle,
1253        Self::BorderRightStyle,
1254        Self::BorderLeftStyle,
1255        Self::BorderBottomStyle,
1256        Self::BorderTopWidth,
1257        Self::BorderRightWidth,
1258        Self::BorderLeftWidth,
1259        Self::BorderBottomWidth,
1260        Self::BoxShadowLeft,
1261        Self::BoxShadowRight,
1262        Self::BoxShadowTop,
1263        Self::BoxShadowBottom,
1264        Self::ScrollbarTrack,
1265        Self::ScrollbarThumb,
1266        Self::ScrollbarButton,
1267        Self::ScrollbarCorner,
1268        Self::ScrollbarResizer,
1269        Self::ScrollbarWidth,
1270        Self::OverscrollBehaviorX,
1271        Self::OverscrollBehaviorY,
1272        Self::ScrollbarColor,
1273        Self::ScrollbarVisibility,
1274        Self::ScrollbarFadeDelay,
1275        Self::ScrollbarFadeDuration,
1276        Self::Opacity,
1277        Self::Visibility,
1278        Self::Transform,
1279        Self::TransformOrigin,
1280        Self::PerspectiveOrigin,
1281        Self::BackfaceVisibility,
1282        Self::AppRegion,
1283        Self::SpatialNavigationAction,
1284        Self::SpatialNavigationContain,
1285        Self::MixBlendMode,
1286        Self::Filter,
1287        Self::BackdropFilter,
1288        Self::TextShadow,
1289        Self::BreakBefore,
1290        Self::BreakAfter,
1291        Self::BreakInside,
1292        Self::Orphans,
1293        Self::Widows,
1294        Self::BoxDecorationBreak,
1295        Self::ColumnCount,
1296        Self::ColumnWidth,
1297        Self::ColumnSpan,
1298        Self::ColumnFill,
1299        Self::ColumnRuleWidth,
1300        Self::ColumnRuleStyle,
1301        Self::ColumnRuleColor,
1302        Self::FlowInto,
1303        Self::FlowFrom,
1304        Self::ShapeOutside,
1305        Self::ShapeInside,
1306        Self::ClipPath,
1307        Self::ShapeMargin,
1308        Self::ShapeImageThreshold,
1309        Self::TableLayout,
1310        Self::BorderCollapse,
1311        Self::BorderSpacing,
1312        Self::CaptionSide,
1313        Self::EmptyCells,
1314        Self::Content,
1315        Self::CounterReset,
1316        Self::CounterIncrement,
1317        Self::ListStyleType,
1318        Self::ListStylePosition,
1319        Self::StringSet,
1320    ];
1321
1322    /// Returns an iterator over all CSS property types.
1323    pub fn iter() -> impl Iterator<Item = Self> {
1324        Self::ALL.iter().copied()
1325    }
1326}
1327
1328impl fmt::Debug for CssPropertyType {
1329    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1330        write!(f, "{}", self.to_str())
1331    }
1332}
1333
1334impl fmt::Display for CssPropertyType {
1335    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1336        write!(f, "{}", self.to_str())
1337    }
1338}
1339
1340impl CssPropertyType {
1341    /// Parses a CSS key, such as `width` from a string:
1342    ///
1343    /// # Example
1344    ///
1345    /// ```rust
1346    /// # use azul_css::props::property::{CssPropertyType, get_css_key_map};
1347    /// let map = get_css_key_map();
1348    /// assert_eq!(
1349    ///     Some(CssPropertyType::Width),
1350    ///     CssPropertyType::from_str("width", &map)
1351    /// );
1352    /// assert_eq!(
1353    ///     Some(CssPropertyType::JustifyContent),
1354    ///     CssPropertyType::from_str("justify-content", &map)
1355    /// );
1356    /// assert_eq!(None, CssPropertyType::from_str("asdfasdfasdf", &map));
1357    /// ```
1358    #[must_use]
1359    pub fn from_str(input: &str, map: &CssKeyMap) -> Option<Self> {
1360        let input = input.trim();
1361        map.non_shorthands.get(input).copied()
1362    }
1363
1364    /// Returns the original string that was used to construct this `CssPropertyType`.
1365    #[allow(clippy::too_many_lines)]
1366    // large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
1367    #[must_use]
1368    pub const fn to_str(&self) -> &'static str {
1369        match self {
1370            Self::CaretColor => "caret-color",
1371            Self::CaretAnimationDuration => "caret-animation-duration",
1372            Self::Animation => "animation",
1373            Self::AnimationIn => "-azul-animation-in",
1374            Self::AnimationOut => "-azul-animation-out",
1375            Self::CaretWidth => "-azul-caret-width",
1376            Self::SelectionBackgroundColor => "-azul-selection-background-color",
1377            Self::SelectionColor => "-azul-selection-color",
1378            Self::SelectionRadius => "-azul-selection-radius",
1379            Self::TextColor => "color",
1380            Self::FontSize => "font-size",
1381            Self::FontFamily => "font-family",
1382            Self::FontWeight => "font-weight",
1383            Self::FontStyle => "font-style",
1384            Self::TextAlign => "text-align",
1385            Self::TextJustify => "text-justify",
1386            Self::VerticalAlign => "vertical-align",
1387            Self::LetterSpacing => "letter-spacing",
1388            Self::TextIndent => "text-indent",
1389            Self::InitialLetter => "initial-letter",
1390            Self::LineClamp => "line-clamp",
1391            Self::HangingPunctuation => "hanging-punctuation",
1392            Self::TextCombineUpright => "text-combine-upright",
1393            Self::UnicodeBidi => "unicode-bidi",
1394            Self::TextBoxTrim => "text-box-trim",
1395            Self::TextBoxEdge => "text-box-edge",
1396            Self::DominantBaseline => "dominant-baseline",
1397            Self::AlignmentBaseline => "alignment-baseline",
1398            Self::BaselineSource => "baseline-source",
1399            Self::LineFitEdge => "line-fit-edge",
1400            Self::InitialLetterAlign => "initial-letter-align",
1401            Self::InitialLetterWrap => "initial-letter-wrap",
1402            Self::ScrollbarGutter => "scrollbar-gutter",
1403            Self::OverflowClipMargin => "overflow-clip-margin",
1404            Self::Clip => "clip",
1405            Self::ExclusionMargin => "-azul-exclusion-margin",
1406            Self::HyphenationLanguage => "-azul-hyphenation-language",
1407            Self::LineHeight => "line-height",
1408            Self::WordSpacing => "word-spacing",
1409            Self::TabSize => "tab-size",
1410            Self::Cursor => "cursor",
1411            Self::Display => "display",
1412            Self::Float => "float",
1413            Self::BoxSizing => "box-sizing",
1414            Self::Width => "width",
1415            Self::Height => "height",
1416            Self::MinWidth => "min-width",
1417            Self::MinHeight => "min-height",
1418            Self::MaxWidth => "max-width",
1419            Self::MaxHeight => "max-height",
1420            Self::Position => "position",
1421            Self::Top => "top",
1422            Self::Right => "right",
1423            Self::Left => "left",
1424            Self::Bottom => "bottom",
1425            Self::ZIndex => "z-index",
1426            Self::FlexWrap => "flex-wrap",
1427            Self::FlexDirection => "flex-direction",
1428            Self::FlexGrow => "flex-grow",
1429            Self::FlexShrink => "flex-shrink",
1430            Self::FlexBasis => "flex-basis",
1431            Self::JustifyContent => "justify-content",
1432            Self::AlignItems => "align-items",
1433            Self::AlignContent => "align-content",
1434            Self::ColumnGap => "column-gap",
1435            Self::RowGap => "row-gap",
1436            Self::GridTemplateColumns => "grid-template-columns",
1437            Self::GridTemplateRows => "grid-template-rows",
1438            Self::GridAutoFlow => "grid-auto-flow",
1439            Self::JustifySelf => "justify-self",
1440            Self::JustifyItems => "justify-items",
1441            Self::Gap => "gap",
1442            Self::GridGap => "grid-gap",
1443            Self::AlignSelf => "align-self",
1444            Self::Font => "font",
1445            Self::GridAutoColumns => "grid-auto-columns",
1446            Self::GridAutoRows => "grid-auto-rows",
1447            Self::GridColumn => "grid-column",
1448            Self::GridRow => "grid-row",
1449            Self::GridTemplateAreas => "grid-template-areas",
1450            Self::WritingMode => "writing-mode",
1451            Self::Clear => "clear",
1452            Self::BackgroundContent => "background",
1453            Self::BackgroundPosition => "background-position",
1454            Self::BackgroundSize => "background-size",
1455            Self::BackgroundRepeat => "background-repeat",
1456            Self::OverflowX => "overflow-x",
1457            Self::OverflowY => "overflow-y",
1458            Self::OverflowBlock => "overflow-block",
1459            Self::OverflowInline => "overflow-inline",
1460            Self::PaddingTop => "padding-top",
1461            Self::PaddingLeft => "padding-left",
1462            Self::PaddingRight => "padding-right",
1463            Self::PaddingBottom => "padding-bottom",
1464            Self::PaddingInlineStart => "padding-inline-start",
1465            Self::PaddingInlineEnd => "padding-inline-end",
1466            Self::MarginTop => "margin-top",
1467            Self::MarginLeft => "margin-left",
1468            Self::MarginRight => "margin-right",
1469            Self::MarginBottom => "margin-bottom",
1470            Self::BorderTopLeftRadius => "border-top-left-radius",
1471            Self::BorderTopRightRadius => "border-top-right-radius",
1472            Self::BorderBottomLeftRadius => "border-bottom-left-radius",
1473            Self::BorderBottomRightRadius => "border-bottom-right-radius",
1474            Self::BorderTopColor => "border-top-color",
1475            Self::BorderRightColor => "border-right-color",
1476            Self::BorderLeftColor => "border-left-color",
1477            Self::BorderBottomColor => "border-bottom-color",
1478            Self::BorderTopStyle => "border-top-style",
1479            Self::BorderRightStyle => "border-right-style",
1480            Self::BorderLeftStyle => "border-left-style",
1481            Self::BorderBottomStyle => "border-bottom-style",
1482            Self::BorderTopWidth => "border-top-width",
1483            Self::BorderRightWidth => "border-right-width",
1484            Self::BorderLeftWidth => "border-left-width",
1485            Self::BorderBottomWidth => "border-bottom-width",
1486            Self::BoxShadowLeft => "-azul-box-shadow-left",
1487            Self::BoxShadowRight => "-azul-box-shadow-right",
1488            Self::BoxShadowTop => "-azul-box-shadow-top",
1489            Self::BoxShadowBottom => "-azul-box-shadow-bottom",
1490            Self::ScrollbarTrack => "-azul-scrollbar-track",
1491            Self::ScrollbarThumb => "-azul-scrollbar-thumb",
1492            Self::ScrollbarButton => "-azul-scrollbar-button",
1493            Self::ScrollbarCorner => "-azul-scrollbar-corner",
1494            Self::ScrollbarResizer => "-azul-scrollbar-resizer",
1495            Self::ScrollbarWidth => "scrollbar-width",
1496            Self::OverscrollBehaviorX => "overscroll-behavior-x",
1497            Self::OverscrollBehaviorY => "overscroll-behavior-y",
1498            Self::ScrollbarColor => "scrollbar-color",
1499            Self::ScrollbarVisibility => "-azul-scrollbar-visibility",
1500            Self::ScrollbarFadeDelay => "-azul-scrollbar-fade-delay",
1501            Self::ScrollbarFadeDuration => "-azul-scrollbar-fade-duration",
1502            Self::Opacity => "opacity",
1503            Self::Visibility => "visibility",
1504            Self::Transform => "transform",
1505            Self::TransformOrigin => "transform-origin",
1506            Self::PerspectiveOrigin => "perspective-origin",
1507            Self::BackfaceVisibility => "backface-visibility",
1508            Self::AppRegion => "-azul-app-region",
1509            Self::SpatialNavigationAction => "spatial-navigation-action",
1510            Self::SpatialNavigationContain => "spatial-navigation-contain",
1511            Self::MixBlendMode => "mix-blend-mode",
1512            Self::Filter => "filter",
1513            Self::BackdropFilter => "backdrop-filter",
1514            Self::TextShadow => "text-shadow",
1515            Self::WhiteSpace => "white-space",
1516            Self::Hyphens => "hyphens",
1517            Self::WordBreak => "word-break",
1518            Self::OverflowWrap => "overflow-wrap",
1519            Self::LineBreak => "line-break",
1520            Self::TextOverflow => "text-overflow",
1521            Self::ObjectFit => "object-fit",
1522            Self::ObjectPosition => "object-position",
1523            Self::AspectRatio => "aspect-ratio",
1524            Self::TextOrientation => "text-orientation",
1525            Self::TextAlignLast => "text-align-last",
1526            Self::TextTransform => "text-transform",
1527            Self::Direction => "direction",
1528            Self::UserSelect => "user-select",
1529            Self::TextDecoration => "text-decoration",
1530            Self::BreakBefore => "break-before",
1531            Self::BreakAfter => "break-after",
1532            Self::BreakInside => "break-inside",
1533            Self::Orphans => "orphans",
1534            Self::Widows => "widows",
1535            Self::BoxDecorationBreak => "box-decoration-break",
1536            Self::ColumnCount => "column-count",
1537            Self::ColumnWidth => "column-width",
1538            Self::ColumnSpan => "column-span",
1539            Self::ColumnFill => "column-fill",
1540            Self::ColumnRuleWidth => "column-rule-width",
1541            Self::ColumnRuleStyle => "column-rule-style",
1542            Self::ColumnRuleColor => "column-rule-color",
1543            Self::FlowInto => "flow-into",
1544            Self::FlowFrom => "flow-from",
1545            Self::ShapeOutside => "shape-outside",
1546            Self::ShapeInside => "shape-inside",
1547            Self::ClipPath => "clip-path",
1548            Self::ShapeMargin => "shape-margin",
1549            Self::ShapeImageThreshold => "shape-image-threshold",
1550            Self::TableLayout => "table-layout",
1551            Self::BorderCollapse => "border-collapse",
1552            Self::BorderSpacing => "border-spacing",
1553            Self::CaptionSide => "caption-side",
1554            Self::EmptyCells => "empty-cells",
1555            Self::Content => "content",
1556            Self::CounterReset => "counter-reset",
1557            Self::CounterIncrement => "counter-increment",
1558            Self::ListStyleType => "list-style-type",
1559            Self::ListStylePosition => "list-style-position",
1560            Self::StringSet => "string-set",
1561        }
1562    }
1563
1564    /// Returns whether this property will be inherited during cascading
1565    /// Returns whether this CSS property is inherited by default according to CSS specifications.
1566    ///
1567    /// Reference: <https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Cascade/Inheritance>
1568    // +spec:display-property:b4cf6d - unicode-bidi does not inherit (removed from inheritable set)
1569    #[must_use]
1570    pub const fn is_inheritable(&self) -> bool {
1571        use self::CssPropertyType::{
1572            BorderCollapse, BorderSpacing, CaptionSide, Cursor, Direction, EmptyCells, FontFamily,
1573            FontSize, FontStyle, FontWeight, HangingPunctuation, HyphenationLanguage, Hyphens,
1574            LetterSpacing, LineBreak, LineHeight, ListStylePosition, ListStyleType, Orphans,
1575            OverflowWrap, TabSize, TextAlign, TextAlignLast, TextColor, TextCombineUpright,
1576            TextDecoration, TextIndent, TextJustify, TextOrientation, TextTransform, UserSelect,
1577            Visibility, WhiteSpace, Widows, WordBreak, WordSpacing, WritingMode,
1578        };
1579        match self {
1580            // Font properties
1581            FontFamily | FontSize | FontWeight | FontStyle | LineHeight | LetterSpacing | WordSpacing | TextIndent |
1582
1583            // Text properties
1584            TextColor | TextAlign | TextJustify | TextDecoration | WhiteSpace | Direction | Hyphens | TabSize |
1585            WordBreak | OverflowWrap | LineBreak | TextAlignLast | TextTransform |
1586            TextOrientation |
1587            HangingPunctuation | TextCombineUpright | HyphenationLanguage |
1588
1589            // List properties
1590            ListStyleType | ListStylePosition |
1591
1592            // Table properties
1593            BorderCollapse | BorderSpacing | CaptionSide | EmptyCells |
1594
1595            // Other inherited properties
1596            // NOTE: Cursor is inheritable per CSS spec (https://developer.mozilla.org/en-US/docs/Web/CSS/cursor)
1597            // This means a Button with cursor:pointer will pass that to child Text nodes.
1598            // This is correct behavior - if you want text inside a button to show I-beam,
1599            // the Text node needs an explicit cursor:text style that overrides the inherited value.
1600            Visibility | Cursor | Widows | Orphans |
1601
1602            // Writing mode
1603            WritingMode |
1604
1605            // User interaction
1606            UserSelect
1607            => true,
1608
1609            _ => false,
1610        }
1611    }
1612
1613    #[must_use]
1614    pub const fn has_compact_encoding(&self) -> bool {
1615        use self::CssPropertyType::{
1616            AlignContent, AlignItems, AlignSelf, BorderBottomColor, BorderBottomStyle,
1617            BorderBottomWidth, BorderCollapse, BorderLeftColor, BorderLeftStyle, BorderLeftWidth,
1618            BorderRightColor, BorderRightStyle, BorderRightWidth, BorderSpacing, BorderTopColor,
1619            BorderTopStyle, BorderTopWidth, Bottom, BoxSizing, Clear, ColumnGap, Direction,
1620            Display, FlexBasis, FlexDirection, FlexGrow, FlexShrink, FlexWrap, Float, FontFamily,
1621            FontSize, FontStyle, FontWeight, Gap, GridAutoFlow, GridColumn, GridRow, Height,
1622            JustifyContent, JustifyItems, JustifySelf, Left, LetterSpacing, LineHeight,
1623            MarginBottom, MarginLeft, MarginRight, MarginTop, MaxHeight, MaxWidth, MinHeight,
1624            MinWidth, OverflowX, OverflowY, PaddingBottom, PaddingLeft, PaddingRight, PaddingTop,
1625            Position, Right, RowGap, TabSize, TextAlign, TextColor, TextIndent, Top, VerticalAlign,
1626            Visibility, WhiteSpace, Width, WordSpacing, WritingMode, ZIndex,
1627        };
1628        matches!(
1629            self,
1630            // Tier 1 enums
1631            Display | Position | Float | OverflowX | OverflowY | BoxSizing |
1632            FlexDirection | FlexWrap | JustifyContent | AlignItems | AlignContent |
1633            WritingMode | Clear | FontWeight | FontStyle | TextAlign |
1634            Visibility | WhiteSpace | Direction | VerticalAlign | BorderCollapse |
1635            // Tier 2 dims
1636            Width | Height | MinWidth | MaxWidth | MinHeight | MaxHeight |
1637            FlexBasis | FontSize |
1638            PaddingTop | PaddingRight | PaddingBottom | PaddingLeft |
1639            MarginTop | MarginRight | MarginBottom | MarginLeft |
1640            BorderTopWidth | BorderRightWidth | BorderBottomWidth | BorderLeftWidth |
1641            Top | Right | Bottom | Left |
1642            FlexGrow | FlexShrink |
1643            // Tier 2 cold
1644            ZIndex |
1645            BorderTopStyle | BorderRightStyle | BorderBottomStyle | BorderLeftStyle |
1646            BorderTopColor | BorderRightColor | BorderBottomColor | BorderLeftColor |
1647            BorderSpacing | TabSize |
1648            // Tier 2b text
1649            TextColor | FontFamily | LineHeight | LetterSpacing | WordSpacing | TextIndent |
1650            // Grid/flex alignment (tier1 extension)
1651            AlignSelf | JustifySelf | GridAutoFlow | JustifyItems |
1652            // Gap (tier2 extension)
1653            ColumnGap | RowGap | Gap |
1654            // Grid placement (tier2_cold extension)
1655            GridColumn | GridRow
1656        )
1657    }
1658
1659    #[must_use]
1660    pub const fn get_category(&self) -> CssPropertyCategory {
1661        if self.is_gpu_only_property() {
1662            CssPropertyCategory::GpuOnly
1663        } else {
1664            let is_inheritable = self.is_inheritable();
1665            let can_trigger_layout = self.can_trigger_relayout();
1666            match (is_inheritable, can_trigger_layout) {
1667                (true, true) => CssPropertyCategory::InheritedLayout,
1668                (true, false) => CssPropertyCategory::InheritedPaint,
1669                (false, true) => CssPropertyCategory::Layout,
1670                (false, false) => CssPropertyCategory::Paint,
1671            }
1672        }
1673    }
1674
1675    /// Returns whether this property can trigger a re-layout (important for incremental layout and
1676    /// caching layouted DOMs).
1677    #[must_use]
1678    pub const fn can_trigger_relayout(&self) -> bool {
1679        use self::CssPropertyType::{
1680            Animation, AnimationIn, AnimationOut, AppRegion, BackdropFilter, BackfaceVisibility,
1681            SpatialNavigationAction, SpatialNavigationContain,
1682            BackgroundContent, BackgroundPosition, BackgroundRepeat, BackgroundSize,
1683            BorderBottomColor, BorderBottomLeftRadius, BorderBottomRightRadius, BorderBottomStyle,
1684            BorderLeftColor, BorderLeftStyle, BorderRightColor, BorderRightStyle, BorderTopColor,
1685            BorderTopLeftRadius, BorderTopRightRadius, BorderTopStyle, BoxDecorationBreak,
1686            BoxShadowBottom, BoxShadowLeft, BoxShadowRight, BoxShadowTop, Clip, ColumnRuleColor,
1687            ColumnRuleStyle, Cursor, Filter, MixBlendMode, Opacity, PerspectiveOrigin,
1688            ScrollbarButton, ScrollbarCorner, ScrollbarResizer, ScrollbarThumb, ScrollbarTrack,
1689            TextColor, TextShadow, Transform, TransformOrigin,
1690        };
1691
1692        // Since the border can be larger than the content,
1693        // in which case the content needs to be re-layouted, assume true for Border
1694
1695        // FontFamily, FontSize, LetterSpacing and LineHeight can affect
1696        // the text layout and therefore the screen layout
1697
1698        !matches!(
1699            self,
1700            TextColor
1701            | Cursor
1702            | BackgroundContent
1703            | BackgroundPosition
1704            | BackgroundSize
1705            | BackgroundRepeat
1706            | BorderTopLeftRadius
1707            | BorderTopRightRadius
1708            | BorderBottomLeftRadius
1709            | BorderBottomRightRadius
1710            | BorderTopColor
1711            | BorderRightColor
1712            | BorderLeftColor
1713            | BorderBottomColor
1714            | BorderTopStyle
1715            | BorderRightStyle
1716            | BorderLeftStyle
1717            | BorderBottomStyle
1718            | ColumnRuleColor
1719            | ColumnRuleStyle
1720            | BoxShadowLeft
1721            | BoxShadowRight
1722            | BoxShadowTop
1723            | BoxShadowBottom
1724            | BoxDecorationBreak
1725            | ScrollbarTrack
1726            | ScrollbarThumb
1727            | ScrollbarButton
1728            | ScrollbarCorner
1729            | ScrollbarResizer
1730            | Opacity
1731            | Transform
1732            | TransformOrigin
1733            | PerspectiveOrigin
1734            | BackfaceVisibility
1735            | MixBlendMode
1736            | Filter
1737            | BackdropFilter
1738            | TextShadow
1739            | Clip
1740            // The animation properties are META: they DESCRIBE motion, they
1741            // are not motion. Changing them must never charge a layout pass
1742            // (the transition driver reads them at the diff seam).
1743            | Animation
1744            | AnimationIn
1745            | AnimationOut
1746            // The spatial-navigation properties are meta in the same way, and
1747            // one step further: they describe what an ARROW KEY does. They
1748            // move no box and paint no pixel, so a relayout here would be pure
1749            // cost. The default for an unlisted property is `true`, which is
1750            // why they have to be named.
1751            | SpatialNavigationAction
1752            | SpatialNavigationContain
1753        )
1754    }
1755
1756    /// Returns whether the property is a GPU property (currently only opacity and transforms)
1757    #[must_use]
1758    pub const fn is_gpu_only_property(&self) -> bool {
1759        match self {
1760            Self::Opacity |
1761            Self::Transform /* | CssPropertyType::Color */ => true,
1762            _ => false
1763        }
1764    }
1765
1766    /// Context-dependent relayout scope for a CSS property change.
1767    ///
1768    /// This is a more granular replacement for `can_trigger_relayout()`.
1769    /// Instead of returning a flat bool, it classifies the property change
1770    /// into one of four impact levels (see `RelayoutScope`).
1771    ///
1772    /// Inspired by Taffy's binary dirty flag, extended with CSS-specific
1773    /// knowledge: font/text changes only affect IFC, sizing changes don't
1774    /// require full subtree relayout, and paint-only changes skip layout entirely.
1775    ///
1776    /// `node_is_ifc_member`: whether this node participates in an IFC
1777    /// (has inline formatting context membership). When true, font/text
1778    /// property changes trigger IFC-only relayout instead of being ignored.
1779    #[must_use]
1780    pub const fn relayout_scope(&self, node_is_ifc_member: bool) -> RelayoutScope {
1781        use CssPropertyType::{
1782            AlignmentBaseline, Animation, AnimationIn, AnimationOut, AppRegion, BackdropFilter,
1783            SpatialNavigationAction, SpatialNavigationContain,
1784            BackfaceVisibility, BackgroundContent, BackgroundPosition, BackgroundRepeat,
1785            BackgroundSize, BaselineSource, BorderBottomColor, BorderBottomLeftRadius,
1786            BorderBottomRightRadius, BorderBottomStyle, BorderBottomWidth, BorderLeftColor,
1787            BorderLeftStyle, BorderLeftWidth, BorderRightColor, BorderRightStyle, BorderRightWidth,
1788            BorderTopColor, BorderTopLeftRadius, BorderTopRightRadius, BorderTopStyle,
1789            BorderTopWidth, BoxDecorationBreak, BoxShadowBottom, BoxShadowLeft, BoxShadowRight,
1790            BoxShadowTop, BoxSizing, CaretAnimationDuration, CaretColor, CaretWidth, Clip,
1791            ColumnRuleColor, ColumnRuleStyle, Cursor, Direction, DominantBaseline, Filter,
1792            FontFamily, FontSize, FontStyle, FontWeight, HangingPunctuation, Height,
1793            HyphenationLanguage, Hyphens, InitialLetter, InitialLetterAlign, InitialLetterWrap,
1794            LetterSpacing, LineBreak, LineClamp, LineFitEdge, LineHeight, MaxHeight, MaxWidth,
1795            MinHeight, MinWidth, MixBlendMode, ObjectFit, ObjectPosition, Opacity,
1796            OverflowClipMargin, OverflowWrap, PaddingBottom, PaddingInlineEnd, PaddingInlineStart,
1797            PaddingLeft, PaddingRight, PaddingTop, PerspectiveOrigin, ScrollbarButton,
1798            ScrollbarCorner, ScrollbarGutter, ScrollbarResizer, ScrollbarThumb, ScrollbarTrack,
1799            ScrollbarVisibility, ScrollbarWidth, SelectionBackgroundColor, SelectionColor,
1800            SelectionRadius, TabSize, TextAlign, TextAlignLast, TextBoxEdge, TextBoxTrim,
1801            TextColor, TextCombineUpright, TextDecoration, TextIndent, TextJustify,
1802            TextOrientation, TextOverflow, TextShadow, Transform, TransformOrigin, UnicodeBidi,
1803            VerticalAlign, WhiteSpace, Width, WordBreak, WordSpacing,
1804        };
1805        match self {
1806            // Pure paint — never triggers relayout
1807            TextColor
1808            | Cursor
1809            | BackgroundContent
1810            | BackgroundPosition
1811            | BackgroundSize
1812            | BackgroundRepeat
1813            | BorderTopColor
1814            | BorderRightColor
1815            | BorderLeftColor
1816            | BorderBottomColor
1817            | BorderTopStyle
1818            | BorderRightStyle
1819            | BorderLeftStyle
1820            | BorderBottomStyle
1821            | BorderTopLeftRadius
1822            | BorderTopRightRadius
1823            | BorderBottomLeftRadius
1824            | BorderBottomRightRadius
1825            | ColumnRuleColor
1826            | ColumnRuleStyle
1827            | BoxShadowLeft
1828            | BoxShadowRight
1829            | BoxShadowTop
1830            | BoxShadowBottom
1831            | BoxDecorationBreak
1832            | ScrollbarTrack
1833            | ScrollbarThumb
1834            | ScrollbarButton
1835            | ScrollbarCorner
1836            | ScrollbarResizer
1837            | Opacity
1838            | Transform
1839            | TransformOrigin
1840            | PerspectiveOrigin
1841            | BackfaceVisibility
1842            | MixBlendMode
1843            | Filter
1844            | BackdropFilter
1845            | TextShadow
1846            | SelectionBackgroundColor
1847            | SelectionColor
1848            | SelectionRadius
1849            | CaretColor
1850            | CaretAnimationDuration
1851            | CaretWidth
1852            | TextOverflow
1853            | ObjectFit
1854            | ObjectPosition
1855            | Clip
1856            // Meta-properties describing animations — never layout by
1857            // themselves (see can_trigger_relayout).
1858            | Animation
1859            | AnimationIn
1860            | AnimationOut
1861            // Same argument, one step further: these describe what an arrow
1862            // key does and change nothing on screen at all. `None` and not
1863            // `PaintOnly`, because there is nothing to repaint either. The
1864            // fallthrough here is `Full`, so being unlisted would cost a whole
1865            // layout pass per declaration.
1866            | SpatialNavigationAction
1867            | SpatialNavigationContain => RelayoutScope::None,
1868
1869            // Font/text properties — IFC-only if inside inline context,
1870            // otherwise no layout impact (block with only block children
1871            // inherits but doesn't directly reflow).
1872            FontFamily | FontSize | FontWeight | FontStyle | LetterSpacing | WordSpacing
1873            | LineHeight | TextAlign | TextJustify | TextIndent | WhiteSpace | TabSize
1874            | Hyphens | WordBreak | OverflowWrap | LineBreak | TextAlignLast | TextOrientation
1875            | HyphenationLanguage | TextCombineUpright | TextDecoration | HangingPunctuation
1876            | InitialLetter | LineClamp | Direction | VerticalAlign | UnicodeBidi | TextBoxTrim
1877            | TextBoxEdge | DominantBaseline | AlignmentBaseline | BaselineSource
1878            | LineFitEdge | InitialLetterAlign | InitialLetterWrap => {
1879                if node_is_ifc_member {
1880                    RelayoutScope::IfcOnly
1881                } else {
1882                    // Block container with only block children: font properties
1883                    // are inherited but don't affect this node's own sizing.
1884                    // Children pick up the change via inheritance and get their
1885                    // own dirty flags.
1886                    RelayoutScope::None
1887                }
1888            }
1889
1890            // Sizing properties — only this node's size changes.
1891            // Parent may reposition subsequent siblings but doesn't need
1892            // full recursive relayout of unaffected subtrees.
1893            Width | Height | MinWidth | MinHeight | MaxWidth | MaxHeight | PaddingTop
1894            | PaddingRight | PaddingBottom | PaddingLeft | PaddingInlineStart
1895            | PaddingInlineEnd | BorderTopWidth | BorderRightWidth | BorderBottomWidth
1896            | BorderLeftWidth | BoxSizing | ScrollbarWidth | ScrollbarVisibility
1897            | ScrollbarGutter | OverflowClipMargin => RelayoutScope::SizingOnly,
1898
1899            // Everything else: display, position, float, margin, flex-*,
1900            // grid-*, overflow, writing-mode, etc. — full relayout.
1901            _ => RelayoutScope::Full,
1902        }
1903    }
1904}
1905
1906// -- PARSING --
1907
1908/// Master error type that aggregates all possible CSS parsing errors.
1909#[derive(Clone, PartialEq)]
1910pub enum CssParsingError<'a> {
1911    // Shorthand properties
1912    Border(CssBorderParseError<'a>),
1913    BorderRadius(CssBorderRadiusParseError<'a>),
1914    Padding(LayoutPaddingParseError<'a>),
1915    Margin(LayoutMarginParseError<'a>),
1916    Overflow(InvalidValueErr<'a>),
1917    BoxShadow(CssShadowParseError<'a>),
1918
1919    // Individual properties
1920    Color(CssColorParseError<'a>),
1921    PixelValue(CssPixelValueParseError<'a>),
1922    Percentage(PercentageParseError),
1923    FontFamily(CssStyleFontFamilyParseError<'a>),
1924    InvalidValue(InvalidValueErr<'a>),
1925    FlexGrow(FlexGrowParseError<'a>),
1926    FlexShrink(FlexShrinkParseError<'a>),
1927    Background(CssBackgroundParseError<'a>),
1928    BackgroundPosition(CssBackgroundPositionParseError<'a>),
1929    Opacity(OpacityParseError<'a>),
1930    Visibility(StyleVisibilityParseError<'a>),
1931    LayoutScrollbarWidth(LayoutScrollbarWidthParseError<'a>),
1932    OverscrollBehavior(OverscrollBehaviorParseError<'a>),
1933    StyleScrollbarColor(StyleScrollbarColorParseError<'a>),
1934    ScrollbarVisibilityMode(ScrollbarVisibilityModeParseError<'a>),
1935    ScrollbarFadeDelay(ScrollbarFadeDelayParseError<'a>),
1936    ScrollbarFadeDuration(ScrollbarFadeDurationParseError<'a>),
1937    Transform(CssStyleTransformParseError<'a>),
1938    TransformOrigin(CssStyleTransformOriginParseError<'a>),
1939    PerspectiveOrigin(CssStylePerspectiveOriginParseError<'a>),
1940    Filter(CssStyleFilterParseError<'a>),
1941
1942    // Text/Style properties
1943    TextColor(StyleTextColorParseError<'a>),
1944    FontSize(CssStyleFontSizeParseError<'a>),
1945    FontWeight(CssFontWeightParseError<'a>),
1946    FontStyle(CssFontStyleParseError<'a>),
1947    TextAlign(StyleTextAlignParseError<'a>),
1948    TextJustify(TextJustifyParseError<'a>),
1949    VerticalAlign(StyleVerticalAlignParseError<'a>),
1950    LetterSpacing(StyleLetterSpacingParseError<'a>),
1951    TextIndent(StyleTextIndentParseError<'a>),
1952    InitialLetter(StyleInitialLetterParseError<'a>),
1953    LineClamp(StyleLineClampParseError<'a>),
1954    HangingPunctuation(StyleHangingPunctuationParseError<'a>),
1955    TextCombineUpright(StyleTextCombineUprightParseError<'a>),
1956    UnicodeBidi(StyleUnicodeBidiParseError<'a>),
1957    TextBoxTrim(StyleTextBoxTrimParseError<'a>),
1958    TextBoxEdge(StyleTextBoxEdgeParseError<'a>),
1959    DominantBaseline(StyleDominantBaselineParseError<'a>),
1960    AlignmentBaseline(StyleAlignmentBaselineParseError<'a>),
1961    BaselineSource(StyleBaselineSourceParseError<'a>),
1962    LineFitEdge(StyleLineFitEdgeParseError<'a>),
1963    InitialLetterAlign(StyleInitialLetterAlignParseError<'a>),
1964    InitialLetterWrap(StyleInitialLetterWrapParseError<'a>),
1965    ScrollbarGutter(StyleScrollbarGutterParseError<'a>),
1966    OverflowClipMargin(StyleOverflowClipMarginParseError<'a>),
1967    Clip(StyleClipRectParseError<'a>),
1968    ExclusionMargin(StyleExclusionMarginParseError),
1969    HyphenationLanguage(StyleHyphenationLanguageParseError),
1970    LineHeight(StyleLineHeightParseError),
1971    WordSpacing(StyleWordSpacingParseError<'a>),
1972    TabSize(StyleTabSizeParseError<'a>),
1973    WhiteSpace(StyleWhiteSpaceParseError<'a>),
1974    Hyphens(StyleHyphensParseError<'a>),
1975    WordBreak(StyleWordBreakParseError<'a>),
1976    OverflowWrap(StyleOverflowWrapParseError<'a>),
1977    LineBreak(StyleLineBreakParseError<'a>),
1978    TextOverflow(StyleTextOverflowParseError<'a>),
1979    ObjectFit(StyleObjectFitParseError<'a>),
1980    ObjectPosition(StyleObjectPositionParseError<'a>),
1981    AspectRatio(StyleAspectRatioParseError<'a>),
1982    TextOrientation(StyleTextOrientationParseError<'a>),
1983    TextAlignLast(StyleTextAlignLastParseError<'a>),
1984    TextTransform(StyleTextTransformParseError<'a>),
1985    Direction(StyleDirectionParseError<'a>),
1986    UserSelect(StyleUserSelectParseError<'a>),
1987    TextDecoration(StyleTextDecorationParseError<'a>),
1988    Cursor(CursorParseError<'a>),
1989    CaretColor(CssColorParseError<'a>),
1990    CaretAnimationDuration(DurationParseError<'a>),
1991    Animation(crate::props::basic::animation::StyleAnimationParseError<'a>),
1992    CaretWidth(CssPixelValueParseError<'a>),
1993    SelectionBackgroundColor(CssColorParseError<'a>),
1994    SelectionColor(CssColorParseError<'a>),
1995    SelectionRadius(CssPixelValueParseError<'a>),
1996
1997    // Layout basic properties
1998    LayoutDisplay(LayoutDisplayParseError<'a>),
1999    LayoutFloat(LayoutFloatParseError<'a>),
2000    LayoutBoxSizing(LayoutBoxSizingParseError<'a>),
2001
2002    // Layout dimensions
2003    LayoutWidth(LayoutWidthParseError<'a>),
2004    LayoutHeight(LayoutHeightParseError<'a>),
2005    LayoutMinWidth(LayoutMinWidthParseError<'a>),
2006    LayoutMinHeight(LayoutMinHeightParseError<'a>),
2007    LayoutMaxWidth(LayoutMaxWidthParseError<'a>),
2008    LayoutMaxHeight(LayoutMaxHeightParseError<'a>),
2009
2010    // Layout position
2011    LayoutPosition(LayoutPositionParseError<'a>),
2012    LayoutTop(LayoutTopParseError<'a>),
2013    LayoutRight(LayoutRightParseError<'a>),
2014    LayoutLeft(LayoutLeftParseError<'a>),
2015    LayoutInsetBottom(LayoutInsetBottomParseError<'a>),
2016    LayoutZIndex(LayoutZIndexParseError<'a>),
2017
2018    // Layout flex
2019    FlexWrap(FlexWrapParseError<'a>),
2020    FlexDirection(FlexDirectionParseError<'a>),
2021    FlexBasis(FlexBasisParseError<'a>),
2022    JustifyContent(JustifyContentParseError<'a>),
2023    AlignItems(AlignItemsParseError<'a>),
2024    AlignContent(AlignContentParseError<'a>),
2025
2026    // Layout grid
2027    Grid(GridParseError<'a>),
2028    GridAutoFlow(GridAutoFlowParseError<'a>),
2029    JustifySelf(JustifySelfParseError<'a>),
2030    JustifyItems(JustifyItemsParseError<'a>),
2031    AlignSelf(AlignSelfParseError<'a>),
2032
2033    // Layout wrapping
2034    LayoutWritingMode(LayoutWritingModeParseError<'a>),
2035    LayoutClear(LayoutClearParseError<'a>),
2036
2037    // Layout overflow
2038    LayoutOverflow(LayoutOverflowParseError<'a>),
2039
2040    // Border radius individual corners
2041    BorderTopLeftRadius(StyleBorderTopLeftRadiusParseError<'a>),
2042    BorderTopRightRadius(StyleBorderTopRightRadiusParseError<'a>),
2043    BorderBottomLeftRadius(StyleBorderBottomLeftRadiusParseError<'a>),
2044    BorderBottomRightRadius(StyleBorderBottomRightRadiusParseError<'a>),
2045
2046    // Border style
2047    BorderStyle(CssBorderStyleParseError<'a>),
2048
2049    // Effects
2050    BackfaceVisibility(CssBackfaceVisibilityParseError<'a>),
2051    AppRegion(CssAppRegionParseError<'a>),
2052    SpatialNavigationAction(CssSpatialNavigationActionParseError<'a>),
2053    SpatialNavigationContain(CssSpatialNavigationContainParseError<'a>),
2054    MixBlendMode(MixBlendModeParseError<'a>),
2055
2056    // Fragmentation
2057    PageBreak(PageBreakParseError<'a>),
2058    BreakInside(BreakInsideParseError<'a>),
2059    Widows(WidowsParseError<'a>),
2060    Orphans(OrphansParseError<'a>),
2061    BoxDecorationBreak(BoxDecorationBreakParseError<'a>),
2062
2063    // Columns
2064    ColumnCount(ColumnCountParseError<'a>),
2065    ColumnWidth(ColumnWidthParseError<'a>),
2066    ColumnSpan(ColumnSpanParseError<'a>),
2067    ColumnFill(ColumnFillParseError<'a>),
2068    ColumnRuleWidth(ColumnRuleWidthParseError<'a>),
2069    ColumnRuleStyle(ColumnRuleStyleParseError<'a>),
2070    ColumnRuleColor(ColumnRuleColorParseError<'a>),
2071
2072    // Flow & Shape
2073    FlowInto(FlowIntoParseError<'a>),
2074    FlowFrom(FlowFromParseError<'a>),
2075    GenericParseError,
2076
2077    // Content
2078    Content, // Simplified errors for now
2079    Counter,
2080    ListStyleType(StyleListStyleTypeParseError<'a>),
2081    ListStylePosition(StyleListStylePositionParseError<'a>),
2082    StringSet,
2083}
2084
2085/// Owned version of `CssParsingError`.
2086#[derive(Debug, Clone, PartialEq)]
2087#[repr(C, u8)]
2088pub enum CssParsingErrorOwned {
2089    // Shorthand properties
2090    Border(CssBorderParseErrorOwned),
2091    BorderRadius(CssStyleBorderRadiusParseErrorOwned),
2092    Padding(LayoutPaddingParseErrorOwned),
2093    Margin(LayoutMarginParseErrorOwned),
2094    Overflow(InvalidValueErrOwned),
2095    BoxShadow(CssShadowParseErrorOwned),
2096
2097    // Individual properties
2098    Color(CssColorParseErrorOwned),
2099    PixelValue(CssPixelValueParseErrorOwned),
2100    Percentage(PercentageParseError),
2101    FontFamily(CssStyleFontFamilyParseErrorOwned),
2102    InvalidValue(InvalidValueErrOwned),
2103    FlexGrow(FlexGrowParseErrorOwned),
2104    FlexShrink(FlexShrinkParseErrorOwned),
2105    Background(CssBackgroundParseErrorOwned),
2106    BackgroundPosition(CssBackgroundPositionParseErrorOwned),
2107    Opacity(OpacityParseErrorOwned),
2108    Visibility(StyleVisibilityParseErrorOwned),
2109    LayoutScrollbarWidth(LayoutScrollbarWidthParseErrorOwned),
2110    OverscrollBehavior(OverscrollBehaviorParseErrorOwned),
2111    StyleScrollbarColor(StyleScrollbarColorParseErrorOwned),
2112    ScrollbarVisibilityMode(ScrollbarVisibilityModeParseErrorOwned),
2113    ScrollbarFadeDelay(ScrollbarFadeDelayParseErrorOwned),
2114    ScrollbarFadeDuration(ScrollbarFadeDurationParseErrorOwned),
2115    Transform(CssStyleTransformParseErrorOwned),
2116    TransformOrigin(CssStyleTransformOriginParseErrorOwned),
2117    PerspectiveOrigin(CssStylePerspectiveOriginParseErrorOwned),
2118    Filter(CssStyleFilterParseErrorOwned),
2119
2120    // Text/Style properties
2121    TextColor(StyleTextColorParseErrorOwned),
2122    FontSize(CssStyleFontSizeParseErrorOwned),
2123    FontWeight(CssFontWeightParseErrorOwned),
2124    FontStyle(CssFontStyleParseErrorOwned),
2125    TextAlign(StyleTextAlignParseErrorOwned),
2126    TextJustify(TextJustifyParseErrorOwned),
2127    VerticalAlign(StyleVerticalAlignParseErrorOwned),
2128    LetterSpacing(StyleLetterSpacingParseErrorOwned),
2129    TextIndent(StyleTextIndentParseErrorOwned),
2130    InitialLetter(StyleInitialLetterParseErrorOwned),
2131    LineClamp(StyleLineClampParseErrorOwned),
2132    HangingPunctuation(StyleHangingPunctuationParseErrorOwned),
2133    TextCombineUpright(StyleTextCombineUprightParseErrorOwned),
2134    UnicodeBidi(StyleUnicodeBidiParseErrorOwned),
2135    TextBoxTrim(StyleTextBoxTrimParseErrorOwned),
2136    TextBoxEdge(StyleTextBoxEdgeParseErrorOwned),
2137    DominantBaseline(StyleDominantBaselineParseErrorOwned),
2138    AlignmentBaseline(StyleAlignmentBaselineParseErrorOwned),
2139    BaselineSource(StyleBaselineSourceParseErrorOwned),
2140    LineFitEdge(StyleLineFitEdgeParseErrorOwned),
2141    InitialLetterAlign(StyleInitialLetterAlignParseErrorOwned),
2142    InitialLetterWrap(StyleInitialLetterWrapParseErrorOwned),
2143    ScrollbarGutter(StyleScrollbarGutterParseErrorOwned),
2144    OverflowClipMargin(StyleOverflowClipMarginParseErrorOwned),
2145    Clip(StyleClipRectParseErrorOwned),
2146    ExclusionMargin(StyleExclusionMarginParseErrorOwned),
2147    HyphenationLanguage(StyleHyphenationLanguageParseErrorOwned),
2148    LineHeight(StyleLineHeightParseError),
2149    WordSpacing(StyleWordSpacingParseErrorOwned),
2150    TabSize(StyleTabSizeParseErrorOwned),
2151    WhiteSpace(StyleWhiteSpaceParseErrorOwned),
2152    Hyphens(StyleHyphensParseErrorOwned),
2153    WordBreak(StyleWordBreakParseErrorOwned),
2154    OverflowWrap(StyleOverflowWrapParseErrorOwned),
2155    LineBreak(StyleLineBreakParseErrorOwned),
2156    TextOverflow(StyleTextOverflowParseErrorOwned),
2157    ObjectFit(StyleObjectFitParseErrorOwned),
2158    ObjectPosition(StyleObjectPositionParseErrorOwned),
2159    AspectRatio(StyleAspectRatioParseErrorOwned),
2160    TextOrientation(StyleTextOrientationParseErrorOwned),
2161    TextAlignLast(StyleTextAlignLastParseErrorOwned),
2162    TextTransform(StyleTextTransformParseErrorOwned),
2163    Direction(StyleDirectionParseErrorOwned),
2164    UserSelect(StyleUserSelectParseErrorOwned),
2165    TextDecoration(StyleTextDecorationParseErrorOwned),
2166    Cursor(CursorParseErrorOwned),
2167    CaretColor(CssColorParseErrorOwned),
2168    CaretAnimationDuration(DurationParseErrorOwned),
2169    Animation(crate::props::basic::animation::StyleAnimationParseErrorOwned),
2170    CaretWidth(CssPixelValueParseErrorOwned),
2171    SelectionBackgroundColor(CssColorParseErrorOwned),
2172    SelectionColor(CssColorParseErrorOwned),
2173    SelectionRadius(CssPixelValueParseErrorOwned),
2174
2175    // Layout basic properties
2176    LayoutDisplay(LayoutDisplayParseErrorOwned),
2177    LayoutFloat(LayoutFloatParseErrorOwned),
2178    LayoutBoxSizing(LayoutBoxSizingParseErrorOwned),
2179
2180    // Layout dimensions
2181    LayoutWidth(LayoutWidthParseErrorOwned),
2182    LayoutHeight(LayoutHeightParseErrorOwned),
2183    LayoutMinWidth(LayoutMinWidthParseErrorOwned),
2184    LayoutMinHeight(LayoutMinHeightParseErrorOwned),
2185    LayoutMaxWidth(LayoutMaxWidthParseErrorOwned),
2186    LayoutMaxHeight(LayoutMaxHeightParseErrorOwned),
2187
2188    // Layout position
2189    LayoutPosition(LayoutPositionParseErrorOwned),
2190    LayoutTop(LayoutTopParseErrorOwned),
2191    LayoutRight(LayoutRightParseErrorOwned),
2192    LayoutLeft(LayoutLeftParseErrorOwned),
2193    LayoutInsetBottom(LayoutInsetBottomParseErrorOwned),
2194    LayoutZIndex(LayoutZIndexParseErrorOwned),
2195
2196    // Layout flex
2197    FlexWrap(FlexWrapParseErrorOwned),
2198    FlexDirection(FlexDirectionParseErrorOwned),
2199    FlexBasis(FlexBasisParseErrorOwned),
2200    JustifyContent(JustifyContentParseErrorOwned),
2201    AlignItems(AlignItemsParseErrorOwned),
2202    AlignContent(AlignContentParseErrorOwned),
2203
2204    // Layout grid
2205    Grid(GridParseErrorOwned),
2206    GridAutoFlow(GridAutoFlowParseErrorOwned),
2207    JustifySelf(JustifySelfParseErrorOwned),
2208    JustifyItems(JustifyItemsParseErrorOwned),
2209    AlignSelf(AlignSelfParseErrorOwned),
2210
2211    // Layout wrapping
2212    LayoutWritingMode(LayoutWritingModeParseErrorOwned),
2213    LayoutClear(LayoutClearParseErrorOwned),
2214
2215    // Layout overflow
2216    LayoutOverflow(LayoutOverflowParseErrorOwned),
2217
2218    // Border radius individual corners
2219    BorderTopLeftRadius(StyleBorderTopLeftRadiusParseErrorOwned),
2220    BorderTopRightRadius(StyleBorderTopRightRadiusParseErrorOwned),
2221    BorderBottomLeftRadius(StyleBorderBottomLeftRadiusParseErrorOwned),
2222    BorderBottomRightRadius(StyleBorderBottomRightRadiusParseErrorOwned),
2223
2224    // Border style
2225    BorderStyle(CssBorderStyleParseErrorOwned),
2226
2227    // Effects
2228    BackfaceVisibility(CssBackfaceVisibilityParseErrorOwned),
2229    AppRegion(CssAppRegionParseErrorOwned),
2230    SpatialNavigationAction(CssSpatialNavigationActionParseErrorOwned),
2231    SpatialNavigationContain(CssSpatialNavigationContainParseErrorOwned),
2232    MixBlendMode(MixBlendModeParseErrorOwned),
2233
2234    // Fragmentation
2235    PageBreak(PageBreakParseErrorOwned),
2236    BreakInside(BreakInsideParseErrorOwned),
2237    Widows(WidowsParseErrorOwned),
2238    Orphans(OrphansParseErrorOwned),
2239    BoxDecorationBreak(BoxDecorationBreakParseErrorOwned),
2240
2241    // Columns
2242    ColumnCount(ColumnCountParseErrorOwned),
2243    ColumnWidth(ColumnWidthParseErrorOwned),
2244    ColumnSpan(ColumnSpanParseErrorOwned),
2245    ColumnFill(ColumnFillParseErrorOwned),
2246    ColumnRuleWidth(ColumnRuleWidthParseErrorOwned),
2247    ColumnRuleStyle(ColumnRuleStyleParseErrorOwned),
2248    ColumnRuleColor(ColumnRuleColorParseErrorOwned),
2249
2250    // Flow & Shape
2251    FlowInto(FlowIntoParseErrorOwned),
2252    FlowFrom(FlowFromParseErrorOwned),
2253    GenericParseError,
2254
2255    // Content
2256    Content,
2257    Counter,
2258    ListStyleType(StyleListStyleTypeParseErrorOwned),
2259    ListStylePosition(StyleListStylePositionParseErrorOwned),
2260    StringSet,
2261}
2262
2263// -- PARSING ERROR IMPLEMENTATIONS --
2264
2265impl_debug_as_display!(CssParsingError<'a>);
2266impl_display! { CssParsingError<'a>, {
2267    CaretColor(e) => format!("Invalid caret-color: {}", e),
2268    CaretAnimationDuration(e) => format!("Invalid caret-animation-duration: {}", e),
2269    Animation(e) => format!("Invalid animation: {}", e),
2270    CaretWidth(e) => format!("Invalid -azul-caret-width: {}", e),
2271    SelectionBackgroundColor(e) => format!("Invalid -azul-selection-background-color: {}", e),
2272    SelectionColor(e) => format!("Invalid -azul-selection-color: {}", e),
2273    SelectionRadius(e) => format!("Invalid -azul-selection-radius: {}", e),
2274    Border(e) => format!("Invalid border property: {}", e),
2275    BorderRadius(e) => format!("Invalid border-radius: {}", e),
2276    Padding(e) => format!("Invalid padding property: {}", e),
2277    Margin(e) => format!("Invalid margin property: {}", e),
2278    Overflow(e) => format!("Invalid overflow property: \"{}\"", e.0),
2279    BoxShadow(e) => format!("Invalid shadow property: {}", e),
2280    Color(e) => format!("Invalid color value: {}", e),
2281    PixelValue(e) => format!("Invalid pixel value: {}", e),
2282    Percentage(e) => format!("Invalid percentage value: {}", e),
2283    FontFamily(e) => format!("Invalid font-family value: {}", e),
2284    InvalidValue(e) => format!("Invalid value: \"{}\"", e.0),
2285    FlexGrow(e) => format!("Invalid flex-grow value: {}", e),
2286    FlexShrink(e) => format!("Invalid flex-shrink value: {}", e),
2287    Background(e) => format!("Invalid background property: {}", e),
2288    BackgroundPosition(e) => format!("Invalid background-position: {}", e),
2289    Opacity(e) => format!("Invalid opacity value: {}", e),
2290    Visibility(e) => format!("Invalid visibility value: {}", e),
2291    LayoutScrollbarWidth(e) => format!("Invalid scrollbar-width: {}", e),
2292    OverscrollBehavior(e) => format!("Invalid overscroll-behavior: {}", e),
2293    StyleScrollbarColor(e) => format!("Invalid scrollbar-color: {}", e),
2294    ScrollbarVisibilityMode(e) => format!("Invalid scrollbar-visibility: {}", e),
2295    ScrollbarFadeDelay(e) => format!("Invalid scrollbar-fade-delay: {}", e),
2296    ScrollbarFadeDuration(e) => format!("Invalid scrollbar-fade-duration: {}", e),
2297    Transform(e) => format!("Invalid transform property: {}", e),
2298    TransformOrigin(e) => format!("Invalid transform-origin: {}", e),
2299    PerspectiveOrigin(e) => format!("Invalid perspective-origin: {}", e),
2300    Filter(e) => format!("Invalid filter property: {}", e),
2301    LayoutWidth(e) => format!("Invalid width value: {}", e),
2302    LayoutHeight(e) => format!("Invalid height value: {}", e),
2303    LayoutMinWidth(e) => format!("Invalid min-width value: {}", e),
2304    LayoutMinHeight(e) => format!("Invalid min-height value: {}", e),
2305    LayoutMaxWidth(e) => format!("Invalid max-width value: {}", e),
2306    LayoutMaxHeight(e) => format!("Invalid max-height value: {}", e),
2307    LayoutPosition(e) => format!("Invalid position value: {}", e),
2308    LayoutTop(e) => format!("Invalid top value: {}", e),
2309    LayoutRight(e) => format!("Invalid right value: {}", e),
2310    LayoutLeft(e) => format!("Invalid left value: {}", e),
2311    LayoutInsetBottom(e) => format!("Invalid bottom value: {}", e),
2312    LayoutZIndex(e) => format!("Invalid z-index value: {}", e),
2313    FlexWrap(e) => format!("Invalid flex-wrap value: {}", e),
2314    FlexDirection(e) => format!("Invalid flex-direction value: {}", e),
2315    FlexBasis(e) => format!("Invalid flex-basis value: {}", e),
2316    JustifyContent(e) => format!("Invalid justify-content value: {}", e),
2317    AlignItems(e) => format!("Invalid align-items value: {}", e),
2318    AlignContent(e) => format!("Invalid align-content value: {}", e),
2319    GridAutoFlow(e) => format!("Invalid grid-auto-flow value: {}", e),
2320    JustifySelf(e) => format!("Invalid justify-self value: {}", e),
2321    JustifyItems(e) => format!("Invalid justify-items value: {}", e),
2322    AlignSelf(e) => format!("Invalid align-self value: {}", e),
2323    Grid(e) => format!("Invalid grid value: {}", e),
2324    LayoutWritingMode(e) => format!("Invalid writing-mode value: {}", e),
2325    LayoutClear(e) => format!("Invalid clear value: {}", e),
2326    LayoutOverflow(e) => format!("Invalid overflow value: {}", e),
2327    BorderTopLeftRadius(e) => format!("Invalid border-top-left-radius: {}", e),
2328    BorderTopRightRadius(e) => format!("Invalid border-top-right-radius: {}", e),
2329    BorderBottomLeftRadius(e) => format!("Invalid border-bottom-left-radius: {}", e),
2330    BorderBottomRightRadius(e) => format!("Invalid border-bottom-right-radius: {}", e),
2331    BorderStyle(e) => format!("Invalid border style: {}", e),
2332    BackfaceVisibility(e) => format!("Invalid backface-visibility: {}", e),
2333    AppRegion(e) => format!("Invalid app-region: {}", e),
2334    SpatialNavigationAction(e) => format!("Invalid spatial-navigation-action: {}", e),
2335    SpatialNavigationContain(e) => format!("Invalid spatial-navigation-contain: {}", e),
2336    MixBlendMode(e) => format!("Invalid mix-blend-mode: {}", e),
2337    TextColor(e) => format!("Invalid text color: {}", e),
2338    FontSize(e) => format!("Invalid font-size: {}", e),
2339    FontWeight(e) => format!("Invalid font-weight: {}", e),
2340    FontStyle(e) => format!("Invalid font-style: {}", e),
2341    TextAlign(e) => format!("Invalid text-align: {}", e),
2342    TextJustify(e) => format!("Invalid text-justify: {}", e),
2343    VerticalAlign(e) => format!("Invalid vertical-align: {}", e),
2344    LetterSpacing(e) => format!("Invalid letter-spacing: {}", e),
2345    TextIndent(e) => format!("Invalid text-indent: {}", e),
2346    InitialLetter(e) => format!("Invalid initial-letter: {}", e),
2347    LineClamp(e) => format!("Invalid line-clamp: {}", e),
2348    HangingPunctuation(e) => format!("Invalid hanging-punctuation: {}", e),
2349    TextCombineUpright(e) => format!("Invalid text-combine-upright: {}", e),
2350    UnicodeBidi(e) => format!("Invalid unicode-bidi: {}", e),
2351    TextBoxTrim(e) => format!("Invalid text-box-trim: {}", e),
2352    TextBoxEdge(e) => format!("Invalid text-box-edge: {}", e),
2353    DominantBaseline(e) => format!("Invalid dominant-baseline: {}", e),
2354    AlignmentBaseline(e) => format!("Invalid alignment-baseline: {}", e),
2355    BaselineSource(e) => format!("Invalid baseline-source: {}", e),
2356    LineFitEdge(e) => format!("Invalid line-fit-edge: {}", e),
2357    InitialLetterAlign(e) => format!("Invalid initial-letter-align: {}", e),
2358    InitialLetterWrap(e) => format!("Invalid initial-letter-wrap: {}", e),
2359    ScrollbarGutter(e) => format!("Invalid scrollbar-gutter: {}", e),
2360    OverflowClipMargin(e) => format!("Invalid overflow-clip-margin: {}", e),
2361    Clip(e) => format!("Invalid clip: {}", e),
2362    ExclusionMargin(e) => format!("Invalid -azul-exclusion-margin: {}", e),
2363    HyphenationLanguage(e) => format!("Invalid -azul-hyphenation-language: {}", e),
2364    LineHeight(e) => format!("Invalid line-height: {}", e),
2365    WordSpacing(e) => format!("Invalid word-spacing: {}", e),
2366    TabSize(e) => format!("Invalid tab-size: {}", e),
2367    WhiteSpace(e) => format!("Invalid white-space: {}", e),
2368    Hyphens(e) => format!("Invalid hyphens: {}", e),
2369    WordBreak(e) => format!("Invalid word-break: {}", e),
2370    OverflowWrap(e) => format!("Invalid overflow-wrap: {}", e),
2371    LineBreak(e) => format!("Invalid line-break: {}", e),
2372    TextOverflow(e) => format!("Invalid text-overflow: {}", e),
2373    ObjectFit(e) => format!("Invalid object-fit: {}", e),
2374    ObjectPosition(e) => format!("Invalid object-position: {}", e),
2375    AspectRatio(e) => format!("Invalid aspect-ratio: {}", e),
2376    TextOrientation(e) => format!("Invalid text-orientation: {}", e),
2377    TextAlignLast(e) => format!("Invalid text-align-last: {}", e),
2378    TextTransform(e) => format!("Invalid text-transform: {}", e),
2379    Direction(e) => format!("Invalid direction: {}", e),
2380    UserSelect(e) => format!("Invalid user-select: {}", e),
2381    TextDecoration(e) => format!("Invalid text-decoration: {}", e),
2382    Cursor(e) => format!("Invalid cursor: {}", e),
2383    LayoutDisplay(e) => format!("Invalid display: {}", e),
2384    LayoutFloat(e) => format!("Invalid float: {}", e),
2385    LayoutBoxSizing(e) => format!("Invalid box-sizing: {}", e),
2386    PageBreak(e) => format!("Invalid break property: {}", e),
2387    BreakInside(e) => format!("Invalid break-inside property: {}", e),
2388    Widows(e) => format!("Invalid widows property: {}", e),
2389    Orphans(e) => format!("Invalid orphans property: {}", e),
2390    BoxDecorationBreak(e) => format!("Invalid box-decoration-break property: {}", e),
2391    ColumnCount(e) => format!("Invalid column-count: {}", e),
2392    ColumnWidth(e) => format!("Invalid column-width: {}", e),
2393    ColumnSpan(e) => format!("Invalid column-span: {}", e),
2394    ColumnFill(e) => format!("Invalid column-fill: {}", e),
2395    ColumnRuleWidth(e) => format!("Invalid column-rule-width: {}", e),
2396    ColumnRuleStyle(e) => format!("Invalid column-rule-style: {}", e),
2397    ColumnRuleColor(e) => format!("Invalid column-rule-color: {}", e),
2398    FlowInto(e) => format!("Invalid flow-into: {}", e),
2399    FlowFrom(e) => format!("Invalid flow-from: {}", e),
2400    GenericParseError => "Failed to parse value",
2401    Content => "Failed to parse content property",
2402    Counter => "Failed to parse counter property",
2403    ListStyleType(e) => format!("Invalid list-style-type: {}", e),
2404    ListStylePosition(e) => format!("Invalid list-style-position: {}", e),
2405    StringSet => "Failed to parse string-set property",
2406}}
2407
2408// From impls for CssParsingError
2409impl_from!(
2410    DurationParseError<'a>,
2411    CssParsingError::CaretAnimationDuration
2412);
2413impl<'a> From<crate::props::basic::animation::StyleAnimationParseError<'a>>
2414    for CssParsingError<'a>
2415{
2416    fn from(e: crate::props::basic::animation::StyleAnimationParseError<'a>) -> Self {
2417        CssParsingError::Animation(e)
2418    }
2419}
2420impl_from!(CssBorderParseError<'a>, CssParsingError::Border);
2421impl_from!(CssBorderRadiusParseError<'a>, CssParsingError::BorderRadius);
2422impl_from!(LayoutPaddingParseError<'a>, CssParsingError::Padding);
2423impl_from!(LayoutMarginParseError<'a>, CssParsingError::Margin);
2424impl_from!(CssShadowParseError<'a>, CssParsingError::BoxShadow);
2425impl_from!(CssColorParseError<'a>, CssParsingError::Color);
2426impl_from!(CssPixelValueParseError<'a>, CssParsingError::PixelValue);
2427impl_from!(
2428    CssStyleFontFamilyParseError<'a>,
2429    CssParsingError::FontFamily
2430);
2431impl_from!(CssFontWeightParseError<'a>, CssParsingError::FontWeight);
2432impl_from!(CssFontStyleParseError<'a>, CssParsingError::FontStyle);
2433impl_from!(
2434    StyleInitialLetterParseError<'a>,
2435    CssParsingError::InitialLetter
2436);
2437impl_from!(StyleLineClampParseError<'a>, CssParsingError::LineClamp);
2438impl_from!(
2439    StyleHangingPunctuationParseError<'a>,
2440    CssParsingError::HangingPunctuation
2441);
2442impl_from!(
2443    StyleTextCombineUprightParseError<'a>,
2444    CssParsingError::TextCombineUpright
2445);
2446impl_from!(StyleUnicodeBidiParseError<'a>, CssParsingError::UnicodeBidi);
2447impl_from!(StyleTextBoxTrimParseError<'a>, CssParsingError::TextBoxTrim);
2448impl_from!(StyleTextBoxEdgeParseError<'a>, CssParsingError::TextBoxEdge);
2449impl_from!(
2450    StyleDominantBaselineParseError<'a>,
2451    CssParsingError::DominantBaseline
2452);
2453impl_from!(
2454    StyleAlignmentBaselineParseError<'a>,
2455    CssParsingError::AlignmentBaseline
2456);
2457impl_from!(
2458    StyleBaselineSourceParseError<'a>,
2459    CssParsingError::BaselineSource
2460);
2461impl_from!(StyleLineFitEdgeParseError<'a>, CssParsingError::LineFitEdge);
2462impl_from!(
2463    StyleInitialLetterAlignParseError<'a>,
2464    CssParsingError::InitialLetterAlign
2465);
2466impl_from!(
2467    StyleInitialLetterWrapParseError<'a>,
2468    CssParsingError::InitialLetterWrap
2469);
2470impl_from!(
2471    StyleScrollbarGutterParseError<'a>,
2472    CssParsingError::ScrollbarGutter
2473);
2474impl_from!(
2475    StyleOverflowClipMarginParseError<'a>,
2476    CssParsingError::OverflowClipMargin
2477);
2478impl_from!(StyleClipRectParseError<'a>, CssParsingError::Clip);
2479
2480// Manual From implementation for StyleExclusionMarginParseError (no lifetime)
2481#[cfg(feature = "parser")]
2482impl From<StyleExclusionMarginParseError> for CssParsingError<'_> {
2483    fn from(e: StyleExclusionMarginParseError) -> Self {
2484        CssParsingError::ExclusionMargin(e)
2485    }
2486}
2487
2488// Manual From implementation for StyleHyphenationLanguageParseError (no lifetime)
2489#[cfg(feature = "parser")]
2490impl From<StyleHyphenationLanguageParseError> for CssParsingError<'_> {
2491    fn from(e: StyleHyphenationLanguageParseError) -> Self {
2492        CssParsingError::HyphenationLanguage(e)
2493    }
2494}
2495impl_from!(FlexGrowParseError<'a>, CssParsingError::FlexGrow);
2496impl_from!(FlexShrinkParseError<'a>, CssParsingError::FlexShrink);
2497impl_from!(CssBackgroundParseError<'a>, CssParsingError::Background);
2498impl_from!(
2499    CssBackgroundPositionParseError<'a>,
2500    CssParsingError::BackgroundPosition
2501);
2502impl_from!(OpacityParseError<'a>, CssParsingError::Opacity);
2503impl_from!(StyleVisibilityParseError<'a>, CssParsingError::Visibility);
2504impl_from!(
2505    LayoutScrollbarWidthParseError<'a>,
2506    CssParsingError::LayoutScrollbarWidth
2507);
2508impl_from!(
2509    StyleScrollbarColorParseError<'a>,
2510    CssParsingError::StyleScrollbarColor
2511);
2512impl_from!(
2513    OverscrollBehaviorParseError<'a>,
2514    CssParsingError::OverscrollBehavior
2515);
2516impl_from!(
2517    ScrollbarVisibilityModeParseError<'a>,
2518    CssParsingError::ScrollbarVisibilityMode
2519);
2520impl_from!(
2521    ScrollbarFadeDelayParseError<'a>,
2522    CssParsingError::ScrollbarFadeDelay
2523);
2524impl_from!(
2525    ScrollbarFadeDurationParseError<'a>,
2526    CssParsingError::ScrollbarFadeDuration
2527);
2528impl_from!(CssStyleTransformParseError<'a>, CssParsingError::Transform);
2529impl_from!(
2530    CssStyleTransformOriginParseError<'a>,
2531    CssParsingError::TransformOrigin
2532);
2533impl_from!(
2534    CssStylePerspectiveOriginParseError<'a>,
2535    CssParsingError::PerspectiveOrigin
2536);
2537impl_from!(CssStyleFilterParseError<'a>, CssParsingError::Filter);
2538
2539// Layout dimensions
2540impl_from!(LayoutWidthParseError<'a>, CssParsingError::LayoutWidth);
2541impl_from!(LayoutHeightParseError<'a>, CssParsingError::LayoutHeight);
2542impl_from!(
2543    LayoutMinWidthParseError<'a>,
2544    CssParsingError::LayoutMinWidth
2545);
2546impl_from!(
2547    LayoutMinHeightParseError<'a>,
2548    CssParsingError::LayoutMinHeight
2549);
2550impl_from!(
2551    LayoutMaxWidthParseError<'a>,
2552    CssParsingError::LayoutMaxWidth
2553);
2554impl_from!(
2555    LayoutMaxHeightParseError<'a>,
2556    CssParsingError::LayoutMaxHeight
2557);
2558
2559// Layout position
2560impl_from!(
2561    LayoutPositionParseError<'a>,
2562    CssParsingError::LayoutPosition
2563);
2564impl_from!(LayoutTopParseError<'a>, CssParsingError::LayoutTop);
2565impl_from!(LayoutRightParseError<'a>, CssParsingError::LayoutRight);
2566impl_from!(LayoutLeftParseError<'a>, CssParsingError::LayoutLeft);
2567impl_from!(
2568    LayoutInsetBottomParseError<'a>,
2569    CssParsingError::LayoutInsetBottom
2570);
2571impl_from!(LayoutZIndexParseError<'a>, CssParsingError::LayoutZIndex);
2572
2573// Layout flex
2574impl_from!(FlexWrapParseError<'a>, CssParsingError::FlexWrap);
2575impl_from!(FlexDirectionParseError<'a>, CssParsingError::FlexDirection);
2576impl_from!(FlexBasisParseError<'a>, CssParsingError::FlexBasis);
2577impl_from!(
2578    JustifyContentParseError<'a>,
2579    CssParsingError::JustifyContent
2580);
2581impl_from!(AlignItemsParseError<'a>, CssParsingError::AlignItems);
2582impl_from!(AlignContentParseError<'a>, CssParsingError::AlignContent);
2583
2584// Layout grid
2585impl_from!(GridParseError<'a>, CssParsingError::Grid);
2586impl_from!(GridAutoFlowParseError<'a>, CssParsingError::GridAutoFlow);
2587impl_from!(JustifySelfParseError<'a>, CssParsingError::JustifySelf);
2588impl_from!(JustifyItemsParseError<'a>, CssParsingError::JustifyItems);
2589// pixel value impl_from already exists earlier; avoid duplicate impl
2590// impl_from!(CssPixelValueParseError<'a>, CssParsingError::PixelValue);
2591impl_from!(AlignSelfParseError<'a>, CssParsingError::AlignSelf);
2592
2593// Layout wrapping
2594impl_from!(
2595    LayoutWritingModeParseError<'a>,
2596    CssParsingError::LayoutWritingMode
2597);
2598impl_from!(LayoutClearParseError<'a>, CssParsingError::LayoutClear);
2599
2600// Layout overflow
2601impl_from!(
2602    LayoutOverflowParseError<'a>,
2603    CssParsingError::LayoutOverflow
2604);
2605
2606// Border radius individual corners
2607impl_from!(
2608    StyleBorderTopLeftRadiusParseError<'a>,
2609    CssParsingError::BorderTopLeftRadius
2610);
2611impl_from!(
2612    StyleBorderTopRightRadiusParseError<'a>,
2613    CssParsingError::BorderTopRightRadius
2614);
2615impl_from!(
2616    StyleBorderBottomLeftRadiusParseError<'a>,
2617    CssParsingError::BorderBottomLeftRadius
2618);
2619impl_from!(
2620    StyleBorderBottomRightRadiusParseError<'a>,
2621    CssParsingError::BorderBottomRightRadius
2622);
2623
2624// Border style
2625impl_from!(CssBorderStyleParseError<'a>, CssParsingError::BorderStyle);
2626
2627// Effects
2628impl_from!(
2629    CssBackfaceVisibilityParseError<'a>,
2630    CssParsingError::BackfaceVisibility
2631);
2632impl_from!(CssAppRegionParseError<'a>, CssParsingError::AppRegion);
2633impl_from!(
2634    CssSpatialNavigationActionParseError<'a>,
2635    CssParsingError::SpatialNavigationAction
2636);
2637impl_from!(
2638    CssSpatialNavigationContainParseError<'a>,
2639    CssParsingError::SpatialNavigationContain
2640);
2641impl_from!(MixBlendModeParseError<'a>, CssParsingError::MixBlendMode);
2642
2643// Text/Style properties
2644impl_from!(StyleTextColorParseError<'a>, CssParsingError::TextColor);
2645impl_from!(CssStyleFontSizeParseError<'a>, CssParsingError::FontSize);
2646impl_from!(StyleTextAlignParseError<'a>, CssParsingError::TextAlign);
2647impl_from!(TextJustifyParseError<'a>, CssParsingError::TextJustify);
2648impl_from!(
2649    StyleLetterSpacingParseError<'a>,
2650    CssParsingError::LetterSpacing
2651);
2652impl_from!(StyleWordSpacingParseError<'a>, CssParsingError::WordSpacing);
2653impl_from!(StyleTabSizeParseError<'a>, CssParsingError::TabSize);
2654impl_from!(StyleWhiteSpaceParseError<'a>, CssParsingError::WhiteSpace);
2655impl_from!(StyleHyphensParseError<'a>, CssParsingError::Hyphens);
2656impl_from!(StyleWordBreakParseError<'a>, CssParsingError::WordBreak);
2657impl_from!(
2658    StyleOverflowWrapParseError<'a>,
2659    CssParsingError::OverflowWrap
2660);
2661impl_from!(StyleLineBreakParseError<'a>, CssParsingError::LineBreak);
2662impl_from!(
2663    StyleTextOverflowParseError<'a>,
2664    CssParsingError::TextOverflow
2665);
2666impl_from!(StyleObjectFitParseError<'a>, CssParsingError::ObjectFit);
2667impl_from!(
2668    StyleObjectPositionParseError<'a>,
2669    CssParsingError::ObjectPosition
2670);
2671impl_from!(StyleAspectRatioParseError<'a>, CssParsingError::AspectRatio);
2672impl_from!(
2673    StyleTextOrientationParseError<'a>,
2674    CssParsingError::TextOrientation
2675);
2676impl_from!(
2677    StyleTextAlignLastParseError<'a>,
2678    CssParsingError::TextAlignLast
2679);
2680impl_from!(
2681    StyleTextTransformParseError<'a>,
2682    CssParsingError::TextTransform
2683);
2684impl_from!(StyleDirectionParseError<'a>, CssParsingError::Direction);
2685impl_from!(StyleUserSelectParseError<'a>, CssParsingError::UserSelect);
2686impl_from!(
2687    StyleTextDecorationParseError<'a>,
2688    CssParsingError::TextDecoration
2689);
2690impl_from!(CursorParseError<'a>, CssParsingError::Cursor);
2691
2692// Layout basic properties
2693impl_from!(LayoutDisplayParseError<'a>, CssParsingError::LayoutDisplay);
2694impl_from!(LayoutFloatParseError<'a>, CssParsingError::LayoutFloat);
2695impl_from!(
2696    LayoutBoxSizingParseError<'a>,
2697    CssParsingError::LayoutBoxSizing
2698);
2699
2700// DTP properties
2701impl_from!(PageBreakParseError<'a>, CssParsingError::PageBreak);
2702impl_from!(BreakInsideParseError<'a>, CssParsingError::BreakInside);
2703impl_from!(WidowsParseError<'a>, CssParsingError::Widows);
2704impl_from!(OrphansParseError<'a>, CssParsingError::Orphans);
2705impl_from!(
2706    BoxDecorationBreakParseError<'a>,
2707    CssParsingError::BoxDecorationBreak
2708);
2709impl_from!(ColumnCountParseError<'a>, CssParsingError::ColumnCount);
2710impl_from!(ColumnWidthParseError<'a>, CssParsingError::ColumnWidth);
2711impl_from!(ColumnSpanParseError<'a>, CssParsingError::ColumnSpan);
2712impl_from!(ColumnFillParseError<'a>, CssParsingError::ColumnFill);
2713impl_from!(
2714    ColumnRuleWidthParseError<'a>,
2715    CssParsingError::ColumnRuleWidth
2716);
2717impl_from!(
2718    ColumnRuleStyleParseError<'a>,
2719    CssParsingError::ColumnRuleStyle
2720);
2721impl_from!(
2722    ColumnRuleColorParseError<'a>,
2723    CssParsingError::ColumnRuleColor
2724);
2725impl_from!(FlowIntoParseError<'a>, CssParsingError::FlowInto);
2726impl_from!(FlowFromParseError<'a>, CssParsingError::FlowFrom);
2727
2728impl<'a> From<InvalidValueErr<'a>> for CssParsingError<'a> {
2729    fn from(e: InvalidValueErr<'a>) -> Self {
2730        CssParsingError::InvalidValue(e)
2731    }
2732}
2733
2734impl From<PercentageParseError> for CssParsingError<'_> {
2735    fn from(e: PercentageParseError) -> Self {
2736        CssParsingError::Percentage(e)
2737    }
2738}
2739
2740impl From<StyleLineHeightParseError> for CssParsingError<'_> {
2741    fn from(e: StyleLineHeightParseError) -> Self {
2742        CssParsingError::LineHeight(e)
2743    }
2744}
2745
2746impl<'a> From<StyleTextIndentParseError<'a>> for CssParsingError<'a> {
2747    fn from(e: StyleTextIndentParseError<'a>) -> Self {
2748        CssParsingError::TextIndent(e)
2749    }
2750}
2751
2752impl<'a> From<StyleVerticalAlignParseError<'a>> for CssParsingError<'a> {
2753    fn from(e: StyleVerticalAlignParseError<'a>) -> Self {
2754        CssParsingError::VerticalAlign(e)
2755    }
2756}
2757
2758impl CssParsingError<'_> {
2759    #[allow(clippy::too_many_lines)]
2760    // large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
2761    #[must_use]
2762    pub fn to_contained(&self) -> CssParsingErrorOwned {
2763        match self {
2764            CssParsingError::CaretColor(e) => CssParsingErrorOwned::CaretColor(e.to_contained()),
2765            CssParsingError::CaretWidth(e) => CssParsingErrorOwned::CaretWidth(e.to_contained()),
2766            CssParsingError::CaretAnimationDuration(e) => {
2767                CssParsingErrorOwned::CaretAnimationDuration(e.to_contained())
2768            }
2769            CssParsingError::Animation(e) => CssParsingErrorOwned::Animation(e.to_contained()),
2770            CssParsingError::SelectionBackgroundColor(e) => {
2771                CssParsingErrorOwned::SelectionBackgroundColor(e.to_contained())
2772            }
2773            CssParsingError::SelectionColor(e) => {
2774                CssParsingErrorOwned::SelectionColor(e.to_contained())
2775            }
2776            CssParsingError::SelectionRadius(e) => {
2777                CssParsingErrorOwned::SelectionRadius(e.to_contained())
2778            }
2779            CssParsingError::Border(e) => CssParsingErrorOwned::Border(e.to_contained().into()),
2780            CssParsingError::BorderRadius(e) => {
2781                CssParsingErrorOwned::BorderRadius(e.to_contained().into())
2782            }
2783            CssParsingError::Padding(e) => CssParsingErrorOwned::Padding(e.to_contained()),
2784            CssParsingError::Margin(e) => CssParsingErrorOwned::Margin(e.to_contained()),
2785            CssParsingError::Overflow(e) => CssParsingErrorOwned::Overflow(e.to_contained()),
2786            CssParsingError::BoxShadow(e) => CssParsingErrorOwned::BoxShadow(e.to_contained()),
2787            CssParsingError::Color(e) => CssParsingErrorOwned::Color(e.to_contained()),
2788            CssParsingError::PixelValue(e) => CssParsingErrorOwned::PixelValue(e.to_contained()),
2789            CssParsingError::Percentage(e) => CssParsingErrorOwned::Percentage(e.clone()),
2790            CssParsingError::FontFamily(e) => CssParsingErrorOwned::FontFamily(e.to_contained()),
2791            CssParsingError::InvalidValue(e) => {
2792                CssParsingErrorOwned::InvalidValue(e.to_contained())
2793            }
2794            CssParsingError::FlexGrow(e) => CssParsingErrorOwned::FlexGrow(e.to_contained()),
2795            CssParsingError::FlexShrink(e) => CssParsingErrorOwned::FlexShrink(e.to_contained()),
2796            CssParsingError::Background(e) => CssParsingErrorOwned::Background(e.to_contained()),
2797            CssParsingError::BackgroundPosition(e) => {
2798                CssParsingErrorOwned::BackgroundPosition(e.to_contained())
2799            }
2800            CssParsingError::GridAutoFlow(e) => {
2801                CssParsingErrorOwned::GridAutoFlow(e.to_contained())
2802            }
2803            CssParsingError::JustifySelf(e) => CssParsingErrorOwned::JustifySelf(e.to_contained()),
2804            CssParsingError::JustifyItems(e) => {
2805                CssParsingErrorOwned::JustifyItems(e.to_contained())
2806            }
2807            CssParsingError::AlignSelf(e) => CssParsingErrorOwned::AlignSelf(e.to_contained()),
2808            CssParsingError::Opacity(e) => CssParsingErrorOwned::Opacity(e.to_contained()),
2809            CssParsingError::Visibility(e) => CssParsingErrorOwned::Visibility(e.to_contained()),
2810            CssParsingError::OverscrollBehavior(e) => {
2811                CssParsingErrorOwned::OverscrollBehavior(e.to_contained())
2812            }
2813            CssParsingError::LayoutScrollbarWidth(e) => {
2814                CssParsingErrorOwned::LayoutScrollbarWidth(e.to_contained())
2815            }
2816            CssParsingError::StyleScrollbarColor(e) => {
2817                CssParsingErrorOwned::StyleScrollbarColor(e.to_contained())
2818            }
2819            CssParsingError::ScrollbarVisibilityMode(e) => {
2820                CssParsingErrorOwned::ScrollbarVisibilityMode(e.to_contained())
2821            }
2822            CssParsingError::ScrollbarFadeDelay(e) => {
2823                CssParsingErrorOwned::ScrollbarFadeDelay(e.to_contained())
2824            }
2825            CssParsingError::ScrollbarFadeDuration(e) => {
2826                CssParsingErrorOwned::ScrollbarFadeDuration(e.to_contained())
2827            }
2828            CssParsingError::Transform(e) => CssParsingErrorOwned::Transform(e.to_contained()),
2829            CssParsingError::TransformOrigin(e) => {
2830                CssParsingErrorOwned::TransformOrigin(e.to_contained())
2831            }
2832            CssParsingError::PerspectiveOrigin(e) => {
2833                CssParsingErrorOwned::PerspectiveOrigin(e.to_contained())
2834            }
2835            CssParsingError::Filter(e) => CssParsingErrorOwned::Filter(e.to_contained()),
2836            CssParsingError::LayoutWidth(e) => CssParsingErrorOwned::LayoutWidth(e.to_contained()),
2837            CssParsingError::LayoutHeight(e) => {
2838                CssParsingErrorOwned::LayoutHeight(e.to_contained())
2839            }
2840            CssParsingError::LayoutMinWidth(e) => {
2841                CssParsingErrorOwned::LayoutMinWidth(e.to_contained())
2842            }
2843            CssParsingError::LayoutMinHeight(e) => {
2844                CssParsingErrorOwned::LayoutMinHeight(e.to_contained())
2845            }
2846            CssParsingError::LayoutMaxWidth(e) => {
2847                CssParsingErrorOwned::LayoutMaxWidth(e.to_contained())
2848            }
2849            CssParsingError::LayoutMaxHeight(e) => {
2850                CssParsingErrorOwned::LayoutMaxHeight(e.to_contained())
2851            }
2852            CssParsingError::LayoutPosition(e) => {
2853                CssParsingErrorOwned::LayoutPosition(e.to_contained())
2854            }
2855            CssParsingError::LayoutTop(e) => CssParsingErrorOwned::LayoutTop(e.to_contained()),
2856            CssParsingError::LayoutRight(e) => CssParsingErrorOwned::LayoutRight(e.to_contained()),
2857            CssParsingError::LayoutLeft(e) => CssParsingErrorOwned::LayoutLeft(e.to_contained()),
2858            CssParsingError::LayoutInsetBottom(e) => {
2859                CssParsingErrorOwned::LayoutInsetBottom(e.to_contained())
2860            }
2861            CssParsingError::LayoutZIndex(e) => {
2862                CssParsingErrorOwned::LayoutZIndex(e.to_contained())
2863            }
2864            CssParsingError::FlexWrap(e) => CssParsingErrorOwned::FlexWrap(e.to_contained()),
2865            CssParsingError::FlexDirection(e) => {
2866                CssParsingErrorOwned::FlexDirection(e.to_contained())
2867            }
2868            CssParsingError::FlexBasis(e) => CssParsingErrorOwned::FlexBasis(e.to_contained()),
2869            CssParsingError::JustifyContent(e) => {
2870                CssParsingErrorOwned::JustifyContent(e.to_contained())
2871            }
2872            CssParsingError::AlignItems(e) => CssParsingErrorOwned::AlignItems(e.to_contained()),
2873            CssParsingError::AlignContent(e) => {
2874                CssParsingErrorOwned::AlignContent(e.to_contained())
2875            }
2876            CssParsingError::Grid(e) => CssParsingErrorOwned::Grid(e.to_contained()),
2877            CssParsingError::LayoutWritingMode(e) => {
2878                CssParsingErrorOwned::LayoutWritingMode(e.to_contained())
2879            }
2880            CssParsingError::LayoutClear(e) => CssParsingErrorOwned::LayoutClear(e.to_contained()),
2881            CssParsingError::LayoutOverflow(e) => {
2882                CssParsingErrorOwned::LayoutOverflow(e.to_contained())
2883            }
2884            CssParsingError::BorderTopLeftRadius(e) => {
2885                CssParsingErrorOwned::BorderTopLeftRadius(e.to_contained())
2886            }
2887            CssParsingError::BorderTopRightRadius(e) => {
2888                CssParsingErrorOwned::BorderTopRightRadius(e.to_contained())
2889            }
2890            CssParsingError::BorderBottomLeftRadius(e) => {
2891                CssParsingErrorOwned::BorderBottomLeftRadius(e.to_contained())
2892            }
2893            CssParsingError::BorderBottomRightRadius(e) => {
2894                CssParsingErrorOwned::BorderBottomRightRadius(e.to_contained())
2895            }
2896            CssParsingError::BorderStyle(e) => CssParsingErrorOwned::BorderStyle(e.to_contained()),
2897            CssParsingError::AppRegion(e) => CssParsingErrorOwned::AppRegion(e.to_contained()),
2898            CssParsingError::SpatialNavigationAction(e) => {
2899                CssParsingErrorOwned::SpatialNavigationAction(e.to_contained())
2900            }
2901            CssParsingError::SpatialNavigationContain(e) => {
2902                CssParsingErrorOwned::SpatialNavigationContain(e.to_contained())
2903            }
2904            CssParsingError::BackfaceVisibility(e) => {
2905                CssParsingErrorOwned::BackfaceVisibility(e.to_contained())
2906            }
2907            CssParsingError::MixBlendMode(e) => {
2908                CssParsingErrorOwned::MixBlendMode(e.to_contained())
2909            }
2910            CssParsingError::TextColor(e) => CssParsingErrorOwned::TextColor(e.to_contained()),
2911            CssParsingError::FontSize(e) => CssParsingErrorOwned::FontSize(e.to_contained()),
2912            CssParsingError::TextAlign(e) => CssParsingErrorOwned::TextAlign(e.to_contained()),
2913            CssParsingError::TextJustify(e) => CssParsingErrorOwned::TextJustify(e.to_owned()),
2914            CssParsingError::VerticalAlign(e) => {
2915                CssParsingErrorOwned::VerticalAlign(e.to_contained())
2916            }
2917            CssParsingError::LetterSpacing(e) => {
2918                CssParsingErrorOwned::LetterSpacing(e.to_contained())
2919            }
2920            CssParsingError::TextIndent(e) => CssParsingErrorOwned::TextIndent(e.to_contained()),
2921            CssParsingError::InitialLetter(e) => {
2922                CssParsingErrorOwned::InitialLetter(e.to_contained())
2923            }
2924            CssParsingError::LineClamp(e) => CssParsingErrorOwned::LineClamp(e.to_contained()),
2925            CssParsingError::HangingPunctuation(e) => {
2926                CssParsingErrorOwned::HangingPunctuation(e.to_contained())
2927            }
2928            CssParsingError::TextCombineUpright(e) => {
2929                CssParsingErrorOwned::TextCombineUpright(e.to_contained())
2930            }
2931            CssParsingError::UnicodeBidi(e) => CssParsingErrorOwned::UnicodeBidi(e.to_contained()),
2932            CssParsingError::TextBoxTrim(e) => CssParsingErrorOwned::TextBoxTrim(e.to_contained()),
2933            CssParsingError::TextBoxEdge(e) => CssParsingErrorOwned::TextBoxEdge(e.to_contained()),
2934            CssParsingError::DominantBaseline(e) => {
2935                CssParsingErrorOwned::DominantBaseline(e.to_contained())
2936            }
2937            CssParsingError::AlignmentBaseline(e) => {
2938                CssParsingErrorOwned::AlignmentBaseline(e.to_contained())
2939            }
2940            CssParsingError::BaselineSource(e) => {
2941                CssParsingErrorOwned::BaselineSource(e.to_contained())
2942            }
2943            CssParsingError::LineFitEdge(e) => CssParsingErrorOwned::LineFitEdge(e.to_contained()),
2944            CssParsingError::InitialLetterAlign(e) => {
2945                CssParsingErrorOwned::InitialLetterAlign(e.to_contained())
2946            }
2947            CssParsingError::InitialLetterWrap(e) => {
2948                CssParsingErrorOwned::InitialLetterWrap(e.to_contained())
2949            }
2950            CssParsingError::ScrollbarGutter(e) => {
2951                CssParsingErrorOwned::ScrollbarGutter(e.to_contained())
2952            }
2953            CssParsingError::OverflowClipMargin(e) => {
2954                CssParsingErrorOwned::OverflowClipMargin(e.to_contained())
2955            }
2956            CssParsingError::Clip(e) => CssParsingErrorOwned::Clip(e.to_contained()),
2957            CssParsingError::ExclusionMargin(e) => {
2958                CssParsingErrorOwned::ExclusionMargin(e.to_contained())
2959            }
2960            CssParsingError::HyphenationLanguage(e) => {
2961                CssParsingErrorOwned::HyphenationLanguage(e.to_contained())
2962            }
2963            CssParsingError::LineHeight(e) => CssParsingErrorOwned::LineHeight(e.clone()),
2964            CssParsingError::WordSpacing(e) => CssParsingErrorOwned::WordSpacing(e.to_contained()),
2965            CssParsingError::TabSize(e) => CssParsingErrorOwned::TabSize(e.to_contained()),
2966            CssParsingError::WhiteSpace(e) => CssParsingErrorOwned::WhiteSpace(e.to_contained()),
2967            CssParsingError::Hyphens(e) => CssParsingErrorOwned::Hyphens(e.to_contained()),
2968            CssParsingError::WordBreak(e) => CssParsingErrorOwned::WordBreak(e.to_contained()),
2969            CssParsingError::OverflowWrap(e) => {
2970                CssParsingErrorOwned::OverflowWrap(e.to_contained())
2971            }
2972            CssParsingError::LineBreak(e) => CssParsingErrorOwned::LineBreak(e.to_contained()),
2973            CssParsingError::TextOverflow(e) => {
2974                CssParsingErrorOwned::TextOverflow(e.to_contained())
2975            }
2976            CssParsingError::ObjectFit(e) => CssParsingErrorOwned::ObjectFit(e.to_contained()),
2977            CssParsingError::ObjectPosition(e) => {
2978                CssParsingErrorOwned::ObjectPosition(e.to_contained())
2979            }
2980            CssParsingError::AspectRatio(e) => CssParsingErrorOwned::AspectRatio(e.to_contained()),
2981            CssParsingError::TextOrientation(e) => {
2982                CssParsingErrorOwned::TextOrientation(e.to_contained())
2983            }
2984            CssParsingError::TextAlignLast(e) => {
2985                CssParsingErrorOwned::TextAlignLast(e.to_contained())
2986            }
2987            CssParsingError::TextTransform(e) => {
2988                CssParsingErrorOwned::TextTransform(e.to_contained())
2989            }
2990            CssParsingError::Direction(e) => CssParsingErrorOwned::Direction(e.to_contained()),
2991            CssParsingError::UserSelect(e) => CssParsingErrorOwned::UserSelect(e.to_contained()),
2992            CssParsingError::TextDecoration(e) => {
2993                CssParsingErrorOwned::TextDecoration(e.to_contained())
2994            }
2995            CssParsingError::Cursor(e) => CssParsingErrorOwned::Cursor(e.to_contained()),
2996            CssParsingError::LayoutDisplay(e) => {
2997                CssParsingErrorOwned::LayoutDisplay(e.to_contained())
2998            }
2999            CssParsingError::LayoutFloat(e) => CssParsingErrorOwned::LayoutFloat(e.to_contained()),
3000            CssParsingError::LayoutBoxSizing(e) => {
3001                CssParsingErrorOwned::LayoutBoxSizing(e.to_contained())
3002            }
3003            // DTP properties...
3004            CssParsingError::PageBreak(e) => CssParsingErrorOwned::PageBreak(e.to_contained()),
3005            CssParsingError::BreakInside(e) => CssParsingErrorOwned::BreakInside(e.to_contained()),
3006            CssParsingError::Widows(e) => CssParsingErrorOwned::Widows(e.to_contained()),
3007            CssParsingError::Orphans(e) => CssParsingErrorOwned::Orphans(e.to_contained()),
3008            CssParsingError::BoxDecorationBreak(e) => {
3009                CssParsingErrorOwned::BoxDecorationBreak(e.to_contained())
3010            }
3011            CssParsingError::ColumnCount(e) => CssParsingErrorOwned::ColumnCount(e.to_contained()),
3012            CssParsingError::ColumnWidth(e) => CssParsingErrorOwned::ColumnWidth(e.to_contained()),
3013            CssParsingError::ColumnSpan(e) => CssParsingErrorOwned::ColumnSpan(e.to_contained()),
3014            CssParsingError::ColumnFill(e) => CssParsingErrorOwned::ColumnFill(e.to_contained()),
3015            CssParsingError::ColumnRuleWidth(e) => {
3016                CssParsingErrorOwned::ColumnRuleWidth(e.to_contained())
3017            }
3018            CssParsingError::ColumnRuleStyle(e) => {
3019                CssParsingErrorOwned::ColumnRuleStyle(e.to_contained())
3020            }
3021            CssParsingError::ColumnRuleColor(e) => {
3022                CssParsingErrorOwned::ColumnRuleColor(e.to_contained())
3023            }
3024            CssParsingError::FlowInto(e) => CssParsingErrorOwned::FlowInto(e.to_contained()),
3025            CssParsingError::FlowFrom(e) => CssParsingErrorOwned::FlowFrom(e.to_contained()),
3026            CssParsingError::GenericParseError => CssParsingErrorOwned::GenericParseError,
3027            CssParsingError::Content => CssParsingErrorOwned::Content,
3028            CssParsingError::Counter => CssParsingErrorOwned::Counter,
3029            CssParsingError::ListStyleType(e) => {
3030                CssParsingErrorOwned::ListStyleType(e.to_contained())
3031            }
3032            CssParsingError::ListStylePosition(e) => {
3033                CssParsingErrorOwned::ListStylePosition(e.to_contained())
3034            }
3035            CssParsingError::StringSet => CssParsingErrorOwned::StringSet,
3036            CssParsingError::FontWeight(e) => CssParsingErrorOwned::FontWeight(e.to_contained()),
3037            CssParsingError::FontStyle(e) => CssParsingErrorOwned::FontStyle(e.to_contained()),
3038        }
3039    }
3040}
3041
3042impl CssParsingErrorOwned {
3043    #[allow(clippy::too_many_lines)]
3044    // large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
3045    #[must_use]
3046    pub fn to_shared(&self) -> CssParsingError<'_> {
3047        match self {
3048            Self::CaretColor(e) => CssParsingError::CaretColor(e.to_shared()),
3049            Self::CaretWidth(e) => CssParsingError::CaretWidth(e.to_shared()),
3050            Self::CaretAnimationDuration(e) => {
3051                CssParsingError::CaretAnimationDuration(e.to_shared())
3052            }
3053            Self::Animation(e) => CssParsingError::Animation(e.to_shared()),
3054            Self::SelectionBackgroundColor(e) => {
3055                CssParsingError::SelectionBackgroundColor(e.to_shared())
3056            }
3057            Self::SelectionColor(e) => CssParsingError::SelectionColor(e.to_shared()),
3058            Self::SelectionRadius(e) => CssParsingError::SelectionRadius(e.to_shared()),
3059            Self::Border(e) => CssParsingError::Border(e.inner.to_shared()),
3060            Self::BorderRadius(e) => CssParsingError::BorderRadius(e.inner.to_shared()),
3061            Self::Padding(e) => CssParsingError::Padding(e.to_shared()),
3062            Self::Margin(e) => CssParsingError::Margin(e.to_shared()),
3063            Self::Overflow(e) => CssParsingError::Overflow(e.to_shared()),
3064            Self::BoxShadow(e) => CssParsingError::BoxShadow(e.to_shared()),
3065            Self::Color(e) => CssParsingError::Color(e.to_shared()),
3066            Self::PixelValue(e) => CssParsingError::PixelValue(e.to_shared()),
3067            Self::Percentage(e) => CssParsingError::Percentage(e.clone()),
3068            Self::FontFamily(e) => CssParsingError::FontFamily(e.to_shared()),
3069            Self::InvalidValue(e) => CssParsingError::InvalidValue(e.to_shared()),
3070            Self::FlexGrow(e) => CssParsingError::FlexGrow(e.to_shared()),
3071            Self::FlexShrink(e) => CssParsingError::FlexShrink(e.to_shared()),
3072            Self::Background(e) => CssParsingError::Background(e.to_shared()),
3073            Self::BackgroundPosition(e) => CssParsingError::BackgroundPosition(e.to_shared()),
3074            Self::Opacity(e) => CssParsingError::Opacity(e.to_shared()),
3075            Self::Visibility(e) => CssParsingError::Visibility(e.to_shared()),
3076            Self::OverscrollBehavior(e) => CssParsingError::OverscrollBehavior(e.to_shared()),
3077            Self::LayoutScrollbarWidth(e) => CssParsingError::LayoutScrollbarWidth(e.to_shared()),
3078            Self::StyleScrollbarColor(e) => CssParsingError::StyleScrollbarColor(e.to_shared()),
3079            Self::ScrollbarVisibilityMode(e) => {
3080                CssParsingError::ScrollbarVisibilityMode(e.to_shared())
3081            }
3082            Self::ScrollbarFadeDelay(e) => CssParsingError::ScrollbarFadeDelay(e.to_shared()),
3083            Self::ScrollbarFadeDuration(e) => CssParsingError::ScrollbarFadeDuration(e.to_shared()),
3084            Self::Transform(e) => CssParsingError::Transform(e.to_shared()),
3085            Self::TransformOrigin(e) => CssParsingError::TransformOrigin(e.to_shared()),
3086            Self::PerspectiveOrigin(e) => CssParsingError::PerspectiveOrigin(e.to_shared()),
3087            Self::Filter(e) => CssParsingError::Filter(e.to_shared()),
3088            Self::LayoutWidth(e) => CssParsingError::LayoutWidth(e.to_shared()),
3089            Self::LayoutHeight(e) => CssParsingError::LayoutHeight(e.to_shared()),
3090            Self::LayoutMinWidth(e) => CssParsingError::LayoutMinWidth(e.to_shared()),
3091            Self::LayoutMinHeight(e) => CssParsingError::LayoutMinHeight(e.to_shared()),
3092            Self::LayoutMaxWidth(e) => CssParsingError::LayoutMaxWidth(e.to_shared()),
3093            Self::LayoutMaxHeight(e) => CssParsingError::LayoutMaxHeight(e.to_shared()),
3094            Self::LayoutPosition(e) => CssParsingError::LayoutPosition(e.to_shared()),
3095            Self::LayoutTop(e) => CssParsingError::LayoutTop(e.to_shared()),
3096            Self::LayoutRight(e) => CssParsingError::LayoutRight(e.to_shared()),
3097            Self::LayoutLeft(e) => CssParsingError::LayoutLeft(e.to_shared()),
3098            Self::LayoutInsetBottom(e) => CssParsingError::LayoutInsetBottom(e.to_shared()),
3099            Self::LayoutZIndex(e) => CssParsingError::LayoutZIndex(e.to_shared()),
3100            Self::FlexWrap(e) => CssParsingError::FlexWrap(e.to_shared()),
3101            Self::FlexDirection(e) => CssParsingError::FlexDirection(e.to_shared()),
3102            Self::FlexBasis(e) => CssParsingError::FlexBasis(e.to_shared()),
3103            Self::JustifyContent(e) => CssParsingError::JustifyContent(e.to_shared()),
3104            Self::AlignItems(e) => CssParsingError::AlignItems(e.to_shared()),
3105            Self::AlignContent(e) => CssParsingError::AlignContent(e.to_shared()),
3106            Self::Grid(e) => CssParsingError::Grid(e.to_shared()),
3107            Self::GridAutoFlow(e) => CssParsingError::GridAutoFlow(e.to_shared()),
3108            Self::JustifySelf(e) => CssParsingError::JustifySelf(e.to_shared()),
3109            Self::JustifyItems(e) => CssParsingError::JustifyItems(e.to_shared()),
3110            Self::AlignSelf(e) => CssParsingError::AlignSelf(e.to_shared()),
3111            Self::LayoutWritingMode(e) => CssParsingError::LayoutWritingMode(e.to_shared()),
3112            Self::LayoutClear(e) => CssParsingError::LayoutClear(e.to_shared()),
3113            Self::LayoutOverflow(e) => CssParsingError::LayoutOverflow(e.to_shared()),
3114            Self::BorderTopLeftRadius(e) => CssParsingError::BorderTopLeftRadius(e.to_shared()),
3115            Self::BorderTopRightRadius(e) => CssParsingError::BorderTopRightRadius(e.to_shared()),
3116            Self::BorderBottomLeftRadius(e) => {
3117                CssParsingError::BorderBottomLeftRadius(e.to_shared())
3118            }
3119            Self::BorderBottomRightRadius(e) => {
3120                CssParsingError::BorderBottomRightRadius(e.to_shared())
3121            }
3122            Self::BorderStyle(e) => CssParsingError::BorderStyle(e.to_shared()),
3123            Self::AppRegion(e) => CssParsingError::AppRegion(e.to_shared()),
3124            Self::SpatialNavigationAction(e) => {
3125                CssParsingError::SpatialNavigationAction(e.to_shared())
3126            }
3127            Self::SpatialNavigationContain(e) => {
3128                CssParsingError::SpatialNavigationContain(e.to_shared())
3129            }
3130            Self::BackfaceVisibility(e) => CssParsingError::BackfaceVisibility(e.to_shared()),
3131            Self::MixBlendMode(e) => CssParsingError::MixBlendMode(e.to_shared()),
3132            Self::TextColor(e) => CssParsingError::TextColor(e.to_shared()),
3133            Self::FontSize(e) => CssParsingError::FontSize(e.to_shared()),
3134            Self::TextAlign(e) => CssParsingError::TextAlign(e.to_shared()),
3135            Self::TextJustify(e) => CssParsingError::TextJustify(e.to_borrowed()),
3136            Self::LetterSpacing(e) => CssParsingError::LetterSpacing(e.to_shared()),
3137            Self::TextIndent(e) => CssParsingError::TextIndent(e.to_shared()),
3138            Self::InitialLetter(e) => CssParsingError::InitialLetter(e.to_shared()),
3139            Self::LineClamp(e) => CssParsingError::LineClamp(e.to_shared()),
3140            Self::HangingPunctuation(e) => CssParsingError::HangingPunctuation(e.to_shared()),
3141            Self::TextCombineUpright(e) => CssParsingError::TextCombineUpright(e.to_shared()),
3142            Self::UnicodeBidi(e) => CssParsingError::UnicodeBidi(e.to_shared()),
3143            Self::TextBoxTrim(e) => CssParsingError::TextBoxTrim(e.to_shared()),
3144            Self::TextBoxEdge(e) => CssParsingError::TextBoxEdge(e.to_shared()),
3145            Self::DominantBaseline(e) => CssParsingError::DominantBaseline(e.to_shared()),
3146            Self::AlignmentBaseline(e) => CssParsingError::AlignmentBaseline(e.to_shared()),
3147            Self::BaselineSource(e) => CssParsingError::BaselineSource(e.to_shared()),
3148            Self::LineFitEdge(e) => CssParsingError::LineFitEdge(e.to_shared()),
3149            Self::InitialLetterAlign(e) => CssParsingError::InitialLetterAlign(e.to_shared()),
3150            Self::InitialLetterWrap(e) => CssParsingError::InitialLetterWrap(e.to_shared()),
3151            Self::ScrollbarGutter(e) => CssParsingError::ScrollbarGutter(e.to_shared()),
3152            Self::OverflowClipMargin(e) => CssParsingError::OverflowClipMargin(e.to_shared()),
3153            Self::Clip(e) => CssParsingError::Clip(e.to_shared()),
3154            Self::ExclusionMargin(e) => CssParsingError::ExclusionMargin(e.to_shared()),
3155            Self::HyphenationLanguage(e) => CssParsingError::HyphenationLanguage(e.to_shared()),
3156            Self::LineHeight(e) => CssParsingError::LineHeight(e.clone()),
3157            Self::WordSpacing(e) => CssParsingError::WordSpacing(e.to_shared()),
3158            Self::TabSize(e) => CssParsingError::TabSize(e.to_shared()),
3159            Self::WhiteSpace(e) => CssParsingError::WhiteSpace(e.to_shared()),
3160            Self::Hyphens(e) => CssParsingError::Hyphens(e.to_shared()),
3161            Self::WordBreak(e) => CssParsingError::WordBreak(e.to_shared()),
3162            Self::OverflowWrap(e) => CssParsingError::OverflowWrap(e.to_shared()),
3163            Self::LineBreak(e) => CssParsingError::LineBreak(e.to_shared()),
3164            Self::TextOverflow(e) => CssParsingError::TextOverflow(e.to_shared()),
3165            Self::ObjectFit(e) => CssParsingError::ObjectFit(e.to_shared()),
3166            Self::ObjectPosition(e) => CssParsingError::ObjectPosition(e.to_shared()),
3167            Self::AspectRatio(e) => CssParsingError::AspectRatio(e.to_shared()),
3168            Self::TextOrientation(e) => CssParsingError::TextOrientation(e.to_shared()),
3169            Self::TextAlignLast(e) => CssParsingError::TextAlignLast(e.to_shared()),
3170            Self::TextTransform(e) => CssParsingError::TextTransform(e.to_shared()),
3171            Self::Direction(e) => CssParsingError::Direction(e.to_shared()),
3172            Self::UserSelect(e) => CssParsingError::UserSelect(e.to_shared()),
3173            Self::TextDecoration(e) => CssParsingError::TextDecoration(e.to_shared()),
3174            Self::Cursor(e) => CssParsingError::Cursor(e.to_shared()),
3175            Self::LayoutDisplay(e) => CssParsingError::LayoutDisplay(e.to_shared()),
3176            Self::LayoutFloat(e) => CssParsingError::LayoutFloat(e.to_shared()),
3177            Self::LayoutBoxSizing(e) => CssParsingError::LayoutBoxSizing(e.to_shared()),
3178            // DTP properties...
3179            Self::PageBreak(e) => CssParsingError::PageBreak(e.to_shared()),
3180            Self::BreakInside(e) => CssParsingError::BreakInside(e.to_shared()),
3181            Self::Widows(e) => CssParsingError::Widows(e.to_shared()),
3182            Self::Orphans(e) => CssParsingError::Orphans(e.to_shared()),
3183            Self::BoxDecorationBreak(e) => CssParsingError::BoxDecorationBreak(e.to_shared()),
3184            Self::ColumnCount(e) => CssParsingError::ColumnCount(e.to_shared()),
3185            Self::ColumnWidth(e) => CssParsingError::ColumnWidth(e.to_shared()),
3186            Self::ColumnSpan(e) => CssParsingError::ColumnSpan(e.to_shared()),
3187            Self::ColumnFill(e) => CssParsingError::ColumnFill(e.to_shared()),
3188            Self::ColumnRuleWidth(e) => CssParsingError::ColumnRuleWidth(e.to_shared()),
3189            Self::ColumnRuleStyle(e) => CssParsingError::ColumnRuleStyle(e.to_shared()),
3190            Self::ColumnRuleColor(e) => CssParsingError::ColumnRuleColor(e.to_shared()),
3191            Self::FlowInto(e) => CssParsingError::FlowInto(e.to_shared()),
3192            Self::FlowFrom(e) => CssParsingError::FlowFrom(e.to_shared()),
3193            Self::GenericParseError => CssParsingError::GenericParseError,
3194            Self::Content => CssParsingError::Content,
3195            Self::Counter => CssParsingError::Counter,
3196            Self::ListStyleType(e) => CssParsingError::ListStyleType(e.to_shared()),
3197            Self::ListStylePosition(e) => CssParsingError::ListStylePosition(e.to_shared()),
3198            Self::StringSet => CssParsingError::StringSet,
3199            Self::FontWeight(e) => CssParsingError::FontWeight(e.to_shared()),
3200            Self::FontStyle(e) => CssParsingError::FontStyle(e.to_shared()),
3201            Self::VerticalAlign(e) => CssParsingError::VerticalAlign(e.to_shared()),
3202        }
3203    }
3204}
3205
3206#[cfg(feature = "parser")]
3207#[allow(clippy::too_many_lines)]
3208// large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
3209/// # Errors
3210///
3211/// Returns an error if `input` is not a valid CSS `css-property` value.
3212pub fn parse_css_property(
3213    key: CssPropertyType,
3214    value: &str,
3215) -> Result<CssProperty, CssParsingError<'_>> {
3216    use crate::props::style::{
3217        parse_selection_background_color, parse_selection_color, parse_selection_radius,
3218    };
3219
3220    let value = value.trim();
3221
3222    // For properties where "auto" or "none" is a valid typed value (not just the generic CSS
3223    // keyword), we must NOT intercept them here. Let the specific parser handle them.
3224    let has_typed_auto = matches!(
3225        key,
3226        CssPropertyType::Hyphens |      // hyphens: auto means StyleHyphens::Auto
3227        CssPropertyType::LineBreak |    // line-break: auto means StyleLineBreak::Auto
3228        CssPropertyType::TextAlignLast | // text-align-last: auto means StyleTextAlignLast::Auto
3229        CssPropertyType::OverflowX |
3230        CssPropertyType::OverflowY |
3231        CssPropertyType::OverflowBlock |
3232        CssPropertyType::OverflowInline |
3233        CssPropertyType::UserSelect | // user-select: auto is a typed value
3234        // overscroll-behavior: auto/none are TYPED values (OverscrollBehavior::
3235        // Auto / ::None), not the CSS-wide keywords. Intercepting them here
3236        // produced `CssPropertyValue::None`, which reads back as "no value" —
3237        // so `overscroll-behavior-x: none` silently resolved to the default.
3238        CssPropertyType::OverscrollBehaviorX |
3239        CssPropertyType::OverscrollBehaviorY |
3240        CssPropertyType::AspectRatio // aspect-ratio: auto means StyleAspectRatio::Auto
3241    );
3242
3243    let has_typed_none = matches!(
3244        key,
3245        CssPropertyType::Hyphens |      // hyphens: none means StyleHyphens::None
3246        CssPropertyType::Display |      // display: none means LayoutDisplay::None
3247        CssPropertyType::UserSelect |
3248        CssPropertyType::Float |        // float: none means LayoutFloat::None
3249        CssPropertyType::TextDecoration | // text-decoration: none is a typed value
3250        CssPropertyType::OverscrollBehaviorX | // see the auto list above
3251        CssPropertyType::OverscrollBehaviorY |
3252        CssPropertyType::ObjectFit // object-fit: none means StyleObjectFit::None
3253    );
3254
3255    Ok(match value {
3256        "auto" if !has_typed_auto => CssProperty::auto(key),
3257        "none" if !has_typed_none => CssProperty::none(key),
3258        "initial" => CssProperty::initial(key),
3259        "inherit" => CssProperty::inherit(key),
3260        value => match key {
3261            CssPropertyType::CaretColor => parse_caret_color(value)?.into(),
3262            CssPropertyType::CaretWidth => parse_caret_width(value)?.into(),
3263            CssPropertyType::CaretAnimationDuration => {
3264                parse_caret_animation_duration(value)?.into()
3265            }
3266            CssPropertyType::Animation => CssProperty::Animation(CssPropertyValue::Exact(
3267                crate::props::basic::animation::parse_style_animation_vec(value)?,
3268            )),
3269            CssPropertyType::AnimationIn => CssProperty::AnimationIn(CssPropertyValue::Exact(
3270                crate::props::basic::animation::parse_style_animation_vec(value)?,
3271            )),
3272            CssPropertyType::AnimationOut => CssProperty::AnimationOut(CssPropertyValue::Exact(
3273                crate::props::basic::animation::parse_style_animation_vec(value)?,
3274            )),
3275            CssPropertyType::SelectionBackgroundColor => {
3276                parse_selection_background_color(value)?.into()
3277            }
3278            CssPropertyType::SelectionColor => parse_selection_color(value)?.into(),
3279            CssPropertyType::SelectionRadius => parse_selection_radius(value)?.into(),
3280
3281            CssPropertyType::TextColor => parse_style_text_color(value)?.into(),
3282            CssPropertyType::FontSize => {
3283                CssProperty::FontSize(parse_style_font_size(value)?.into())
3284            }
3285            CssPropertyType::FontFamily => parse_style_font_family(value)?.into(),
3286            CssPropertyType::FontWeight => {
3287                CssProperty::FontWeight(parse_font_weight(value)?.into())
3288            }
3289            CssPropertyType::FontStyle => CssProperty::FontStyle(parse_font_style(value)?.into()),
3290            CssPropertyType::TextAlign => parse_style_text_align(value)?.into(),
3291            CssPropertyType::TextJustify => parse_layout_text_justify(value)?.into(),
3292            CssPropertyType::VerticalAlign => parse_style_vertical_align(value)?.into(),
3293            CssPropertyType::LetterSpacing => parse_style_letter_spacing(value)?.into(),
3294            CssPropertyType::TextIndent => parse_style_text_indent(value)?.into(),
3295            CssPropertyType::InitialLetter => parse_style_initial_letter(value)?.into(),
3296            CssPropertyType::LineClamp => parse_style_line_clamp(value)?.into(),
3297            CssPropertyType::HangingPunctuation => parse_style_hanging_punctuation(value)?.into(),
3298            CssPropertyType::TextCombineUpright => parse_style_text_combine_upright(value)?.into(),
3299            CssPropertyType::UnicodeBidi => parse_style_unicode_bidi(value)?.into(),
3300            CssPropertyType::TextBoxTrim => parse_style_text_box_trim(value)?.into(),
3301            CssPropertyType::TextBoxEdge => parse_style_text_box_edge(value)?.into(),
3302            CssPropertyType::DominantBaseline => parse_style_dominant_baseline(value)?.into(),
3303            CssPropertyType::AlignmentBaseline => parse_style_alignment_baseline(value)?.into(),
3304            CssPropertyType::BaselineSource => parse_style_baseline_source(value)?.into(),
3305            CssPropertyType::LineFitEdge => parse_style_line_fit_edge(value)?.into(),
3306            CssPropertyType::InitialLetterAlign => parse_style_initial_letter_align(value)?.into(),
3307            CssPropertyType::InitialLetterWrap => parse_style_initial_letter_wrap(value)?.into(),
3308            CssPropertyType::ScrollbarGutter => parse_style_scrollbar_gutter(value)?.into(),
3309            CssPropertyType::OverflowClipMargin => parse_style_overflow_clip_margin(value)?.into(),
3310            CssPropertyType::Clip => parse_clip_rect(value)?.into(),
3311            CssPropertyType::ExclusionMargin => parse_style_exclusion_margin(value)?.into(),
3312            CssPropertyType::HyphenationLanguage => parse_style_hyphenation_language(value)?.into(),
3313            CssPropertyType::LineHeight => parse_style_line_height(value)?.into(),
3314            CssPropertyType::WordSpacing => parse_style_word_spacing(value)?.into(),
3315            CssPropertyType::TabSize => parse_style_tab_size(value)?.into(),
3316            CssPropertyType::WhiteSpace => parse_style_white_space(value)?.into(),
3317            CssPropertyType::Hyphens => parse_style_hyphens(value)?.into(),
3318            CssPropertyType::WordBreak => parse_style_word_break(value)?.into(),
3319            CssPropertyType::OverflowWrap => parse_style_overflow_wrap(value)?.into(),
3320            CssPropertyType::LineBreak => parse_style_line_break(value)?.into(),
3321            CssPropertyType::TextOverflow => parse_style_text_overflow(value)?.into(),
3322            CssPropertyType::ObjectFit => parse_style_object_fit(value)?.into(),
3323            CssPropertyType::ObjectPosition => parse_style_object_position(value)?.into(),
3324            CssPropertyType::AspectRatio => parse_style_aspect_ratio(value)?.into(),
3325            CssPropertyType::TextOrientation => parse_style_text_orientation(value)?.into(),
3326            CssPropertyType::TextAlignLast => parse_style_text_align_last(value)?.into(),
3327            CssPropertyType::TextTransform => parse_style_text_transform(value)?.into(),
3328            CssPropertyType::Direction => parse_style_direction(value)?.into(),
3329            CssPropertyType::UserSelect => parse_style_user_select(value)?.into(),
3330            CssPropertyType::TextDecoration => parse_style_text_decoration(value)?.into(),
3331            CssPropertyType::Cursor => parse_style_cursor(value)?.into(),
3332
3333            CssPropertyType::Display => parse_layout_display(value)?.into(),
3334            CssPropertyType::Float => parse_layout_float(value)?.into(),
3335            CssPropertyType::BoxSizing => parse_layout_box_sizing(value)?.into(),
3336            CssPropertyType::Width => parse_layout_width(value)?.into(),
3337            CssPropertyType::Height => parse_layout_height(value)?.into(),
3338            CssPropertyType::MinWidth => parse_layout_min_width(value)?.into(),
3339            CssPropertyType::MinHeight => parse_layout_min_height(value)?.into(),
3340            CssPropertyType::MaxWidth => parse_layout_max_width(value)?.into(),
3341            CssPropertyType::MaxHeight => parse_layout_max_height(value)?.into(),
3342            CssPropertyType::Position => parse_layout_position(value)?.into(),
3343            CssPropertyType::Top => parse_layout_top(value)?.into(),
3344            CssPropertyType::Right => parse_layout_right(value)?.into(),
3345            CssPropertyType::Left => parse_layout_left(value)?.into(),
3346            CssPropertyType::Bottom => parse_layout_bottom(value)?.into(),
3347            CssPropertyType::ZIndex => CssProperty::ZIndex(parse_layout_z_index(value)?.into()),
3348
3349            CssPropertyType::FlexWrap => parse_layout_flex_wrap(value)?.into(),
3350            CssPropertyType::FlexDirection => parse_layout_flex_direction(value)?.into(),
3351            CssPropertyType::FlexGrow => parse_layout_flex_grow(value)?.into(),
3352            CssPropertyType::FlexShrink => parse_layout_flex_shrink(value)?.into(),
3353            CssPropertyType::FlexBasis => parse_layout_flex_basis(value)?.into(),
3354            CssPropertyType::JustifyContent => parse_layout_justify_content(value)?.into(),
3355            CssPropertyType::AlignItems => parse_layout_align_items(value)?.into(),
3356            CssPropertyType::AlignContent => parse_layout_align_content(value)?.into(),
3357            CssPropertyType::ColumnGap => parse_layout_column_gap(value)?.into(),
3358            CssPropertyType::RowGap => parse_layout_row_gap(value)?.into(),
3359            CssPropertyType::GridTemplateColumns => {
3360                CssProperty::GridTemplateColumns(parse_grid_template(value)?.into())
3361            }
3362            CssPropertyType::GridTemplateRows => {
3363                CssProperty::GridTemplateRows(parse_grid_template(value)?.into())
3364            }
3365            CssPropertyType::GridAutoColumns => {
3366                let template = parse_grid_template(value)?;
3367                CssProperty::GridAutoColumns(CssPropertyValue::Exact(GridAutoTracks::from(
3368                    template,
3369                )))
3370            }
3371            CssPropertyType::GridAutoFlow => {
3372                CssProperty::GridAutoFlow(parse_layout_grid_auto_flow(value)?.into())
3373            }
3374            CssPropertyType::JustifySelf => {
3375                CssProperty::JustifySelf(parse_layout_justify_self(value)?.into())
3376            }
3377            CssPropertyType::JustifyItems => {
3378                CssProperty::JustifyItems(parse_layout_justify_items(value)?.into())
3379            }
3380            CssPropertyType::Gap => {
3381                // gap shorthand: single value -> both row & column
3382                CssProperty::Gap(parse_layout_gap(value)?.into())
3383            }
3384            CssPropertyType::GridGap => CssProperty::GridGap(parse_layout_gap(value)?.into()),
3385            CssPropertyType::AlignSelf => {
3386                CssProperty::AlignSelf(parse_layout_align_self(value)?.into())
3387            }
3388            CssPropertyType::Font => {
3389                // minimal font parser: map to font-family for now
3390                let fam = parse_style_font_family(value)?;
3391                CssProperty::Font(fam.into())
3392            }
3393            CssPropertyType::GridAutoRows => {
3394                let template = parse_grid_template(value)?;
3395                CssProperty::GridAutoRows(CssPropertyValue::Exact(GridAutoTracks::from(template)))
3396            }
3397            CssPropertyType::GridColumn => {
3398                CssProperty::GridColumn(CssPropertyValue::Exact(parse_grid_placement(value)?))
3399            }
3400            CssPropertyType::GridRow => {
3401                CssProperty::GridRow(CssPropertyValue::Exact(parse_grid_placement(value)?))
3402            }
3403            CssPropertyType::GridTemplateAreas => {
3404                use crate::props::layout::grid::parse_grid_template_areas;
3405                let areas = parse_grid_template_areas(value)
3406                    .map_err(|()| CssParsingError::InvalidValue(InvalidValueErr(value)))?;
3407                CssProperty::GridTemplateAreas(CssPropertyValue::Exact(areas))
3408            }
3409            CssPropertyType::WritingMode => parse_layout_writing_mode(value)?.into(),
3410            CssPropertyType::Clear => parse_layout_clear(value)?.into(),
3411
3412            CssPropertyType::BackgroundContent => {
3413                parse_style_background_content_multiple(value)?.into()
3414            }
3415            CssPropertyType::BackgroundPosition => {
3416                parse_style_background_position_multiple(value)?.into()
3417            }
3418            CssPropertyType::BackgroundSize => parse_style_background_size_multiple(value)?.into(),
3419            CssPropertyType::BackgroundRepeat => {
3420                parse_style_background_repeat_multiple(value)?.into()
3421            }
3422
3423            CssPropertyType::OverflowX => {
3424                CssProperty::OverflowX(parse_layout_overflow(value)?.into())
3425            }
3426            CssPropertyType::OverflowY => {
3427                CssProperty::OverflowY(parse_layout_overflow(value)?.into())
3428            }
3429            CssPropertyType::OverflowBlock => {
3430                CssProperty::OverflowBlock(parse_layout_overflow(value)?.into())
3431            }
3432            CssPropertyType::OverflowInline => {
3433                CssProperty::OverflowInline(parse_layout_overflow(value)?.into())
3434            }
3435
3436            CssPropertyType::PaddingTop => parse_layout_padding_top(value)?.into(),
3437            CssPropertyType::PaddingLeft => parse_layout_padding_left(value)?.into(),
3438            CssPropertyType::PaddingRight => parse_layout_padding_right(value)?.into(),
3439            CssPropertyType::PaddingBottom => parse_layout_padding_bottom(value)?.into(),
3440            CssPropertyType::PaddingInlineStart => parse_layout_padding_inline_start(value)?.into(),
3441            CssPropertyType::PaddingInlineEnd => parse_layout_padding_inline_end(value)?.into(),
3442
3443            CssPropertyType::MarginTop => parse_layout_margin_top(value)?.into(),
3444            CssPropertyType::MarginLeft => parse_layout_margin_left(value)?.into(),
3445            CssPropertyType::MarginRight => parse_layout_margin_right(value)?.into(),
3446            CssPropertyType::MarginBottom => parse_layout_margin_bottom(value)?.into(),
3447
3448            CssPropertyType::BorderTopLeftRadius => {
3449                parse_style_border_top_left_radius(value)?.into()
3450            }
3451            CssPropertyType::BorderTopRightRadius => {
3452                parse_style_border_top_right_radius(value)?.into()
3453            }
3454            CssPropertyType::BorderBottomLeftRadius => {
3455                parse_style_border_bottom_left_radius(value)?.into()
3456            }
3457            CssPropertyType::BorderBottomRightRadius => {
3458                parse_style_border_bottom_right_radius(value)?.into()
3459            }
3460
3461            CssPropertyType::BorderTopColor => parse_border_top_color(value)?.into(),
3462            CssPropertyType::BorderRightColor => parse_border_right_color(value)?.into(),
3463            CssPropertyType::BorderLeftColor => parse_border_left_color(value)?.into(),
3464            CssPropertyType::BorderBottomColor => parse_border_bottom_color(value)?.into(),
3465
3466            CssPropertyType::BorderTopStyle => parse_border_top_style(value)?.into(),
3467            CssPropertyType::BorderRightStyle => parse_border_right_style(value)?.into(),
3468            CssPropertyType::BorderLeftStyle => parse_border_left_style(value)?.into(),
3469            CssPropertyType::BorderBottomStyle => parse_border_bottom_style(value)?.into(),
3470
3471            CssPropertyType::BorderTopWidth => parse_border_top_width(value)?.into(),
3472            CssPropertyType::BorderRightWidth => parse_border_right_width(value)?.into(),
3473            CssPropertyType::BorderLeftWidth => parse_border_left_width(value)?.into(),
3474            CssPropertyType::BorderBottomWidth => parse_border_bottom_width(value)?.into(),
3475
3476            CssPropertyType::BoxShadowLeft => CssProperty::BoxShadowLeft(CssPropertyValue::Exact(
3477                BoxOrStatic::heap(parse_style_box_shadow(value)?),
3478            )),
3479            CssPropertyType::BoxShadowRight => CssProperty::BoxShadowRight(
3480                CssPropertyValue::Exact(BoxOrStatic::heap(parse_style_box_shadow(value)?)),
3481            ),
3482            CssPropertyType::BoxShadowTop => CssProperty::BoxShadowTop(CssPropertyValue::Exact(
3483                BoxOrStatic::heap(parse_style_box_shadow(value)?),
3484            )),
3485            CssPropertyType::BoxShadowBottom => CssProperty::BoxShadowBottom(
3486                CssPropertyValue::Exact(BoxOrStatic::heap(parse_style_box_shadow(value)?)),
3487            ),
3488
3489            CssPropertyType::ScrollbarTrack => CssProperty::ScrollbarTrack(
3490                CssPropertyValue::Exact(parse_style_background_content(value)?),
3491            ),
3492            CssPropertyType::ScrollbarThumb => CssProperty::ScrollbarThumb(
3493                CssPropertyValue::Exact(parse_style_background_content(value)?),
3494            ),
3495            CssPropertyType::ScrollbarButton => CssProperty::ScrollbarButton(
3496                CssPropertyValue::Exact(parse_style_background_content(value)?),
3497            ),
3498            CssPropertyType::ScrollbarCorner => CssProperty::ScrollbarCorner(
3499                CssPropertyValue::Exact(parse_style_background_content(value)?),
3500            ),
3501            CssPropertyType::ScrollbarResizer => CssProperty::ScrollbarResizer(
3502                CssPropertyValue::Exact(parse_style_background_content(value)?),
3503            ),
3504            CssPropertyType::ScrollbarWidth => parse_layout_scrollbar_width(value)?.into(),
3505            CssPropertyType::OverscrollBehaviorX => CssProperty::OverscrollBehaviorX(
3506                CssPropertyValue::Exact(parse_overscroll_behavior(value)?),
3507            ),
3508            CssPropertyType::OverscrollBehaviorY => CssProperty::OverscrollBehaviorY(
3509                CssPropertyValue::Exact(parse_overscroll_behavior(value)?),
3510            ),
3511            CssPropertyType::ScrollbarColor => parse_style_scrollbar_color(value)?.into(),
3512            CssPropertyType::ScrollbarVisibility => parse_scrollbar_visibility_mode(value)?.into(),
3513            CssPropertyType::ScrollbarFadeDelay => parse_scrollbar_fade_delay(value)?.into(),
3514            CssPropertyType::ScrollbarFadeDuration => parse_scrollbar_fade_duration(value)?.into(),
3515            CssPropertyType::Opacity => parse_style_opacity(value)?.into(),
3516            CssPropertyType::Visibility => parse_style_visibility(value)?.into(),
3517            CssPropertyType::Transform => parse_style_transform_vec(value)?.into(),
3518            CssPropertyType::TransformOrigin => parse_style_transform_origin(value)?.into(),
3519            CssPropertyType::PerspectiveOrigin => parse_style_perspective_origin(value)?.into(),
3520            CssPropertyType::BackfaceVisibility => parse_style_backface_visibility(value)?.into(),
3521            CssPropertyType::AppRegion => parse_style_app_region(value)?.into(),
3522            CssPropertyType::SpatialNavigationAction => {
3523                parse_style_spatial_navigation_action(value)?.into()
3524            }
3525            CssPropertyType::SpatialNavigationContain => {
3526                parse_style_spatial_navigation_contain(value)?.into()
3527            }
3528
3529            CssPropertyType::MixBlendMode => parse_style_mix_blend_mode(value)?.into(),
3530            CssPropertyType::Filter => CssProperty::Filter(parse_style_filter_vec(value)?.into()),
3531            CssPropertyType::BackdropFilter => {
3532                CssProperty::BackdropFilter(parse_style_filter_vec(value)?.into())
3533            }
3534            CssPropertyType::TextShadow => CssProperty::TextShadow(CssPropertyValue::Exact(
3535                BoxOrStatic::heap(parse_style_box_shadow(value)?),
3536            )),
3537
3538            // DTP properties
3539            CssPropertyType::BreakBefore => {
3540                CssProperty::BreakBefore(parse_page_break(value)?.into())
3541            }
3542            CssPropertyType::BreakAfter => CssProperty::BreakAfter(parse_page_break(value)?.into()),
3543            CssPropertyType::BreakInside => {
3544                CssProperty::BreakInside(parse_break_inside(value)?.into())
3545            }
3546            CssPropertyType::Orphans => CssProperty::Orphans(parse_orphans(value)?.into()),
3547            CssPropertyType::Widows => CssProperty::Widows(parse_widows(value)?.into()),
3548            CssPropertyType::BoxDecorationBreak => {
3549                CssProperty::BoxDecorationBreak(parse_box_decoration_break(value)?.into())
3550            }
3551            CssPropertyType::ColumnCount => {
3552                CssProperty::ColumnCount(parse_column_count(value)?.into())
3553            }
3554            CssPropertyType::ColumnWidth => {
3555                CssProperty::ColumnWidth(parse_column_width(value)?.into())
3556            }
3557            CssPropertyType::ColumnSpan => {
3558                CssProperty::ColumnSpan(parse_column_span(value)?.into())
3559            }
3560            CssPropertyType::ColumnFill => {
3561                CssProperty::ColumnFill(parse_column_fill(value)?.into())
3562            }
3563            CssPropertyType::ColumnRuleWidth => {
3564                CssProperty::ColumnRuleWidth(parse_column_rule_width(value)?.into())
3565            }
3566            CssPropertyType::ColumnRuleStyle => {
3567                CssProperty::ColumnRuleStyle(parse_column_rule_style(value)?.into())
3568            }
3569            CssPropertyType::ColumnRuleColor => {
3570                CssProperty::ColumnRuleColor(parse_column_rule_color(value)?.into())
3571            }
3572            CssPropertyType::FlowInto => CssProperty::FlowInto(parse_flow_into(value)?.into()),
3573            CssPropertyType::FlowFrom => CssProperty::FlowFrom(parse_flow_from(value)?.into()),
3574            CssPropertyType::ShapeOutside => CssProperty::ShapeOutside(CssPropertyValue::Exact(
3575                parse_shape_outside(value).map_err(|_| CssParsingError::GenericParseError)?,
3576            )),
3577            CssPropertyType::ShapeInside => CssProperty::ShapeInside(CssPropertyValue::Exact(
3578                parse_shape_inside(value).map_err(|_| CssParsingError::GenericParseError)?,
3579            )),
3580            CssPropertyType::ClipPath => CssProperty::ClipPath(CssPropertyValue::Exact(
3581                parse_clip_path(value).map_err(|_| CssParsingError::GenericParseError)?,
3582            )),
3583            CssPropertyType::ShapeMargin => {
3584                CssProperty::ShapeMargin(parse_shape_margin(value)?.into())
3585            }
3586            CssPropertyType::ShapeImageThreshold => CssProperty::ShapeImageThreshold(
3587                parse_shape_image_threshold(value)
3588                    .map_err(|_| CssParsingError::GenericParseError)?
3589                    .into(),
3590            ),
3591            CssPropertyType::Content => CssProperty::Content(
3592                parse_content(value)
3593                    .map_err(|()| CssParsingError::Content)?
3594                    .into(),
3595            ),
3596            CssPropertyType::CounterReset => CssProperty::CounterReset(
3597                parse_counter_reset(value)
3598                    .map_err(|()| CssParsingError::Counter)?
3599                    .into(),
3600            ),
3601            CssPropertyType::CounterIncrement => CssProperty::CounterIncrement(
3602                parse_counter_increment(value)
3603                    .map_err(|()| CssParsingError::Counter)?
3604                    .into(),
3605            ),
3606            CssPropertyType::ListStyleType => CssProperty::ListStyleType(
3607                parse_style_list_style_type(value)
3608                    .map_err(CssParsingError::ListStyleType)?
3609                    .into(),
3610            ),
3611            CssPropertyType::ListStylePosition => CssProperty::ListStylePosition(
3612                parse_style_list_style_position(value)
3613                    .map_err(CssParsingError::ListStylePosition)?
3614                    .into(),
3615            ),
3616            CssPropertyType::StringSet => CssProperty::StringSet(
3617                parse_string_set(value)
3618                    .map_err(|()| CssParsingError::StringSet)?
3619                    .into(),
3620            ),
3621            CssPropertyType::TableLayout => CssProperty::TableLayout(
3622                parse_table_layout(value)
3623                    .map_err(|_| CssParsingError::GenericParseError)?
3624                    .into(),
3625            ),
3626            CssPropertyType::BorderCollapse => CssProperty::BorderCollapse(
3627                parse_border_collapse(value)
3628                    .map_err(|_| CssParsingError::GenericParseError)?
3629                    .into(),
3630            ),
3631            CssPropertyType::BorderSpacing => CssProperty::BorderSpacing(
3632                parse_border_spacing(value)
3633                    .map_err(|_| CssParsingError::GenericParseError)?
3634                    .into(),
3635            ),
3636            CssPropertyType::CaptionSide => CssProperty::CaptionSide(
3637                parse_caption_side(value)
3638                    .map_err(|_| CssParsingError::GenericParseError)?
3639                    .into(),
3640            ),
3641            CssPropertyType::EmptyCells => CssProperty::EmptyCells(
3642                parse_empty_cells(value)
3643                    .map_err(|_| CssParsingError::GenericParseError)?
3644                    .into(),
3645            ),
3646        },
3647    })
3648}
3649
3650/// Parses a combined CSS property or a CSS property shorthand, for example "margin"
3651/// (as a shorthand for setting all four properties of "margin-top", "margin-bottom",
3652/// "margin-left" and "margin-right")
3653///
3654/// ```rust
3655/// # extern crate azul_css;
3656/// # use azul_css::*;
3657/// # use azul_css::props::style::*;
3658/// # use azul_css::css::CssPropertyValue;
3659/// # use azul_css::props::property::*;
3660/// assert_eq!(
3661///     parse_combined_css_property(CombinedCssPropertyType::BorderRadius, "10px"),
3662///     Ok(vec![
3663///         CssProperty::BorderTopLeftRadius(CssPropertyValue::Exact(
3664///             StyleBorderTopLeftRadius::px(10.0)
3665///         )),
3666///         CssProperty::BorderTopRightRadius(CssPropertyValue::Exact(
3667///             StyleBorderTopRightRadius::px(10.0)
3668///         )),
3669///         CssProperty::BorderBottomLeftRadius(CssPropertyValue::Exact(
3670///             StyleBorderBottomLeftRadius::px(10.0)
3671///         )),
3672///         CssProperty::BorderBottomRightRadius(CssPropertyValue::Exact(
3673///             StyleBorderBottomRightRadius::px(10.0)
3674///         )),
3675///     ])
3676/// )
3677/// ```
3678#[cfg(feature = "parser")]
3679#[allow(clippy::too_many_lines)]
3680// large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
3681/// # Errors
3682///
3683/// Returns an error if `input` is not a valid CSS `combined-css-property` value.
3684pub fn parse_combined_css_property(
3685    key: CombinedCssPropertyType,
3686    value: &str,
3687) -> Result<Vec<CssProperty>, CssParsingError<'_>> {
3688    use self::CombinedCssPropertyType::{
3689        Background, BackgroundColor, BackgroundImage, Border, BorderBottom, BorderColor,
3690        BorderLeft, BorderRadius, BorderRight, BorderStyle, BorderTop, BorderWidth, BoxShadow,
3691        ColumnRule, Columns, Flex, Font, Gap, Grid, GridArea, GridGap, InsetBlock, InsetInline,
3692        Margin, Overflow, OverscrollBehavior, Padding, TextBox,
3693    };
3694
3695    macro_rules! convert_value {
3696        ($thing:expr, $prop_type:ident, $wrapper:ident) => {
3697            match $thing {
3698                PixelValueWithAuto::None => CssProperty::none(CssPropertyType::$prop_type),
3699                PixelValueWithAuto::Initial => CssProperty::initial(CssPropertyType::$prop_type),
3700                PixelValueWithAuto::Inherit => CssProperty::inherit(CssPropertyType::$prop_type),
3701                PixelValueWithAuto::Auto => CssProperty::auto(CssPropertyType::$prop_type),
3702                PixelValueWithAuto::Exact(x) => {
3703                    CssProperty::$prop_type($wrapper { inner: x }.into())
3704                }
3705            }
3706        };
3707    }
3708
3709    let keys = match key {
3710        BorderRadius => {
3711            vec![
3712                CssPropertyType::BorderTopLeftRadius,
3713                CssPropertyType::BorderTopRightRadius,
3714                CssPropertyType::BorderBottomLeftRadius,
3715                CssPropertyType::BorderBottomRightRadius,
3716            ]
3717        }
3718        OverscrollBehavior => {
3719            vec![
3720                CssPropertyType::OverscrollBehaviorX,
3721                CssPropertyType::OverscrollBehaviorY,
3722            ]
3723        }
3724        Overflow => {
3725            vec![CssPropertyType::OverflowX, CssPropertyType::OverflowY]
3726        }
3727        Padding => {
3728            vec![
3729                CssPropertyType::PaddingTop,
3730                CssPropertyType::PaddingBottom,
3731                CssPropertyType::PaddingLeft,
3732                CssPropertyType::PaddingRight,
3733            ]
3734        }
3735        Margin => {
3736            vec![
3737                CssPropertyType::MarginTop,
3738                CssPropertyType::MarginBottom,
3739                CssPropertyType::MarginLeft,
3740                CssPropertyType::MarginRight,
3741            ]
3742        }
3743        Border => {
3744            vec![
3745                CssPropertyType::BorderTopColor,
3746                CssPropertyType::BorderRightColor,
3747                CssPropertyType::BorderLeftColor,
3748                CssPropertyType::BorderBottomColor,
3749                CssPropertyType::BorderTopStyle,
3750                CssPropertyType::BorderRightStyle,
3751                CssPropertyType::BorderLeftStyle,
3752                CssPropertyType::BorderBottomStyle,
3753                CssPropertyType::BorderTopWidth,
3754                CssPropertyType::BorderRightWidth,
3755                CssPropertyType::BorderLeftWidth,
3756                CssPropertyType::BorderBottomWidth,
3757            ]
3758        }
3759        BorderLeft => {
3760            vec![
3761                CssPropertyType::BorderLeftColor,
3762                CssPropertyType::BorderLeftStyle,
3763                CssPropertyType::BorderLeftWidth,
3764            ]
3765        }
3766        BorderRight => {
3767            vec![
3768                CssPropertyType::BorderRightColor,
3769                CssPropertyType::BorderRightStyle,
3770                CssPropertyType::BorderRightWidth,
3771            ]
3772        }
3773        BorderTop => {
3774            vec![
3775                CssPropertyType::BorderTopColor,
3776                CssPropertyType::BorderTopStyle,
3777                CssPropertyType::BorderTopWidth,
3778            ]
3779        }
3780        BorderBottom => {
3781            vec![
3782                CssPropertyType::BorderBottomColor,
3783                CssPropertyType::BorderBottomStyle,
3784                CssPropertyType::BorderBottomWidth,
3785            ]
3786        }
3787        BorderColor => {
3788            vec![
3789                CssPropertyType::BorderTopColor,
3790                CssPropertyType::BorderRightColor,
3791                CssPropertyType::BorderBottomColor,
3792                CssPropertyType::BorderLeftColor,
3793            ]
3794        }
3795        BorderStyle => {
3796            vec![
3797                CssPropertyType::BorderTopStyle,
3798                CssPropertyType::BorderRightStyle,
3799                CssPropertyType::BorderBottomStyle,
3800                CssPropertyType::BorderLeftStyle,
3801            ]
3802        }
3803        BorderWidth => {
3804            vec![
3805                CssPropertyType::BorderTopWidth,
3806                CssPropertyType::BorderRightWidth,
3807                CssPropertyType::BorderBottomWidth,
3808                CssPropertyType::BorderLeftWidth,
3809            ]
3810        }
3811        BoxShadow => {
3812            vec![
3813                CssPropertyType::BoxShadowLeft,
3814                CssPropertyType::BoxShadowRight,
3815                CssPropertyType::BoxShadowTop,
3816                CssPropertyType::BoxShadowBottom,
3817            ]
3818        }
3819        BackgroundColor | BackgroundImage | Background => {
3820            vec![CssPropertyType::BackgroundContent]
3821        }
3822        Flex => {
3823            vec![
3824                CssPropertyType::FlexGrow,
3825                CssPropertyType::FlexShrink,
3826                CssPropertyType::FlexBasis,
3827            ]
3828        }
3829        Grid => {
3830            vec![
3831                CssPropertyType::GridTemplateColumns,
3832                CssPropertyType::GridTemplateRows,
3833            ]
3834        }
3835        Gap | GridGap => {
3836            vec![CssPropertyType::RowGap, CssPropertyType::ColumnGap]
3837        }
3838        Font => {
3839            vec![CssPropertyType::Font]
3840        }
3841        Columns => {
3842            vec![CssPropertyType::ColumnWidth, CssPropertyType::ColumnCount]
3843        }
3844        GridArea => {
3845            vec![CssPropertyType::GridRow, CssPropertyType::GridColumn]
3846        }
3847        ColumnRule => {
3848            vec![
3849                CssPropertyType::ColumnRuleWidth,
3850                CssPropertyType::ColumnRuleStyle,
3851                CssPropertyType::ColumnRuleColor,
3852            ]
3853        }
3854        TextBox => {
3855            vec![CssPropertyType::TextBoxTrim, CssPropertyType::TextBoxEdge]
3856        }
3857        // +spec:writing-modes:798cca - inset-block/inset-inline shorthand expansion
3858        // In horizontal-tb (default), block axis = vertical, inline axis = horizontal.
3859        // First value = start side, second = end side; if omitted, second defaults to first.
3860        InsetBlock => {
3861            vec![CssPropertyType::Top, CssPropertyType::Bottom]
3862        }
3863        InsetInline => {
3864            vec![CssPropertyType::Left, CssPropertyType::Right]
3865        }
3866    };
3867
3868    // For Overflow, "auto" is a typed value (LayoutOverflow::Auto), not the generic CSS keyword,
3869    // so we must not intercept it here and let the specific parser handle it below.
3870    let has_typed_auto = matches!(key, Overflow);
3871    let has_typed_none = false; // Currently no combined properties have typed "none"
3872
3873    match value {
3874        "auto" if !has_typed_auto => return Ok(keys.into_iter().map(CssProperty::auto).collect()),
3875        "none" if !has_typed_none => return Ok(keys.into_iter().map(CssProperty::none).collect()),
3876        "initial" => {
3877            return Ok(keys.into_iter().map(CssProperty::initial).collect());
3878        }
3879        "inherit" => {
3880            return Ok(keys.into_iter().map(CssProperty::inherit).collect());
3881        }
3882        _ => {}
3883    }
3884
3885    match key {
3886        BorderRadius => {
3887            let border_radius = parse_style_border_radius(value)?;
3888            Ok(vec![
3889                CssProperty::BorderTopLeftRadius(
3890                    StyleBorderTopLeftRadius {
3891                        inner: border_radius.top_left,
3892                    }
3893                    .into(),
3894                ),
3895                CssProperty::BorderTopRightRadius(
3896                    StyleBorderTopRightRadius {
3897                        inner: border_radius.top_right,
3898                    }
3899                    .into(),
3900                ),
3901                CssProperty::BorderBottomLeftRadius(
3902                    StyleBorderBottomLeftRadius {
3903                        inner: border_radius.bottom_left,
3904                    }
3905                    .into(),
3906                ),
3907                CssProperty::BorderBottomRightRadius(
3908                    StyleBorderBottomRightRadius {
3909                        inner: border_radius.bottom_right,
3910                    }
3911                    .into(),
3912                ),
3913            ])
3914        }
3915        // +spec:overflow:ff5ea4 - overflow shorthand sets overflow-x and overflow-y; second value copied from first if omitted
3916        OverscrollBehavior => {
3917            // Same 1-or-2-value shape as `overflow`: one value applies to both
3918            // axes, two are `x y`.
3919            let parts: Vec<&str> = value.split_whitespace().collect();
3920            match parts.len() {
3921                1 => {
3922                    let b = parse_overscroll_behavior(value)?;
3923                    Ok(vec![
3924                        CssProperty::OverscrollBehaviorX(b.into()),
3925                        CssProperty::OverscrollBehaviorY(b.into()),
3926                    ])
3927                }
3928                2 => {
3929                    let bx = parse_overscroll_behavior(parts[0])?;
3930                    let by = parse_overscroll_behavior(parts[1])?;
3931                    Ok(vec![
3932                        CssProperty::OverscrollBehaviorX(bx.into()),
3933                        CssProperty::OverscrollBehaviorY(by.into()),
3934                    ])
3935                }
3936                _ => Err(CssParsingError::OverscrollBehavior(
3937                    OverscrollBehaviorParseError::InvalidValue(value),
3938                )),
3939            }
3940        }
3941        Overflow => {
3942            let parts: Vec<&str> = value.split_whitespace().collect();
3943            match parts.len() {
3944                1 => {
3945                    let overflow = parse_layout_overflow(value)?;
3946                    Ok(vec![
3947                        CssProperty::OverflowX(overflow.into()),
3948                        CssProperty::OverflowY(overflow.into()),
3949                    ])
3950                }
3951                2 => {
3952                    let overflow_x = parse_layout_overflow(parts[0])?;
3953                    let overflow_y = parse_layout_overflow(parts[1])?;
3954                    Ok(vec![
3955                        CssProperty::OverflowX(overflow_x.into()),
3956                        CssProperty::OverflowY(overflow_y.into()),
3957                    ])
3958                }
3959                _ => Err(CssParsingError::InvalidValue(InvalidValueErr(value))),
3960            }
3961        }
3962        Padding => {
3963            let padding = parse_layout_padding(value)?;
3964            Ok(vec![
3965                convert_value!(padding.top, PaddingTop, LayoutPaddingTop),
3966                convert_value!(padding.bottom, PaddingBottom, LayoutPaddingBottom),
3967                convert_value!(padding.left, PaddingLeft, LayoutPaddingLeft),
3968                convert_value!(padding.right, PaddingRight, LayoutPaddingRight),
3969            ])
3970        }
3971        Margin => {
3972            let margin = parse_layout_margin(value)?;
3973            Ok(vec![
3974                convert_value!(margin.top, MarginTop, LayoutMarginTop),
3975                convert_value!(margin.bottom, MarginBottom, LayoutMarginBottom),
3976                convert_value!(margin.left, MarginLeft, LayoutMarginLeft),
3977                convert_value!(margin.right, MarginRight, LayoutMarginRight),
3978            ])
3979        }
3980        Border => {
3981            let border = parse_style_border(value)?;
3982            Ok(vec![
3983                CssProperty::BorderTopColor(
3984                    StyleBorderTopColor {
3985                        inner: border.border_color,
3986                    }
3987                    .into(),
3988                ),
3989                CssProperty::BorderRightColor(
3990                    StyleBorderRightColor {
3991                        inner: border.border_color,
3992                    }
3993                    .into(),
3994                ),
3995                CssProperty::BorderLeftColor(
3996                    StyleBorderLeftColor {
3997                        inner: border.border_color,
3998                    }
3999                    .into(),
4000                ),
4001                CssProperty::BorderBottomColor(
4002                    StyleBorderBottomColor {
4003                        inner: border.border_color,
4004                    }
4005                    .into(),
4006                ),
4007                CssProperty::BorderTopStyle(
4008                    StyleBorderTopStyle {
4009                        inner: border.border_style,
4010                    }
4011                    .into(),
4012                ),
4013                CssProperty::BorderRightStyle(
4014                    StyleBorderRightStyle {
4015                        inner: border.border_style,
4016                    }
4017                    .into(),
4018                ),
4019                CssProperty::BorderLeftStyle(
4020                    StyleBorderLeftStyle {
4021                        inner: border.border_style,
4022                    }
4023                    .into(),
4024                ),
4025                CssProperty::BorderBottomStyle(
4026                    StyleBorderBottomStyle {
4027                        inner: border.border_style,
4028                    }
4029                    .into(),
4030                ),
4031                CssProperty::BorderTopWidth(
4032                    LayoutBorderTopWidth {
4033                        inner: border.border_width,
4034                    }
4035                    .into(),
4036                ),
4037                CssProperty::BorderRightWidth(
4038                    LayoutBorderRightWidth {
4039                        inner: border.border_width,
4040                    }
4041                    .into(),
4042                ),
4043                CssProperty::BorderLeftWidth(
4044                    LayoutBorderLeftWidth {
4045                        inner: border.border_width,
4046                    }
4047                    .into(),
4048                ),
4049                CssProperty::BorderBottomWidth(
4050                    LayoutBorderBottomWidth {
4051                        inner: border.border_width,
4052                    }
4053                    .into(),
4054                ),
4055            ])
4056        }
4057        BorderLeft => {
4058            let border = parse_style_border(value)?;
4059            Ok(vec![
4060                CssProperty::BorderLeftColor(
4061                    StyleBorderLeftColor {
4062                        inner: border.border_color,
4063                    }
4064                    .into(),
4065                ),
4066                CssProperty::BorderLeftStyle(
4067                    StyleBorderLeftStyle {
4068                        inner: border.border_style,
4069                    }
4070                    .into(),
4071                ),
4072                CssProperty::BorderLeftWidth(
4073                    LayoutBorderLeftWidth {
4074                        inner: border.border_width,
4075                    }
4076                    .into(),
4077                ),
4078            ])
4079        }
4080        BorderRight => {
4081            let border = parse_style_border(value)?;
4082            Ok(vec![
4083                CssProperty::BorderRightColor(
4084                    StyleBorderRightColor {
4085                        inner: border.border_color,
4086                    }
4087                    .into(),
4088                ),
4089                CssProperty::BorderRightStyle(
4090                    StyleBorderRightStyle {
4091                        inner: border.border_style,
4092                    }
4093                    .into(),
4094                ),
4095                CssProperty::BorderRightWidth(
4096                    LayoutBorderRightWidth {
4097                        inner: border.border_width,
4098                    }
4099                    .into(),
4100                ),
4101            ])
4102        }
4103        BorderTop => {
4104            let border = parse_style_border(value)?;
4105            Ok(vec![
4106                CssProperty::BorderTopColor(
4107                    StyleBorderTopColor {
4108                        inner: border.border_color,
4109                    }
4110                    .into(),
4111                ),
4112                CssProperty::BorderTopStyle(
4113                    StyleBorderTopStyle {
4114                        inner: border.border_style,
4115                    }
4116                    .into(),
4117                ),
4118                CssProperty::BorderTopWidth(
4119                    LayoutBorderTopWidth {
4120                        inner: border.border_width,
4121                    }
4122                    .into(),
4123                ),
4124            ])
4125        }
4126        BorderBottom => {
4127            let border = parse_style_border(value)?;
4128            Ok(vec![
4129                CssProperty::BorderBottomColor(
4130                    StyleBorderBottomColor {
4131                        inner: border.border_color,
4132                    }
4133                    .into(),
4134                ),
4135                CssProperty::BorderBottomStyle(
4136                    StyleBorderBottomStyle {
4137                        inner: border.border_style,
4138                    }
4139                    .into(),
4140                ),
4141                CssProperty::BorderBottomWidth(
4142                    LayoutBorderBottomWidth {
4143                        inner: border.border_width,
4144                    }
4145                    .into(),
4146                ),
4147            ])
4148        }
4149        BorderColor => {
4150            let colors = parse_style_border_color(value)?;
4151            Ok(vec![
4152                CssProperty::BorderTopColor(StyleBorderTopColor { inner: colors.top }.into()),
4153                CssProperty::BorderRightColor(
4154                    StyleBorderRightColor {
4155                        inner: colors.right,
4156                    }
4157                    .into(),
4158                ),
4159                CssProperty::BorderBottomColor(
4160                    StyleBorderBottomColor {
4161                        inner: colors.bottom,
4162                    }
4163                    .into(),
4164                ),
4165                CssProperty::BorderLeftColor(StyleBorderLeftColor { inner: colors.left }.into()),
4166            ])
4167        }
4168        BorderStyle => {
4169            let styles = parse_style_border_style(value)?;
4170            Ok(vec![
4171                CssProperty::BorderTopStyle(StyleBorderTopStyle { inner: styles.top }.into()),
4172                CssProperty::BorderRightStyle(
4173                    StyleBorderRightStyle {
4174                        inner: styles.right,
4175                    }
4176                    .into(),
4177                ),
4178                CssProperty::BorderBottomStyle(
4179                    StyleBorderBottomStyle {
4180                        inner: styles.bottom,
4181                    }
4182                    .into(),
4183                ),
4184                CssProperty::BorderLeftStyle(StyleBorderLeftStyle { inner: styles.left }.into()),
4185            ])
4186        }
4187        BorderWidth => {
4188            let widths = parse_style_border_width(value)?;
4189            Ok(vec![
4190                CssProperty::BorderTopWidth(LayoutBorderTopWidth { inner: widths.top }.into()),
4191                CssProperty::BorderRightWidth(
4192                    LayoutBorderRightWidth {
4193                        inner: widths.right,
4194                    }
4195                    .into(),
4196                ),
4197                CssProperty::BorderBottomWidth(
4198                    LayoutBorderBottomWidth {
4199                        inner: widths.bottom,
4200                    }
4201                    .into(),
4202                ),
4203                CssProperty::BorderLeftWidth(LayoutBorderLeftWidth { inner: widths.left }.into()),
4204            ])
4205        }
4206        BoxShadow => {
4207            let box_shadow = parse_style_box_shadow(value)?;
4208            Ok(vec![
4209                CssProperty::BoxShadowLeft(CssPropertyValue::Exact(BoxOrStatic::heap(box_shadow))),
4210                CssProperty::BoxShadowRight(CssPropertyValue::Exact(BoxOrStatic::heap(box_shadow))),
4211                CssProperty::BoxShadowTop(CssPropertyValue::Exact(BoxOrStatic::heap(box_shadow))),
4212                CssProperty::BoxShadowBottom(CssPropertyValue::Exact(BoxOrStatic::heap(
4213                    box_shadow,
4214                ))),
4215            ])
4216        }
4217        BackgroundColor => {
4218            let color = parse_css_color(value)?;
4219            let vec: StyleBackgroundContentVec = vec![StyleBackgroundContent::Color(color)].into();
4220            Ok(vec![CssProperty::BackgroundContent(
4221                CssPropertyValue::Exact(vec),
4222            )])
4223        }
4224        BackgroundImage => {
4225            let background_content = parse_style_background_content(value)?;
4226            let vec: StyleBackgroundContentVec = vec![background_content].into();
4227            Ok(vec![CssProperty::BackgroundContent(
4228                CssPropertyValue::Exact(vec),
4229            )])
4230        }
4231        Background => {
4232            let background_content = parse_style_background_content_multiple(value)?;
4233            Ok(vec![CssProperty::BackgroundContent(
4234                CssPropertyValue::Exact(background_content),
4235            )])
4236        }
4237        Flex => {
4238            // parse shorthand into grow/shrink/basis
4239            let parts: Vec<&str> = value.split_whitespace().collect();
4240            if parts.len() == 1 && parts[0] == "none" {
4241                return Ok(vec![
4242                    CssProperty::FlexGrow(
4243                        LayoutFlexGrow {
4244                            inner: crate::props::basic::length::FloatValue::const_new(0),
4245                        }
4246                        .into(),
4247                    ),
4248                    CssProperty::FlexShrink(
4249                        LayoutFlexShrink {
4250                            inner: crate::props::basic::length::FloatValue::const_new(0),
4251                        }
4252                        .into(),
4253                    ),
4254                    CssProperty::FlexBasis(LayoutFlexBasis::Auto.into()),
4255                ]);
4256            }
4257            if parts.len() == 1 {
4258                // CSS spec: flex: <number> => grow: <number>, shrink: 1, basis: 0
4259                if let Ok(g) = parse_layout_flex_grow(parts[0]) {
4260                    return Ok(vec![
4261                        CssProperty::FlexGrow(g.into()),
4262                        CssProperty::FlexShrink(
4263                            LayoutFlexShrink {
4264                                inner: crate::props::basic::length::FloatValue::const_new(1),
4265                            }
4266                            .into(),
4267                        ),
4268                        CssProperty::FlexBasis(LayoutFlexBasis::Exact(PixelValue::px(0.0)).into()),
4269                    ]);
4270                }
4271                if let Ok(b) = parse_layout_flex_basis(parts[0]) {
4272                    return Ok(vec![CssProperty::FlexBasis(b.into())]);
4273                }
4274            }
4275            if parts.len() == 2 {
4276                // CSS spec: flex: <number> <number> => grow, shrink, basis: 0
4277                // Try grow+shrink first (two unitless numbers)
4278                if let (Ok(g), Ok(s)) = (
4279                    parse_layout_flex_grow(parts[0]),
4280                    parse_layout_flex_shrink(parts[1]),
4281                ) {
4282                    return Ok(vec![
4283                        CssProperty::FlexGrow(g.into()),
4284                        CssProperty::FlexShrink(s.into()),
4285                        CssProperty::FlexBasis(LayoutFlexBasis::Exact(PixelValue::px(0.0)).into()),
4286                    ]);
4287                }
4288                // CSS spec: flex: <number> <width> => grow, shrink: 1, basis: <width>
4289                if let (Ok(g), Ok(b)) = (
4290                    parse_layout_flex_grow(parts[0]),
4291                    parse_layout_flex_basis(parts[1]),
4292                ) {
4293                    return Ok(vec![
4294                        CssProperty::FlexGrow(g.into()),
4295                        CssProperty::FlexShrink(
4296                            LayoutFlexShrink {
4297                                inner: crate::props::basic::length::FloatValue::const_new(1),
4298                            }
4299                            .into(),
4300                        ),
4301                        CssProperty::FlexBasis(b.into()),
4302                    ]);
4303                }
4304            }
4305            if parts.len() == 3 {
4306                let g = parse_layout_flex_grow(parts[0])?;
4307                let s = parse_layout_flex_shrink(parts[1])?;
4308                let b = parse_layout_flex_basis(parts[2])?;
4309                return Ok(vec![
4310                    CssProperty::FlexGrow(g.into()),
4311                    CssProperty::FlexShrink(s.into()),
4312                    CssProperty::FlexBasis(b.into()),
4313                ]);
4314            }
4315            Err(CssParsingError::InvalidValue(InvalidValueErr(value)))
4316        }
4317        Grid => {
4318            // minimal: try to parse as grid-template and set both columns and rows
4319            let tpl = parse_grid_template(value)?;
4320            Ok(vec![
4321                CssProperty::GridTemplateColumns(tpl.clone().into()),
4322                CssProperty::GridTemplateRows(tpl.into()),
4323            ])
4324        }
4325        Gap | GridGap => {
4326            let parts: Vec<&str> = value.split_whitespace().collect();
4327            if parts.len() == 1 {
4328                let g = parse_layout_gap(parts[0])?;
4329                Ok(vec![
4330                    CssProperty::RowGap(LayoutRowGap { inner: g.inner }.into()),
4331                    CssProperty::ColumnGap(LayoutColumnGap { inner: g.inner }.into()),
4332                ])
4333            } else if parts.len() == 2 {
4334                let row = parse_layout_gap(parts[0])?;
4335                let col = parse_layout_gap(parts[1])?;
4336                Ok(vec![
4337                    CssProperty::RowGap(LayoutRowGap { inner: row.inner }.into()),
4338                    CssProperty::ColumnGap(LayoutColumnGap { inner: col.inner }.into()),
4339                ])
4340            } else {
4341                Err(CssParsingError::InvalidValue(InvalidValueErr(value)))
4342            }
4343        }
4344        Font => {
4345            let fam = parse_style_font_family(value)?;
4346            Ok(vec![CssProperty::Font(fam.into())])
4347        }
4348        Columns => {
4349            let mut props = Vec::new();
4350            for part in value.split_whitespace() {
4351                if let Ok(width) = parse_column_width(part) {
4352                    props.push(CssProperty::ColumnWidth(width.into()));
4353                } else if let Ok(count) = parse_column_count(part) {
4354                    props.push(CssProperty::ColumnCount(count.into()));
4355                } else {
4356                    return Err(CssParsingError::InvalidValue(InvalidValueErr(value)));
4357                }
4358            }
4359            Ok(props)
4360        }
4361        GridArea => {
4362            // CSS grid-area shorthand: grid-area: <name>
4363            // Expands to grid-row: <name> / <name> and grid-column: <name> / <name>
4364            // This tells taffy to resolve the named area via NamedLineResolver.
4365            //
4366            // Full syntax: grid-area: row-start / column-start / row-end / column-end
4367            // But for named areas, typically just: grid-area: <name>
4368            let parts: Vec<&str> = value.split('/').map(str::trim).collect();
4369            let (row_start, col_start, row_end, col_end) = match parts.len() {
4370                1 => (parts[0], parts[0], parts[0], parts[0]),
4371                2 => (parts[0], parts[1], parts[0], parts[1]),
4372                3 => (parts[0], parts[1], parts[2], parts[1]),
4373                4 => (parts[0], parts[1], parts[2], parts[3]),
4374                _ => return Err(CssParsingError::InvalidValue(InvalidValueErr(value))),
4375            };
4376            let parse_line = |s: &str| -> Result<GridLine, CssParsingError<'_>> {
4377                parse_grid_line_owned(s.trim())
4378                    .map_err(|()| CssParsingError::InvalidValue(InvalidValueErr(value)))
4379            };
4380            Ok(vec![
4381                CssProperty::GridRow(CssPropertyValue::Exact(GridPlacement {
4382                    grid_start: parse_line(row_start)?,
4383                    grid_end: parse_line(row_end)?,
4384                })),
4385                CssProperty::GridColumn(CssPropertyValue::Exact(GridPlacement {
4386                    grid_start: parse_line(col_start)?,
4387                    grid_end: parse_line(col_end)?,
4388                })),
4389            ])
4390        }
4391        ColumnRule => {
4392            let border = parse_style_border(value)?;
4393            Ok(vec![
4394                CssProperty::ColumnRuleWidth(
4395                    ColumnRuleWidth {
4396                        inner: border.border_width,
4397                    }
4398                    .into(),
4399                ),
4400                CssProperty::ColumnRuleStyle(
4401                    ColumnRuleStyle {
4402                        inner: border.border_style,
4403                    }
4404                    .into(),
4405                ),
4406                CssProperty::ColumnRuleColor(
4407                    ColumnRuleColor {
4408                        inner: border.border_color,
4409                    }
4410                    .into(),
4411                ),
4412            ])
4413        }
4414        // +spec:overflow:33aaf7 - text-box shorthand: "normal" sets trim=none/edge=auto,
4415        // omitting trim defaults to "both", omitting edge defaults to "auto"
4416        TextBox => {
4417            let trimmed = value.trim();
4418            if trimmed == "normal" {
4419                return Ok(vec![
4420                    CssProperty::TextBoxTrim(CssPropertyValue::Exact(StyleTextBoxTrim::None)),
4421                    CssProperty::TextBoxEdge(CssPropertyValue::Exact(StyleTextBoxEdge::AUTO)),
4422                ]);
4423            }
4424            // Trim keywords are single tokens; the edge is ONE value of up
4425            // to TWO tokens ("cap alphabetic"). Collect all non-trim tokens
4426            // and parse them as one edge - the per-token loop rejected every
4427            // two-token edge and silently dropped the whole declaration.
4428            let parts: Vec<&str> = trimmed.split_whitespace().collect();
4429            let mut trim_val = None;
4430            let mut edge_tokens: Vec<&str> = Vec::new();
4431            for part in &parts {
4432                if let Ok(t) = parse_style_text_box_trim(part) {
4433                    if trim_val.is_some() {
4434                        return Err(CssParsingError::InvalidValue(InvalidValueErr(value)));
4435                    }
4436                    trim_val = Some(t);
4437                } else {
4438                    edge_tokens.push(part);
4439                }
4440            }
4441            let edge_val = if edge_tokens.is_empty() {
4442                None
4443            } else {
4444                match parse_style_text_box_edge(&edge_tokens.join(" ")) {
4445                    Ok(e) => Some(e),
4446                    Err(_) => return Err(CssParsingError::InvalidValue(InvalidValueErr(value))),
4447                }
4448            };
4449            // Per spec: omitting trim defaults to "both" (not the initial "none")
4450            let trim = trim_val.unwrap_or(StyleTextBoxTrim::TrimBoth);
4451            // Per spec: omitting edge defaults to "auto" (the initial value)
4452            let edge = edge_val.unwrap_or(StyleTextBoxEdge::AUTO);
4453            Ok(vec![
4454                CssProperty::TextBoxTrim(CssPropertyValue::Exact(trim)),
4455                CssProperty::TextBoxEdge(CssPropertyValue::Exact(edge)),
4456            ])
4457        }
4458        // +spec:writing-modes:798cca - inset-block shorthand: first value = start, second = end;
4459        // if omitted, second defaults to first. Maps to top/bottom in horizontal-tb.
4460        InsetBlock => {
4461            let parts: Vec<&str> = value.split_whitespace().collect();
4462            let start_val = parts
4463                .first()
4464                .ok_or(CssParsingError::InvalidValue(InvalidValueErr(value)))?;
4465            let end_val = parts.get(1).unwrap_or(start_val);
4466            let start = parse_layout_top(start_val)?;
4467            let end = parse_layout_bottom(end_val)?;
4468            Ok(vec![
4469                CssProperty::Top(start.into()),
4470                CssProperty::Bottom(end.into()),
4471            ])
4472        }
4473        // +spec:writing-modes:798cca - inset-inline shorthand: first value = start, second = end;
4474        // if omitted, second defaults to first. Maps to left/right in horizontal-tb.
4475        InsetInline => {
4476            let parts: Vec<&str> = value.split_whitespace().collect();
4477            let start_val = parts
4478                .first()
4479                .ok_or(CssParsingError::InvalidValue(InvalidValueErr(value)))?;
4480            let end_val = parts.get(1).unwrap_or(start_val);
4481            let start = parse_layout_left(start_val)?;
4482            let end = parse_layout_right(end_val)?;
4483            Ok(vec![
4484                CssProperty::Left(start.into()),
4485                CssProperty::Right(end.into()),
4486            ])
4487        }
4488    }
4489}
4490
4491// Re-add the From implementations for convenience
4492macro_rules! impl_from_css_prop {
4493    ($a:ident, $b:ident:: $enum_type:ident) => {
4494        impl From<$a> for $b {
4495            fn from(e: $a) -> Self {
4496                $b::$enum_type(CssPropertyValue::from(e))
4497            }
4498        }
4499    };
4500}
4501
4502impl_from_css_prop!(CaretColor, CssProperty::CaretColor);
4503impl_from_css_prop!(CaretWidth, CssProperty::CaretWidth);
4504impl_from_css_prop!(CaretAnimationDuration, CssProperty::CaretAnimationDuration);
4505impl_from_css_prop!(
4506    SelectionBackgroundColor,
4507    CssProperty::SelectionBackgroundColor
4508);
4509impl_from_css_prop!(SelectionColor, CssProperty::SelectionColor);
4510impl_from_css_prop!(SelectionRadius, CssProperty::SelectionRadius);
4511impl_from_css_prop!(StyleTextColor, CssProperty::TextColor);
4512impl_from_css_prop!(StyleFontSize, CssProperty::FontSize);
4513impl_from_css_prop!(StyleFontFamilyVec, CssProperty::FontFamily);
4514impl_from_css_prop!(StyleTextAlign, CssProperty::TextAlign);
4515impl_from_css_prop!(LayoutTextJustify, CssProperty::TextJustify);
4516impl_from_css_prop!(StyleVerticalAlign, CssProperty::VerticalAlign);
4517impl_from_css_prop!(StyleLetterSpacing, CssProperty::LetterSpacing);
4518impl_from_css_prop!(StyleTextIndent, CssProperty::TextIndent);
4519impl_from_css_prop!(StyleInitialLetter, CssProperty::InitialLetter);
4520impl_from_css_prop!(StyleLineClamp, CssProperty::LineClamp);
4521impl_from_css_prop!(StyleHangingPunctuation, CssProperty::HangingPunctuation);
4522impl_from_css_prop!(StyleTextCombineUpright, CssProperty::TextCombineUpright);
4523impl_from_css_prop!(StyleUnicodeBidi, CssProperty::UnicodeBidi);
4524impl_from_css_prop!(StyleTextBoxTrim, CssProperty::TextBoxTrim);
4525impl_from_css_prop!(StyleTextBoxEdge, CssProperty::TextBoxEdge);
4526impl_from_css_prop!(StyleDominantBaseline, CssProperty::DominantBaseline);
4527impl_from_css_prop!(StyleAlignmentBaseline, CssProperty::AlignmentBaseline);
4528impl_from_css_prop!(StyleBaselineSource, CssProperty::BaselineSource);
4529impl_from_css_prop!(StyleLineFitEdge, CssProperty::LineFitEdge);
4530impl_from_css_prop!(StyleInitialLetterAlign, CssProperty::InitialLetterAlign);
4531impl_from_css_prop!(StyleInitialLetterWrap, CssProperty::InitialLetterWrap);
4532impl_from_css_prop!(StyleScrollbarGutter, CssProperty::ScrollbarGutter);
4533impl_from_css_prop!(StyleOverflowClipMargin, CssProperty::OverflowClipMargin);
4534impl_from_css_prop!(StyleClipRect, CssProperty::Clip);
4535impl_from_css_prop!(StyleExclusionMargin, CssProperty::ExclusionMargin);
4536impl_from_css_prop!(StyleHyphenationLanguage, CssProperty::HyphenationLanguage);
4537impl_from_css_prop!(StyleLineHeight, CssProperty::LineHeight);
4538impl_from_css_prop!(StyleWordSpacing, CssProperty::WordSpacing);
4539impl_from_css_prop!(StyleTabSize, CssProperty::TabSize);
4540impl_from_css_prop!(StyleCursor, CssProperty::Cursor);
4541impl_from_css_prop!(LayoutDisplay, CssProperty::Display);
4542impl_from_css_prop!(LayoutFloat, CssProperty::Float);
4543impl_from_css_prop!(LayoutBoxSizing, CssProperty::BoxSizing);
4544impl_from_css_prop!(LayoutWidth, CssProperty::Width);
4545impl_from_css_prop!(LayoutHeight, CssProperty::Height);
4546impl_from_css_prop!(LayoutMinWidth, CssProperty::MinWidth);
4547impl_from_css_prop!(LayoutMinHeight, CssProperty::MinHeight);
4548impl_from_css_prop!(LayoutMaxWidth, CssProperty::MaxWidth);
4549impl_from_css_prop!(LayoutMaxHeight, CssProperty::MaxHeight);
4550impl_from_css_prop!(LayoutPosition, CssProperty::Position);
4551impl_from_css_prop!(LayoutTop, CssProperty::Top);
4552impl_from_css_prop!(LayoutRight, CssProperty::Right);
4553impl_from_css_prop!(LayoutLeft, CssProperty::Left);
4554impl_from_css_prop!(LayoutInsetBottom, CssProperty::Bottom);
4555impl_from_css_prop!(LayoutFlexWrap, CssProperty::FlexWrap);
4556impl_from_css_prop!(LayoutFlexDirection, CssProperty::FlexDirection);
4557impl_from_css_prop!(LayoutFlexGrow, CssProperty::FlexGrow);
4558impl_from_css_prop!(LayoutFlexShrink, CssProperty::FlexShrink);
4559impl_from_css_prop!(LayoutFlexBasis, CssProperty::FlexBasis);
4560impl_from_css_prop!(LayoutJustifyContent, CssProperty::JustifyContent);
4561impl_from_css_prop!(LayoutAlignItems, CssProperty::AlignItems);
4562impl_from_css_prop!(LayoutAlignContent, CssProperty::AlignContent);
4563impl_from_css_prop!(LayoutColumnGap, CssProperty::ColumnGap);
4564impl_from_css_prop!(LayoutRowGap, CssProperty::RowGap);
4565impl_from_css_prop!(LayoutGridAutoFlow, CssProperty::GridAutoFlow);
4566impl_from_css_prop!(LayoutJustifySelf, CssProperty::JustifySelf);
4567impl_from_css_prop!(LayoutJustifyItems, CssProperty::JustifyItems);
4568impl_from_css_prop!(LayoutGap, CssProperty::Gap);
4569impl_from_css_prop!(LayoutAlignSelf, CssProperty::AlignSelf);
4570impl_from_css_prop!(LayoutWritingMode, CssProperty::WritingMode);
4571impl_from_css_prop!(LayoutClear, CssProperty::Clear);
4572
4573// BackgroundContent uses the standard From pattern
4574impl_from_css_prop!(StyleBackgroundContentVec, CssProperty::BackgroundContent);
4575
4576impl_from_css_prop!(StyleBackgroundPositionVec, CssProperty::BackgroundPosition);
4577impl_from_css_prop!(StyleBackgroundSizeVec, CssProperty::BackgroundSize);
4578impl_from_css_prop!(StyleBackgroundRepeatVec, CssProperty::BackgroundRepeat);
4579impl_from_css_prop!(LayoutPaddingTop, CssProperty::PaddingTop);
4580impl_from_css_prop!(LayoutPaddingLeft, CssProperty::PaddingLeft);
4581impl_from_css_prop!(LayoutPaddingRight, CssProperty::PaddingRight);
4582impl_from_css_prop!(LayoutPaddingBottom, CssProperty::PaddingBottom);
4583impl_from_css_prop!(LayoutPaddingInlineStart, CssProperty::PaddingInlineStart);
4584impl_from_css_prop!(LayoutPaddingInlineEnd, CssProperty::PaddingInlineEnd);
4585impl_from_css_prop!(LayoutMarginTop, CssProperty::MarginTop);
4586impl_from_css_prop!(LayoutMarginLeft, CssProperty::MarginLeft);
4587impl_from_css_prop!(LayoutMarginRight, CssProperty::MarginRight);
4588impl_from_css_prop!(LayoutMarginBottom, CssProperty::MarginBottom);
4589impl_from_css_prop!(StyleBorderTopLeftRadius, CssProperty::BorderTopLeftRadius);
4590impl_from_css_prop!(StyleBorderTopRightRadius, CssProperty::BorderTopRightRadius);
4591impl_from_css_prop!(
4592    StyleBorderBottomLeftRadius,
4593    CssProperty::BorderBottomLeftRadius
4594);
4595impl_from_css_prop!(
4596    StyleBorderBottomRightRadius,
4597    CssProperty::BorderBottomRightRadius
4598);
4599impl_from_css_prop!(StyleBorderTopColor, CssProperty::BorderTopColor);
4600impl_from_css_prop!(StyleBorderRightColor, CssProperty::BorderRightColor);
4601impl_from_css_prop!(StyleBorderLeftColor, CssProperty::BorderLeftColor);
4602impl_from_css_prop!(StyleBorderBottomColor, CssProperty::BorderBottomColor);
4603impl_from_css_prop!(StyleBorderTopStyle, CssProperty::BorderTopStyle);
4604impl_from_css_prop!(StyleBorderRightStyle, CssProperty::BorderRightStyle);
4605impl_from_css_prop!(StyleBorderLeftStyle, CssProperty::BorderLeftStyle);
4606impl_from_css_prop!(StyleBorderBottomStyle, CssProperty::BorderBottomStyle);
4607impl_from_css_prop!(LayoutBorderTopWidth, CssProperty::BorderTopWidth);
4608impl_from_css_prop!(LayoutBorderRightWidth, CssProperty::BorderRightWidth);
4609impl_from_css_prop!(LayoutBorderLeftWidth, CssProperty::BorderLeftWidth);
4610impl_from_css_prop!(LayoutBorderBottomWidth, CssProperty::BorderBottomWidth);
4611impl_from_css_prop!(LayoutScrollbarWidth, CssProperty::ScrollbarWidth);
4612impl_from_css_prop!(StyleScrollbarColor, CssProperty::ScrollbarColor);
4613impl_from_css_prop!(ScrollbarVisibilityMode, CssProperty::ScrollbarVisibility);
4614impl_from_css_prop!(ScrollbarFadeDelay, CssProperty::ScrollbarFadeDelay);
4615impl_from_css_prop!(ScrollbarFadeDuration, CssProperty::ScrollbarFadeDuration);
4616impl_from_css_prop!(StyleOpacity, CssProperty::Opacity);
4617impl_from_css_prop!(StyleVisibility, CssProperty::Visibility);
4618impl_from_css_prop!(StyleTransformVec, CssProperty::Transform);
4619impl_from_css_prop!(StyleTransformOrigin, CssProperty::TransformOrigin);
4620impl_from_css_prop!(StylePerspectiveOrigin, CssProperty::PerspectiveOrigin);
4621impl_from_css_prop!(StyleBackfaceVisibility, CssProperty::BackfaceVisibility);
4622impl_from_css_prop!(StyleAppRegion, CssProperty::AppRegion);
4623impl_from_css_prop!(
4624    StyleSpatialNavigationAction,
4625    CssProperty::SpatialNavigationAction
4626);
4627impl_from_css_prop!(
4628    StyleSpatialNavigationContain,
4629    CssProperty::SpatialNavigationContain
4630);
4631impl_from_css_prop!(StyleMixBlendMode, CssProperty::MixBlendMode);
4632impl_from_css_prop!(StyleHyphens, CssProperty::Hyphens);
4633impl_from_css_prop!(StyleWordBreak, CssProperty::WordBreak);
4634impl_from_css_prop!(StyleOverflowWrap, CssProperty::OverflowWrap);
4635impl_from_css_prop!(StyleLineBreak, CssProperty::LineBreak);
4636impl_from_css_prop!(StyleTextOverflow, CssProperty::TextOverflow);
4637impl_from_css_prop!(StyleObjectFit, CssProperty::ObjectFit);
4638impl_from_css_prop!(StyleObjectPosition, CssProperty::ObjectPosition);
4639impl_from_css_prop!(StyleAspectRatio, CssProperty::AspectRatio);
4640impl_from_css_prop!(StyleTextOrientation, CssProperty::TextOrientation);
4641impl_from_css_prop!(StyleTextAlignLast, CssProperty::TextAlignLast);
4642impl_from_css_prop!(StyleTextTransform, CssProperty::TextTransform);
4643impl_from_css_prop!(StyleDirection, CssProperty::Direction);
4644impl_from_css_prop!(StyleWhiteSpace, CssProperty::WhiteSpace);
4645impl_from_css_prop!(PageBreak, CssProperty::BreakBefore);
4646impl_from_css_prop!(BreakInside, CssProperty::BreakInside);
4647impl_from_css_prop!(Widows, CssProperty::Widows);
4648impl_from_css_prop!(Orphans, CssProperty::Orphans);
4649impl_from_css_prop!(BoxDecorationBreak, CssProperty::BoxDecorationBreak);
4650impl_from_css_prop!(ColumnCount, CssProperty::ColumnCount);
4651impl_from_css_prop!(ColumnWidth, CssProperty::ColumnWidth);
4652impl_from_css_prop!(ColumnSpan, CssProperty::ColumnSpan);
4653impl_from_css_prop!(ColumnFill, CssProperty::ColumnFill);
4654impl_from_css_prop!(ColumnRuleWidth, CssProperty::ColumnRuleWidth);
4655impl_from_css_prop!(ColumnRuleStyle, CssProperty::ColumnRuleStyle);
4656impl_from_css_prop!(ColumnRuleColor, CssProperty::ColumnRuleColor);
4657impl_from_css_prop!(FlowInto, CssProperty::FlowInto);
4658impl_from_css_prop!(FlowFrom, CssProperty::FlowFrom);
4659impl_from_css_prop!(ShapeOutside, CssProperty::ShapeOutside);
4660impl_from_css_prop!(ShapeInside, CssProperty::ShapeInside);
4661impl_from_css_prop!(ClipPath, CssProperty::ClipPath);
4662impl_from_css_prop!(ShapeMargin, CssProperty::ShapeMargin);
4663impl_from_css_prop!(ShapeImageThreshold, CssProperty::ShapeImageThreshold);
4664impl_from_css_prop!(Content, CssProperty::Content);
4665impl_from_css_prop!(CounterReset, CssProperty::CounterReset);
4666impl_from_css_prop!(CounterIncrement, CssProperty::CounterIncrement);
4667impl_from_css_prop!(StyleListStyleType, CssProperty::ListStyleType);
4668impl_from_css_prop!(StyleListStylePosition, CssProperty::ListStylePosition);
4669impl_from_css_prop!(StringSet, CssProperty::StringSet);
4670impl_from_css_prop!(LayoutTableLayout, CssProperty::TableLayout);
4671impl_from_css_prop!(StyleBorderCollapse, CssProperty::BorderCollapse);
4672impl_from_css_prop!(LayoutBorderSpacing, CssProperty::BorderSpacing);
4673impl_from_css_prop!(StyleCaptionSide, CssProperty::CaptionSide);
4674impl_from_css_prop!(StyleEmptyCells, CssProperty::EmptyCells);
4675
4676impl CssProperty {
4677    #[must_use]
4678    pub const fn key(&self) -> &'static str {
4679        self.get_type().to_str()
4680    }
4681
4682    // Every arm delegates to `v.get_css_value_fmt()`, but each `v` is a different
4683    // `CssPropertyValue<T>` — the identical bodies cannot merge into one or-pattern
4684    // (mismatched binding types), so clippy::match_same_arms is a false positive here.
4685    #[allow(clippy::match_same_arms)]
4686    #[allow(clippy::too_many_lines)]
4687    // large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
4688    #[must_use]
4689    pub fn value(&self) -> String {
4690        match self {
4691            Self::CaretColor(v) => v.get_css_value_fmt(),
4692            Self::CaretWidth(v) => v.get_css_value_fmt(),
4693            Self::CaretAnimationDuration(v) => v.get_css_value_fmt(),
4694            Self::Animation(v) => v.get_css_value_fmt(),
4695            Self::AnimationIn(v) => v.get_css_value_fmt(),
4696            Self::AnimationOut(v) => v.get_css_value_fmt(),
4697            Self::SelectionBackgroundColor(v) => v.get_css_value_fmt(),
4698            Self::SelectionColor(v) => v.get_css_value_fmt(),
4699            Self::SelectionRadius(v) => v.get_css_value_fmt(),
4700            Self::TextJustify(v) => v.get_css_value_fmt(),
4701            Self::TextColor(v) => v.get_css_value_fmt(),
4702            Self::FontSize(v) => v.get_css_value_fmt(),
4703            Self::FontFamily(v) => v.get_css_value_fmt(),
4704            Self::TextAlign(v) => v.get_css_value_fmt(),
4705            Self::LetterSpacing(v) => v.get_css_value_fmt(),
4706            Self::TextIndent(v) => v.get_css_value_fmt(),
4707            Self::InitialLetter(v) => v.get_css_value_fmt(),
4708            Self::LineClamp(v) => v.get_css_value_fmt(),
4709            Self::HangingPunctuation(v) => v.get_css_value_fmt(),
4710            Self::TextCombineUpright(v) => v.get_css_value_fmt(),
4711            Self::UnicodeBidi(v) => v.get_css_value_fmt(),
4712            Self::TextBoxTrim(v) => v.get_css_value_fmt(),
4713            Self::TextBoxEdge(v) => v.get_css_value_fmt(),
4714            Self::DominantBaseline(v) => v.get_css_value_fmt(),
4715            Self::AlignmentBaseline(v) => v.get_css_value_fmt(),
4716            Self::BaselineSource(v) => v.get_css_value_fmt(),
4717            Self::LineFitEdge(v) => v.get_css_value_fmt(),
4718            Self::InitialLetterAlign(v) => v.get_css_value_fmt(),
4719            Self::InitialLetterWrap(v) => v.get_css_value_fmt(),
4720            Self::ScrollbarGutter(v) => v.get_css_value_fmt(),
4721            Self::OverflowClipMargin(v) => v.get_css_value_fmt(),
4722            Self::Clip(v) => v.get_css_value_fmt(),
4723            Self::ExclusionMargin(v) => v.get_css_value_fmt(),
4724            Self::HyphenationLanguage(v) => v.get_css_value_fmt(),
4725            Self::LineHeight(v) => v.get_css_value_fmt(),
4726            Self::WordSpacing(v) => v.get_css_value_fmt(),
4727            Self::TabSize(v) => v.get_css_value_fmt(),
4728            Self::Cursor(v) => v.get_css_value_fmt(),
4729            Self::Display(v) => v.get_css_value_fmt(),
4730            Self::Float(v) => v.get_css_value_fmt(),
4731            Self::BoxSizing(v) => v.get_css_value_fmt(),
4732            Self::Width(v) => v.get_css_value_fmt(),
4733            Self::Height(v) => v.get_css_value_fmt(),
4734            Self::MinWidth(v) => v.get_css_value_fmt(),
4735            Self::MinHeight(v) => v.get_css_value_fmt(),
4736            Self::MaxWidth(v) => v.get_css_value_fmt(),
4737            Self::MaxHeight(v) => v.get_css_value_fmt(),
4738            Self::Position(v) => v.get_css_value_fmt(),
4739            Self::Top(v) => v.get_css_value_fmt(),
4740            Self::Right(v) => v.get_css_value_fmt(),
4741            Self::Left(v) => v.get_css_value_fmt(),
4742            Self::Bottom(v) => v.get_css_value_fmt(),
4743            Self::ZIndex(v) => v.get_css_value_fmt(),
4744            Self::FlexWrap(v) => v.get_css_value_fmt(),
4745            Self::FlexDirection(v) => v.get_css_value_fmt(),
4746            Self::FlexGrow(v) => v.get_css_value_fmt(),
4747            Self::FlexShrink(v) => v.get_css_value_fmt(),
4748            Self::FlexBasis(v) => v.get_css_value_fmt(),
4749            Self::JustifyContent(v) => v.get_css_value_fmt(),
4750            Self::AlignItems(v) => v.get_css_value_fmt(),
4751            Self::AlignContent(v) => v.get_css_value_fmt(),
4752            Self::ColumnGap(v) => v.get_css_value_fmt(),
4753            Self::RowGap(v) => v.get_css_value_fmt(),
4754            Self::GridTemplateColumns(v) => v.get_css_value_fmt(),
4755            Self::GridTemplateRows(v) => v.get_css_value_fmt(),
4756            Self::GridAutoFlow(v) => v.get_css_value_fmt(),
4757            Self::JustifySelf(v) => v.get_css_value_fmt(),
4758            Self::JustifyItems(v) => v.get_css_value_fmt(),
4759            Self::Gap(v) => v.get_css_value_fmt(),
4760            Self::GridGap(v) => v.get_css_value_fmt(),
4761            Self::AlignSelf(v) => v.get_css_value_fmt(),
4762            Self::Font(v) => v.get_css_value_fmt(),
4763            Self::GridAutoColumns(v) => v.get_css_value_fmt(),
4764            Self::GridAutoRows(v) => v.get_css_value_fmt(),
4765            Self::GridColumn(v) => v.get_css_value_fmt(),
4766            Self::GridRow(v) => v.get_css_value_fmt(),
4767            Self::GridTemplateAreas(v) => v.get_css_value_fmt(),
4768            Self::WritingMode(v) => v.get_css_value_fmt(),
4769            Self::Clear(v) => v.get_css_value_fmt(),
4770            Self::BackgroundContent(v) => v.get_css_value_fmt(),
4771            Self::BackgroundPosition(v) => v.get_css_value_fmt(),
4772            Self::BackgroundSize(v) => v.get_css_value_fmt(),
4773            Self::BackgroundRepeat(v) => v.get_css_value_fmt(),
4774            Self::OverflowX(v) => v.get_css_value_fmt(),
4775            Self::OverflowY(v) => v.get_css_value_fmt(),
4776            Self::OverflowBlock(v) => v.get_css_value_fmt(),
4777            Self::OverflowInline(v) => v.get_css_value_fmt(),
4778            Self::PaddingTop(v) => v.get_css_value_fmt(),
4779            Self::PaddingLeft(v) => v.get_css_value_fmt(),
4780            Self::PaddingRight(v) => v.get_css_value_fmt(),
4781            Self::PaddingBottom(v) => v.get_css_value_fmt(),
4782            Self::PaddingInlineStart(v) => v.get_css_value_fmt(),
4783            Self::PaddingInlineEnd(v) => v.get_css_value_fmt(),
4784            Self::MarginTop(v) => v.get_css_value_fmt(),
4785            Self::MarginLeft(v) => v.get_css_value_fmt(),
4786            Self::MarginRight(v) => v.get_css_value_fmt(),
4787            Self::MarginBottom(v) => v.get_css_value_fmt(),
4788            Self::BorderTopLeftRadius(v) => v.get_css_value_fmt(),
4789            Self::BorderTopRightRadius(v) => v.get_css_value_fmt(),
4790            Self::BorderBottomLeftRadius(v) => v.get_css_value_fmt(),
4791            Self::BorderBottomRightRadius(v) => v.get_css_value_fmt(),
4792            Self::BorderTopColor(v) => v.get_css_value_fmt(),
4793            Self::BorderRightColor(v) => v.get_css_value_fmt(),
4794            Self::BorderLeftColor(v) => v.get_css_value_fmt(),
4795            Self::BorderBottomColor(v) => v.get_css_value_fmt(),
4796            Self::BorderTopStyle(v) => v.get_css_value_fmt(),
4797            Self::BorderRightStyle(v) => v.get_css_value_fmt(),
4798            Self::BorderLeftStyle(v) => v.get_css_value_fmt(),
4799            Self::BorderBottomStyle(v) => v.get_css_value_fmt(),
4800            Self::BorderTopWidth(v) => v.get_css_value_fmt(),
4801            Self::BorderRightWidth(v) => v.get_css_value_fmt(),
4802            Self::BorderLeftWidth(v) => v.get_css_value_fmt(),
4803            Self::BorderBottomWidth(v) => v.get_css_value_fmt(),
4804            Self::BoxShadowLeft(v) => v.get_css_value_fmt(),
4805            Self::BoxShadowRight(v) => v.get_css_value_fmt(),
4806            Self::BoxShadowTop(v) => v.get_css_value_fmt(),
4807            Self::BoxShadowBottom(v) => v.get_css_value_fmt(),
4808            Self::ScrollbarTrack(v) => v.get_css_value_fmt(),
4809            Self::ScrollbarThumb(v) => v.get_css_value_fmt(),
4810            Self::ScrollbarButton(v) => v.get_css_value_fmt(),
4811            Self::ScrollbarCorner(v) => v.get_css_value_fmt(),
4812            Self::ScrollbarResizer(v) => v.get_css_value_fmt(),
4813            Self::ScrollbarWidth(v) => v.get_css_value_fmt(),
4814            Self::OverscrollBehaviorX(v) | Self::OverscrollBehaviorY(v) => v.get_css_value_fmt(),
4815            Self::ScrollbarColor(v) => v.get_css_value_fmt(),
4816            Self::ScrollbarVisibility(v) => v.get_css_value_fmt(),
4817            Self::ScrollbarFadeDelay(v) => v.get_css_value_fmt(),
4818            Self::ScrollbarFadeDuration(v) => v.get_css_value_fmt(),
4819            Self::Opacity(v) => v.get_css_value_fmt(),
4820            Self::Visibility(v) => v.get_css_value_fmt(),
4821            Self::Transform(v) => v.get_css_value_fmt(),
4822            Self::TransformOrigin(v) => v.get_css_value_fmt(),
4823            Self::PerspectiveOrigin(v) => v.get_css_value_fmt(),
4824            Self::BackfaceVisibility(v) => v.get_css_value_fmt(),
4825            Self::AppRegion(v) => v.get_css_value_fmt(),
4826            Self::SpatialNavigationAction(v) => v.get_css_value_fmt(),
4827            Self::SpatialNavigationContain(v) => v.get_css_value_fmt(),
4828            Self::MixBlendMode(v) => v.get_css_value_fmt(),
4829            Self::Filter(v) => v.get_css_value_fmt(),
4830            Self::BackdropFilter(v) => v.get_css_value_fmt(),
4831            Self::TextShadow(v) => v.get_css_value_fmt(),
4832            Self::Hyphens(v) => v.get_css_value_fmt(),
4833            Self::WordBreak(v) => v.get_css_value_fmt(),
4834            Self::OverflowWrap(v) => v.get_css_value_fmt(),
4835            Self::LineBreak(v) => v.get_css_value_fmt(),
4836            Self::TextOverflow(v) => v.get_css_value_fmt(),
4837            Self::ObjectFit(v) => v.get_css_value_fmt(),
4838            Self::ObjectPosition(v) => v.get_css_value_fmt(),
4839            Self::AspectRatio(v) => v.get_css_value_fmt(),
4840            Self::TextOrientation(v) => v.get_css_value_fmt(),
4841            Self::TextAlignLast(v) => v.get_css_value_fmt(),
4842            Self::TextTransform(v) => v.get_css_value_fmt(),
4843            Self::Direction(v) => v.get_css_value_fmt(),
4844            Self::UserSelect(v) => v.get_css_value_fmt(),
4845            Self::TextDecoration(v) => v.get_css_value_fmt(),
4846            Self::WhiteSpace(v) => v.get_css_value_fmt(),
4847            Self::BreakBefore(v) => v.get_css_value_fmt(),
4848            Self::BreakAfter(v) => v.get_css_value_fmt(),
4849            Self::BreakInside(v) => v.get_css_value_fmt(),
4850            Self::Orphans(v) => v.get_css_value_fmt(),
4851            Self::Widows(v) => v.get_css_value_fmt(),
4852            Self::BoxDecorationBreak(v) => v.get_css_value_fmt(),
4853            Self::ColumnCount(v) => v.get_css_value_fmt(),
4854            Self::ColumnWidth(v) => v.get_css_value_fmt(),
4855            Self::ColumnSpan(v) => v.get_css_value_fmt(),
4856            Self::ColumnFill(v) => v.get_css_value_fmt(),
4857            Self::ColumnRuleWidth(v) => v.get_css_value_fmt(),
4858            Self::ColumnRuleStyle(v) => v.get_css_value_fmt(),
4859            Self::ColumnRuleColor(v) => v.get_css_value_fmt(),
4860            Self::FlowInto(v) => v.get_css_value_fmt(),
4861            Self::FlowFrom(v) => v.get_css_value_fmt(),
4862            Self::ShapeOutside(v) => v.get_css_value_fmt(),
4863            Self::ShapeInside(v) => v.get_css_value_fmt(),
4864            Self::ClipPath(v) => v.get_css_value_fmt(),
4865            Self::ShapeMargin(v) => v.get_css_value_fmt(),
4866            Self::ShapeImageThreshold(v) => v.get_css_value_fmt(),
4867            Self::Content(v) => v.get_css_value_fmt(),
4868            Self::CounterReset(v) => v.get_css_value_fmt(),
4869            Self::CounterIncrement(v) => v.get_css_value_fmt(),
4870            Self::ListStyleType(v) => v.get_css_value_fmt(),
4871            Self::ListStylePosition(v) => v.get_css_value_fmt(),
4872            Self::StringSet(v) => v.get_css_value_fmt(),
4873            Self::TableLayout(v) => v.get_css_value_fmt(),
4874            Self::BorderCollapse(v) => v.get_css_value_fmt(),
4875            Self::BorderSpacing(v) => v.get_css_value_fmt(),
4876            Self::CaptionSide(v) => v.get_css_value_fmt(),
4877            Self::EmptyCells(v) => v.get_css_value_fmt(),
4878            Self::FontWeight(v) => v.get_css_value_fmt(),
4879            Self::FontStyle(v) => v.get_css_value_fmt(),
4880            Self::VerticalAlign(v) => v.get_css_value_fmt(),
4881        }
4882    }
4883
4884    #[must_use]
4885    pub fn format_css(&self) -> String {
4886        format!("{}: {};", self.key(), self.value())
4887    }
4888
4889    #[allow(clippy::too_many_lines)]
4890    // large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
4891    #[must_use]
4892    pub fn interpolate(
4893        &self,
4894        other: &Self,
4895        t: f32,
4896        interpolate_resolver: &InterpolateResolver,
4897    ) -> Self {
4898        if t <= 0.0 {
4899            return self.clone();
4900        } else if t >= 1.0 {
4901            return other.clone();
4902        }
4903
4904        // Map from linear interpolation function to Easing curve
4905        let t: f32 = interpolate_resolver.interpolate_func.evaluate(f64::from(t));
4906
4907        let t = t.clamp(0.0, 1.0);
4908
4909        match (self, other) {
4910            (Self::TextColor(col_start), Self::TextColor(col_end)) => {
4911                let col_start = col_start.get_property().copied().unwrap_or_default();
4912                let col_end = col_end.get_property().copied().unwrap_or_default();
4913                Self::text_color(col_start.interpolate(&col_end, t))
4914            }
4915            (Self::FontSize(fs_start), Self::FontSize(fs_end)) => {
4916                let fs_start = fs_start.get_property().copied().unwrap_or_default();
4917                let fs_end = fs_end.get_property().copied().unwrap_or_default();
4918                Self::font_size(fs_start.interpolate(&fs_end, t))
4919            }
4920            (Self::LetterSpacing(ls_start), Self::LetterSpacing(ls_end)) => {
4921                let ls_start = ls_start.get_property().copied().unwrap_or_default();
4922                let ls_end = ls_end.get_property().copied().unwrap_or_default();
4923                Self::letter_spacing(ls_start.interpolate(&ls_end, t))
4924            }
4925            (Self::TextIndent(ti_start), Self::TextIndent(ti_end)) => {
4926                let ti_start = ti_start.get_property().copied().unwrap_or_default();
4927                let ti_end = ti_end.get_property().copied().unwrap_or_default();
4928                Self::text_indent(ti_start.interpolate(&ti_end, t))
4929            }
4930            (Self::LineHeight(lh_start), Self::LineHeight(lh_end)) => {
4931                let lh_start = lh_start.get_property().copied().unwrap_or_default();
4932                let lh_end = lh_end.get_property().copied().unwrap_or_default();
4933                Self::line_height(lh_start.interpolate(&lh_end, t))
4934            }
4935            (Self::WordSpacing(ws_start), Self::WordSpacing(ws_end)) => {
4936                let ws_start = ws_start.get_property().copied().unwrap_or_default();
4937                let ws_end = ws_end.get_property().copied().unwrap_or_default();
4938                Self::word_spacing(ws_start.interpolate(&ws_end, t))
4939            }
4940            (Self::TabSize(tw_start), Self::TabSize(tw_end)) => {
4941                let tw_start = tw_start.get_property().copied().unwrap_or_default();
4942                let tw_end = tw_end.get_property().copied().unwrap_or_default();
4943                Self::tab_size(tw_start.interpolate(&tw_end, t))
4944            }
4945            (Self::Width(start), Self::Width(end)) => {
4946                let start =
4947                    start
4948                        .get_property()
4949                        .cloned()
4950                        .unwrap_or(LayoutWidth::Px(PixelValue::px(
4951                            interpolate_resolver.current_rect_width,
4952                        )));
4953                let end = end.get_property().cloned().unwrap_or_default();
4954                Self::Width(CssPropertyValue::Exact(start.interpolate(&end, t)))
4955            }
4956            (Self::Height(start), Self::Height(end)) => {
4957                let start =
4958                    start
4959                        .get_property()
4960                        .cloned()
4961                        .unwrap_or(LayoutHeight::Px(PixelValue::px(
4962                            interpolate_resolver.current_rect_height,
4963                        )));
4964                let end = end.get_property().cloned().unwrap_or_default();
4965                Self::Height(CssPropertyValue::Exact(start.interpolate(&end, t)))
4966            }
4967            (Self::MinWidth(start), Self::MinWidth(end)) => {
4968                let start = start.get_property().copied().unwrap_or_default();
4969                let end = end.get_property().copied().unwrap_or_default();
4970                Self::MinWidth(CssPropertyValue::Exact(start.interpolate(&end, t)))
4971            }
4972            (Self::MinHeight(start), Self::MinHeight(end)) => {
4973                let start = start.get_property().copied().unwrap_or_default();
4974                let end = end.get_property().copied().unwrap_or_default();
4975                Self::MinHeight(CssPropertyValue::Exact(start.interpolate(&end, t)))
4976            }
4977            (Self::MaxWidth(start), Self::MaxWidth(end)) => {
4978                let start = start.get_property().copied().unwrap_or_default();
4979                let end = end.get_property().copied().unwrap_or_default();
4980                Self::MaxWidth(CssPropertyValue::Exact(start.interpolate(&end, t)))
4981            }
4982            (Self::MaxHeight(start), Self::MaxHeight(end)) => {
4983                let start = start.get_property().copied().unwrap_or_default();
4984                let end = end.get_property().copied().unwrap_or_default();
4985                Self::MaxHeight(CssPropertyValue::Exact(start.interpolate(&end, t)))
4986            }
4987            (Self::Top(start), Self::Top(end)) => {
4988                let start = start.get_property().copied().unwrap_or_default();
4989                let end = end.get_property().copied().unwrap_or_default();
4990                Self::Top(CssPropertyValue::Exact(start.interpolate(&end, t)))
4991            }
4992            (Self::Right(start), Self::Right(end)) => {
4993                let start = start.get_property().copied().unwrap_or_default();
4994                let end = end.get_property().copied().unwrap_or_default();
4995                Self::Right(CssPropertyValue::Exact(start.interpolate(&end, t)))
4996            }
4997            (Self::Left(start), Self::Left(end)) => {
4998                let start = start.get_property().copied().unwrap_or_default();
4999                let end = end.get_property().copied().unwrap_or_default();
5000                Self::Left(CssPropertyValue::Exact(start.interpolate(&end, t)))
5001            }
5002            (Self::Bottom(start), Self::Bottom(end)) => {
5003                let start = start.get_property().copied().unwrap_or_default();
5004                let end = end.get_property().copied().unwrap_or_default();
5005                Self::Bottom(CssPropertyValue::Exact(start.interpolate(&end, t)))
5006            }
5007            (Self::FlexGrow(start), Self::FlexGrow(end)) => {
5008                let start = start.get_property().copied().unwrap_or_default();
5009                let end = end.get_property().copied().unwrap_or_default();
5010                Self::FlexGrow(CssPropertyValue::Exact(start.interpolate(&end, t)))
5011            }
5012            (Self::FlexShrink(start), Self::FlexShrink(end)) => {
5013                let start = start.get_property().copied().unwrap_or_default();
5014                let end = end.get_property().copied().unwrap_or_default();
5015                Self::FlexShrink(CssPropertyValue::Exact(start.interpolate(&end, t)))
5016            }
5017            (Self::PaddingTop(start), Self::PaddingTop(end)) => {
5018                let start = start.get_property().copied().unwrap_or_default();
5019                let end = end.get_property().copied().unwrap_or_default();
5020                Self::PaddingTop(CssPropertyValue::Exact(start.interpolate(&end, t)))
5021            }
5022            (Self::PaddingLeft(start), Self::PaddingLeft(end)) => {
5023                let start = start.get_property().copied().unwrap_or_default();
5024                let end = end.get_property().copied().unwrap_or_default();
5025                Self::PaddingLeft(CssPropertyValue::Exact(start.interpolate(&end, t)))
5026            }
5027            (Self::PaddingRight(start), Self::PaddingRight(end)) => {
5028                let start = start.get_property().copied().unwrap_or_default();
5029                let end = end.get_property().copied().unwrap_or_default();
5030                Self::PaddingRight(CssPropertyValue::Exact(start.interpolate(&end, t)))
5031            }
5032            (Self::PaddingBottom(start), Self::PaddingBottom(end)) => {
5033                let start = start.get_property().copied().unwrap_or_default();
5034                let end = end.get_property().copied().unwrap_or_default();
5035                Self::PaddingBottom(CssPropertyValue::Exact(start.interpolate(&end, t)))
5036            }
5037            (Self::MarginTop(start), Self::MarginTop(end)) => {
5038                let start = start.get_property().copied().unwrap_or_default();
5039                let end = end.get_property().copied().unwrap_or_default();
5040                Self::MarginTop(CssPropertyValue::Exact(start.interpolate(&end, t)))
5041            }
5042            (Self::MarginLeft(start), Self::MarginLeft(end)) => {
5043                let start = start.get_property().copied().unwrap_or_default();
5044                let end = end.get_property().copied().unwrap_or_default();
5045                Self::MarginLeft(CssPropertyValue::Exact(start.interpolate(&end, t)))
5046            }
5047            (Self::MarginRight(start), Self::MarginRight(end)) => {
5048                let start = start.get_property().copied().unwrap_or_default();
5049                let end = end.get_property().copied().unwrap_or_default();
5050                Self::MarginRight(CssPropertyValue::Exact(start.interpolate(&end, t)))
5051            }
5052            (Self::MarginBottom(start), Self::MarginBottom(end)) => {
5053                let start = start.get_property().copied().unwrap_or_default();
5054                let end = end.get_property().copied().unwrap_or_default();
5055                Self::MarginBottom(CssPropertyValue::Exact(start.interpolate(&end, t)))
5056            }
5057            (Self::BorderTopLeftRadius(start), Self::BorderTopLeftRadius(end)) => {
5058                let start = start.get_property().copied().unwrap_or_default();
5059                let end = end.get_property().copied().unwrap_or_default();
5060                Self::BorderTopLeftRadius(CssPropertyValue::Exact(start.interpolate(&end, t)))
5061            }
5062            (Self::BorderTopRightRadius(start), Self::BorderTopRightRadius(end)) => {
5063                let start = start.get_property().copied().unwrap_or_default();
5064                let end = end.get_property().copied().unwrap_or_default();
5065                Self::BorderTopRightRadius(CssPropertyValue::Exact(start.interpolate(&end, t)))
5066            }
5067            (Self::BorderBottomLeftRadius(start), Self::BorderBottomLeftRadius(end)) => {
5068                let start = start.get_property().copied().unwrap_or_default();
5069                let end = end.get_property().copied().unwrap_or_default();
5070                Self::BorderBottomLeftRadius(CssPropertyValue::Exact(start.interpolate(&end, t)))
5071            }
5072            (Self::BorderBottomRightRadius(start), Self::BorderBottomRightRadius(end)) => {
5073                let start = start.get_property().copied().unwrap_or_default();
5074                let end = end.get_property().copied().unwrap_or_default();
5075                Self::BorderBottomRightRadius(CssPropertyValue::Exact(start.interpolate(&end, t)))
5076            }
5077            (Self::BorderTopColor(start), Self::BorderTopColor(end)) => {
5078                let start = start.get_property().copied().unwrap_or_default();
5079                let end = end.get_property().copied().unwrap_or_default();
5080                Self::BorderTopColor(CssPropertyValue::Exact(start.interpolate(&end, t)))
5081            }
5082            (Self::BorderRightColor(start), Self::BorderRightColor(end)) => {
5083                let start = start.get_property().copied().unwrap_or_default();
5084                let end = end.get_property().copied().unwrap_or_default();
5085                Self::BorderRightColor(CssPropertyValue::Exact(start.interpolate(&end, t)))
5086            }
5087            (Self::BorderLeftColor(start), Self::BorderLeftColor(end)) => {
5088                let start = start.get_property().copied().unwrap_or_default();
5089                let end = end.get_property().copied().unwrap_or_default();
5090                Self::BorderLeftColor(CssPropertyValue::Exact(start.interpolate(&end, t)))
5091            }
5092            (Self::BorderBottomColor(start), Self::BorderBottomColor(end)) => {
5093                let start = start.get_property().copied().unwrap_or_default();
5094                let end = end.get_property().copied().unwrap_or_default();
5095                Self::BorderBottomColor(CssPropertyValue::Exact(start.interpolate(&end, t)))
5096            }
5097            (Self::BorderTopWidth(start), Self::BorderTopWidth(end)) => {
5098                let start = start.get_property().copied().unwrap_or_default();
5099                let end = end.get_property().copied().unwrap_or_default();
5100                Self::BorderTopWidth(CssPropertyValue::Exact(start.interpolate(&end, t)))
5101            }
5102            (Self::BorderRightWidth(start), Self::BorderRightWidth(end)) => {
5103                let start = start.get_property().copied().unwrap_or_default();
5104                let end = end.get_property().copied().unwrap_or_default();
5105                Self::BorderRightWidth(CssPropertyValue::Exact(start.interpolate(&end, t)))
5106            }
5107            (Self::BorderLeftWidth(start), Self::BorderLeftWidth(end)) => {
5108                let start = start.get_property().copied().unwrap_or_default();
5109                let end = end.get_property().copied().unwrap_or_default();
5110                Self::BorderLeftWidth(CssPropertyValue::Exact(start.interpolate(&end, t)))
5111            }
5112            (Self::BorderBottomWidth(start), Self::BorderBottomWidth(end)) => {
5113                let start = start.get_property().copied().unwrap_or_default();
5114                let end = end.get_property().copied().unwrap_or_default();
5115                Self::BorderBottomWidth(CssPropertyValue::Exact(start.interpolate(&end, t)))
5116            }
5117            (Self::Opacity(start), Self::Opacity(end)) => {
5118                let start = start.get_property().copied().unwrap_or_default();
5119                let end = end.get_property().copied().unwrap_or_default();
5120                Self::Opacity(CssPropertyValue::Exact(start.interpolate(&end, t)))
5121            }
5122            (Self::TransformOrigin(start), Self::TransformOrigin(end)) => {
5123                let start = start.get_property().copied().unwrap_or_default();
5124                let end = end.get_property().copied().unwrap_or_default();
5125                Self::TransformOrigin(CssPropertyValue::Exact(start.interpolate(&end, t)))
5126            }
5127            (Self::PerspectiveOrigin(start), Self::PerspectiveOrigin(end)) => {
5128                let start = start.get_property().copied().unwrap_or_default();
5129                let end = end.get_property().copied().unwrap_or_default();
5130                Self::PerspectiveOrigin(CssPropertyValue::Exact(start.interpolate(&end, t)))
5131            }
5132            /*
5133            animate transform:
5134            CssProperty::Transform(CssPropertyValue<StyleTransformVec>),
5135
5136            animate box shadow:
5137            CssProperty::BoxShadowLeft(CssPropertyValue<StyleBoxShadow>),
5138            CssProperty::BoxShadowRight(CssPropertyValue<StyleBoxShadow>),
5139            CssProperty::BoxShadowTop(CssPropertyValue<StyleBoxShadow>),
5140            CssProperty::BoxShadowBottom(CssPropertyValue<StyleBoxShadow>),
5141
5142            animate background:
5143            CssProperty::BackgroundContent(CssPropertyValue<StyleBackgroundContentVec>),
5144            CssProperty::BackgroundPosition(CssPropertyValue<StyleBackgroundPositionVec>),
5145            CssProperty::BackgroundSize(CssPropertyValue<StyleBackgroundSizeVec>),
5146            */
5147            (_, _) => {
5148                // not animatable, fallback
5149                if t > 0.5 {
5150                    other.clone()
5151                } else {
5152                    self.clone()
5153                }
5154            }
5155        }
5156    }
5157
5158    /// Return the type (key) of this property as a statically typed enum
5159    #[allow(clippy::too_many_lines)]
5160    // large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
5161    #[must_use]
5162    pub const fn get_type(&self) -> CssPropertyType {
5163        match &self {
5164            Self::CaretColor(_) => CssPropertyType::CaretColor,
5165            Self::CaretWidth(_) => CssPropertyType::CaretWidth,
5166            Self::CaretAnimationDuration(_) => CssPropertyType::CaretAnimationDuration,
5167            Self::Animation(_) => CssPropertyType::Animation,
5168            Self::AnimationIn(_) => CssPropertyType::AnimationIn,
5169            Self::AnimationOut(_) => CssPropertyType::AnimationOut,
5170            Self::SelectionBackgroundColor(_) => CssPropertyType::SelectionBackgroundColor,
5171            Self::SelectionColor(_) => CssPropertyType::SelectionColor,
5172            Self::SelectionRadius(_) => CssPropertyType::SelectionRadius,
5173
5174            Self::TextJustify(_) => CssPropertyType::TextJustify,
5175            Self::TextColor(_) => CssPropertyType::TextColor,
5176            Self::FontSize(_) => CssPropertyType::FontSize,
5177            Self::FontFamily(_) => CssPropertyType::FontFamily,
5178            Self::FontWeight(_) => CssPropertyType::FontWeight,
5179            Self::FontStyle(_) => CssPropertyType::FontStyle,
5180            Self::TextAlign(_) => CssPropertyType::TextAlign,
5181            Self::VerticalAlign(_) => CssPropertyType::VerticalAlign,
5182            Self::LetterSpacing(_) => CssPropertyType::LetterSpacing,
5183            Self::TextIndent(_) => CssPropertyType::TextIndent,
5184            Self::InitialLetter(_) => CssPropertyType::InitialLetter,
5185            Self::LineClamp(_) => CssPropertyType::LineClamp,
5186            Self::HangingPunctuation(_) => CssPropertyType::HangingPunctuation,
5187            Self::TextCombineUpright(_) => CssPropertyType::TextCombineUpright,
5188            Self::UnicodeBidi(_) => CssPropertyType::UnicodeBidi,
5189            Self::TextBoxTrim(_) => CssPropertyType::TextBoxTrim,
5190            Self::TextBoxEdge(_) => CssPropertyType::TextBoxEdge,
5191            Self::DominantBaseline(_) => CssPropertyType::DominantBaseline,
5192            Self::AlignmentBaseline(_) => CssPropertyType::AlignmentBaseline,
5193            Self::BaselineSource(_) => CssPropertyType::BaselineSource,
5194            Self::LineFitEdge(_) => CssPropertyType::LineFitEdge,
5195            Self::InitialLetterAlign(_) => CssPropertyType::InitialLetterAlign,
5196            Self::InitialLetterWrap(_) => CssPropertyType::InitialLetterWrap,
5197            Self::ScrollbarGutter(_) => CssPropertyType::ScrollbarGutter,
5198            Self::OverflowClipMargin(_) => CssPropertyType::OverflowClipMargin,
5199            Self::Clip(_) => CssPropertyType::Clip,
5200            Self::ExclusionMargin(_) => CssPropertyType::ExclusionMargin,
5201            Self::HyphenationLanguage(_) => CssPropertyType::HyphenationLanguage,
5202            Self::LineHeight(_) => CssPropertyType::LineHeight,
5203            Self::WordSpacing(_) => CssPropertyType::WordSpacing,
5204            Self::TabSize(_) => CssPropertyType::TabSize,
5205            Self::Cursor(_) => CssPropertyType::Cursor,
5206            Self::Display(_) => CssPropertyType::Display,
5207            Self::Float(_) => CssPropertyType::Float,
5208            Self::BoxSizing(_) => CssPropertyType::BoxSizing,
5209            Self::Width(_) => CssPropertyType::Width,
5210            Self::Height(_) => CssPropertyType::Height,
5211            Self::MinWidth(_) => CssPropertyType::MinWidth,
5212            Self::MinHeight(_) => CssPropertyType::MinHeight,
5213            Self::MaxWidth(_) => CssPropertyType::MaxWidth,
5214            Self::MaxHeight(_) => CssPropertyType::MaxHeight,
5215            Self::Position(_) => CssPropertyType::Position,
5216            Self::Top(_) => CssPropertyType::Top,
5217            Self::Right(_) => CssPropertyType::Right,
5218            Self::Left(_) => CssPropertyType::Left,
5219            Self::Bottom(_) => CssPropertyType::Bottom,
5220            Self::ZIndex(_) => CssPropertyType::ZIndex,
5221            Self::FlexWrap(_) => CssPropertyType::FlexWrap,
5222            Self::FlexDirection(_) => CssPropertyType::FlexDirection,
5223            Self::FlexGrow(_) => CssPropertyType::FlexGrow,
5224            Self::FlexShrink(_) => CssPropertyType::FlexShrink,
5225            Self::FlexBasis(_) => CssPropertyType::FlexBasis,
5226            Self::JustifyContent(_) => CssPropertyType::JustifyContent,
5227            Self::AlignItems(_) => CssPropertyType::AlignItems,
5228            Self::AlignContent(_) => CssPropertyType::AlignContent,
5229            Self::ColumnGap(_) => CssPropertyType::ColumnGap,
5230            Self::RowGap(_) => CssPropertyType::RowGap,
5231            Self::GridTemplateColumns(_) => CssPropertyType::GridTemplateColumns,
5232            Self::GridTemplateRows(_) => CssPropertyType::GridTemplateRows,
5233            Self::GridAutoColumns(_) => CssPropertyType::GridAutoColumns,
5234            Self::GridAutoRows(_) => CssPropertyType::GridAutoRows,
5235            Self::GridColumn(_) => CssPropertyType::GridColumn,
5236            Self::GridAutoFlow(_) => CssPropertyType::GridAutoFlow,
5237            Self::JustifySelf(_) => CssPropertyType::JustifySelf,
5238            Self::JustifyItems(_) => CssPropertyType::JustifyItems,
5239            Self::Gap(_) => CssPropertyType::Gap,
5240            Self::GridGap(_) => CssPropertyType::GridGap,
5241            Self::AlignSelf(_) => CssPropertyType::AlignSelf,
5242            Self::Font(_) => CssPropertyType::Font,
5243            Self::GridRow(_) => CssPropertyType::GridRow,
5244            Self::GridTemplateAreas(_) => CssPropertyType::GridTemplateAreas,
5245            Self::WritingMode(_) => CssPropertyType::WritingMode,
5246            Self::Clear(_) => CssPropertyType::Clear,
5247            Self::BackgroundContent(_) => CssPropertyType::BackgroundContent,
5248            Self::BackgroundPosition(_) => CssPropertyType::BackgroundPosition,
5249            Self::BackgroundSize(_) => CssPropertyType::BackgroundSize,
5250            Self::BackgroundRepeat(_) => CssPropertyType::BackgroundRepeat,
5251            Self::OverflowX(_) => CssPropertyType::OverflowX,
5252            Self::OverflowY(_) => CssPropertyType::OverflowY,
5253            Self::OverflowBlock(_) => CssPropertyType::OverflowBlock,
5254            Self::OverflowInline(_) => CssPropertyType::OverflowInline,
5255            Self::PaddingTop(_) => CssPropertyType::PaddingTop,
5256            Self::PaddingLeft(_) => CssPropertyType::PaddingLeft,
5257            Self::PaddingRight(_) => CssPropertyType::PaddingRight,
5258            Self::PaddingBottom(_) => CssPropertyType::PaddingBottom,
5259            Self::PaddingInlineStart(_) => CssPropertyType::PaddingInlineStart,
5260            Self::PaddingInlineEnd(_) => CssPropertyType::PaddingInlineEnd,
5261            Self::MarginTop(_) => CssPropertyType::MarginTop,
5262            Self::MarginLeft(_) => CssPropertyType::MarginLeft,
5263            Self::MarginRight(_) => CssPropertyType::MarginRight,
5264            Self::MarginBottom(_) => CssPropertyType::MarginBottom,
5265            Self::BorderTopLeftRadius(_) => CssPropertyType::BorderTopLeftRadius,
5266            Self::BorderTopRightRadius(_) => CssPropertyType::BorderTopRightRadius,
5267            Self::BorderBottomLeftRadius(_) => CssPropertyType::BorderBottomLeftRadius,
5268            Self::BorderBottomRightRadius(_) => CssPropertyType::BorderBottomRightRadius,
5269            Self::BorderTopColor(_) => CssPropertyType::BorderTopColor,
5270            Self::BorderRightColor(_) => CssPropertyType::BorderRightColor,
5271            Self::BorderLeftColor(_) => CssPropertyType::BorderLeftColor,
5272            Self::BorderBottomColor(_) => CssPropertyType::BorderBottomColor,
5273            Self::BorderTopStyle(_) => CssPropertyType::BorderTopStyle,
5274            Self::BorderRightStyle(_) => CssPropertyType::BorderRightStyle,
5275            Self::BorderLeftStyle(_) => CssPropertyType::BorderLeftStyle,
5276            Self::BorderBottomStyle(_) => CssPropertyType::BorderBottomStyle,
5277            Self::BorderTopWidth(_) => CssPropertyType::BorderTopWidth,
5278            Self::BorderRightWidth(_) => CssPropertyType::BorderRightWidth,
5279            Self::BorderLeftWidth(_) => CssPropertyType::BorderLeftWidth,
5280            Self::BorderBottomWidth(_) => CssPropertyType::BorderBottomWidth,
5281            Self::BoxShadowLeft(_) => CssPropertyType::BoxShadowLeft,
5282            Self::BoxShadowRight(_) => CssPropertyType::BoxShadowRight,
5283            Self::BoxShadowTop(_) => CssPropertyType::BoxShadowTop,
5284            Self::BoxShadowBottom(_) => CssPropertyType::BoxShadowBottom,
5285            Self::ScrollbarTrack(_) => CssPropertyType::ScrollbarTrack,
5286            Self::ScrollbarThumb(_) => CssPropertyType::ScrollbarThumb,
5287            Self::ScrollbarButton(_) => CssPropertyType::ScrollbarButton,
5288            Self::ScrollbarCorner(_) => CssPropertyType::ScrollbarCorner,
5289            Self::ScrollbarResizer(_) => CssPropertyType::ScrollbarResizer,
5290            Self::ScrollbarWidth(_) => CssPropertyType::ScrollbarWidth,
5291            Self::OverscrollBehaviorX(_) => CssPropertyType::OverscrollBehaviorX,
5292            Self::OverscrollBehaviorY(_) => CssPropertyType::OverscrollBehaviorY,
5293            Self::ScrollbarColor(_) => CssPropertyType::ScrollbarColor,
5294            Self::ScrollbarVisibility(_) => CssPropertyType::ScrollbarVisibility,
5295            Self::ScrollbarFadeDelay(_) => CssPropertyType::ScrollbarFadeDelay,
5296            Self::ScrollbarFadeDuration(_) => CssPropertyType::ScrollbarFadeDuration,
5297            Self::Opacity(_) => CssPropertyType::Opacity,
5298            Self::Visibility(_) => CssPropertyType::Visibility,
5299            Self::Transform(_) => CssPropertyType::Transform,
5300            Self::PerspectiveOrigin(_) => CssPropertyType::PerspectiveOrigin,
5301            Self::TransformOrigin(_) => CssPropertyType::TransformOrigin,
5302            Self::BackfaceVisibility(_) => CssPropertyType::BackfaceVisibility,
5303            Self::AppRegion(_) => CssPropertyType::AppRegion,
5304            Self::SpatialNavigationAction(_) => CssPropertyType::SpatialNavigationAction,
5305            Self::SpatialNavigationContain(_) => CssPropertyType::SpatialNavigationContain,
5306            Self::MixBlendMode(_) => CssPropertyType::MixBlendMode,
5307            Self::Filter(_) => CssPropertyType::Filter,
5308            Self::BackdropFilter(_) => CssPropertyType::BackdropFilter,
5309            Self::TextShadow(_) => CssPropertyType::TextShadow,
5310            Self::WhiteSpace(_) => CssPropertyType::WhiteSpace,
5311            Self::Hyphens(_) => CssPropertyType::Hyphens,
5312            Self::WordBreak(_) => CssPropertyType::WordBreak,
5313            Self::OverflowWrap(_) => CssPropertyType::OverflowWrap,
5314            Self::LineBreak(_) => CssPropertyType::LineBreak,
5315            Self::TextOverflow(_) => CssPropertyType::TextOverflow,
5316            Self::ObjectFit(_) => CssPropertyType::ObjectFit,
5317            Self::ObjectPosition(_) => CssPropertyType::ObjectPosition,
5318            Self::AspectRatio(_) => CssPropertyType::AspectRatio,
5319            Self::TextOrientation(_) => CssPropertyType::TextOrientation,
5320            Self::TextAlignLast(_) => CssPropertyType::TextAlignLast,
5321            Self::TextTransform(_) => CssPropertyType::TextTransform,
5322            Self::Direction(_) => CssPropertyType::Direction,
5323            Self::UserSelect(_) => CssPropertyType::UserSelect,
5324            Self::TextDecoration(_) => CssPropertyType::TextDecoration,
5325            Self::BreakBefore(_) => CssPropertyType::BreakBefore,
5326            Self::BreakAfter(_) => CssPropertyType::BreakAfter,
5327            Self::BreakInside(_) => CssPropertyType::BreakInside,
5328            Self::Orphans(_) => CssPropertyType::Orphans,
5329            Self::Widows(_) => CssPropertyType::Widows,
5330            Self::BoxDecorationBreak(_) => CssPropertyType::BoxDecorationBreak,
5331            Self::ColumnCount(_) => CssPropertyType::ColumnCount,
5332            Self::ColumnWidth(_) => CssPropertyType::ColumnWidth,
5333            Self::ColumnSpan(_) => CssPropertyType::ColumnSpan,
5334            Self::ColumnFill(_) => CssPropertyType::ColumnFill,
5335            Self::ColumnRuleWidth(_) => CssPropertyType::ColumnRuleWidth,
5336            Self::ColumnRuleStyle(_) => CssPropertyType::ColumnRuleStyle,
5337            Self::ColumnRuleColor(_) => CssPropertyType::ColumnRuleColor,
5338            Self::FlowInto(_) => CssPropertyType::FlowInto,
5339            Self::FlowFrom(_) => CssPropertyType::FlowFrom,
5340            Self::ShapeOutside(_) => CssPropertyType::ShapeOutside,
5341            Self::ShapeInside(_) => CssPropertyType::ShapeInside,
5342            Self::ClipPath(_) => CssPropertyType::ClipPath,
5343            Self::ShapeMargin(_) => CssPropertyType::ShapeMargin,
5344            Self::ShapeImageThreshold(_) => CssPropertyType::ShapeImageThreshold,
5345            Self::Content(_) => CssPropertyType::Content,
5346            Self::CounterReset(_) => CssPropertyType::CounterReset,
5347            Self::CounterIncrement(_) => CssPropertyType::CounterIncrement,
5348            Self::ListStyleType(_) => CssPropertyType::ListStyleType,
5349            Self::ListStylePosition(_) => CssPropertyType::ListStylePosition,
5350            Self::StringSet(_) => CssPropertyType::StringSet,
5351            Self::TableLayout(_) => CssPropertyType::TableLayout,
5352            Self::BorderCollapse(_) => CssPropertyType::BorderCollapse,
5353            Self::BorderSpacing(_) => CssPropertyType::BorderSpacing,
5354            Self::CaptionSide(_) => CssPropertyType::CaptionSide,
5355            Self::EmptyCells(_) => CssPropertyType::EmptyCells,
5356        }
5357    }
5358
5359    // const constructors for easier API access
5360
5361    #[must_use]
5362    pub const fn none(prop_type: CssPropertyType) -> Self {
5363        css_property_from_type!(prop_type, None)
5364    }
5365    #[must_use]
5366    pub const fn auto(prop_type: CssPropertyType) -> Self {
5367        css_property_from_type!(prop_type, Auto)
5368    }
5369    #[must_use]
5370    pub const fn initial(prop_type: CssPropertyType) -> Self {
5371        css_property_from_type!(prop_type, Initial)
5372    }
5373    #[must_use]
5374    pub const fn inherit(prop_type: CssPropertyType) -> Self {
5375        css_property_from_type!(prop_type, Inherit)
5376    }
5377
5378    #[must_use]
5379    pub const fn text_color(input: StyleTextColor) -> Self {
5380        Self::TextColor(CssPropertyValue::Exact(input))
5381    }
5382    #[must_use]
5383    pub const fn font_size(input: StyleFontSize) -> Self {
5384        Self::FontSize(CssPropertyValue::Exact(input))
5385    }
5386    #[must_use]
5387    pub const fn font_family(input: StyleFontFamilyVec) -> Self {
5388        Self::FontFamily(CssPropertyValue::Exact(input))
5389    }
5390    #[must_use]
5391    pub const fn font_weight(input: StyleFontWeight) -> Self {
5392        Self::FontWeight(CssPropertyValue::Exact(input))
5393    }
5394    #[must_use]
5395    pub const fn font_style(input: StyleFontStyle) -> Self {
5396        Self::FontStyle(CssPropertyValue::Exact(input))
5397    }
5398    #[must_use]
5399    pub const fn text_align(input: StyleTextAlign) -> Self {
5400        Self::TextAlign(CssPropertyValue::Exact(input))
5401    }
5402    #[must_use]
5403    pub const fn text_justify(input: LayoutTextJustify) -> Self {
5404        Self::TextJustify(CssPropertyValue::Exact(input))
5405    }
5406    #[must_use]
5407    pub const fn vertical_align(input: StyleVerticalAlign) -> Self {
5408        Self::VerticalAlign(CssPropertyValue::Exact(input))
5409    }
5410    #[must_use]
5411    pub const fn letter_spacing(input: StyleLetterSpacing) -> Self {
5412        Self::LetterSpacing(CssPropertyValue::Exact(input))
5413    }
5414    #[must_use]
5415    pub const fn text_indent(input: StyleTextIndent) -> Self {
5416        Self::TextIndent(CssPropertyValue::Exact(input))
5417    }
5418    #[must_use]
5419    pub const fn line_height(input: StyleLineHeight) -> Self {
5420        Self::LineHeight(CssPropertyValue::Exact(input))
5421    }
5422    #[must_use]
5423    pub const fn word_spacing(input: StyleWordSpacing) -> Self {
5424        Self::WordSpacing(CssPropertyValue::Exact(input))
5425    }
5426    #[must_use]
5427    pub const fn tab_size(input: StyleTabSize) -> Self {
5428        Self::TabSize(CssPropertyValue::Exact(input))
5429    }
5430    #[must_use]
5431    pub const fn cursor(input: StyleCursor) -> Self {
5432        Self::Cursor(CssPropertyValue::Exact(input))
5433    }
5434    #[must_use]
5435    pub const fn user_select(input: StyleUserSelect) -> Self {
5436        Self::UserSelect(CssPropertyValue::Exact(input))
5437    }
5438    #[must_use]
5439    pub const fn text_decoration(input: StyleTextDecoration) -> Self {
5440        Self::TextDecoration(CssPropertyValue::Exact(input))
5441    }
5442    #[must_use]
5443    pub const fn display(input: LayoutDisplay) -> Self {
5444        Self::Display(CssPropertyValue::Exact(input))
5445    }
5446    #[must_use]
5447    pub const fn box_sizing(input: LayoutBoxSizing) -> Self {
5448        Self::BoxSizing(CssPropertyValue::Exact(input))
5449    }
5450    #[must_use]
5451    pub const fn width(input: LayoutWidth) -> Self {
5452        Self::Width(CssPropertyValue::Exact(input))
5453    }
5454    #[must_use]
5455    pub const fn height(input: LayoutHeight) -> Self {
5456        Self::Height(CssPropertyValue::Exact(input))
5457    }
5458    #[must_use]
5459    pub const fn min_width(input: LayoutMinWidth) -> Self {
5460        Self::MinWidth(CssPropertyValue::Exact(input))
5461    }
5462    #[must_use]
5463    pub const fn caret_color(input: CaretColor) -> Self {
5464        Self::CaretColor(CssPropertyValue::Exact(input))
5465    }
5466    #[must_use]
5467    pub const fn caret_width(input: CaretWidth) -> Self {
5468        Self::CaretWidth(CssPropertyValue::Exact(input))
5469    }
5470    #[must_use]
5471    pub const fn caret_animation_duration(input: CaretAnimationDuration) -> Self {
5472        Self::CaretAnimationDuration(CssPropertyValue::Exact(input))
5473    }
5474    #[must_use]
5475    pub const fn selection_background_color(input: SelectionBackgroundColor) -> Self {
5476        Self::SelectionBackgroundColor(CssPropertyValue::Exact(input))
5477    }
5478    #[must_use]
5479    pub const fn selection_color(input: SelectionColor) -> Self {
5480        Self::SelectionColor(CssPropertyValue::Exact(input))
5481    }
5482    #[must_use]
5483    pub const fn min_height(input: LayoutMinHeight) -> Self {
5484        Self::MinHeight(CssPropertyValue::Exact(input))
5485    }
5486    #[must_use]
5487    pub const fn max_width(input: LayoutMaxWidth) -> Self {
5488        Self::MaxWidth(CssPropertyValue::Exact(input))
5489    }
5490    #[must_use]
5491    pub const fn max_height(input: LayoutMaxHeight) -> Self {
5492        Self::MaxHeight(CssPropertyValue::Exact(input))
5493    }
5494    #[must_use]
5495    pub const fn position(input: LayoutPosition) -> Self {
5496        Self::Position(CssPropertyValue::Exact(input))
5497    }
5498    #[must_use]
5499    pub const fn top(input: LayoutTop) -> Self {
5500        Self::Top(CssPropertyValue::Exact(input))
5501    }
5502    #[must_use]
5503    pub const fn right(input: LayoutRight) -> Self {
5504        Self::Right(CssPropertyValue::Exact(input))
5505    }
5506    #[must_use]
5507    pub const fn left(input: LayoutLeft) -> Self {
5508        Self::Left(CssPropertyValue::Exact(input))
5509    }
5510    #[must_use]
5511    pub const fn bottom(input: LayoutInsetBottom) -> Self {
5512        Self::Bottom(CssPropertyValue::Exact(input))
5513    }
5514    #[must_use]
5515    pub const fn z_index(input: LayoutZIndex) -> Self {
5516        Self::ZIndex(CssPropertyValue::Exact(input))
5517    }
5518    #[must_use]
5519    pub const fn flex_wrap(input: LayoutFlexWrap) -> Self {
5520        Self::FlexWrap(CssPropertyValue::Exact(input))
5521    }
5522    #[must_use]
5523    pub const fn flex_direction(input: LayoutFlexDirection) -> Self {
5524        Self::FlexDirection(CssPropertyValue::Exact(input))
5525    }
5526    #[must_use]
5527    pub const fn flex_grow(input: LayoutFlexGrow) -> Self {
5528        Self::FlexGrow(CssPropertyValue::Exact(input))
5529    }
5530    #[must_use]
5531    pub const fn flex_shrink(input: LayoutFlexShrink) -> Self {
5532        Self::FlexShrink(CssPropertyValue::Exact(input))
5533    }
5534    #[must_use]
5535    pub const fn justify_content(input: LayoutJustifyContent) -> Self {
5536        Self::JustifyContent(CssPropertyValue::Exact(input))
5537    }
5538    #[must_use]
5539    pub const fn grid_auto_flow(input: LayoutGridAutoFlow) -> Self {
5540        Self::GridAutoFlow(CssPropertyValue::Exact(input))
5541    }
5542    #[must_use]
5543    pub const fn justify_self(input: LayoutJustifySelf) -> Self {
5544        Self::JustifySelf(CssPropertyValue::Exact(input))
5545    }
5546    #[must_use]
5547    pub const fn justify_items(input: LayoutJustifyItems) -> Self {
5548        Self::JustifyItems(CssPropertyValue::Exact(input))
5549    }
5550    #[must_use]
5551    pub const fn gap(input: LayoutGap) -> Self {
5552        Self::Gap(CssPropertyValue::Exact(input))
5553    }
5554    #[must_use]
5555    pub const fn grid_gap(input: LayoutGap) -> Self {
5556        Self::GridGap(CssPropertyValue::Exact(input))
5557    }
5558    #[must_use]
5559    pub const fn align_self(input: LayoutAlignSelf) -> Self {
5560        Self::AlignSelf(CssPropertyValue::Exact(input))
5561    }
5562    #[must_use]
5563    pub const fn font(input: StyleFontFamilyVec) -> Self {
5564        Self::Font(StyleFontValue::Exact(input))
5565    }
5566    #[must_use]
5567    pub const fn align_items(input: LayoutAlignItems) -> Self {
5568        Self::AlignItems(CssPropertyValue::Exact(input))
5569    }
5570    #[must_use]
5571    pub const fn align_content(input: LayoutAlignContent) -> Self {
5572        Self::AlignContent(CssPropertyValue::Exact(input))
5573    }
5574    #[must_use]
5575    pub const fn background_content(input: StyleBackgroundContentVec) -> Self {
5576        Self::BackgroundContent(CssPropertyValue::Exact(input))
5577    }
5578    #[must_use]
5579    pub const fn background_position(input: StyleBackgroundPositionVec) -> Self {
5580        Self::BackgroundPosition(CssPropertyValue::Exact(input))
5581    }
5582    #[must_use]
5583    pub const fn background_size(input: StyleBackgroundSizeVec) -> Self {
5584        Self::BackgroundSize(CssPropertyValue::Exact(input))
5585    }
5586    #[must_use]
5587    pub const fn background_repeat(input: StyleBackgroundRepeatVec) -> Self {
5588        Self::BackgroundRepeat(CssPropertyValue::Exact(input))
5589    }
5590    #[must_use]
5591    pub const fn overflow_x(input: LayoutOverflow) -> Self {
5592        Self::OverflowX(CssPropertyValue::Exact(input))
5593    }
5594    #[must_use]
5595    pub const fn overflow_y(input: LayoutOverflow) -> Self {
5596        Self::OverflowY(CssPropertyValue::Exact(input))
5597    }
5598    #[must_use]
5599    pub const fn overflow_block(input: LayoutOverflow) -> Self {
5600        Self::OverflowBlock(CssPropertyValue::Exact(input))
5601    }
5602    #[must_use]
5603    pub const fn overflow_inline(input: LayoutOverflow) -> Self {
5604        Self::OverflowInline(CssPropertyValue::Exact(input))
5605    }
5606    #[must_use]
5607    pub const fn padding_top(input: LayoutPaddingTop) -> Self {
5608        Self::PaddingTop(CssPropertyValue::Exact(input))
5609    }
5610    #[must_use]
5611    pub const fn padding_left(input: LayoutPaddingLeft) -> Self {
5612        Self::PaddingLeft(CssPropertyValue::Exact(input))
5613    }
5614    #[must_use]
5615    pub const fn padding_right(input: LayoutPaddingRight) -> Self {
5616        Self::PaddingRight(CssPropertyValue::Exact(input))
5617    }
5618    #[must_use]
5619    pub const fn padding_bottom(input: LayoutPaddingBottom) -> Self {
5620        Self::PaddingBottom(CssPropertyValue::Exact(input))
5621    }
5622    #[must_use]
5623    pub const fn margin_top(input: LayoutMarginTop) -> Self {
5624        Self::MarginTop(CssPropertyValue::Exact(input))
5625    }
5626    #[must_use]
5627    pub const fn margin_left(input: LayoutMarginLeft) -> Self {
5628        Self::MarginLeft(CssPropertyValue::Exact(input))
5629    }
5630    #[must_use]
5631    pub const fn margin_right(input: LayoutMarginRight) -> Self {
5632        Self::MarginRight(CssPropertyValue::Exact(input))
5633    }
5634    #[must_use]
5635    pub const fn margin_bottom(input: LayoutMarginBottom) -> Self {
5636        Self::MarginBottom(CssPropertyValue::Exact(input))
5637    }
5638    #[must_use]
5639    pub const fn border_top_left_radius(input: StyleBorderTopLeftRadius) -> Self {
5640        Self::BorderTopLeftRadius(CssPropertyValue::Exact(input))
5641    }
5642    #[must_use]
5643    pub const fn border_top_right_radius(input: StyleBorderTopRightRadius) -> Self {
5644        Self::BorderTopRightRadius(CssPropertyValue::Exact(input))
5645    }
5646    #[must_use]
5647    pub const fn border_bottom_left_radius(input: StyleBorderBottomLeftRadius) -> Self {
5648        Self::BorderBottomLeftRadius(CssPropertyValue::Exact(input))
5649    }
5650    #[must_use]
5651    pub const fn border_bottom_right_radius(input: StyleBorderBottomRightRadius) -> Self {
5652        Self::BorderBottomRightRadius(CssPropertyValue::Exact(input))
5653    }
5654    #[must_use]
5655    pub const fn border_top_color(input: StyleBorderTopColor) -> Self {
5656        Self::BorderTopColor(CssPropertyValue::Exact(input))
5657    }
5658    #[must_use]
5659    pub const fn border_right_color(input: StyleBorderRightColor) -> Self {
5660        Self::BorderRightColor(CssPropertyValue::Exact(input))
5661    }
5662    #[must_use]
5663    pub const fn border_left_color(input: StyleBorderLeftColor) -> Self {
5664        Self::BorderLeftColor(CssPropertyValue::Exact(input))
5665    }
5666    #[must_use]
5667    pub const fn border_bottom_color(input: StyleBorderBottomColor) -> Self {
5668        Self::BorderBottomColor(CssPropertyValue::Exact(input))
5669    }
5670    #[must_use]
5671    pub const fn border_top_style(input: StyleBorderTopStyle) -> Self {
5672        Self::BorderTopStyle(CssPropertyValue::Exact(input))
5673    }
5674    #[must_use]
5675    pub const fn border_right_style(input: StyleBorderRightStyle) -> Self {
5676        Self::BorderRightStyle(CssPropertyValue::Exact(input))
5677    }
5678    #[must_use]
5679    pub const fn border_left_style(input: StyleBorderLeftStyle) -> Self {
5680        Self::BorderLeftStyle(CssPropertyValue::Exact(input))
5681    }
5682    #[must_use]
5683    pub const fn border_bottom_style(input: StyleBorderBottomStyle) -> Self {
5684        Self::BorderBottomStyle(CssPropertyValue::Exact(input))
5685    }
5686    #[must_use]
5687    pub const fn border_top_width(input: LayoutBorderTopWidth) -> Self {
5688        Self::BorderTopWidth(CssPropertyValue::Exact(input))
5689    }
5690    #[must_use]
5691    pub const fn border_right_width(input: LayoutBorderRightWidth) -> Self {
5692        Self::BorderRightWidth(CssPropertyValue::Exact(input))
5693    }
5694    #[must_use]
5695    pub const fn border_left_width(input: LayoutBorderLeftWidth) -> Self {
5696        Self::BorderLeftWidth(CssPropertyValue::Exact(input))
5697    }
5698    #[must_use]
5699    pub const fn border_bottom_width(input: LayoutBorderBottomWidth) -> Self {
5700        Self::BorderBottomWidth(CssPropertyValue::Exact(input))
5701    }
5702    #[must_use]
5703    pub fn box_shadow_left(input: StyleBoxShadow) -> Self {
5704        Self::BoxShadowLeft(CssPropertyValue::Exact(BoxOrStatic::heap(input)))
5705    }
5706    #[must_use]
5707    pub fn box_shadow_right(input: StyleBoxShadow) -> Self {
5708        Self::BoxShadowRight(CssPropertyValue::Exact(BoxOrStatic::heap(input)))
5709    }
5710    #[must_use]
5711    pub fn box_shadow_top(input: StyleBoxShadow) -> Self {
5712        Self::BoxShadowTop(CssPropertyValue::Exact(BoxOrStatic::heap(input)))
5713    }
5714    #[must_use]
5715    pub fn box_shadow_bottom(input: StyleBoxShadow) -> Self {
5716        Self::BoxShadowBottom(CssPropertyValue::Exact(BoxOrStatic::heap(input)))
5717    }
5718    #[must_use]
5719    pub const fn opacity(input: StyleOpacity) -> Self {
5720        Self::Opacity(CssPropertyValue::Exact(input))
5721    }
5722    #[must_use]
5723    pub const fn visibility(input: StyleVisibility) -> Self {
5724        Self::Visibility(CssPropertyValue::Exact(input))
5725    }
5726    #[must_use]
5727    pub const fn transform(input: StyleTransformVec) -> Self {
5728        Self::Transform(CssPropertyValue::Exact(input))
5729    }
5730    #[must_use]
5731    pub const fn transform_origin(input: StyleTransformOrigin) -> Self {
5732        Self::TransformOrigin(CssPropertyValue::Exact(input))
5733    }
5734    #[must_use]
5735    pub const fn perspective_origin(input: StylePerspectiveOrigin) -> Self {
5736        Self::PerspectiveOrigin(CssPropertyValue::Exact(input))
5737    }
5738    #[must_use]
5739    pub const fn backface_visibility(input: StyleBackfaceVisibility) -> Self {
5740        Self::BackfaceVisibility(CssPropertyValue::Exact(input))
5741    }
5742
5743    // New DTP const fn constructors
5744    #[must_use]
5745    pub const fn break_before(input: PageBreak) -> Self {
5746        Self::BreakBefore(CssPropertyValue::Exact(input))
5747    }
5748    #[must_use]
5749    pub const fn break_after(input: PageBreak) -> Self {
5750        Self::BreakAfter(CssPropertyValue::Exact(input))
5751    }
5752    #[must_use]
5753    pub const fn break_inside(input: BreakInside) -> Self {
5754        Self::BreakInside(CssPropertyValue::Exact(input))
5755    }
5756    #[must_use]
5757    pub const fn orphans(input: Orphans) -> Self {
5758        Self::Orphans(CssPropertyValue::Exact(input))
5759    }
5760    #[must_use]
5761    pub const fn widows(input: Widows) -> Self {
5762        Self::Widows(CssPropertyValue::Exact(input))
5763    }
5764    #[must_use]
5765    pub const fn box_decoration_break(input: BoxDecorationBreak) -> Self {
5766        Self::BoxDecorationBreak(CssPropertyValue::Exact(input))
5767    }
5768    #[must_use]
5769    pub const fn column_count(input: ColumnCount) -> Self {
5770        Self::ColumnCount(CssPropertyValue::Exact(input))
5771    }
5772    #[must_use]
5773    pub const fn column_width(input: ColumnWidth) -> Self {
5774        Self::ColumnWidth(CssPropertyValue::Exact(input))
5775    }
5776    #[must_use]
5777    pub const fn column_span(input: ColumnSpan) -> Self {
5778        Self::ColumnSpan(CssPropertyValue::Exact(input))
5779    }
5780    #[must_use]
5781    pub const fn column_fill(input: ColumnFill) -> Self {
5782        Self::ColumnFill(CssPropertyValue::Exact(input))
5783    }
5784    #[must_use]
5785    pub const fn column_rule_width(input: ColumnRuleWidth) -> Self {
5786        Self::ColumnRuleWidth(CssPropertyValue::Exact(input))
5787    }
5788    #[must_use]
5789    pub const fn column_rule_style(input: ColumnRuleStyle) -> Self {
5790        Self::ColumnRuleStyle(CssPropertyValue::Exact(input))
5791    }
5792    #[must_use]
5793    pub const fn column_rule_color(input: ColumnRuleColor) -> Self {
5794        Self::ColumnRuleColor(CssPropertyValue::Exact(input))
5795    }
5796    #[must_use]
5797    pub const fn flow_into(input: FlowInto) -> Self {
5798        Self::FlowInto(CssPropertyValue::Exact(input))
5799    }
5800    #[must_use]
5801    pub const fn flow_from(input: FlowFrom) -> Self {
5802        Self::FlowFrom(CssPropertyValue::Exact(input))
5803    }
5804    #[must_use]
5805    pub const fn shape_outside(input: ShapeOutside) -> Self {
5806        Self::ShapeOutside(CssPropertyValue::Exact(input))
5807    }
5808    #[must_use]
5809    pub const fn shape_inside(input: ShapeInside) -> Self {
5810        Self::ShapeInside(CssPropertyValue::Exact(input))
5811    }
5812    #[must_use]
5813    pub const fn clip_path(input: ClipPath) -> Self {
5814        Self::ClipPath(CssPropertyValue::Exact(input))
5815    }
5816    #[must_use]
5817    pub const fn shape_margin(input: ShapeMargin) -> Self {
5818        Self::ShapeMargin(CssPropertyValue::Exact(input))
5819    }
5820    #[must_use]
5821    pub const fn shape_image_threshold(input: ShapeImageThreshold) -> Self {
5822        Self::ShapeImageThreshold(CssPropertyValue::Exact(input))
5823    }
5824    #[must_use]
5825    pub const fn content(input: Content) -> Self {
5826        Self::Content(CssPropertyValue::Exact(input))
5827    }
5828    #[must_use]
5829    pub const fn counter_reset(input: CounterReset) -> Self {
5830        Self::CounterReset(CssPropertyValue::Exact(input))
5831    }
5832    #[must_use]
5833    pub const fn counter_increment(input: CounterIncrement) -> Self {
5834        Self::CounterIncrement(CssPropertyValue::Exact(input))
5835    }
5836    #[must_use]
5837    pub const fn list_style_type(input: StyleListStyleType) -> Self {
5838        Self::ListStyleType(CssPropertyValue::Exact(input))
5839    }
5840    #[must_use]
5841    pub const fn list_style_position(input: StyleListStylePosition) -> Self {
5842        Self::ListStylePosition(CssPropertyValue::Exact(input))
5843    }
5844    #[must_use]
5845    pub const fn string_set(input: StringSet) -> Self {
5846        Self::StringSet(CssPropertyValue::Exact(input))
5847    }
5848    #[must_use]
5849    pub const fn table_layout(input: LayoutTableLayout) -> Self {
5850        Self::TableLayout(CssPropertyValue::Exact(input))
5851    }
5852    #[must_use]
5853    pub const fn border_collapse(input: StyleBorderCollapse) -> Self {
5854        Self::BorderCollapse(CssPropertyValue::Exact(input))
5855    }
5856    #[must_use]
5857    pub const fn border_spacing(input: LayoutBorderSpacing) -> Self {
5858        Self::BorderSpacing(CssPropertyValue::Exact(input))
5859    }
5860    #[must_use]
5861    pub const fn caption_side(input: StyleCaptionSide) -> Self {
5862        Self::CaptionSide(CssPropertyValue::Exact(input))
5863    }
5864    #[must_use]
5865    pub const fn empty_cells(input: StyleEmptyCells) -> Self {
5866        Self::EmptyCells(CssPropertyValue::Exact(input))
5867    }
5868
5869    #[must_use]
5870    pub const fn as_z_index(&self) -> Option<&LayoutZIndexValue> {
5871        match self {
5872            Self::ZIndex(f) => Some(f),
5873            _ => None,
5874        }
5875    }
5876
5877    #[must_use]
5878    pub const fn as_flex_basis(&self) -> Option<&LayoutFlexBasisValue> {
5879        match self {
5880            Self::FlexBasis(f) => Some(f),
5881            _ => None,
5882        }
5883    }
5884
5885    #[must_use]
5886    pub const fn as_column_gap(&self) -> Option<&LayoutColumnGapValue> {
5887        match self {
5888            Self::ColumnGap(f) => Some(f),
5889            _ => None,
5890        }
5891    }
5892
5893    #[must_use]
5894    pub const fn as_row_gap(&self) -> Option<&LayoutRowGapValue> {
5895        match self {
5896            Self::RowGap(f) => Some(f),
5897            _ => None,
5898        }
5899    }
5900
5901    #[must_use]
5902    pub const fn as_grid_template_columns(&self) -> Option<&LayoutGridTemplateColumnsValue> {
5903        match self {
5904            Self::GridTemplateColumns(f) => Some(f),
5905            _ => None,
5906        }
5907    }
5908
5909    #[must_use]
5910    pub const fn as_grid_template_rows(&self) -> Option<&LayoutGridTemplateRowsValue> {
5911        match self {
5912            Self::GridTemplateRows(f) => Some(f),
5913            _ => None,
5914        }
5915    }
5916
5917    #[must_use]
5918    pub const fn as_grid_auto_columns(&self) -> Option<&LayoutGridAutoColumnsValue> {
5919        match self {
5920            Self::GridAutoColumns(f) => Some(f),
5921            _ => None,
5922        }
5923    }
5924
5925    #[must_use]
5926    pub const fn as_grid_auto_rows(&self) -> Option<&LayoutGridAutoRowsValue> {
5927        match self {
5928            Self::GridAutoRows(f) => Some(f),
5929            _ => None,
5930        }
5931    }
5932
5933    #[must_use]
5934    pub const fn as_grid_column(&self) -> Option<&LayoutGridColumnValue> {
5935        match self {
5936            Self::GridColumn(f) => Some(f),
5937            _ => None,
5938        }
5939    }
5940
5941    #[must_use]
5942    pub const fn as_grid_row(&self) -> Option<&LayoutGridRowValue> {
5943        match self {
5944            Self::GridRow(f) => Some(f),
5945            _ => None,
5946        }
5947    }
5948
5949    #[must_use]
5950    pub const fn as_writing_mode(&self) -> Option<&LayoutWritingModeValue> {
5951        match self {
5952            Self::WritingMode(f) => Some(f),
5953            _ => None,
5954        }
5955    }
5956
5957    #[must_use]
5958    pub const fn as_clear(&self) -> Option<&LayoutClearValue> {
5959        match self {
5960            Self::Clear(f) => Some(f),
5961            _ => None,
5962        }
5963    }
5964
5965    #[must_use]
5966    pub const fn as_scrollbar_track(&self) -> Option<&StyleBackgroundContentValue> {
5967        match self {
5968            Self::ScrollbarTrack(f) => Some(f),
5969            _ => None,
5970        }
5971    }
5972
5973    #[must_use]
5974    pub const fn as_scrollbar_thumb(&self) -> Option<&StyleBackgroundContentValue> {
5975        match self {
5976            Self::ScrollbarThumb(f) => Some(f),
5977            _ => None,
5978        }
5979    }
5980
5981    #[must_use]
5982    pub const fn as_scrollbar_button(&self) -> Option<&StyleBackgroundContentValue> {
5983        match self {
5984            Self::ScrollbarButton(f) => Some(f),
5985            _ => None,
5986        }
5987    }
5988
5989    #[must_use]
5990    pub const fn as_scrollbar_corner(&self) -> Option<&StyleBackgroundContentValue> {
5991        match self {
5992            Self::ScrollbarCorner(f) => Some(f),
5993            _ => None,
5994        }
5995    }
5996
5997    #[must_use]
5998    pub const fn as_scrollbar_resizer(&self) -> Option<&StyleBackgroundContentValue> {
5999        match self {
6000            Self::ScrollbarResizer(f) => Some(f),
6001            _ => None,
6002        }
6003    }
6004
6005    #[must_use]
6006    pub const fn as_visibility(&self) -> Option<&StyleVisibilityValue> {
6007        match self {
6008            Self::Visibility(f) => Some(f),
6009            _ => None,
6010        }
6011    }
6012
6013    #[must_use]
6014    pub const fn as_background_content(&self) -> Option<&StyleBackgroundContentVecValue> {
6015        match self {
6016            Self::BackgroundContent(f) => Some(f),
6017            _ => None,
6018        }
6019    }
6020    #[must_use]
6021    pub const fn as_text_justify(&self) -> Option<&LayoutTextJustifyValue> {
6022        match self {
6023            Self::TextJustify(f) => Some(f),
6024            _ => None,
6025        }
6026    }
6027    #[must_use]
6028    pub const fn as_caret_color(&self) -> Option<&CaretColorValue> {
6029        match self {
6030            Self::CaretColor(f) => Some(f),
6031            _ => None,
6032        }
6033    }
6034    #[must_use]
6035    pub const fn as_caret_width(&self) -> Option<&CaretWidthValue> {
6036        match self {
6037            Self::CaretWidth(f) => Some(f),
6038            _ => None,
6039        }
6040    }
6041    #[must_use]
6042    pub const fn as_caret_animation_duration(&self) -> Option<&CaretAnimationDurationValue> {
6043        match self {
6044            Self::CaretAnimationDuration(f) => Some(f),
6045            _ => None,
6046        }
6047    }
6048    #[must_use]
6049    pub const fn as_selection_background_color(&self) -> Option<&SelectionBackgroundColorValue> {
6050        match self {
6051            Self::SelectionBackgroundColor(f) => Some(f),
6052            _ => None,
6053        }
6054    }
6055    #[must_use]
6056    pub const fn as_selection_color(&self) -> Option<&SelectionColorValue> {
6057        match self {
6058            Self::SelectionColor(f) => Some(f),
6059            _ => None,
6060        }
6061    }
6062    #[must_use]
6063    pub const fn as_selection_radius(&self) -> Option<&SelectionRadiusValue> {
6064        match self {
6065            Self::SelectionRadius(f) => Some(f),
6066            _ => None,
6067        }
6068    }
6069    #[must_use]
6070    pub const fn as_background_position(&self) -> Option<&StyleBackgroundPositionVecValue> {
6071        match self {
6072            Self::BackgroundPosition(f) => Some(f),
6073            _ => None,
6074        }
6075    }
6076    #[must_use]
6077    pub const fn as_background_size(&self) -> Option<&StyleBackgroundSizeVecValue> {
6078        match self {
6079            Self::BackgroundSize(f) => Some(f),
6080            _ => None,
6081        }
6082    }
6083    #[must_use]
6084    pub const fn as_background_repeat(&self) -> Option<&StyleBackgroundRepeatVecValue> {
6085        match self {
6086            Self::BackgroundRepeat(f) => Some(f),
6087            _ => None,
6088        }
6089    }
6090
6091    #[must_use]
6092    pub const fn as_grid_auto_flow(&self) -> Option<&LayoutGridAutoFlowValue> {
6093        match self {
6094            Self::GridAutoFlow(f) => Some(f),
6095            _ => None,
6096        }
6097    }
6098    #[must_use]
6099    pub const fn as_justify_self(&self) -> Option<&LayoutJustifySelfValue> {
6100        match self {
6101            Self::JustifySelf(f) => Some(f),
6102            _ => None,
6103        }
6104    }
6105    #[must_use]
6106    pub const fn as_justify_items(&self) -> Option<&LayoutJustifyItemsValue> {
6107        match self {
6108            Self::JustifyItems(f) => Some(f),
6109            _ => None,
6110        }
6111    }
6112    #[must_use]
6113    pub const fn as_gap(&self) -> Option<&LayoutGapValue> {
6114        match self {
6115            Self::Gap(f) => Some(f),
6116            _ => None,
6117        }
6118    }
6119    #[must_use]
6120    pub const fn as_grid_gap(&self) -> Option<&LayoutGapValue> {
6121        match self {
6122            Self::GridGap(f) => Some(f),
6123            _ => None,
6124        }
6125    }
6126    #[must_use]
6127    pub const fn as_align_self(&self) -> Option<&LayoutAlignSelfValue> {
6128        match self {
6129            Self::AlignSelf(f) => Some(f),
6130            _ => None,
6131        }
6132    }
6133    #[must_use]
6134    pub const fn as_font(&self) -> Option<&StyleFontValue> {
6135        match self {
6136            Self::Font(f) => Some(f),
6137            _ => None,
6138        }
6139    }
6140    #[must_use]
6141    pub const fn as_font_size(&self) -> Option<&StyleFontSizeValue> {
6142        match self {
6143            Self::FontSize(f) => Some(f),
6144            _ => None,
6145        }
6146    }
6147    #[must_use]
6148    pub const fn as_font_family(&self) -> Option<&StyleFontFamilyVecValue> {
6149        match self {
6150            Self::FontFamily(f) => Some(f),
6151            _ => None,
6152        }
6153    }
6154    #[must_use]
6155    pub const fn as_font_weight(&self) -> Option<&StyleFontWeightValue> {
6156        match self {
6157            Self::FontWeight(f) => Some(f),
6158            _ => None,
6159        }
6160    }
6161    #[must_use]
6162    pub const fn as_font_style(&self) -> Option<&StyleFontStyleValue> {
6163        match self {
6164            Self::FontStyle(f) => Some(f),
6165            _ => None,
6166        }
6167    }
6168    #[must_use]
6169    pub const fn as_text_color(&self) -> Option<&StyleTextColorValue> {
6170        match self {
6171            Self::TextColor(f) => Some(f),
6172            _ => None,
6173        }
6174    }
6175    #[must_use]
6176    pub const fn as_text_align(&self) -> Option<&StyleTextAlignValue> {
6177        match self {
6178            Self::TextAlign(f) => Some(f),
6179            _ => None,
6180        }
6181    }
6182    #[must_use]
6183    pub const fn as_vertical_align(&self) -> Option<&StyleVerticalAlignValue> {
6184        match self {
6185            Self::VerticalAlign(f) => Some(f),
6186            _ => None,
6187        }
6188    }
6189    #[must_use]
6190    pub const fn as_line_height(&self) -> Option<&StyleLineHeightValue> {
6191        match self {
6192            Self::LineHeight(f) => Some(f),
6193            _ => None,
6194        }
6195    }
6196    #[must_use]
6197    pub const fn as_text_indent(&self) -> Option<&StyleTextIndentValue> {
6198        match self {
6199            Self::TextIndent(f) => Some(f),
6200            _ => None,
6201        }
6202    }
6203    #[must_use]
6204    pub const fn as_initial_letter(&self) -> Option<&StyleInitialLetterValue> {
6205        match self {
6206            Self::InitialLetter(f) => Some(f),
6207            _ => None,
6208        }
6209    }
6210    #[must_use]
6211    pub const fn as_line_clamp(&self) -> Option<&StyleLineClampValue> {
6212        match self {
6213            Self::LineClamp(f) => Some(f),
6214            _ => None,
6215        }
6216    }
6217    #[must_use]
6218    pub const fn as_hanging_punctuation(&self) -> Option<&StyleHangingPunctuationValue> {
6219        match self {
6220            Self::HangingPunctuation(f) => Some(f),
6221            _ => None,
6222        }
6223    }
6224    #[must_use]
6225    pub const fn as_text_combine_upright(&self) -> Option<&StyleTextCombineUprightValue> {
6226        match self {
6227            Self::TextCombineUpright(f) => Some(f),
6228            _ => None,
6229        }
6230    }
6231    #[must_use]
6232    pub const fn as_unicode_bidi(&self) -> Option<&StyleUnicodeBidiValue> {
6233        match self {
6234            Self::UnicodeBidi(f) => Some(f),
6235            _ => None,
6236        }
6237    }
6238    #[must_use]
6239    pub const fn as_text_box_trim(&self) -> Option<&StyleTextBoxTrimValue> {
6240        match self {
6241            Self::TextBoxTrim(f) => Some(f),
6242            _ => None,
6243        }
6244    }
6245    #[must_use]
6246    pub const fn as_text_box_edge(&self) -> Option<&StyleTextBoxEdgeValue> {
6247        match self {
6248            Self::TextBoxEdge(f) => Some(f),
6249            _ => None,
6250        }
6251    }
6252    #[must_use]
6253    pub const fn as_dominant_baseline(&self) -> Option<&StyleDominantBaselineValue> {
6254        match self {
6255            Self::DominantBaseline(f) => Some(f),
6256            _ => None,
6257        }
6258    }
6259    #[must_use]
6260    pub const fn as_alignment_baseline(&self) -> Option<&StyleAlignmentBaselineValue> {
6261        match self {
6262            Self::AlignmentBaseline(f) => Some(f),
6263            _ => None,
6264        }
6265    }
6266    #[must_use]
6267    pub const fn as_baseline_source(&self) -> Option<&StyleBaselineSourceValue> {
6268        match self {
6269            Self::BaselineSource(f) => Some(f),
6270            _ => None,
6271        }
6272    }
6273    #[must_use]
6274    pub const fn as_line_fit_edge(&self) -> Option<&StyleLineFitEdgeValue> {
6275        match self {
6276            Self::LineFitEdge(f) => Some(f),
6277            _ => None,
6278        }
6279    }
6280    #[must_use]
6281    pub const fn as_initial_letter_align(&self) -> Option<&StyleInitialLetterAlignValue> {
6282        match self {
6283            Self::InitialLetterAlign(f) => Some(f),
6284            _ => None,
6285        }
6286    }
6287    #[must_use]
6288    pub const fn as_initial_letter_wrap(&self) -> Option<&StyleInitialLetterWrapValue> {
6289        match self {
6290            Self::InitialLetterWrap(f) => Some(f),
6291            _ => None,
6292        }
6293    }
6294    #[must_use]
6295    pub const fn as_scrollbar_gutter(&self) -> Option<&StyleScrollbarGutterValue> {
6296        match self {
6297            Self::ScrollbarGutter(f) => Some(f),
6298            _ => None,
6299        }
6300    }
6301    #[must_use]
6302    pub const fn as_overflow_clip_margin(&self) -> Option<&StyleOverflowClipMarginValue> {
6303        match self {
6304            Self::OverflowClipMargin(f) => Some(f),
6305            _ => None,
6306        }
6307    }
6308    #[must_use]
6309    pub const fn as_clip(&self) -> Option<&StyleClipRectValue> {
6310        match self {
6311            Self::Clip(f) => Some(f),
6312            _ => None,
6313        }
6314    }
6315    #[must_use]
6316    pub const fn as_exclusion_margin(&self) -> Option<&StyleExclusionMarginValue> {
6317        match self {
6318            Self::ExclusionMargin(f) => Some(f),
6319            _ => None,
6320        }
6321    }
6322    #[must_use]
6323    pub const fn as_hyphenation_language(&self) -> Option<&StyleHyphenationLanguageValue> {
6324        match self {
6325            Self::HyphenationLanguage(f) => Some(f),
6326            _ => None,
6327        }
6328    }
6329    #[must_use]
6330    pub const fn as_letter_spacing(&self) -> Option<&StyleLetterSpacingValue> {
6331        match self {
6332            Self::LetterSpacing(f) => Some(f),
6333            _ => None,
6334        }
6335    }
6336    #[must_use]
6337    pub const fn as_word_spacing(&self) -> Option<&StyleWordSpacingValue> {
6338        match self {
6339            Self::WordSpacing(f) => Some(f),
6340            _ => None,
6341        }
6342    }
6343    #[must_use]
6344    pub const fn as_tab_size(&self) -> Option<&StyleTabSizeValue> {
6345        match self {
6346            Self::TabSize(f) => Some(f),
6347            _ => None,
6348        }
6349    }
6350    #[must_use]
6351    pub const fn as_cursor(&self) -> Option<&StyleCursorValue> {
6352        match self {
6353            Self::Cursor(f) => Some(f),
6354            _ => None,
6355        }
6356    }
6357    #[must_use]
6358    pub const fn as_box_shadow_left(&self) -> Option<&StyleBoxShadowValue> {
6359        match self {
6360            Self::BoxShadowLeft(f) => Some(f),
6361            _ => None,
6362        }
6363    }
6364    #[must_use]
6365    pub const fn as_box_shadow_right(&self) -> Option<&StyleBoxShadowValue> {
6366        match self {
6367            Self::BoxShadowRight(f) => Some(f),
6368            _ => None,
6369        }
6370    }
6371    #[must_use]
6372    pub const fn as_box_shadow_top(&self) -> Option<&StyleBoxShadowValue> {
6373        match self {
6374            Self::BoxShadowTop(f) => Some(f),
6375            _ => None,
6376        }
6377    }
6378    #[must_use]
6379    pub const fn as_box_shadow_bottom(&self) -> Option<&StyleBoxShadowValue> {
6380        match self {
6381            Self::BoxShadowBottom(f) => Some(f),
6382            _ => None,
6383        }
6384    }
6385    #[must_use]
6386    pub const fn as_border_top_color(&self) -> Option<&StyleBorderTopColorValue> {
6387        match self {
6388            Self::BorderTopColor(f) => Some(f),
6389            _ => None,
6390        }
6391    }
6392    #[must_use]
6393    pub const fn as_border_left_color(&self) -> Option<&StyleBorderLeftColorValue> {
6394        match self {
6395            Self::BorderLeftColor(f) => Some(f),
6396            _ => None,
6397        }
6398    }
6399    #[must_use]
6400    pub const fn as_border_right_color(&self) -> Option<&StyleBorderRightColorValue> {
6401        match self {
6402            Self::BorderRightColor(f) => Some(f),
6403            _ => None,
6404        }
6405    }
6406    #[must_use]
6407    pub const fn as_border_bottom_color(&self) -> Option<&StyleBorderBottomColorValue> {
6408        match self {
6409            Self::BorderBottomColor(f) => Some(f),
6410            _ => None,
6411        }
6412    }
6413    #[must_use]
6414    pub const fn as_border_top_style(&self) -> Option<&StyleBorderTopStyleValue> {
6415        match self {
6416            Self::BorderTopStyle(f) => Some(f),
6417            _ => None,
6418        }
6419    }
6420    #[must_use]
6421    pub const fn as_border_left_style(&self) -> Option<&StyleBorderLeftStyleValue> {
6422        match self {
6423            Self::BorderLeftStyle(f) => Some(f),
6424            _ => None,
6425        }
6426    }
6427    #[must_use]
6428    pub const fn as_border_right_style(&self) -> Option<&StyleBorderRightStyleValue> {
6429        match self {
6430            Self::BorderRightStyle(f) => Some(f),
6431            _ => None,
6432        }
6433    }
6434    #[must_use]
6435    pub const fn as_border_bottom_style(&self) -> Option<&StyleBorderBottomStyleValue> {
6436        match self {
6437            Self::BorderBottomStyle(f) => Some(f),
6438            _ => None,
6439        }
6440    }
6441    #[must_use]
6442    pub const fn as_border_top_left_radius(&self) -> Option<&StyleBorderTopLeftRadiusValue> {
6443        match self {
6444            Self::BorderTopLeftRadius(f) => Some(f),
6445            _ => None,
6446        }
6447    }
6448    #[must_use]
6449    pub const fn as_border_top_right_radius(&self) -> Option<&StyleBorderTopRightRadiusValue> {
6450        match self {
6451            Self::BorderTopRightRadius(f) => Some(f),
6452            _ => None,
6453        }
6454    }
6455    #[must_use]
6456    pub const fn as_border_bottom_left_radius(&self) -> Option<&StyleBorderBottomLeftRadiusValue> {
6457        match self {
6458            Self::BorderBottomLeftRadius(f) => Some(f),
6459            _ => None,
6460        }
6461    }
6462    #[must_use]
6463    pub const fn as_border_bottom_right_radius(
6464        &self,
6465    ) -> Option<&StyleBorderBottomRightRadiusValue> {
6466        match self {
6467            Self::BorderBottomRightRadius(f) => Some(f),
6468            _ => None,
6469        }
6470    }
6471    #[must_use]
6472    pub const fn as_opacity(&self) -> Option<&StyleOpacityValue> {
6473        match self {
6474            Self::Opacity(f) => Some(f),
6475            _ => None,
6476        }
6477    }
6478    #[must_use]
6479    pub const fn as_transform(&self) -> Option<&StyleTransformVecValue> {
6480        match self {
6481            Self::Transform(f) => Some(f),
6482            _ => None,
6483        }
6484    }
6485    #[must_use]
6486    pub const fn as_transform_origin(&self) -> Option<&StyleTransformOriginValue> {
6487        match self {
6488            Self::TransformOrigin(f) => Some(f),
6489            _ => None,
6490        }
6491    }
6492    #[must_use]
6493    pub const fn as_perspective_origin(&self) -> Option<&StylePerspectiveOriginValue> {
6494        match self {
6495            Self::PerspectiveOrigin(f) => Some(f),
6496            _ => None,
6497        }
6498    }
6499    #[must_use]
6500    pub const fn as_backface_visibility(&self) -> Option<&StyleBackfaceVisibilityValue> {
6501        match self {
6502            Self::BackfaceVisibility(f) => Some(f),
6503            _ => None,
6504        }
6505    }
6506
6507    #[must_use]
6508    pub const fn as_spatial_navigation_action(
6509        &self,
6510    ) -> Option<&StyleSpatialNavigationActionValue> {
6511        match self {
6512            Self::SpatialNavigationAction(f) => Some(f),
6513            _ => None,
6514        }
6515    }
6516
6517    #[must_use]
6518    pub const fn as_spatial_navigation_contain(
6519        &self,
6520    ) -> Option<&StyleSpatialNavigationContainValue> {
6521        match self {
6522            Self::SpatialNavigationContain(f) => Some(f),
6523            _ => None,
6524        }
6525    }
6526
6527    #[must_use]
6528    pub const fn as_app_region(&self) -> Option<&StyleAppRegionValue> {
6529        match self {
6530            Self::AppRegion(f) => Some(f),
6531            _ => None,
6532        }
6533    }
6534    #[must_use]
6535    pub const fn as_mix_blend_mode(&self) -> Option<&StyleMixBlendModeValue> {
6536        match self {
6537            Self::MixBlendMode(f) => Some(f),
6538            _ => None,
6539        }
6540    }
6541    #[must_use]
6542    pub const fn as_filter(&self) -> Option<&StyleFilterVecValue> {
6543        match self {
6544            Self::Filter(f) => Some(f),
6545            _ => None,
6546        }
6547    }
6548    #[must_use]
6549    pub const fn as_backdrop_filter(&self) -> Option<&StyleFilterVecValue> {
6550        match self {
6551            Self::BackdropFilter(f) => Some(f),
6552            _ => None,
6553        }
6554    }
6555    #[must_use]
6556    pub const fn as_text_shadow(&self) -> Option<&StyleBoxShadowValue> {
6557        match self {
6558            Self::TextShadow(f) => Some(f),
6559            _ => None,
6560        }
6561    }
6562
6563    // functions that downcast to the concrete CSS type (layout)
6564
6565    #[must_use]
6566    pub const fn as_display(&self) -> Option<&LayoutDisplayValue> {
6567        match self {
6568            Self::Display(f) => Some(f),
6569            _ => None,
6570        }
6571    }
6572    #[must_use]
6573    pub const fn as_float(&self) -> Option<&LayoutFloatValue> {
6574        match self {
6575            Self::Float(f) => Some(f),
6576            _ => None,
6577        }
6578    }
6579    #[must_use]
6580    pub const fn as_box_sizing(&self) -> Option<&LayoutBoxSizingValue> {
6581        match self {
6582            Self::BoxSizing(f) => Some(f),
6583            _ => None,
6584        }
6585    }
6586    #[must_use]
6587    pub const fn as_width(&self) -> Option<&LayoutWidthValue> {
6588        match self {
6589            Self::Width(f) => Some(f),
6590            _ => None,
6591        }
6592    }
6593    #[must_use]
6594    pub const fn as_height(&self) -> Option<&LayoutHeightValue> {
6595        match self {
6596            Self::Height(f) => Some(f),
6597            _ => None,
6598        }
6599    }
6600    #[must_use]
6601    pub const fn as_min_width(&self) -> Option<&LayoutMinWidthValue> {
6602        match self {
6603            Self::MinWidth(f) => Some(f),
6604            _ => None,
6605        }
6606    }
6607    #[must_use]
6608    pub const fn as_min_height(&self) -> Option<&LayoutMinHeightValue> {
6609        match self {
6610            Self::MinHeight(f) => Some(f),
6611            _ => None,
6612        }
6613    }
6614    #[must_use]
6615    pub const fn as_max_width(&self) -> Option<&LayoutMaxWidthValue> {
6616        match self {
6617            Self::MaxWidth(f) => Some(f),
6618            _ => None,
6619        }
6620    }
6621    #[must_use]
6622    pub const fn as_max_height(&self) -> Option<&LayoutMaxHeightValue> {
6623        match self {
6624            Self::MaxHeight(f) => Some(f),
6625            _ => None,
6626        }
6627    }
6628    #[must_use]
6629    pub const fn as_position(&self) -> Option<&LayoutPositionValue> {
6630        match self {
6631            Self::Position(f) => Some(f),
6632            _ => None,
6633        }
6634    }
6635    #[must_use]
6636    pub const fn as_top(&self) -> Option<&LayoutTopValue> {
6637        match self {
6638            Self::Top(f) => Some(f),
6639            _ => None,
6640        }
6641    }
6642    #[must_use]
6643    pub const fn as_bottom(&self) -> Option<&LayoutInsetBottomValue> {
6644        match self {
6645            Self::Bottom(f) => Some(f),
6646            _ => None,
6647        }
6648    }
6649    #[must_use]
6650    pub const fn as_right(&self) -> Option<&LayoutRightValue> {
6651        match self {
6652            Self::Right(f) => Some(f),
6653            _ => None,
6654        }
6655    }
6656    #[must_use]
6657    pub const fn as_left(&self) -> Option<&LayoutLeftValue> {
6658        match self {
6659            Self::Left(f) => Some(f),
6660            _ => None,
6661        }
6662    }
6663    #[must_use]
6664    pub const fn as_padding_top(&self) -> Option<&LayoutPaddingTopValue> {
6665        match self {
6666            Self::PaddingTop(f) => Some(f),
6667            _ => None,
6668        }
6669    }
6670    #[must_use]
6671    pub const fn as_padding_bottom(&self) -> Option<&LayoutPaddingBottomValue> {
6672        match self {
6673            Self::PaddingBottom(f) => Some(f),
6674            _ => None,
6675        }
6676    }
6677    #[must_use]
6678    pub const fn as_padding_left(&self) -> Option<&LayoutPaddingLeftValue> {
6679        match self {
6680            Self::PaddingLeft(f) => Some(f),
6681            _ => None,
6682        }
6683    }
6684    #[must_use]
6685    pub const fn as_padding_right(&self) -> Option<&LayoutPaddingRightValue> {
6686        match self {
6687            Self::PaddingRight(f) => Some(f),
6688            _ => None,
6689        }
6690    }
6691    #[must_use]
6692    pub const fn as_margin_top(&self) -> Option<&LayoutMarginTopValue> {
6693        match self {
6694            Self::MarginTop(f) => Some(f),
6695            _ => None,
6696        }
6697    }
6698    #[must_use]
6699    pub const fn as_margin_bottom(&self) -> Option<&LayoutMarginBottomValue> {
6700        match self {
6701            Self::MarginBottom(f) => Some(f),
6702            _ => None,
6703        }
6704    }
6705    #[must_use]
6706    pub const fn as_margin_left(&self) -> Option<&LayoutMarginLeftValue> {
6707        match self {
6708            Self::MarginLeft(f) => Some(f),
6709            _ => None,
6710        }
6711    }
6712    #[must_use]
6713    pub const fn as_margin_right(&self) -> Option<&LayoutMarginRightValue> {
6714        match self {
6715            Self::MarginRight(f) => Some(f),
6716            _ => None,
6717        }
6718    }
6719    #[must_use]
6720    pub const fn as_border_top_width(&self) -> Option<&LayoutBorderTopWidthValue> {
6721        match self {
6722            Self::BorderTopWidth(f) => Some(f),
6723            _ => None,
6724        }
6725    }
6726    #[must_use]
6727    pub const fn as_border_left_width(&self) -> Option<&LayoutBorderLeftWidthValue> {
6728        match self {
6729            Self::BorderLeftWidth(f) => Some(f),
6730            _ => None,
6731        }
6732    }
6733    #[must_use]
6734    pub const fn as_border_right_width(&self) -> Option<&LayoutBorderRightWidthValue> {
6735        match self {
6736            Self::BorderRightWidth(f) => Some(f),
6737            _ => None,
6738        }
6739    }
6740    #[must_use]
6741    pub const fn as_border_bottom_width(&self) -> Option<&LayoutBorderBottomWidthValue> {
6742        match self {
6743            Self::BorderBottomWidth(f) => Some(f),
6744            _ => None,
6745        }
6746    }
6747    #[must_use]
6748    pub const fn as_overflow_x(&self) -> Option<&LayoutOverflowValue> {
6749        match self {
6750            Self::OverflowX(f) => Some(f),
6751            _ => None,
6752        }
6753    }
6754    #[must_use]
6755    pub const fn as_overflow_y(&self) -> Option<&LayoutOverflowValue> {
6756        match self {
6757            Self::OverflowY(f) => Some(f),
6758            _ => None,
6759        }
6760    }
6761    #[must_use]
6762    pub const fn as_overflow_block(&self) -> Option<&LayoutOverflowValue> {
6763        match self {
6764            Self::OverflowBlock(f) => Some(f),
6765            _ => None,
6766        }
6767    }
6768    #[must_use]
6769    pub const fn as_overflow_inline(&self) -> Option<&LayoutOverflowValue> {
6770        match self {
6771            Self::OverflowInline(f) => Some(f),
6772            _ => None,
6773        }
6774    }
6775    #[must_use]
6776    pub const fn as_flex_direction(&self) -> Option<&LayoutFlexDirectionValue> {
6777        match self {
6778            Self::FlexDirection(f) => Some(f),
6779            _ => None,
6780        }
6781    }
6782    #[must_use]
6783    pub const fn as_direction(&self) -> Option<&StyleDirectionValue> {
6784        match self {
6785            Self::Direction(f) => Some(f),
6786            _ => None,
6787        }
6788    }
6789    #[must_use]
6790    pub const fn as_user_select(&self) -> Option<&StyleUserSelectValue> {
6791        match self {
6792            Self::UserSelect(f) => Some(f),
6793            _ => None,
6794        }
6795    }
6796    #[must_use]
6797    pub const fn as_text_decoration(&self) -> Option<&StyleTextDecorationValue> {
6798        match self {
6799            Self::TextDecoration(f) => Some(f),
6800            _ => None,
6801        }
6802    }
6803    #[must_use]
6804    pub const fn as_hyphens(&self) -> Option<&StyleHyphensValue> {
6805        match self {
6806            Self::Hyphens(f) => Some(f),
6807            _ => None,
6808        }
6809    }
6810    #[must_use]
6811    pub const fn as_word_break(&self) -> Option<&StyleWordBreakValue> {
6812        match self {
6813            Self::WordBreak(f) => Some(f),
6814            _ => None,
6815        }
6816    }
6817    #[must_use]
6818    pub const fn as_overflow_wrap(&self) -> Option<&StyleOverflowWrapValue> {
6819        match self {
6820            Self::OverflowWrap(f) => Some(f),
6821            _ => None,
6822        }
6823    }
6824    #[must_use]
6825    pub const fn as_line_break(&self) -> Option<&StyleLineBreakValue> {
6826        match self {
6827            Self::LineBreak(f) => Some(f),
6828            _ => None,
6829        }
6830    }
6831    #[must_use]
6832    pub const fn as_object_fit(&self) -> Option<&StyleObjectFitValue> {
6833        match self {
6834            Self::ObjectFit(f) => Some(f),
6835            _ => None,
6836        }
6837    }
6838    #[must_use]
6839    pub const fn as_text_overflow(&self) -> Option<&StyleTextOverflowValue> {
6840        match self {
6841            Self::TextOverflow(f) => Some(f),
6842            _ => None,
6843        }
6844    }
6845    #[must_use]
6846    pub const fn as_object_position(&self) -> Option<&StyleObjectPositionValue> {
6847        match self {
6848            Self::ObjectPosition(f) => Some(f),
6849            _ => None,
6850        }
6851    }
6852    #[must_use]
6853    pub const fn as_aspect_ratio(&self) -> Option<&StyleAspectRatioValue> {
6854        match self {
6855            Self::AspectRatio(f) => Some(f),
6856            _ => None,
6857        }
6858    }
6859    #[must_use]
6860    pub const fn as_text_orientation(&self) -> Option<&StyleTextOrientationValue> {
6861        match self {
6862            Self::TextOrientation(f) => Some(f),
6863            _ => None,
6864        }
6865    }
6866    #[must_use]
6867    pub const fn as_text_transform(&self) -> Option<&StyleTextTransformValue> {
6868        match self {
6869            Self::TextTransform(f) => Some(f),
6870            _ => None,
6871        }
6872    }
6873    #[must_use]
6874    pub const fn as_text_align_last(&self) -> Option<&StyleTextAlignLastValue> {
6875        match self {
6876            Self::TextAlignLast(f) => Some(f),
6877            _ => None,
6878        }
6879    }
6880    #[must_use]
6881    pub const fn as_white_space(&self) -> Option<&StyleWhiteSpaceValue> {
6882        match self {
6883            Self::WhiteSpace(f) => Some(f),
6884            _ => None,
6885        }
6886    }
6887    #[must_use]
6888    pub const fn as_flex_wrap(&self) -> Option<&LayoutFlexWrapValue> {
6889        match self {
6890            Self::FlexWrap(f) => Some(f),
6891            _ => None,
6892        }
6893    }
6894    #[must_use]
6895    pub const fn as_flex_grow(&self) -> Option<&LayoutFlexGrowValue> {
6896        match self {
6897            Self::FlexGrow(f) => Some(f),
6898            _ => None,
6899        }
6900    }
6901    #[must_use]
6902    pub const fn as_flex_shrink(&self) -> Option<&LayoutFlexShrinkValue> {
6903        match self {
6904            Self::FlexShrink(f) => Some(f),
6905            _ => None,
6906        }
6907    }
6908    #[must_use]
6909    pub const fn as_justify_content(&self) -> Option<&LayoutJustifyContentValue> {
6910        match self {
6911            Self::JustifyContent(f) => Some(f),
6912            _ => None,
6913        }
6914    }
6915    #[must_use]
6916    pub const fn as_align_items(&self) -> Option<&LayoutAlignItemsValue> {
6917        match self {
6918            Self::AlignItems(f) => Some(f),
6919            _ => None,
6920        }
6921    }
6922    #[must_use]
6923    pub const fn as_align_content(&self) -> Option<&LayoutAlignContentValue> {
6924        match self {
6925            Self::AlignContent(f) => Some(f),
6926            _ => None,
6927        }
6928    }
6929    #[must_use]
6930    pub const fn as_break_before(&self) -> Option<&PageBreakValue> {
6931        match self {
6932            Self::BreakBefore(f) => Some(f),
6933            _ => None,
6934        }
6935    }
6936    #[must_use]
6937    pub const fn as_break_after(&self) -> Option<&PageBreakValue> {
6938        match self {
6939            Self::BreakAfter(f) => Some(f),
6940            _ => None,
6941        }
6942    }
6943    #[must_use]
6944    pub const fn as_break_inside(&self) -> Option<&BreakInsideValue> {
6945        match self {
6946            Self::BreakInside(f) => Some(f),
6947            _ => None,
6948        }
6949    }
6950    #[must_use]
6951    pub const fn as_orphans(&self) -> Option<&OrphansValue> {
6952        match self {
6953            Self::Orphans(f) => Some(f),
6954            _ => None,
6955        }
6956    }
6957    #[must_use]
6958    pub const fn as_widows(&self) -> Option<&WidowsValue> {
6959        match self {
6960            Self::Widows(f) => Some(f),
6961            _ => None,
6962        }
6963    }
6964    #[must_use]
6965    pub const fn as_box_decoration_break(&self) -> Option<&BoxDecorationBreakValue> {
6966        match self {
6967            Self::BoxDecorationBreak(f) => Some(f),
6968            _ => None,
6969        }
6970    }
6971    #[must_use]
6972    pub const fn as_column_count(&self) -> Option<&ColumnCountValue> {
6973        match self {
6974            Self::ColumnCount(f) => Some(f),
6975            _ => None,
6976        }
6977    }
6978    #[must_use]
6979    pub const fn as_column_width(&self) -> Option<&ColumnWidthValue> {
6980        match self {
6981            Self::ColumnWidth(f) => Some(f),
6982            _ => None,
6983        }
6984    }
6985    #[must_use]
6986    pub const fn as_column_span(&self) -> Option<&ColumnSpanValue> {
6987        match self {
6988            Self::ColumnSpan(f) => Some(f),
6989            _ => None,
6990        }
6991    }
6992    #[must_use]
6993    pub const fn as_column_fill(&self) -> Option<&ColumnFillValue> {
6994        match self {
6995            Self::ColumnFill(f) => Some(f),
6996            _ => None,
6997        }
6998    }
6999    #[must_use]
7000    pub const fn as_column_rule_width(&self) -> Option<&ColumnRuleWidthValue> {
7001        match self {
7002            Self::ColumnRuleWidth(f) => Some(f),
7003            _ => None,
7004        }
7005    }
7006    #[must_use]
7007    pub const fn as_column_rule_style(&self) -> Option<&ColumnRuleStyleValue> {
7008        match self {
7009            Self::ColumnRuleStyle(f) => Some(f),
7010            _ => None,
7011        }
7012    }
7013    #[must_use]
7014    pub const fn as_column_rule_color(&self) -> Option<&ColumnRuleColorValue> {
7015        match self {
7016            Self::ColumnRuleColor(f) => Some(f),
7017            _ => None,
7018        }
7019    }
7020    #[must_use]
7021    pub const fn as_flow_into(&self) -> Option<&FlowIntoValue> {
7022        match self {
7023            Self::FlowInto(f) => Some(f),
7024            _ => None,
7025        }
7026    }
7027    #[must_use]
7028    pub const fn as_flow_from(&self) -> Option<&FlowFromValue> {
7029        match self {
7030            Self::FlowFrom(f) => Some(f),
7031            _ => None,
7032        }
7033    }
7034    #[must_use]
7035    pub const fn as_shape_outside(&self) -> Option<&ShapeOutsideValue> {
7036        match self {
7037            Self::ShapeOutside(f) => Some(f),
7038            _ => None,
7039        }
7040    }
7041    #[must_use]
7042    pub const fn as_shape_inside(&self) -> Option<&ShapeInsideValue> {
7043        match self {
7044            Self::ShapeInside(f) => Some(f),
7045            _ => None,
7046        }
7047    }
7048    #[must_use]
7049    pub const fn as_clip_path(&self) -> Option<&ClipPathValue> {
7050        match self {
7051            Self::ClipPath(f) => Some(f),
7052            _ => None,
7053        }
7054    }
7055    #[must_use]
7056    pub const fn as_shape_margin(&self) -> Option<&ShapeMarginValue> {
7057        match self {
7058            Self::ShapeMargin(f) => Some(f),
7059            _ => None,
7060        }
7061    }
7062    #[must_use]
7063    pub const fn as_shape_image_threshold(&self) -> Option<&ShapeImageThresholdValue> {
7064        match self {
7065            Self::ShapeImageThreshold(f) => Some(f),
7066            _ => None,
7067        }
7068    }
7069    #[must_use]
7070    pub const fn as_content(&self) -> Option<&ContentValue> {
7071        match self {
7072            Self::Content(f) => Some(f),
7073            _ => None,
7074        }
7075    }
7076    #[must_use]
7077    pub const fn as_counter_reset(&self) -> Option<&CounterResetValue> {
7078        match self {
7079            Self::CounterReset(f) => Some(f),
7080            _ => None,
7081        }
7082    }
7083    #[must_use]
7084    pub const fn as_counter_increment(&self) -> Option<&CounterIncrementValue> {
7085        match self {
7086            Self::CounterIncrement(f) => Some(f),
7087            _ => None,
7088        }
7089    }
7090    #[must_use]
7091    pub const fn as_list_style_type(&self) -> Option<&StyleListStyleTypeValue> {
7092        match self {
7093            Self::ListStyleType(f) => Some(f),
7094            _ => None,
7095        }
7096    }
7097    #[must_use]
7098    pub const fn as_list_style_position(&self) -> Option<&StyleListStylePositionValue> {
7099        match self {
7100            Self::ListStylePosition(f) => Some(f),
7101            _ => None,
7102        }
7103    }
7104    #[must_use]
7105    pub const fn as_string_set(&self) -> Option<&StringSetValue> {
7106        match self {
7107            Self::StringSet(f) => Some(f),
7108            _ => None,
7109        }
7110    }
7111    #[must_use]
7112    pub const fn as_table_layout(&self) -> Option<&LayoutTableLayoutValue> {
7113        match self {
7114            Self::TableLayout(f) => Some(f),
7115            _ => None,
7116        }
7117    }
7118    #[must_use]
7119    pub const fn as_border_collapse(&self) -> Option<&StyleBorderCollapseValue> {
7120        match self {
7121            Self::BorderCollapse(f) => Some(f),
7122            _ => None,
7123        }
7124    }
7125    #[must_use]
7126    pub const fn as_border_spacing(&self) -> Option<&LayoutBorderSpacingValue> {
7127        match self {
7128            Self::BorderSpacing(f) => Some(f),
7129            _ => None,
7130        }
7131    }
7132    #[must_use]
7133    pub const fn as_caption_side(&self) -> Option<&StyleCaptionSideValue> {
7134        match self {
7135            Self::CaptionSide(f) => Some(f),
7136            _ => None,
7137        }
7138    }
7139    #[must_use]
7140    pub const fn as_empty_cells(&self) -> Option<&StyleEmptyCellsValue> {
7141        match self {
7142            Self::EmptyCells(f) => Some(f),
7143            _ => None,
7144        }
7145    }
7146
7147    #[must_use]
7148    pub const fn as_overscroll_behavior_x(&self) -> Option<&OverscrollBehaviorValue> {
7149        match self {
7150            Self::OverscrollBehaviorX(f) => Some(f),
7151            _ => None,
7152        }
7153    }
7154    #[must_use]
7155    pub const fn as_overscroll_behavior_y(&self) -> Option<&OverscrollBehaviorValue> {
7156        match self {
7157            Self::OverscrollBehaviorY(f) => Some(f),
7158            _ => None,
7159        }
7160    }
7161    #[must_use]
7162    pub const fn as_scrollbar_width(&self) -> Option<&LayoutScrollbarWidthValue> {
7163        match self {
7164            Self::ScrollbarWidth(f) => Some(f),
7165            _ => None,
7166        }
7167    }
7168    #[must_use]
7169    pub const fn as_scrollbar_color(&self) -> Option<&StyleScrollbarColorValue> {
7170        match self {
7171            Self::ScrollbarColor(f) => Some(f),
7172            _ => None,
7173        }
7174    }
7175
7176    #[must_use]
7177    pub const fn as_scrollbar_visibility(&self) -> Option<&ScrollbarVisibilityModeValue> {
7178        match self {
7179            Self::ScrollbarVisibility(f) => Some(f),
7180            _ => None,
7181        }
7182    }
7183
7184    #[must_use]
7185    pub const fn as_scrollbar_fade_delay(&self) -> Option<&ScrollbarFadeDelayValue> {
7186        match self {
7187            Self::ScrollbarFadeDelay(f) => Some(f),
7188            _ => None,
7189        }
7190    }
7191
7192    #[must_use]
7193    pub const fn as_scrollbar_fade_duration(&self) -> Option<&ScrollbarFadeDurationValue> {
7194        match self {
7195            Self::ScrollbarFadeDuration(f) => Some(f),
7196            _ => None,
7197        }
7198    }
7199
7200    // Cross-type dispatch: each `c` is a different `CssPropertyValue<T>`, so the
7201    // identical `c.is_initial()` bodies can't merge (clippy::match_same_arms FP).
7202    #[allow(clippy::match_same_arms)]
7203    #[allow(clippy::too_many_lines)]
7204    // large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
7205    #[must_use]
7206    pub const fn is_initial(&self) -> bool {
7207        use self::CssProperty::{
7208            AlignContent, AlignItems, AlignSelf, AlignmentBaseline, Animation, AnimationIn,
7209            AnimationOut, AppRegion, AspectRatio, BackdropFilter, BackfaceVisibility,
7210            SpatialNavigationAction, SpatialNavigationContain,
7211            BackgroundContent, BackgroundPosition, BackgroundRepeat, BackgroundSize,
7212            BaselineSource, BorderBottomColor, BorderBottomLeftRadius, BorderBottomRightRadius,
7213            BorderBottomStyle, BorderBottomWidth, BorderCollapse, BorderLeftColor, BorderLeftStyle,
7214            BorderLeftWidth, BorderRightColor, BorderRightStyle, BorderRightWidth, BorderSpacing,
7215            BorderTopColor, BorderTopLeftRadius, BorderTopRightRadius, BorderTopStyle,
7216            BorderTopWidth, Bottom, BoxDecorationBreak, BoxShadowBottom, BoxShadowLeft,
7217            BoxShadowRight, BoxShadowTop, BoxSizing, BreakAfter, BreakBefore, BreakInside,
7218            CaptionSide, CaretAnimationDuration, CaretColor, CaretWidth, Clear, Clip, ClipPath,
7219            ColumnCount, ColumnFill, ColumnGap, ColumnRuleColor, ColumnRuleStyle, ColumnRuleWidth,
7220            ColumnSpan, ColumnWidth, Content, CounterIncrement, CounterReset, Cursor, Direction,
7221            Display, DominantBaseline, EmptyCells, ExclusionMargin, Filter, FlexBasis,
7222            FlexDirection, FlexGrow, FlexShrink, FlexWrap, Float, FlowFrom, FlowInto, Font,
7223            FontFamily, FontSize, FontStyle, FontWeight, Gap, GridAutoColumns, GridAutoFlow,
7224            GridAutoRows, GridColumn, GridGap, GridRow, GridTemplateAreas, GridTemplateColumns,
7225            GridTemplateRows, HangingPunctuation, Height, HyphenationLanguage, Hyphens,
7226            InitialLetter, InitialLetterAlign, InitialLetterWrap, JustifyContent, JustifyItems,
7227            JustifySelf, Left, LetterSpacing, LineBreak, LineClamp, LineFitEdge, LineHeight,
7228            ListStylePosition, ListStyleType, MarginBottom, MarginLeft, MarginRight, MarginTop,
7229            MaxHeight, MaxWidth, MinHeight, MinWidth, MixBlendMode, ObjectFit, ObjectPosition,
7230            Opacity, Orphans, OverflowBlock, OverflowClipMargin, OverflowInline, OverflowWrap,
7231            OverflowX, OverflowY, OverscrollBehaviorX, OverscrollBehaviorY, PaddingBottom,
7232            PaddingInlineEnd, PaddingInlineStart, PaddingLeft, PaddingRight, PaddingTop,
7233            PerspectiveOrigin, Position, Right, RowGap, ScrollbarButton, ScrollbarColor,
7234            ScrollbarCorner, ScrollbarFadeDelay, ScrollbarFadeDuration, ScrollbarGutter,
7235            ScrollbarResizer, ScrollbarThumb, ScrollbarTrack, ScrollbarVisibility, ScrollbarWidth,
7236            SelectionBackgroundColor, SelectionColor, SelectionRadius, ShapeImageThreshold,
7237            ShapeInside, ShapeMargin, ShapeOutside, StringSet, TabSize, TableLayout, TextAlign,
7238            TextAlignLast, TextBoxEdge, TextBoxTrim, TextColor, TextCombineUpright, TextDecoration,
7239            TextIndent, TextJustify, TextOrientation, TextOverflow, TextShadow, TextTransform, Top,
7240            Transform, TransformOrigin, UnicodeBidi, UserSelect, VerticalAlign, Visibility,
7241            WhiteSpace, Widows, Width, WordBreak, WordSpacing, WritingMode, ZIndex,
7242        };
7243        match self {
7244            CaretColor(c) => c.is_initial(),
7245            CaretWidth(c) => c.is_initial(),
7246            CaretAnimationDuration(c) => c.is_initial(),
7247            Animation(c) => c.is_initial(),
7248            AnimationIn(c) => c.is_initial(),
7249            AnimationOut(c) => c.is_initial(),
7250            SelectionBackgroundColor(c) => c.is_initial(),
7251            SelectionColor(c) => c.is_initial(),
7252            SelectionRadius(c) => c.is_initial(),
7253            TextJustify(c) => c.is_initial(),
7254            TextColor(c) => c.is_initial(),
7255            FontSize(c) => c.is_initial(),
7256            FontFamily(c) => c.is_initial(),
7257            TextAlign(c) => c.is_initial(),
7258            LetterSpacing(c) => c.is_initial(),
7259            TextIndent(c) => c.is_initial(),
7260            InitialLetter(c) => c.is_initial(),
7261            LineClamp(c) => c.is_initial(),
7262            HangingPunctuation(c) => c.is_initial(),
7263            TextCombineUpright(c) => c.is_initial(),
7264            UnicodeBidi(c) => c.is_initial(),
7265            TextBoxTrim(c) => c.is_initial(),
7266            TextBoxEdge(c) => c.is_initial(),
7267            DominantBaseline(c) => c.is_initial(),
7268            AlignmentBaseline(c) => c.is_initial(),
7269            BaselineSource(c) => c.is_initial(),
7270            LineFitEdge(c) => c.is_initial(),
7271            InitialLetterAlign(c) => c.is_initial(),
7272            InitialLetterWrap(c) => c.is_initial(),
7273            ScrollbarGutter(c) => c.is_initial(),
7274            OverflowClipMargin(c) => c.is_initial(),
7275            Clip(c) => c.is_initial(),
7276            ExclusionMargin(c) => c.is_initial(),
7277            HyphenationLanguage(c) => c.is_initial(),
7278            LineHeight(c) => c.is_initial(),
7279            WordSpacing(c) => c.is_initial(),
7280            TabSize(c) => c.is_initial(),
7281            Cursor(c) => c.is_initial(),
7282            Display(c) => c.is_initial(),
7283            Float(c) => c.is_initial(),
7284            BoxSizing(c) => c.is_initial(),
7285            Width(c) => c.is_initial(),
7286            Height(c) => c.is_initial(),
7287            MinWidth(c) => c.is_initial(),
7288            MinHeight(c) => c.is_initial(),
7289            MaxWidth(c) => c.is_initial(),
7290            MaxHeight(c) => c.is_initial(),
7291            Position(c) => c.is_initial(),
7292            Top(c) => c.is_initial(),
7293            Right(c) => c.is_initial(),
7294            Left(c) => c.is_initial(),
7295            Bottom(c) => c.is_initial(),
7296            ZIndex(c) => c.is_initial(),
7297            FlexWrap(c) => c.is_initial(),
7298            FlexDirection(c) => c.is_initial(),
7299            FlexGrow(c) => c.is_initial(),
7300            FlexShrink(c) => c.is_initial(),
7301            FlexBasis(c) => c.is_initial(),
7302            JustifyContent(c) => c.is_initial(),
7303            AlignItems(c) => c.is_initial(),
7304            AlignContent(c) => c.is_initial(),
7305            ColumnGap(c) => c.is_initial(),
7306            RowGap(c) => c.is_initial(),
7307            GridTemplateColumns(c) => c.is_initial(),
7308            GridTemplateRows(c) => c.is_initial(),
7309            GridAutoFlow(c) => c.is_initial(),
7310            JustifySelf(c) => c.is_initial(),
7311            JustifyItems(c) => c.is_initial(),
7312            Gap(c) => c.is_initial(),
7313            GridGap(c) => c.is_initial(),
7314            AlignSelf(c) => c.is_initial(),
7315            Font(c) => c.is_initial(),
7316            GridAutoColumns(c) => c.is_initial(),
7317            GridAutoRows(c) => c.is_initial(),
7318            GridColumn(c) => c.is_initial(),
7319            GridRow(c) => c.is_initial(),
7320            GridTemplateAreas(c) => c.is_initial(),
7321            WritingMode(c) => c.is_initial(),
7322            Clear(c) => c.is_initial(),
7323            BackgroundContent(c) => c.is_initial(),
7324            BackgroundPosition(c) => c.is_initial(),
7325            BackgroundSize(c) => c.is_initial(),
7326            BackgroundRepeat(c) => c.is_initial(),
7327            OverflowX(c) => c.is_initial(),
7328            OverflowY(c) => c.is_initial(),
7329            OverflowBlock(c) => c.is_initial(),
7330            OverflowInline(c) => c.is_initial(),
7331            PaddingTop(c) => c.is_initial(),
7332            PaddingLeft(c) => c.is_initial(),
7333            PaddingRight(c) => c.is_initial(),
7334            PaddingBottom(c) => c.is_initial(),
7335            PaddingInlineStart(c) => c.is_initial(),
7336            PaddingInlineEnd(c) => c.is_initial(),
7337            MarginTop(c) => c.is_initial(),
7338            MarginLeft(c) => c.is_initial(),
7339            MarginRight(c) => c.is_initial(),
7340            MarginBottom(c) => c.is_initial(),
7341            BorderTopLeftRadius(c) => c.is_initial(),
7342            BorderTopRightRadius(c) => c.is_initial(),
7343            BorderBottomLeftRadius(c) => c.is_initial(),
7344            BorderBottomRightRadius(c) => c.is_initial(),
7345            BorderTopColor(c) => c.is_initial(),
7346            BorderRightColor(c) => c.is_initial(),
7347            BorderLeftColor(c) => c.is_initial(),
7348            BorderBottomColor(c) => c.is_initial(),
7349            BorderTopStyle(c) => c.is_initial(),
7350            BorderRightStyle(c) => c.is_initial(),
7351            BorderLeftStyle(c) => c.is_initial(),
7352            BorderBottomStyle(c) => c.is_initial(),
7353            BorderTopWidth(c) => c.is_initial(),
7354            BorderRightWidth(c) => c.is_initial(),
7355            BorderLeftWidth(c) => c.is_initial(),
7356            BorderBottomWidth(c) => c.is_initial(),
7357            BoxShadowLeft(c) => c.is_initial(),
7358            BoxShadowRight(c) => c.is_initial(),
7359            BoxShadowTop(c) => c.is_initial(),
7360            BoxShadowBottom(c) => c.is_initial(),
7361            ScrollbarTrack(c) => c.is_initial(),
7362            ScrollbarThumb(c) => c.is_initial(),
7363            ScrollbarButton(c) => c.is_initial(),
7364            ScrollbarCorner(c) => c.is_initial(),
7365            ScrollbarResizer(c) => c.is_initial(),
7366            ScrollbarWidth(c) => c.is_initial(),
7367            OverscrollBehaviorX(c) | OverscrollBehaviorY(c) => c.is_initial(),
7368            ScrollbarColor(c) => c.is_initial(),
7369            ScrollbarVisibility(c) => c.is_initial(),
7370            ScrollbarFadeDelay(c) => c.is_initial(),
7371            ScrollbarFadeDuration(c) => c.is_initial(),
7372            Opacity(c) => c.is_initial(),
7373            Visibility(c) => c.is_initial(),
7374            Transform(c) => c.is_initial(),
7375            TransformOrigin(c) => c.is_initial(),
7376            PerspectiveOrigin(c) => c.is_initial(),
7377            AppRegion(c) => c.is_initial(),
7378            SpatialNavigationAction(c) => c.is_initial(),
7379            SpatialNavigationContain(c) => c.is_initial(),
7380            BackfaceVisibility(c) => c.is_initial(),
7381            MixBlendMode(c) => c.is_initial(),
7382            Filter(c) => c.is_initial(),
7383            BackdropFilter(c) => c.is_initial(),
7384            TextShadow(c) => c.is_initial(),
7385            WhiteSpace(c) => c.is_initial(),
7386            Direction(c) => c.is_initial(),
7387            UserSelect(c) => c.is_initial(),
7388            TextDecoration(c) => c.is_initial(),
7389            Hyphens(c) => c.is_initial(),
7390            WordBreak(c) => c.is_initial(),
7391            OverflowWrap(c) => c.is_initial(),
7392            LineBreak(c) => c.is_initial(),
7393            TextOverflow(c) => c.is_initial(),
7394            ObjectFit(c) => c.is_initial(),
7395            ObjectPosition(c) => c.is_initial(),
7396            AspectRatio(c) => c.is_initial(),
7397            TextOrientation(c) => c.is_initial(),
7398            TextAlignLast(c) => c.is_initial(),
7399            TextTransform(c) => c.is_initial(),
7400            BreakBefore(c) => c.is_initial(),
7401            BreakAfter(c) => c.is_initial(),
7402            BreakInside(c) => c.is_initial(),
7403            Orphans(c) => c.is_initial(),
7404            Widows(c) => c.is_initial(),
7405            BoxDecorationBreak(c) => c.is_initial(),
7406            ColumnCount(c) => c.is_initial(),
7407            ColumnWidth(c) => c.is_initial(),
7408            ColumnSpan(c) => c.is_initial(),
7409            ColumnFill(c) => c.is_initial(),
7410            ColumnRuleWidth(c) => c.is_initial(),
7411            ColumnRuleStyle(c) => c.is_initial(),
7412            ColumnRuleColor(c) => c.is_initial(),
7413            FlowInto(c) => c.is_initial(),
7414            FlowFrom(c) => c.is_initial(),
7415            ShapeOutside(c) => c.is_initial(),
7416            ShapeInside(c) => c.is_initial(),
7417            ClipPath(c) => c.is_initial(),
7418            ShapeMargin(c) => c.is_initial(),
7419            ShapeImageThreshold(c) => c.is_initial(),
7420            Content(c) => c.is_initial(),
7421            CounterReset(c) => c.is_initial(),
7422            CounterIncrement(c) => c.is_initial(),
7423            ListStyleType(c) => c.is_initial(),
7424            ListStylePosition(c) => c.is_initial(),
7425            StringSet(c) => c.is_initial(),
7426            TableLayout(c) => c.is_initial(),
7427            BorderCollapse(c) => c.is_initial(),
7428            BorderSpacing(c) => c.is_initial(),
7429            CaptionSide(c) => c.is_initial(),
7430            EmptyCells(c) => c.is_initial(),
7431            FontWeight(c) => c.is_initial(),
7432            FontStyle(c) => c.is_initial(),
7433            VerticalAlign(c) => c.is_initial(),
7434        }
7435    }
7436
7437    #[must_use]
7438    pub const fn const_none(prop_type: CssPropertyType) -> Self {
7439        css_property_from_type!(prop_type, None)
7440    }
7441    #[must_use]
7442    pub const fn const_auto(prop_type: CssPropertyType) -> Self {
7443        css_property_from_type!(prop_type, Auto)
7444    }
7445    #[must_use]
7446    pub const fn const_initial(prop_type: CssPropertyType) -> Self {
7447        css_property_from_type!(prop_type, Initial)
7448    }
7449    #[must_use]
7450    pub const fn const_inherit(prop_type: CssPropertyType) -> Self {
7451        css_property_from_type!(prop_type, Inherit)
7452    }
7453
7454    #[must_use]
7455    pub const fn const_text_color(input: StyleTextColor) -> Self {
7456        Self::TextColor(StyleTextColorValue::Exact(input))
7457    }
7458    #[must_use]
7459    pub const fn const_font_size(input: StyleFontSize) -> Self {
7460        Self::FontSize(StyleFontSizeValue::Exact(input))
7461    }
7462    #[must_use]
7463    pub const fn const_font_family(input: StyleFontFamilyVec) -> Self {
7464        Self::FontFamily(StyleFontFamilyVecValue::Exact(input))
7465    }
7466    #[must_use]
7467    pub const fn const_text_align(input: StyleTextAlign) -> Self {
7468        Self::TextAlign(StyleTextAlignValue::Exact(input))
7469    }
7470    #[must_use]
7471    pub const fn const_vertical_align(input: StyleVerticalAlign) -> Self {
7472        Self::VerticalAlign(StyleVerticalAlignValue::Exact(input))
7473    }
7474    #[must_use]
7475    pub const fn const_letter_spacing(input: StyleLetterSpacing) -> Self {
7476        Self::LetterSpacing(StyleLetterSpacingValue::Exact(input))
7477    }
7478    #[must_use]
7479    pub const fn const_text_indent(input: StyleTextIndent) -> Self {
7480        Self::TextIndent(StyleTextIndentValue::Exact(input))
7481    }
7482    #[must_use]
7483    pub const fn const_line_height(input: StyleLineHeight) -> Self {
7484        Self::LineHeight(StyleLineHeightValue::Exact(input))
7485    }
7486    #[must_use]
7487    pub const fn const_word_spacing(input: StyleWordSpacing) -> Self {
7488        Self::WordSpacing(StyleWordSpacingValue::Exact(input))
7489    }
7490    #[must_use]
7491    pub const fn const_tab_size(input: StyleTabSize) -> Self {
7492        Self::TabSize(StyleTabSizeValue::Exact(input))
7493    }
7494    #[must_use]
7495    pub const fn const_cursor(input: StyleCursor) -> Self {
7496        Self::Cursor(StyleCursorValue::Exact(input))
7497    }
7498    #[must_use]
7499    pub const fn const_display(input: LayoutDisplay) -> Self {
7500        Self::Display(LayoutDisplayValue::Exact(input))
7501    }
7502    #[must_use]
7503    pub const fn const_float(input: LayoutFloat) -> Self {
7504        Self::Float(LayoutFloatValue::Exact(input))
7505    }
7506    #[must_use]
7507    pub const fn const_box_sizing(input: LayoutBoxSizing) -> Self {
7508        Self::BoxSizing(LayoutBoxSizingValue::Exact(input))
7509    }
7510    #[must_use]
7511    pub const fn const_width(input: LayoutWidth) -> Self {
7512        Self::Width(LayoutWidthValue::Exact(input))
7513    }
7514    #[must_use]
7515    pub const fn const_height(input: LayoutHeight) -> Self {
7516        Self::Height(LayoutHeightValue::Exact(input))
7517    }
7518    #[must_use]
7519    pub const fn const_min_width(input: LayoutMinWidth) -> Self {
7520        Self::MinWidth(LayoutMinWidthValue::Exact(input))
7521    }
7522    #[must_use]
7523    pub const fn const_min_height(input: LayoutMinHeight) -> Self {
7524        Self::MinHeight(LayoutMinHeightValue::Exact(input))
7525    }
7526    #[must_use]
7527    pub const fn const_max_width(input: LayoutMaxWidth) -> Self {
7528        Self::MaxWidth(LayoutMaxWidthValue::Exact(input))
7529    }
7530    #[must_use]
7531    pub const fn const_max_height(input: LayoutMaxHeight) -> Self {
7532        Self::MaxHeight(LayoutMaxHeightValue::Exact(input))
7533    }
7534    #[must_use]
7535    pub const fn const_position(input: LayoutPosition) -> Self {
7536        Self::Position(LayoutPositionValue::Exact(input))
7537    }
7538    #[must_use]
7539    pub const fn const_z_index(input: LayoutZIndex) -> Self {
7540        Self::ZIndex(LayoutZIndexValue::Exact(input))
7541    }
7542    #[must_use]
7543    pub const fn const_top(input: LayoutTop) -> Self {
7544        Self::Top(LayoutTopValue::Exact(input))
7545    }
7546    #[must_use]
7547    pub const fn const_right(input: LayoutRight) -> Self {
7548        Self::Right(LayoutRightValue::Exact(input))
7549    }
7550    #[must_use]
7551    pub const fn const_left(input: LayoutLeft) -> Self {
7552        Self::Left(LayoutLeftValue::Exact(input))
7553    }
7554    #[must_use]
7555    pub const fn const_bottom(input: LayoutInsetBottom) -> Self {
7556        Self::Bottom(LayoutInsetBottomValue::Exact(input))
7557    }
7558    #[must_use]
7559    pub const fn const_flex_wrap(input: LayoutFlexWrap) -> Self {
7560        Self::FlexWrap(LayoutFlexWrapValue::Exact(input))
7561    }
7562    #[must_use]
7563    pub const fn const_flex_direction(input: LayoutFlexDirection) -> Self {
7564        Self::FlexDirection(LayoutFlexDirectionValue::Exact(input))
7565    }
7566    #[must_use]
7567    pub const fn const_flex_grow(input: LayoutFlexGrow) -> Self {
7568        Self::FlexGrow(LayoutFlexGrowValue::Exact(input))
7569    }
7570    #[must_use]
7571    pub const fn const_flex_shrink(input: LayoutFlexShrink) -> Self {
7572        Self::FlexShrink(LayoutFlexShrinkValue::Exact(input))
7573    }
7574    #[must_use]
7575    pub const fn const_justify_content(input: LayoutJustifyContent) -> Self {
7576        Self::JustifyContent(LayoutJustifyContentValue::Exact(input))
7577    }
7578    #[must_use]
7579    pub const fn const_align_items(input: LayoutAlignItems) -> Self {
7580        Self::AlignItems(LayoutAlignItemsValue::Exact(input))
7581    }
7582    #[must_use]
7583    pub const fn const_align_content(input: LayoutAlignContent) -> Self {
7584        Self::AlignContent(LayoutAlignContentValue::Exact(input))
7585    }
7586    #[must_use]
7587    pub const fn const_background_content(input: StyleBackgroundContentVec) -> Self {
7588        Self::BackgroundContent(StyleBackgroundContentVecValue::Exact(input))
7589    }
7590    #[must_use]
7591    pub const fn const_background_position(input: StyleBackgroundPositionVec) -> Self {
7592        Self::BackgroundPosition(StyleBackgroundPositionVecValue::Exact(input))
7593    }
7594    #[must_use]
7595    pub const fn const_background_size(input: StyleBackgroundSizeVec) -> Self {
7596        Self::BackgroundSize(StyleBackgroundSizeVecValue::Exact(input))
7597    }
7598    #[must_use]
7599    pub const fn const_background_repeat(input: StyleBackgroundRepeatVec) -> Self {
7600        Self::BackgroundRepeat(StyleBackgroundRepeatVecValue::Exact(input))
7601    }
7602    #[must_use]
7603    pub const fn const_overflow_x(input: LayoutOverflow) -> Self {
7604        Self::OverflowX(LayoutOverflowValue::Exact(input))
7605    }
7606    #[must_use]
7607    pub const fn const_overflow_y(input: LayoutOverflow) -> Self {
7608        Self::OverflowY(LayoutOverflowValue::Exact(input))
7609    }
7610    #[must_use]
7611    pub const fn const_overflow_block(input: LayoutOverflow) -> Self {
7612        Self::OverflowBlock(LayoutOverflowValue::Exact(input))
7613    }
7614    #[must_use]
7615    pub const fn const_overflow_inline(input: LayoutOverflow) -> Self {
7616        Self::OverflowInline(LayoutOverflowValue::Exact(input))
7617    }
7618    #[must_use]
7619    pub const fn const_padding_top(input: LayoutPaddingTop) -> Self {
7620        Self::PaddingTop(LayoutPaddingTopValue::Exact(input))
7621    }
7622    #[must_use]
7623    pub const fn const_padding_left(input: LayoutPaddingLeft) -> Self {
7624        Self::PaddingLeft(LayoutPaddingLeftValue::Exact(input))
7625    }
7626    #[must_use]
7627    pub const fn const_padding_right(input: LayoutPaddingRight) -> Self {
7628        Self::PaddingRight(LayoutPaddingRightValue::Exact(input))
7629    }
7630    #[must_use]
7631    pub const fn const_padding_bottom(input: LayoutPaddingBottom) -> Self {
7632        Self::PaddingBottom(LayoutPaddingBottomValue::Exact(input))
7633    }
7634    #[must_use]
7635    pub const fn const_margin_top(input: LayoutMarginTop) -> Self {
7636        Self::MarginTop(LayoutMarginTopValue::Exact(input))
7637    }
7638    #[must_use]
7639    pub const fn const_margin_left(input: LayoutMarginLeft) -> Self {
7640        Self::MarginLeft(LayoutMarginLeftValue::Exact(input))
7641    }
7642    #[must_use]
7643    pub const fn const_margin_right(input: LayoutMarginRight) -> Self {
7644        Self::MarginRight(LayoutMarginRightValue::Exact(input))
7645    }
7646    #[must_use]
7647    pub const fn const_margin_bottom(input: LayoutMarginBottom) -> Self {
7648        Self::MarginBottom(LayoutMarginBottomValue::Exact(input))
7649    }
7650    #[must_use]
7651    pub const fn const_border_top_left_radius(input: StyleBorderTopLeftRadius) -> Self {
7652        Self::BorderTopLeftRadius(StyleBorderTopLeftRadiusValue::Exact(input))
7653    }
7654    #[must_use]
7655    pub const fn const_border_top_right_radius(input: StyleBorderTopRightRadius) -> Self {
7656        Self::BorderTopRightRadius(StyleBorderTopRightRadiusValue::Exact(input))
7657    }
7658    #[must_use]
7659    pub const fn const_border_bottom_left_radius(input: StyleBorderBottomLeftRadius) -> Self {
7660        Self::BorderBottomLeftRadius(StyleBorderBottomLeftRadiusValue::Exact(input))
7661    }
7662    #[must_use]
7663    pub const fn const_border_bottom_right_radius(input: StyleBorderBottomRightRadius) -> Self {
7664        Self::BorderBottomRightRadius(StyleBorderBottomRightRadiusValue::Exact(input))
7665    }
7666    #[must_use]
7667    pub const fn const_border_top_color(input: StyleBorderTopColor) -> Self {
7668        Self::BorderTopColor(StyleBorderTopColorValue::Exact(input))
7669    }
7670    #[must_use]
7671    pub const fn const_border_right_color(input: StyleBorderRightColor) -> Self {
7672        Self::BorderRightColor(StyleBorderRightColorValue::Exact(input))
7673    }
7674    #[must_use]
7675    pub const fn const_border_left_color(input: StyleBorderLeftColor) -> Self {
7676        Self::BorderLeftColor(StyleBorderLeftColorValue::Exact(input))
7677    }
7678    #[must_use]
7679    pub const fn const_border_bottom_color(input: StyleBorderBottomColor) -> Self {
7680        Self::BorderBottomColor(StyleBorderBottomColorValue::Exact(input))
7681    }
7682    #[must_use]
7683    pub const fn const_border_top_style(input: StyleBorderTopStyle) -> Self {
7684        Self::BorderTopStyle(StyleBorderTopStyleValue::Exact(input))
7685    }
7686    #[must_use]
7687    pub const fn const_border_right_style(input: StyleBorderRightStyle) -> Self {
7688        Self::BorderRightStyle(StyleBorderRightStyleValue::Exact(input))
7689    }
7690    #[must_use]
7691    pub const fn const_border_left_style(input: StyleBorderLeftStyle) -> Self {
7692        Self::BorderLeftStyle(StyleBorderLeftStyleValue::Exact(input))
7693    }
7694    #[must_use]
7695    pub const fn const_border_bottom_style(input: StyleBorderBottomStyle) -> Self {
7696        Self::BorderBottomStyle(StyleBorderBottomStyleValue::Exact(input))
7697    }
7698    #[must_use]
7699    pub const fn const_border_top_width(input: LayoutBorderTopWidth) -> Self {
7700        Self::BorderTopWidth(LayoutBorderTopWidthValue::Exact(input))
7701    }
7702    #[must_use]
7703    pub const fn const_border_right_width(input: LayoutBorderRightWidth) -> Self {
7704        Self::BorderRightWidth(LayoutBorderRightWidthValue::Exact(input))
7705    }
7706    #[must_use]
7707    pub const fn const_border_left_width(input: LayoutBorderLeftWidth) -> Self {
7708        Self::BorderLeftWidth(LayoutBorderLeftWidthValue::Exact(input))
7709    }
7710    #[must_use]
7711    pub const fn const_border_bottom_width(input: LayoutBorderBottomWidth) -> Self {
7712        Self::BorderBottomWidth(LayoutBorderBottomWidthValue::Exact(input))
7713    }
7714    #[must_use]
7715    pub fn const_box_shadow_left(input: StyleBoxShadow) -> Self {
7716        Self::BoxShadowLeft(StyleBoxShadowValue::Exact(BoxOrStatic::heap(input)))
7717    }
7718    #[must_use]
7719    pub fn const_box_shadow_right(input: StyleBoxShadow) -> Self {
7720        Self::BoxShadowRight(StyleBoxShadowValue::Exact(BoxOrStatic::heap(input)))
7721    }
7722    #[must_use]
7723    pub fn const_box_shadow_top(input: StyleBoxShadow) -> Self {
7724        Self::BoxShadowTop(StyleBoxShadowValue::Exact(BoxOrStatic::heap(input)))
7725    }
7726    #[must_use]
7727    pub fn const_box_shadow_bottom(input: StyleBoxShadow) -> Self {
7728        Self::BoxShadowBottom(StyleBoxShadowValue::Exact(BoxOrStatic::heap(input)))
7729    }
7730    #[must_use]
7731    pub const fn const_opacity(input: StyleOpacity) -> Self {
7732        Self::Opacity(StyleOpacityValue::Exact(input))
7733    }
7734    #[must_use]
7735    pub const fn const_transform(input: StyleTransformVec) -> Self {
7736        Self::Transform(StyleTransformVecValue::Exact(input))
7737    }
7738    #[must_use]
7739    pub const fn const_transform_origin(input: StyleTransformOrigin) -> Self {
7740        Self::TransformOrigin(StyleTransformOriginValue::Exact(input))
7741    }
7742    #[must_use]
7743    pub const fn const_perspective_origin(input: StylePerspectiveOrigin) -> Self {
7744        Self::PerspectiveOrigin(StylePerspectiveOriginValue::Exact(input))
7745    }
7746    #[must_use]
7747    pub const fn const_backface_visibility(input: StyleBackfaceVisibility) -> Self {
7748        Self::BackfaceVisibility(StyleBackfaceVisibilityValue::Exact(input))
7749    }
7750    #[must_use]
7751    pub const fn const_break_before(input: PageBreak) -> Self {
7752        Self::BreakBefore(PageBreakValue::Exact(input))
7753    }
7754    #[must_use]
7755    pub const fn const_break_after(input: PageBreak) -> Self {
7756        Self::BreakAfter(PageBreakValue::Exact(input))
7757    }
7758    #[must_use]
7759    pub const fn const_break_inside(input: BreakInside) -> Self {
7760        Self::BreakInside(BreakInsideValue::Exact(input))
7761    }
7762    #[must_use]
7763    pub const fn const_orphans(input: Orphans) -> Self {
7764        Self::Orphans(OrphansValue::Exact(input))
7765    }
7766    #[must_use]
7767    pub const fn const_widows(input: Widows) -> Self {
7768        Self::Widows(WidowsValue::Exact(input))
7769    }
7770    #[must_use]
7771    pub const fn const_box_decoration_break(input: BoxDecorationBreak) -> Self {
7772        Self::BoxDecorationBreak(BoxDecorationBreakValue::Exact(input))
7773    }
7774    #[must_use]
7775    pub const fn const_column_count(input: ColumnCount) -> Self {
7776        Self::ColumnCount(ColumnCountValue::Exact(input))
7777    }
7778    #[must_use]
7779    pub const fn const_column_width(input: ColumnWidth) -> Self {
7780        Self::ColumnWidth(ColumnWidthValue::Exact(input))
7781    }
7782    #[must_use]
7783    pub const fn const_column_span(input: ColumnSpan) -> Self {
7784        Self::ColumnSpan(ColumnSpanValue::Exact(input))
7785    }
7786    #[must_use]
7787    pub const fn const_column_fill(input: ColumnFill) -> Self {
7788        Self::ColumnFill(ColumnFillValue::Exact(input))
7789    }
7790    #[must_use]
7791    pub const fn const_column_rule_width(input: ColumnRuleWidth) -> Self {
7792        Self::ColumnRuleWidth(ColumnRuleWidthValue::Exact(input))
7793    }
7794    #[must_use]
7795    pub const fn const_column_rule_style(input: ColumnRuleStyle) -> Self {
7796        Self::ColumnRuleStyle(ColumnRuleStyleValue::Exact(input))
7797    }
7798    #[must_use]
7799    pub const fn const_column_rule_color(input: ColumnRuleColor) -> Self {
7800        Self::ColumnRuleColor(ColumnRuleColorValue::Exact(input))
7801    }
7802    #[must_use]
7803    pub const fn const_flow_into(input: FlowInto) -> Self {
7804        Self::FlowInto(FlowIntoValue::Exact(input))
7805    }
7806    #[must_use]
7807    pub const fn const_flow_from(input: FlowFrom) -> Self {
7808        Self::FlowFrom(FlowFromValue::Exact(input))
7809    }
7810    #[must_use]
7811    pub const fn const_shape_outside(input: ShapeOutside) -> Self {
7812        Self::ShapeOutside(ShapeOutsideValue::Exact(input))
7813    }
7814    #[must_use]
7815    pub const fn const_shape_inside(input: ShapeInside) -> Self {
7816        Self::ShapeInside(ShapeInsideValue::Exact(input))
7817    }
7818    #[must_use]
7819    pub const fn const_clip_path(input: ClipPath) -> Self {
7820        Self::ClipPath(ClipPathValue::Exact(input))
7821    }
7822    #[must_use]
7823    pub const fn const_shape_margin(input: ShapeMargin) -> Self {
7824        Self::ShapeMargin(ShapeMarginValue::Exact(input))
7825    }
7826    #[must_use]
7827    pub const fn const_shape_image_threshold(input: ShapeImageThreshold) -> Self {
7828        Self::ShapeImageThreshold(ShapeImageThresholdValue::Exact(input))
7829    }
7830    #[must_use]
7831    pub const fn const_content(input: Content) -> Self {
7832        Self::Content(ContentValue::Exact(input))
7833    }
7834    #[must_use]
7835    pub const fn const_counter_reset(input: CounterReset) -> Self {
7836        Self::CounterReset(CounterResetValue::Exact(input))
7837    }
7838    #[must_use]
7839    pub const fn const_counter_increment(input: CounterIncrement) -> Self {
7840        Self::CounterIncrement(CounterIncrementValue::Exact(input))
7841    }
7842    #[must_use]
7843    pub const fn const_list_style_type(input: StyleListStyleType) -> Self {
7844        Self::ListStyleType(StyleListStyleTypeValue::Exact(input))
7845    }
7846    #[must_use]
7847    pub const fn const_list_style_position(input: StyleListStylePosition) -> Self {
7848        Self::ListStylePosition(StyleListStylePositionValue::Exact(input))
7849    }
7850    #[must_use]
7851    pub const fn const_string_set(input: StringSet) -> Self {
7852        Self::StringSet(StringSetValue::Exact(input))
7853    }
7854    #[must_use]
7855    pub const fn const_table_layout(input: LayoutTableLayout) -> Self {
7856        Self::TableLayout(LayoutTableLayoutValue::Exact(input))
7857    }
7858    #[must_use]
7859    pub const fn const_border_collapse(input: StyleBorderCollapse) -> Self {
7860        Self::BorderCollapse(StyleBorderCollapseValue::Exact(input))
7861    }
7862    #[must_use]
7863    pub const fn const_border_spacing(input: LayoutBorderSpacing) -> Self {
7864        Self::BorderSpacing(LayoutBorderSpacingValue::Exact(input))
7865    }
7866    #[must_use]
7867    pub const fn const_caption_side(input: StyleCaptionSide) -> Self {
7868        Self::CaptionSide(StyleCaptionSideValue::Exact(input))
7869    }
7870    #[must_use]
7871    pub const fn const_empty_cells(input: StyleEmptyCells) -> Self {
7872        Self::EmptyCells(StyleEmptyCellsValue::Exact(input))
7873    }
7874}
7875
7876// Cross-type dispatch over CssProperty variants; identical format! bodies bind
7877// different value types and can't merge (clippy::match_same_arms false positive).
7878#[allow(clippy::match_same_arms)]
7879#[allow(clippy::too_many_lines)]
7880// large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
7881#[must_use]
7882pub fn format_static_css_prop(prop: &CssProperty, tabs: usize) -> String {
7883    match prop {
7884        CssProperty::CaretColor(p) => format!(
7885            "CssProperty::CaretColor({})",
7886            print_css_property_value(p, tabs, "CaretColor")
7887        ),
7888        CssProperty::CaretWidth(p) => format!(
7889            "CssProperty::CaretWidth({})",
7890            print_css_property_value(p, tabs, "CaretWidth")
7891        ),
7892        CssProperty::CaretAnimationDuration(p) => format!(
7893            "CssProperty::CaretAnimationDuration({})",
7894            print_css_property_value(p, tabs, "CaretAnimationDuration")
7895        ),
7896        CssProperty::Animation(p) => format!(
7897            "CssProperty::Animation({})",
7898            print_css_property_value(p, tabs, "StyleAnimation")
7899        ),
7900        CssProperty::AnimationIn(p) => format!(
7901            "CssProperty::AnimationIn({})",
7902            print_css_property_value(p, tabs, "StyleAnimation")
7903        ),
7904        CssProperty::AnimationOut(p) => format!(
7905            "CssProperty::AnimationOut({})",
7906            print_css_property_value(p, tabs, "StyleAnimation")
7907        ),
7908        CssProperty::SelectionBackgroundColor(p) => format!(
7909            "CssProperty::SelectionBackgroundColor({})",
7910            print_css_property_value(p, tabs, "SelectionBackgroundColor")
7911        ),
7912        CssProperty::SelectionColor(p) => format!(
7913            "CssProperty::SelectionColor({})",
7914            print_css_property_value(p, tabs, "SelectionColor")
7915        ),
7916        CssProperty::SelectionRadius(p) => format!(
7917            "CssProperty::SelectionRadius({})",
7918            print_css_property_value(p, tabs, "SelectionRadius")
7919        ),
7920        CssProperty::TextJustify(p) => format!(
7921            "CssProperty::TextJustify({})",
7922            print_css_property_value(p, tabs, "LayoutTextJustify")
7923        ),
7924        CssProperty::TextColor(p) => format!(
7925            "CssProperty::TextColor({})",
7926            print_css_property_value(p, tabs, "StyleTextColor")
7927        ),
7928        CssProperty::FontSize(p) => format!(
7929            "CssProperty::FontSize({})",
7930            print_css_property_value(p, tabs, "StyleFontSize")
7931        ),
7932        CssProperty::FontFamily(p) => format!(
7933            "CssProperty::FontFamily({})",
7934            print_css_property_value(p, tabs, "StyleFontFamilyVec")
7935        ),
7936        CssProperty::TextAlign(p) => format!(
7937            "CssProperty::TextAlign({})",
7938            print_css_property_value(p, tabs, "StyleTextAlign")
7939        ),
7940        CssProperty::VerticalAlign(p) => format!(
7941            "CssProperty::VerticalAlign({})",
7942            print_css_property_value(p, tabs, "StyleVerticalAlign")
7943        ),
7944        CssProperty::LetterSpacing(p) => format!(
7945            "CssProperty::LetterSpacing({})",
7946            print_css_property_value(p, tabs, "StyleLetterSpacing")
7947        ),
7948        CssProperty::TextIndent(p) => format!(
7949            "CssProperty::TextIndent({})",
7950            print_css_property_value(p, tabs, "StyleTextIndent")
7951        ),
7952        CssProperty::InitialLetter(p) => format!(
7953            "CssProperty::InitialLetter({})",
7954            print_css_property_value(p, tabs, "StyleInitialLetter")
7955        ),
7956        CssProperty::LineClamp(p) => format!(
7957            "CssProperty::LineClamp({})",
7958            print_css_property_value(p, tabs, "StyleLineClamp")
7959        ),
7960        CssProperty::HangingPunctuation(p) => format!(
7961            "CssProperty::HangingPunctuation({})",
7962            print_css_property_value(p, tabs, "StyleHangingPunctuation")
7963        ),
7964        CssProperty::TextCombineUpright(p) => format!(
7965            "CssProperty::TextCombineUpright({})",
7966            print_css_property_value(p, tabs, "StyleTextCombineUpright")
7967        ),
7968        CssProperty::UnicodeBidi(p) => format!(
7969            "CssProperty::UnicodeBidi({})",
7970            print_css_property_value(p, tabs, "StyleUnicodeBidi")
7971        ),
7972        CssProperty::TextBoxTrim(p) => format!(
7973            "CssProperty::TextBoxTrim({})",
7974            print_css_property_value(p, tabs, "StyleTextBoxTrim")
7975        ),
7976        CssProperty::TextBoxEdge(p) => format!(
7977            "CssProperty::TextBoxEdge({})",
7978            print_css_property_value(p, tabs, "StyleTextBoxEdge")
7979        ),
7980        CssProperty::DominantBaseline(p) => format!(
7981            "CssProperty::DominantBaseline({})",
7982            print_css_property_value(p, tabs, "StyleDominantBaseline")
7983        ),
7984        CssProperty::AlignmentBaseline(p) => format!(
7985            "CssProperty::AlignmentBaseline({})",
7986            print_css_property_value(p, tabs, "StyleAlignmentBaseline")
7987        ),
7988        CssProperty::BaselineSource(p) => format!(
7989            "CssProperty::BaselineSource({})",
7990            print_css_property_value(p, tabs, "StyleBaselineSource")
7991        ),
7992        CssProperty::LineFitEdge(p) => format!(
7993            "CssProperty::LineFitEdge({})",
7994            print_css_property_value(p, tabs, "StyleLineFitEdge")
7995        ),
7996        CssProperty::InitialLetterAlign(p) => format!(
7997            "CssProperty::InitialLetterAlign({})",
7998            print_css_property_value(p, tabs, "StyleInitialLetterAlign")
7999        ),
8000        CssProperty::InitialLetterWrap(p) => format!(
8001            "CssProperty::InitialLetterWrap({})",
8002            print_css_property_value(p, tabs, "StyleInitialLetterWrap")
8003        ),
8004        CssProperty::ScrollbarGutter(p) => format!(
8005            "CssProperty::ScrollbarGutter({})",
8006            print_css_property_value(p, tabs, "StyleScrollbarGutter")
8007        ),
8008        CssProperty::OverflowClipMargin(p) => format!(
8009            "CssProperty::OverflowClipMargin({})",
8010            print_css_property_value(p, tabs, "StyleOverflowClipMargin")
8011        ),
8012        CssProperty::Clip(p) => format!(
8013            "CssProperty::Clip({})",
8014            print_css_property_value(p, tabs, "StyleClipRect")
8015        ),
8016        CssProperty::ExclusionMargin(p) => format!(
8017            "CssProperty::ExclusionMargin({})",
8018            print_css_property_value(p, tabs, "StyleExclusionMargin")
8019        ),
8020        CssProperty::HyphenationLanguage(p) => format!(
8021            "CssProperty::HyphenationLanguage({})",
8022            print_css_property_value(p, tabs, "StyleHyphenationLanguage")
8023        ),
8024        CssProperty::LineHeight(p) => format!(
8025            "CssProperty::LineHeight({})",
8026            print_css_property_value(p, tabs, "StyleLineHeight")
8027        ),
8028        CssProperty::WordSpacing(p) => format!(
8029            "CssProperty::WordSpacing({})",
8030            print_css_property_value(p, tabs, "StyleWordSpacing")
8031        ),
8032        CssProperty::TabSize(p) => format!(
8033            "CssProperty::TabSize({})",
8034            print_css_property_value(p, tabs, "StyleTabSize")
8035        ),
8036        CssProperty::Cursor(p) => format!(
8037            "CssProperty::Cursor({})",
8038            print_css_property_value(p, tabs, "StyleCursor")
8039        ),
8040        CssProperty::Display(p) => format!(
8041            "CssProperty::Display({})",
8042            print_css_property_value(p, tabs, "LayoutDisplay")
8043        ),
8044        CssProperty::Float(p) => format!(
8045            "CssProperty::Float({})",
8046            print_css_property_value(p, tabs, "LayoutFloat")
8047        ),
8048        CssProperty::BoxSizing(p) => format!(
8049            "CssProperty::BoxSizing({})",
8050            print_css_property_value(p, tabs, "LayoutBoxSizing")
8051        ),
8052        CssProperty::Width(p) => format!(
8053            "CssProperty::Width({})",
8054            print_css_property_value(p, tabs, "LayoutWidth")
8055        ),
8056        CssProperty::Height(p) => format!(
8057            "CssProperty::Height({})",
8058            print_css_property_value(p, tabs, "LayoutHeight")
8059        ),
8060        CssProperty::MinWidth(p) => format!(
8061            "CssProperty::MinWidth({})",
8062            print_css_property_value(p, tabs, "LayoutMinWidth")
8063        ),
8064        CssProperty::MinHeight(p) => format!(
8065            "CssProperty::MinHeight({})",
8066            print_css_property_value(p, tabs, "LayoutMinHeight")
8067        ),
8068        CssProperty::MaxWidth(p) => format!(
8069            "CssProperty::MaxWidth({})",
8070            print_css_property_value(p, tabs, "LayoutMaxWidth")
8071        ),
8072        CssProperty::MaxHeight(p) => format!(
8073            "CssProperty::MaxHeight({})",
8074            print_css_property_value(p, tabs, "LayoutMaxHeight")
8075        ),
8076        CssProperty::Position(p) => format!(
8077            "CssProperty::Position({})",
8078            print_css_property_value(p, tabs, "LayoutPosition")
8079        ),
8080        CssProperty::Top(p) => format!(
8081            "CssProperty::Top({})",
8082            print_css_property_value(p, tabs, "LayoutTop")
8083        ),
8084        CssProperty::Right(p) => format!(
8085            "CssProperty::Right({})",
8086            print_css_property_value(p, tabs, "LayoutRight")
8087        ),
8088        CssProperty::Left(p) => format!(
8089            "CssProperty::Left({})",
8090            print_css_property_value(p, tabs, "LayoutLeft")
8091        ),
8092        CssProperty::Bottom(p) => format!(
8093            "CssProperty::Bottom({})",
8094            print_css_property_value(p, tabs, "LayoutInsetBottom")
8095        ),
8096        CssProperty::ZIndex(p) => format!(
8097            "CssProperty::ZIndex({})",
8098            print_css_property_value(p, tabs, "LayoutZIndex")
8099        ),
8100        CssProperty::FlexWrap(p) => format!(
8101            "CssProperty::FlexWrap({})",
8102            print_css_property_value(p, tabs, "LayoutFlexWrap")
8103        ),
8104        CssProperty::FlexDirection(p) => format!(
8105            "CssProperty::FlexDirection({})",
8106            print_css_property_value(p, tabs, "LayoutFlexDirection")
8107        ),
8108        CssProperty::FlexGrow(p) => format!(
8109            "CssProperty::FlexGrow({})",
8110            print_css_property_value(p, tabs, "LayoutFlexGrow")
8111        ),
8112        CssProperty::FlexShrink(p) => format!(
8113            "CssProperty::FlexShrink({})",
8114            print_css_property_value(p, tabs, "LayoutFlexShrink")
8115        ),
8116        CssProperty::JustifyContent(p) => format!(
8117            "CssProperty::JustifyContent({})",
8118            print_css_property_value(p, tabs, "LayoutJustifyContent")
8119        ),
8120        CssProperty::AlignItems(p) => format!(
8121            "CssProperty::AlignItems({})",
8122            print_css_property_value(p, tabs, "LayoutAlignItems")
8123        ),
8124        CssProperty::AlignContent(p) => format!(
8125            "CssProperty::AlignContent({})",
8126            print_css_property_value(p, tabs, "LayoutAlignContent")
8127        ),
8128        CssProperty::BackgroundContent(p) => format!(
8129            "CssProperty::BackgroundContent({})",
8130            print_css_property_value(p, tabs, "StyleBackgroundContentVec")
8131        ),
8132        CssProperty::BackgroundPosition(p) => format!(
8133            "CssProperty::BackgroundPosition({})",
8134            print_css_property_value(p, tabs, "StyleBackgroundPositionVec")
8135        ),
8136        CssProperty::BackgroundSize(p) => format!(
8137            "CssProperty::BackgroundSize({})",
8138            print_css_property_value(p, tabs, "StyleBackgroundSizeVec")
8139        ),
8140        CssProperty::BackgroundRepeat(p) => format!(
8141            "CssProperty::BackgroundRepeat({})",
8142            print_css_property_value(p, tabs, "StyleBackgroundRepeatVec")
8143        ),
8144        CssProperty::OverflowX(p) => format!(
8145            "CssProperty::OverflowX({})",
8146            print_css_property_value(p, tabs, "LayoutOverflow")
8147        ),
8148        CssProperty::OverflowY(p) => format!(
8149            "CssProperty::OverflowY({})",
8150            print_css_property_value(p, tabs, "LayoutOverflow")
8151        ),
8152        CssProperty::OverflowBlock(p) => format!(
8153            "CssProperty::OverflowBlock({})",
8154            print_css_property_value(p, tabs, "LayoutOverflow")
8155        ),
8156        CssProperty::OverflowInline(p) => format!(
8157            "CssProperty::OverflowInline({})",
8158            print_css_property_value(p, tabs, "LayoutOverflow")
8159        ),
8160        CssProperty::PaddingTop(p) => format!(
8161            "CssProperty::PaddingTop({})",
8162            print_css_property_value(p, tabs, "LayoutPaddingTop")
8163        ),
8164        CssProperty::PaddingLeft(p) => format!(
8165            "CssProperty::PaddingLeft({})",
8166            print_css_property_value(p, tabs, "LayoutPaddingLeft")
8167        ),
8168        CssProperty::PaddingRight(p) => format!(
8169            "CssProperty::PaddingRight({})",
8170            print_css_property_value(p, tabs, "LayoutPaddingRight")
8171        ),
8172        CssProperty::PaddingBottom(p) => format!(
8173            "CssProperty::PaddingBottom({})",
8174            print_css_property_value(p, tabs, "LayoutPaddingBottom")
8175        ),
8176        CssProperty::PaddingInlineStart(p) => format!(
8177            "CssProperty::PaddingInlineStart({})",
8178            print_css_property_value(p, tabs, "LayoutPaddingInlineStart")
8179        ),
8180        CssProperty::PaddingInlineEnd(p) => format!(
8181            "CssProperty::PaddingInlineEnd({})",
8182            print_css_property_value(p, tabs, "LayoutPaddingInlineEnd")
8183        ),
8184        CssProperty::MarginTop(p) => format!(
8185            "CssProperty::MarginTop({})",
8186            print_css_property_value(p, tabs, "LayoutMarginTop")
8187        ),
8188        CssProperty::MarginLeft(p) => format!(
8189            "CssProperty::MarginLeft({})",
8190            print_css_property_value(p, tabs, "LayoutMarginLeft")
8191        ),
8192        CssProperty::MarginRight(p) => format!(
8193            "CssProperty::MarginRight({})",
8194            print_css_property_value(p, tabs, "LayoutMarginRight")
8195        ),
8196        CssProperty::MarginBottom(p) => format!(
8197            "CssProperty::MarginBottom({})",
8198            print_css_property_value(p, tabs, "LayoutMarginBottom")
8199        ),
8200        CssProperty::BorderTopLeftRadius(p) => format!(
8201            "CssProperty::BorderTopLeftRadius({})",
8202            print_css_property_value(p, tabs, "StyleBorderTopLeftRadius")
8203        ),
8204        CssProperty::BorderTopRightRadius(p) => format!(
8205            "CssProperty::BorderTopRightRadius({})",
8206            print_css_property_value(p, tabs, "StyleBorderTopRightRadius")
8207        ),
8208        CssProperty::BorderBottomLeftRadius(p) => format!(
8209            "CssProperty::BorderBottomLeftRadius({})",
8210            print_css_property_value(p, tabs, "StyleBorderBottomLeftRadius")
8211        ),
8212        CssProperty::BorderBottomRightRadius(p) => format!(
8213            "CssProperty::BorderBottomRightRadius({})",
8214            print_css_property_value(p, tabs, "StyleBorderBottomRightRadius")
8215        ),
8216        CssProperty::BorderTopColor(p) => format!(
8217            "CssProperty::BorderTopColor({})",
8218            print_css_property_value(p, tabs, "StyleBorderTopColor")
8219        ),
8220        CssProperty::BorderRightColor(p) => format!(
8221            "CssProperty::BorderRightColor({})",
8222            print_css_property_value(p, tabs, "StyleBorderRightColor")
8223        ),
8224        CssProperty::BorderLeftColor(p) => format!(
8225            "CssProperty::BorderLeftColor({})",
8226            print_css_property_value(p, tabs, "StyleBorderLeftColor")
8227        ),
8228        CssProperty::BorderBottomColor(p) => format!(
8229            "CssProperty::BorderBottomColor({})",
8230            print_css_property_value(p, tabs, "StyleBorderBottomColor")
8231        ),
8232        CssProperty::BorderTopStyle(p) => format!(
8233            "CssProperty::BorderTopStyle({})",
8234            print_css_property_value(p, tabs, "StyleBorderTopStyle")
8235        ),
8236        CssProperty::BorderRightStyle(p) => format!(
8237            "CssProperty::BorderRightStyle({})",
8238            print_css_property_value(p, tabs, "StyleBorderRightStyle")
8239        ),
8240        CssProperty::BorderLeftStyle(p) => format!(
8241            "CssProperty::BorderLeftStyle({})",
8242            print_css_property_value(p, tabs, "StyleBorderLeftStyle")
8243        ),
8244        CssProperty::BorderBottomStyle(p) => format!(
8245            "CssProperty::BorderBottomStyle({})",
8246            print_css_property_value(p, tabs, "StyleBorderBottomStyle")
8247        ),
8248        CssProperty::BorderTopWidth(p) => format!(
8249            "CssProperty::BorderTopWidth({})",
8250            print_css_property_value(p, tabs, "LayoutBorderTopWidth")
8251        ),
8252        CssProperty::BorderRightWidth(p) => format!(
8253            "CssProperty::BorderRightWidth({})",
8254            print_css_property_value(p, tabs, "LayoutBorderRightWidth")
8255        ),
8256        CssProperty::BorderLeftWidth(p) => format!(
8257            "CssProperty::BorderLeftWidth({})",
8258            print_css_property_value(p, tabs, "LayoutBorderLeftWidth")
8259        ),
8260        CssProperty::BorderBottomWidth(p) => format!(
8261            "CssProperty::BorderBottomWidth({})",
8262            print_css_property_value(p, tabs, "LayoutBorderBottomWidth")
8263        ),
8264        CssProperty::BoxShadowLeft(p) => format!(
8265            "CssProperty::BoxShadowLeft({})",
8266            print_css_property_value(p, tabs, "StyleBoxShadow")
8267        ),
8268        CssProperty::BoxShadowRight(p) => format!(
8269            "CssProperty::BoxShadowRight({})",
8270            print_css_property_value(p, tabs, "StyleBoxShadow")
8271        ),
8272        CssProperty::BoxShadowTop(p) => format!(
8273            "CssProperty::BoxShadowTop({})",
8274            print_css_property_value(p, tabs, "StyleBoxShadow")
8275        ),
8276        CssProperty::BoxShadowBottom(p) => format!(
8277            "CssProperty::BoxShadowBottom({})",
8278            print_css_property_value(p, tabs, "StyleBoxShadow")
8279        ),
8280        CssProperty::OverscrollBehaviorX(p) => format!(
8281            "CssProperty::OverscrollBehaviorX({})",
8282            print_css_property_value(p, tabs, "OverscrollBehavior")
8283        ),
8284        CssProperty::OverscrollBehaviorY(p) => format!(
8285            "CssProperty::OverscrollBehaviorY({})",
8286            print_css_property_value(p, tabs, "OverscrollBehavior")
8287        ),
8288        CssProperty::ScrollbarWidth(p) => format!(
8289            "CssProperty::ScrollbarWidth({})",
8290            print_css_property_value(p, tabs, "LayoutScrollbarWidth")
8291        ),
8292        CssProperty::ScrollbarColor(p) => format!(
8293            "CssProperty::ScrollbarColor({})",
8294            print_css_property_value(p, tabs, "StyleScrollbarColor")
8295        ),
8296        CssProperty::ScrollbarVisibility(p) => format!(
8297            "CssProperty::ScrollbarVisibility({})",
8298            print_css_property_value(p, tabs, "ScrollbarVisibilityMode")
8299        ),
8300        CssProperty::ScrollbarFadeDelay(p) => format!(
8301            "CssProperty::ScrollbarFadeDelay({})",
8302            print_css_property_value(p, tabs, "ScrollbarFadeDelay")
8303        ),
8304        CssProperty::ScrollbarFadeDuration(p) => format!(
8305            "CssProperty::ScrollbarFadeDuration({})",
8306            print_css_property_value(p, tabs, "ScrollbarFadeDuration")
8307        ),
8308        CssProperty::ScrollbarTrack(p) => format!(
8309            "CssProperty::ScrollbarTrack({})",
8310            print_css_property_value(p, tabs, "StyleBackgroundContent")
8311        ),
8312        CssProperty::ScrollbarThumb(p) => format!(
8313            "CssProperty::ScrollbarThumb({})",
8314            print_css_property_value(p, tabs, "StyleBackgroundContent")
8315        ),
8316        CssProperty::ScrollbarButton(p) => format!(
8317            "CssProperty::ScrollbarButton({})",
8318            print_css_property_value(p, tabs, "StyleBackgroundContent")
8319        ),
8320        CssProperty::ScrollbarCorner(p) => format!(
8321            "CssProperty::ScrollbarCorner({})",
8322            print_css_property_value(p, tabs, "StyleBackgroundContent")
8323        ),
8324        CssProperty::ScrollbarResizer(p) => format!(
8325            "CssProperty::ScrollbarResizer({})",
8326            print_css_property_value(p, tabs, "StyleBackgroundContent")
8327        ),
8328        CssProperty::Opacity(p) => format!(
8329            "CssProperty::Opacity({})",
8330            print_css_property_value(p, tabs, "StyleOpacity")
8331        ),
8332        CssProperty::Visibility(p) => format!(
8333            "CssProperty::Visibility({})",
8334            print_css_property_value(p, tabs, "StyleVisibility")
8335        ),
8336        CssProperty::Transform(p) => format!(
8337            "CssProperty::Transform({})",
8338            print_css_property_value(p, tabs, "StyleTransformVec")
8339        ),
8340        CssProperty::TransformOrigin(p) => format!(
8341            "CssProperty::TransformOrigin({})",
8342            print_css_property_value(p, tabs, "StyleTransformOrigin")
8343        ),
8344        CssProperty::PerspectiveOrigin(p) => format!(
8345            "CssProperty::PerspectiveOrigin({})",
8346            print_css_property_value(p, tabs, "StylePerspectiveOrigin")
8347        ),
8348        CssProperty::BackfaceVisibility(p) => format!(
8349            "CssProperty::BackfaceVisibility({})",
8350            print_css_property_value(p, tabs, "StyleBackfaceVisibility")
8351        ),
8352        CssProperty::SpatialNavigationAction(p) => format!(
8353            "CssProperty::SpatialNavigationAction({})",
8354            print_css_property_value(p, tabs, "StyleSpatialNavigationAction")
8355        ),
8356        CssProperty::SpatialNavigationContain(p) => format!(
8357            "CssProperty::SpatialNavigationContain({})",
8358            print_css_property_value(p, tabs, "StyleSpatialNavigationContain")
8359        ),
8360        CssProperty::AppRegion(p) => format!(
8361            "CssProperty::AppRegion({})",
8362            print_css_property_value(p, tabs, "StyleAppRegion")
8363        ),
8364        CssProperty::MixBlendMode(p) => format!(
8365            "CssProperty::MixBlendMode({})",
8366            print_css_property_value(p, tabs, "StyleMixBlendMode")
8367        ),
8368        CssProperty::Filter(p) => format!(
8369            "CssProperty::Filter({})",
8370            print_css_property_value(p, tabs, "StyleFilterVec")
8371        ),
8372        CssProperty::BackdropFilter(p) => format!(
8373            "CssProperty::Filter({})",
8374            print_css_property_value(p, tabs, "StyleFilterVec")
8375        ),
8376        CssProperty::TextShadow(p) => format!(
8377            "CssProperty::TextShadow({})",
8378            print_css_property_value(p, tabs, "StyleBoxShadow")
8379        ),
8380        CssProperty::Hyphens(p) => format!(
8381            "CssProperty::Hyphens({})",
8382            print_css_property_value(p, tabs, "StyleHyphens")
8383        ),
8384        CssProperty::WordBreak(p) => format!(
8385            "CssProperty::WordBreak({})",
8386            print_css_property_value(p, tabs, "StyleWordBreak")
8387        ),
8388        CssProperty::OverflowWrap(p) => format!(
8389            "CssProperty::OverflowWrap({})",
8390            print_css_property_value(p, tabs, "StyleOverflowWrap")
8391        ),
8392        CssProperty::LineBreak(p) => format!(
8393            "CssProperty::LineBreak({})",
8394            print_css_property_value(p, tabs, "StyleLineBreak")
8395        ),
8396        CssProperty::TextOverflow(p) => format!(
8397            "CssProperty::TextOverflow({})",
8398            print_css_property_value(p, tabs, "StyleTextOverflow")
8399        ),
8400        CssProperty::ObjectFit(p) => format!(
8401            "CssProperty::ObjectFit({})",
8402            print_css_property_value(p, tabs, "StyleObjectFit")
8403        ),
8404        CssProperty::ObjectPosition(p) => format!(
8405            "CssProperty::ObjectPosition({})",
8406            print_css_property_value(p, tabs, "StyleObjectPosition")
8407        ),
8408        CssProperty::AspectRatio(p) => format!(
8409            "CssProperty::AspectRatio({})",
8410            print_css_property_value(p, tabs, "StyleAspectRatio")
8411        ),
8412        CssProperty::TextOrientation(p) => format!(
8413            "CssProperty::TextOrientation({})",
8414            print_css_property_value(p, tabs, "StyleTextOrientation")
8415        ),
8416        CssProperty::TextAlignLast(p) => format!(
8417            "CssProperty::TextAlignLast({})",
8418            print_css_property_value(p, tabs, "StyleTextAlignLast")
8419        ),
8420        CssProperty::TextTransform(p) => format!(
8421            "CssProperty::TextTransform({})",
8422            print_css_property_value(p, tabs, "StyleTextTransform")
8423        ),
8424        CssProperty::Direction(p) => format!(
8425            "CssProperty::Direction({})",
8426            print_css_property_value(p, tabs, "Direction")
8427        ),
8428        CssProperty::UserSelect(p) => format!(
8429            "CssProperty::UserSelect({})",
8430            print_css_property_value(p, tabs, "StyleUserSelect")
8431        ),
8432        CssProperty::TextDecoration(p) => format!(
8433            "CssProperty::TextDecoration({})",
8434            print_css_property_value(p, tabs, "StyleTextDecoration")
8435        ),
8436        CssProperty::WhiteSpace(p) => format!(
8437            "CssProperty::WhiteSpace({})",
8438            print_css_property_value(p, tabs, "WhiteSpace")
8439        ),
8440        CssProperty::FlexBasis(p) => format!(
8441            "CssProperty::FlexBasis({})",
8442            print_css_property_value(p, tabs, "LayoutFlexBasis")
8443        ),
8444        CssProperty::ColumnGap(p) => format!(
8445            "CssProperty::ColumnGap({})",
8446            print_css_property_value(p, tabs, "LayoutColumnGap")
8447        ),
8448        CssProperty::RowGap(p) => format!(
8449            "CssProperty::RowGap({})",
8450            print_css_property_value(p, tabs, "LayoutRowGap")
8451        ),
8452        CssProperty::GridTemplateColumns(p) => format!(
8453            "CssProperty::GridTemplateColumns({})",
8454            print_css_property_value(p, tabs, "LayoutGridTemplateColumns")
8455        ),
8456        CssProperty::GridTemplateRows(p) => format!(
8457            "CssProperty::GridTemplateRows({})",
8458            print_css_property_value(p, tabs, "LayoutGridTemplateRows")
8459        ),
8460        CssProperty::GridAutoFlow(p) => format!(
8461            "CssProperty::GridAutoFlow({})",
8462            print_css_property_value(p, tabs, "LayoutGridAutoFlow")
8463        ),
8464        CssProperty::JustifySelf(p) => format!(
8465            "CssProperty::JustifySelf({})",
8466            print_css_property_value(p, tabs, "LayoutJustifySelf")
8467        ),
8468        CssProperty::JustifyItems(p) => format!(
8469            "CssProperty::JustifyItems({})",
8470            print_css_property_value(p, tabs, "LayoutJustifyItems")
8471        ),
8472        CssProperty::Gap(p) => format!(
8473            "CssProperty::Gap({})",
8474            print_css_property_value(p, tabs, "LayoutGap")
8475        ),
8476        CssProperty::GridGap(p) => format!(
8477            "CssProperty::GridGap({})",
8478            print_css_property_value(p, tabs, "LayoutGap")
8479        ),
8480        CssProperty::AlignSelf(p) => format!(
8481            "CssProperty::AlignSelf({})",
8482            print_css_property_value(p, tabs, "LayoutAlignSelf")
8483        ),
8484        CssProperty::Font(p) => format!(
8485            "CssProperty::Font({})",
8486            print_css_property_value(p, tabs, "StyleFontFamilyVec")
8487        ),
8488        CssProperty::GridAutoRows(p) => format!(
8489            "CssProperty::GridAutoRows({})",
8490            print_css_property_value(p, tabs, "LayoutGridAutoRows")
8491        ),
8492        CssProperty::GridAutoColumns(p) => format!(
8493            "CssProperty::GridAutoColumns({})",
8494            print_css_property_value(p, tabs, "LayoutGridAutoColumns")
8495        ),
8496        CssProperty::GridRow(p) => format!(
8497            "CssProperty::GridRow({})",
8498            print_css_property_value(p, tabs, "LayoutGridRow")
8499        ),
8500        CssProperty::GridColumn(p) => format!(
8501            "CssProperty::GridColumn({})",
8502            print_css_property_value(p, tabs, "LayoutGridColumn")
8503        ),
8504        CssProperty::GridTemplateAreas(p) => format!(
8505            "CssProperty::GridTemplateAreas({})",
8506            print_css_property_value(p, tabs, "GridTemplateAreas")
8507        ),
8508        CssProperty::WritingMode(p) => format!(
8509            "CssProperty::WritingMode({})",
8510            print_css_property_value(p, tabs, "LayoutWritingMode")
8511        ),
8512        CssProperty::Clear(p) => format!(
8513            "CssProperty::Clear({})",
8514            print_css_property_value(p, tabs, "LayoutClear")
8515        ),
8516        CssProperty::BreakBefore(p) => format!(
8517            "CssProperty::BreakBefore({})",
8518            print_css_property_value(p, tabs, "PageBreak")
8519        ),
8520        CssProperty::BreakAfter(p) => format!(
8521            "CssProperty::BreakAfter({})",
8522            print_css_property_value(p, tabs, "PageBreak")
8523        ),
8524        CssProperty::BreakInside(p) => format!(
8525            "CssProperty::BreakInside({})",
8526            print_css_property_value(p, tabs, "BreakInside")
8527        ),
8528        CssProperty::Orphans(p) => format!(
8529            "CssProperty::Orphans({})",
8530            print_css_property_value(p, tabs, "Orphans")
8531        ),
8532        CssProperty::Widows(p) => format!(
8533            "CssProperty::Widows({})",
8534            print_css_property_value(p, tabs, "Widows")
8535        ),
8536        CssProperty::BoxDecorationBreak(p) => format!(
8537            "CssProperty::BoxDecorationBreak({})",
8538            print_css_property_value(p, tabs, "BoxDecorationBreak")
8539        ),
8540        CssProperty::ColumnCount(p) => format!(
8541            "CssProperty::ColumnCount({})",
8542            print_css_property_value(p, tabs, "ColumnCount")
8543        ),
8544        CssProperty::ColumnWidth(p) => format!(
8545            "CssProperty::ColumnWidth({})",
8546            print_css_property_value(p, tabs, "ColumnWidth")
8547        ),
8548        CssProperty::ColumnSpan(p) => format!(
8549            "CssProperty::ColumnSpan({})",
8550            print_css_property_value(p, tabs, "ColumnSpan")
8551        ),
8552        CssProperty::ColumnFill(p) => format!(
8553            "CssProperty::ColumnFill({})",
8554            print_css_property_value(p, tabs, "ColumnFill")
8555        ),
8556        CssProperty::ColumnRuleWidth(p) => format!(
8557            "CssProperty::ColumnRuleWidth({})",
8558            print_css_property_value(p, tabs, "ColumnRuleWidth")
8559        ),
8560        CssProperty::ColumnRuleStyle(p) => format!(
8561            "CssProperty::ColumnRuleStyle({})",
8562            print_css_property_value(p, tabs, "ColumnRuleStyle")
8563        ),
8564        CssProperty::ColumnRuleColor(p) => format!(
8565            "CssProperty::ColumnRuleColor({})",
8566            print_css_property_value(p, tabs, "ColumnRuleColor")
8567        ),
8568        CssProperty::FlowInto(p) => format!(
8569            "CssProperty::FlowInto({})",
8570            print_css_property_value(p, tabs, "FlowInto")
8571        ),
8572        CssProperty::FlowFrom(p) => format!(
8573            "CssProperty::FlowFrom({})",
8574            print_css_property_value(p, tabs, "FlowFrom")
8575        ),
8576        CssProperty::ShapeOutside(p) => format!(
8577            "CssProperty::ShapeOutside({})",
8578            print_css_property_value(p, tabs, "ShapeOutside")
8579        ),
8580        CssProperty::ShapeInside(p) => format!(
8581            "CssProperty::ShapeInside({})",
8582            print_css_property_value(p, tabs, "ShapeInside")
8583        ),
8584        CssProperty::ClipPath(p) => format!(
8585            "CssProperty::ClipPath({})",
8586            print_css_property_value(p, tabs, "ClipPath")
8587        ),
8588        CssProperty::ShapeMargin(p) => format!(
8589            "CssProperty::ShapeMargin({})",
8590            print_css_property_value(p, tabs, "ShapeMargin")
8591        ),
8592        CssProperty::ShapeImageThreshold(p) => format!(
8593            "CssProperty::ShapeImageThreshold({})",
8594            print_css_property_value(p, tabs, "ShapeImageThreshold")
8595        ),
8596        CssProperty::Content(p) => format!(
8597            "CssProperty::Content({})",
8598            print_css_property_value(p, tabs, "Content")
8599        ),
8600        CssProperty::CounterReset(p) => format!(
8601            "CssProperty::CounterReset({})",
8602            print_css_property_value(p, tabs, "CounterReset")
8603        ),
8604        CssProperty::CounterIncrement(p) => format!(
8605            "CssProperty::CounterIncrement({})",
8606            print_css_property_value(p, tabs, "CounterIncrement")
8607        ),
8608        CssProperty::ListStyleType(p) => format!(
8609            "CssProperty::ListStyleType({})",
8610            print_css_property_value(p, tabs, "StyleListStyleType")
8611        ),
8612        CssProperty::ListStylePosition(p) => format!(
8613            "CssProperty::ListStylePosition({})",
8614            print_css_property_value(p, tabs, "StyleListStylePosition")
8615        ),
8616        CssProperty::StringSet(p) => format!(
8617            "CssProperty::StringSet({})",
8618            print_css_property_value(p, tabs, "StringSet")
8619        ),
8620        CssProperty::TableLayout(p) => format!(
8621            "CssProperty::TableLayout({})",
8622            print_css_property_value(p, tabs, "LayoutTableLayout")
8623        ),
8624        CssProperty::BorderCollapse(p) => format!(
8625            "CssProperty::BorderCollapse({})",
8626            print_css_property_value(p, tabs, "StyleBorderCollapse")
8627        ),
8628        CssProperty::BorderSpacing(p) => format!(
8629            "CssProperty::BorderSpacing({})",
8630            print_css_property_value(p, tabs, "LayoutBorderSpacing")
8631        ),
8632        CssProperty::CaptionSide(p) => format!(
8633            "CssProperty::CaptionSide({})",
8634            print_css_property_value(p, tabs, "StyleCaptionSide")
8635        ),
8636        CssProperty::EmptyCells(p) => format!(
8637            "CssProperty::EmptyCells({})",
8638            print_css_property_value(p, tabs, "StyleEmptyCells")
8639        ),
8640        CssProperty::FontWeight(p) => format!(
8641            "CssProperty::FontWeight({})",
8642            print_css_property_value(p, tabs, "StyleFontWeight")
8643        ),
8644        CssProperty::FontStyle(p) => format!(
8645            "CssProperty::FontStyle({})",
8646            print_css_property_value(p, tabs, "StyleFontStyle")
8647        ),
8648    }
8649}
8650
8651fn print_css_property_value<T: FormatAsRustCode>(
8652    prop_val: &CssPropertyValue<T>,
8653    tabs: usize,
8654    property_value_type: &'static str,
8655) -> String {
8656    match prop_val {
8657        CssPropertyValue::Auto => format!("{property_value_type}Value::Auto"),
8658        CssPropertyValue::None => format!("{property_value_type}Value::None"),
8659        CssPropertyValue::Initial => format!("{property_value_type}Value::Initial"),
8660        CssPropertyValue::Inherit => format!("{property_value_type}Value::Inherit"),
8661        CssPropertyValue::Revert => format!("{property_value_type}Value::Revert"),
8662        CssPropertyValue::Unset => format!("{property_value_type}Value::Unset"),
8663        CssPropertyValue::Exact(t) => format!(
8664            "{}Value::Exact({})",
8665            property_value_type,
8666            t.format_as_rust_code(tabs)
8667        ),
8668    }
8669}
8670
8671#[cfg(test)]
8672#[allow(clippy::float_cmp)]
8673mod autotest_generated {
8674    use super::*;
8675    use crate::props::basic::animation::AnimationInterpolationFunction;
8676
8677    // ---- helpers -----------------------------------------------------------
8678
8679    fn resolver() -> InterpolateResolver {
8680        InterpolateResolver {
8681            interpolate_func: AnimationInterpolationFunction::Linear,
8682            parent_rect_width: 800.0,
8683            parent_rect_height: 600.0,
8684            current_rect_width: 400.0,
8685            current_rect_height: 300.0,
8686        }
8687    }
8688
8689    fn font_size(px: f32) -> CssProperty {
8690        CssProperty::font_size(StyleFontSize {
8691            inner: PixelValue::px(px),
8692        })
8693    }
8694
8695    fn font_size_px_of(prop: &CssProperty) -> f32 {
8696        match prop {
8697            CssProperty::FontSize(CssPropertyValue::Exact(fs)) => fs.inner.number.get(),
8698            other => panic!("expected an exact FontSize, got {other:?}"),
8699        }
8700    }
8701
8702    /// The five CSS table properties that `CssPropertyType::to_str()` names but
8703    /// `CSS_PROPERTY_KEY_MAP` never registers, so `from_str` can't find them.
8704    /// See `bug_table_properties_are_unreachable_from_stylesheet_text`.
8705    // Every property type now resolves through CSS_PROPERTY_KEY_MAP.
8706    const KEYS_MISSING_FROM_KEY_MAP: &[CssPropertyType] = &[];
8707
8708    // ---- CssKeyMap / get_css_key_map ---------------------------------------
8709
8710    #[test]
8711    fn key_map_is_populated_and_deterministic() {
8712        let a = get_css_key_map();
8713        let b = CssKeyMap::get();
8714        assert_eq!(a, b, "CssKeyMap::get() must equal get_css_key_map()");
8715        assert!(!a.non_shorthands.is_empty());
8716        assert!(!a.shorthands.is_empty());
8717        // Every registered key resolves back to the type it was registered under.
8718        for (k, v) in &a.non_shorthands {
8719            assert_eq!(CssPropertyType::from_str(k, &a), Some(*v), "key {k}");
8720        }
8721        for (k, v) in &a.shorthands {
8722            assert_eq!(
8723                CombinedCssPropertyType::from_str(k, &a),
8724                Some(*v),
8725                "shorthand {k}"
8726            );
8727        }
8728    }
8729
8730    // ---- from_str: malformed / boundary / unicode ---------------------------
8731
8732    #[test]
8733    fn from_str_empty_input_returns_none() {
8734        let map = get_css_key_map();
8735        assert_eq!(CssPropertyType::from_str("", &map), None);
8736        assert_eq!(CombinedCssPropertyType::from_str("", &map), None);
8737    }
8738
8739    #[test]
8740    fn from_str_whitespace_only_returns_none() {
8741        let map = get_css_key_map();
8742        for input in ["   ", "\t", "\n", "\r\n", " \t \n \r ", "\u{a0}"] {
8743            assert_eq!(CssPropertyType::from_str(input, &map), None, "{input:?}");
8744            assert_eq!(
8745                CombinedCssPropertyType::from_str(input, &map),
8746                None,
8747                "{input:?}"
8748            );
8749        }
8750    }
8751
8752    #[test]
8753    fn from_str_trims_surrounding_whitespace() {
8754        let map = get_css_key_map();
8755        assert_eq!(
8756            CssPropertyType::from_str("  \t width \n ", &map),
8757            Some(CssPropertyType::Width)
8758        );
8759        assert_eq!(
8760            CombinedCssPropertyType::from_str("\n border \t", &map),
8761            Some(CombinedCssPropertyType::Border)
8762        );
8763    }
8764
8765    #[test]
8766    fn from_str_garbage_returns_none() {
8767        let map = get_css_key_map();
8768        for input in [
8769            "asdfasdfasdf",
8770            ";",
8771            "{}",
8772            "widthh",
8773            "wid th",
8774            "width:",
8775            "width;garbage",
8776            "width!important",
8777            "\0",
8778            "\u{0}width\u{0}",
8779            "../../etc/passwd",
8780            "%s%s%s%n",
8781            "-",
8782            "--",
8783            "--custom-property",
8784        ] {
8785            assert_eq!(CssPropertyType::from_str(input, &map), None, "{input:?}");
8786            assert_eq!(
8787                CombinedCssPropertyType::from_str(input, &map),
8788                None,
8789                "{input:?}"
8790            );
8791        }
8792    }
8793
8794    #[test]
8795    fn from_str_is_case_sensitive() {
8796        // CSS keys are case-insensitive per spec, but these lookups are raw map
8797        // hits: normalisation is the caller's job (see parser2). Locked in so a
8798        // future change to the casing contract is a deliberate, visible one.
8799        let map = get_css_key_map();
8800        for input in ["WIDTH", "Width", "wIdTh"] {
8801            assert_eq!(CssPropertyType::from_str(input, &map), None, "{input:?}");
8802        }
8803        assert_eq!(
8804            CssPropertyType::from_str("width", &map),
8805            Some(CssPropertyType::Width)
8806        );
8807    }
8808
8809    #[test]
8810    fn from_str_boundary_number_strings_return_none() {
8811        let map = get_css_key_map();
8812        for input in [
8813            "0",
8814            "-0",
8815            "NaN",
8816            "nan",
8817            "inf",
8818            "-inf",
8819            "Infinity",
8820            "9223372036854775807",                     // i64::MAX
8821            "-9223372036854775808",                    // i64::MIN
8822            "340282350000000000000000000000000000000", // ~f32::MAX
8823            "1e309",                                   // overflows f64
8824            "0.00000000000000000001",
8825        ] {
8826            assert_eq!(CssPropertyType::from_str(input, &map), None, "{input:?}");
8827            assert_eq!(
8828                CombinedCssPropertyType::from_str(input, &map),
8829                None,
8830                "{input:?}"
8831            );
8832        }
8833    }
8834
8835    #[test]
8836    fn from_str_unicode_does_not_panic() {
8837        let map = get_css_key_map();
8838        for input in [
8839            "\u{1F600}",                // emoji
8840            "wi\u{0301}dth",            // combining acute accent
8841            "\u{202E}width",            // RTL override
8842            "width",               // fullwidth latin
8843            "width\u{FEFF}",            // BOM suffix
8844            "𝓌𝒾𝒹𝓉𝒽",                    // mathematical script
8845            "ширина",                   // cyrillic
8846            "\u{0301}\u{0301}\u{0301}", // lone combining marks
8847        ] {
8848            assert_eq!(CssPropertyType::from_str(input, &map), None, "{input:?}");
8849            assert_eq!(
8850                CombinedCssPropertyType::from_str(input, &map),
8851                None,
8852                "{input:?}"
8853            );
8854        }
8855    }
8856
8857    #[test]
8858    fn from_str_extremely_long_input_does_not_panic_or_hang() {
8859        let map = get_css_key_map();
8860        let huge = "width".repeat(200_000); // 1_000_000 chars
8861        assert_eq!(huge.len(), 1_000_000);
8862        assert_eq!(CssPropertyType::from_str(&huge, &map), None);
8863        assert_eq!(CombinedCssPropertyType::from_str(&huge, &map), None);
8864
8865        // A valid key buried in a megabyte of padding is still not a valid key.
8866        let padded = format!("{}width{}", "x".repeat(500_000), "x".repeat(500_000));
8867        assert_eq!(CssPropertyType::from_str(&padded, &map), None);
8868    }
8869
8870    #[test]
8871    fn from_str_deeply_nested_brackets_do_not_stack_overflow() {
8872        let map = get_css_key_map();
8873        let nested = format!("{}{}", "(".repeat(10_000), ")".repeat(10_000));
8874        assert_eq!(CssPropertyType::from_str(&nested, &map), None);
8875        assert_eq!(CombinedCssPropertyType::from_str(&nested, &map), None);
8876    }
8877
8878    #[test]
8879    fn from_str_valid_minimal_positive_control() {
8880        let map = get_css_key_map();
8881        assert_eq!(
8882            CssPropertyType::from_str("width", &map),
8883            Some(CssPropertyType::Width)
8884        );
8885        assert_eq!(
8886            CssPropertyType::from_str("justify-content", &map),
8887            Some(CssPropertyType::JustifyContent)
8888        );
8889        assert_eq!(
8890            CombinedCssPropertyType::from_str("border", &map),
8891            Some(CombinedCssPropertyType::Border)
8892        );
8893    }
8894
8895    #[test]
8896    fn word_wrap_is_a_registered_alias_for_overflow_wrap() {
8897        let map = get_css_key_map();
8898        assert_eq!(
8899            CssPropertyType::from_str("word-wrap", &map),
8900            Some(CssPropertyType::OverflowWrap)
8901        );
8902        assert_eq!(
8903            CssPropertyType::from_str("overflow-wrap", &map),
8904            Some(CssPropertyType::OverflowWrap)
8905        );
8906        // The alias is not the canonical name.
8907        assert_eq!(CssPropertyType::OverflowWrap.to_str(), "overflow-wrap");
8908    }
8909
8910    #[test]
8911    fn keys_present_in_both_maps_are_shorthand_shadowed() {
8912        // These four strings are registered in *both* key maps. parser2 consults
8913        // the shorthand map first, so the CombinedCssPropertyType always wins and
8914        // the same-named CssPropertyType is never reached from stylesheet text.
8915        let map = get_css_key_map();
8916        for k in ["background", "font", "gap", "grid-gap"] {
8917            assert!(
8918                CssPropertyType::from_str(k, &map).is_some(),
8919                "{k} should be in the non-shorthand map"
8920            );
8921            assert!(
8922                CombinedCssPropertyType::from_str(k, &map).is_some(),
8923                "{k} should be in the shorthand map"
8924            );
8925        }
8926    }
8927
8928    // ---- to_str / Display / Debug round-trips -------------------------------
8929
8930    #[test]
8931    fn css_property_type_to_str_is_non_empty_and_unique() {
8932        let mut seen = BTreeMap::new();
8933        for t in CssPropertyType::iter() {
8934            let s = t.to_str();
8935            assert!(!s.is_empty(), "{t:?} has an empty to_str()");
8936            assert!(
8937                !s.contains(' '),
8938                "{t:?} to_str() contains whitespace: {s:?}"
8939            );
8940            assert_eq!(s.trim(), s, "{t:?} to_str() is not trimmed: {s:?}");
8941            if let Some(prev) = seen.insert(s, t) {
8942                panic!("to_str() collision: {prev:?} and {t:?} both return {s:?}");
8943            }
8944        }
8945        assert_eq!(seen.len(), CssPropertyType::ALL.len());
8946    }
8947
8948    #[test]
8949    fn css_property_type_display_and_debug_agree_with_to_str() {
8950        for t in CssPropertyType::iter() {
8951            assert_eq!(format!("{t}"), t.to_str());
8952            assert_eq!(format!("{t:?}"), t.to_str());
8953        }
8954    }
8955
8956    #[test]
8957    fn css_property_type_iter_matches_all() {
8958        let collected: Vec<CssPropertyType> = CssPropertyType::iter().collect();
8959        assert_eq!(collected.as_slice(), CssPropertyType::ALL);
8960        // Iteration is repeatable (no interior state).
8961        let again: Vec<CssPropertyType> = CssPropertyType::iter().collect();
8962        assert_eq!(collected, again);
8963    }
8964
8965    #[test]
8966    fn css_property_type_to_str_round_trips_except_known_gap() {
8967        // parse(serialize(x)) == x for every property type that is actually
8968        // registered in the key map. The set that fails to round-trip is pinned
8969        // to the five table properties below; a sixth regression fails here.
8970        let map = get_css_key_map();
8971        let mut unreachable = Vec::new();
8972        for t in CssPropertyType::iter() {
8973            match CssPropertyType::from_str(t.to_str(), &map) {
8974                Some(back) => assert_eq!(back, t, "{t:?} round-tripped to the wrong type"),
8975                None => unreachable.push(t),
8976            }
8977        }
8978        assert_eq!(
8979            unreachable.as_slice(),
8980            KEYS_MISSING_FROM_KEY_MAP,
8981            "the set of property types missing from CSS_PROPERTY_KEY_MAP changed"
8982        );
8983    }
8984
8985    #[test]
8986    fn bug_table_properties_are_unreachable_from_stylesheet_text() {
8987        let map = get_css_key_map();
8988        for t in KEYS_MISSING_FROM_KEY_MAP {
8989            assert_eq!(
8990                CssPropertyType::from_str(t.to_str(), &map),
8991                Some(*t),
8992                "`{}` has a to_str() name and a working value parser, but no key-map \
8993                 entry, so parser2 rejects the declaration outright",
8994                t.to_str()
8995            );
8996        }
8997    }
8998
8999    #[test]
9000    #[cfg(feature = "parser")]
9001    fn table_property_value_parsers_work_even_though_the_keys_do_not_resolve() {
9002        // Proves the gap above is purely in CSS_PROPERTY_KEY_MAP: given the key
9003        // *type*, every one of these values parses fine. Only the string -> type
9004        // lookup is missing.
9005        for (t, value) in [
9006            (CssPropertyType::TableLayout, "fixed"),
9007            (CssPropertyType::BorderCollapse, "collapse"),
9008            (CssPropertyType::CaptionSide, "top"),
9009            (CssPropertyType::EmptyCells, "hide"),
9010        ] {
9011            let parsed = parse_css_property(t, value)
9012                .unwrap_or_else(|e| panic!("`{}: {value}` should parse: {e}", t.to_str()));
9013            assert_eq!(parsed.get_type(), t);
9014        }
9015    }
9016
9017    #[test]
9018    fn combined_css_property_type_round_trips_and_display_agrees() {
9019        let map = get_css_key_map();
9020        for t in map.shorthands.values() {
9021            let s = t.to_str(&map);
9022            assert!(!s.is_empty());
9023            assert_eq!(
9024                CombinedCssPropertyType::from_str(s, &map),
9025                Some(*t),
9026                "{t:?} did not round-trip"
9027            );
9028            // Display is derived from the static array, to_str from the map:
9029            // the two sources must not drift apart.
9030            assert_eq!(format!("{t}"), s, "Display disagrees with to_str for {t:?}");
9031        }
9032        assert_eq!(map.shorthands.len(), COMBINED_CSS_PROPERTIES_KEY_MAP.len());
9033    }
9034
9035    // ---- predicates: totality + known true/false -----------------------------
9036
9037    #[test]
9038    fn is_inheritable_matches_the_css_spec_for_known_properties() {
9039        for t in [
9040            CssPropertyType::TextColor,
9041            CssPropertyType::FontFamily,
9042            CssPropertyType::FontSize,
9043            CssPropertyType::LineHeight,
9044            CssPropertyType::Visibility,
9045            CssPropertyType::Cursor,
9046            CssPropertyType::WritingMode,
9047        ] {
9048            assert!(t.is_inheritable(), "{t:?} is inherited per CSS spec");
9049        }
9050        for t in [
9051            CssPropertyType::Width,
9052            CssPropertyType::Height,
9053            CssPropertyType::Display,
9054            CssPropertyType::Position,
9055            CssPropertyType::Opacity,
9056            CssPropertyType::Transform,
9057            CssPropertyType::BackgroundContent,
9058            CssPropertyType::UnicodeBidi, // explicitly non-inherited, see +spec:display-property
9059        ] {
9060            assert!(!t.is_inheritable(), "{t:?} is NOT inherited per CSS spec");
9061        }
9062    }
9063
9064    #[test]
9065    fn predicates_are_total_over_every_property_type() {
9066        // Every predicate must return a deterministic bool for all 180 variants
9067        // without panicking, and must be pure (same answer twice).
9068        for t in CssPropertyType::iter() {
9069            assert_eq!(t.is_inheritable(), t.is_inheritable());
9070            assert_eq!(t.has_compact_encoding(), t.has_compact_encoding());
9071            assert_eq!(t.can_trigger_relayout(), t.can_trigger_relayout());
9072            assert_eq!(t.is_gpu_only_property(), t.is_gpu_only_property());
9073            assert_eq!(t.get_category(), t.get_category());
9074            assert_eq!(t.relayout_scope(false), t.relayout_scope(false));
9075            assert_eq!(t.relayout_scope(true), t.relayout_scope(true));
9076        }
9077    }
9078
9079    #[test]
9080    fn is_gpu_only_property_is_exactly_opacity_and_transform() {
9081        let gpu: Vec<CssPropertyType> = CssPropertyType::iter()
9082            .filter(CssPropertyType::is_gpu_only_property)
9083            .collect();
9084        assert_eq!(
9085            gpu,
9086            vec![CssPropertyType::Opacity, CssPropertyType::Transform]
9087        );
9088    }
9089
9090    #[test]
9091    fn has_compact_encoding_known_true_false() {
9092        assert!(CssPropertyType::Display.has_compact_encoding());
9093        assert!(CssPropertyType::Width.has_compact_encoding());
9094        assert!(CssPropertyType::FlexGrow.has_compact_encoding());
9095        assert!(!CssPropertyType::Transform.has_compact_encoding());
9096        assert!(!CssPropertyType::Filter.has_compact_encoding());
9097        assert!(!CssPropertyType::Content.has_compact_encoding());
9098    }
9099
9100    #[test]
9101    fn can_trigger_relayout_known_true_false() {
9102        for t in [
9103            CssPropertyType::Width,
9104            CssPropertyType::Display,
9105            CssPropertyType::FontSize,
9106            CssPropertyType::MarginTop,
9107        ] {
9108            assert!(t.can_trigger_relayout(), "{t:?} affects geometry");
9109        }
9110        for t in [
9111            CssPropertyType::TextColor,
9112            CssPropertyType::Opacity,
9113            CssPropertyType::Transform,
9114            CssPropertyType::BackgroundContent,
9115        ] {
9116            assert!(!t.can_trigger_relayout(), "{t:?} is paint-only");
9117        }
9118    }
9119
9120    #[test]
9121    fn get_category_is_derived_consistently_from_the_predicates() {
9122        for t in CssPropertyType::iter() {
9123            let expected = if t.is_gpu_only_property() {
9124                CssPropertyCategory::GpuOnly
9125            } else {
9126                match (t.is_inheritable(), t.can_trigger_relayout()) {
9127                    (true, true) => CssPropertyCategory::InheritedLayout,
9128                    (true, false) => CssPropertyCategory::InheritedPaint,
9129                    (false, true) => CssPropertyCategory::Layout,
9130                    (false, false) => CssPropertyCategory::Paint,
9131                }
9132            };
9133            assert_eq!(t.get_category(), expected, "{t:?}");
9134        }
9135        assert_eq!(
9136            CssPropertyType::Opacity.get_category(),
9137            CssPropertyCategory::GpuOnly
9138        );
9139        assert_eq!(
9140            CssPropertyType::Width.get_category(),
9141            CssPropertyCategory::Layout
9142        );
9143        assert_eq!(
9144            CssPropertyType::FontSize.get_category(),
9145            CssPropertyCategory::InheritedLayout
9146        );
9147    }
9148
9149    // ---- relayout_scope ------------------------------------------------------
9150
9151    #[test]
9152    fn relayout_scope_never_contradicts_can_trigger_relayout() {
9153        // relayout_scope is documented as "a more granular replacement for
9154        // can_trigger_relayout()". The safe direction must hold: anything the
9155        // coarse predicate calls paint-only must also be scope None, or an
9156        // incremental-layout consumer would skip a relayout it actually needs.
9157        for t in CssPropertyType::iter() {
9158            if !t.can_trigger_relayout() {
9159                for ifc in [false, true] {
9160                    assert_eq!(
9161                        t.relayout_scope(ifc),
9162                        RelayoutScope::None,
9163                        "{t:?} is paint-only but claims a relayout scope (ifc={ifc})"
9164                    );
9165                }
9166            }
9167        }
9168    }
9169
9170    #[test]
9171    fn relayout_scope_paint_only_ignores_the_ifc_flag() {
9172        for t in [
9173            CssPropertyType::TextColor,
9174            CssPropertyType::Opacity,
9175            CssPropertyType::Transform,
9176            CssPropertyType::BackgroundContent,
9177            CssPropertyType::CaretColor,
9178            CssPropertyType::ObjectFit,
9179        ] {
9180            assert_eq!(t.relayout_scope(false), RelayoutScope::None, "{t:?}");
9181            assert_eq!(t.relayout_scope(true), RelayoutScope::None, "{t:?}");
9182        }
9183    }
9184
9185    #[test]
9186    fn relayout_scope_upgrades_text_properties_only_inside_an_ifc() {
9187        // Font/text changes reflow an inline formatting context but do not
9188        // resize a block container that has only block children.
9189        for t in [
9190            CssPropertyType::FontSize,
9191            CssPropertyType::FontFamily,
9192            CssPropertyType::LineHeight,
9193            CssPropertyType::LetterSpacing,
9194        ] {
9195            assert_eq!(t.relayout_scope(true), RelayoutScope::IfcOnly, "{t:?}");
9196            assert_ne!(t.relayout_scope(false), RelayoutScope::IfcOnly, "{t:?}");
9197        }
9198    }
9199
9200    // ---- CssProperty keyword constructors: totality over all 180 variants -----
9201
9202    #[test]
9203    fn keyword_constructors_preserve_the_property_type_for_every_variant() {
9204        // css_property_from_type! is a 180-arm hand-written macro: a single
9205        // copy-paste slip would silently build the wrong variant.
9206        for t in CssPropertyType::iter() {
9207            assert_eq!(CssProperty::none(t).get_type(), t, "none({t:?})");
9208            assert_eq!(CssProperty::auto(t).get_type(), t, "auto({t:?})");
9209            assert_eq!(CssProperty::initial(t).get_type(), t, "initial({t:?})");
9210            assert_eq!(CssProperty::inherit(t).get_type(), t, "inherit({t:?})");
9211        }
9212    }
9213
9214    #[test]
9215    fn key_agrees_with_get_type_for_every_variant() {
9216        for t in CssPropertyType::iter() {
9217            assert_eq!(CssProperty::none(t).key(), t.to_str(), "{t:?}");
9218        }
9219    }
9220
9221    #[test]
9222    fn value_and_format_css_are_well_formed_for_every_keyword_variant() {
9223        for t in CssPropertyType::iter() {
9224            for (ctor, keyword) in [
9225                (
9226                    CssProperty::none as fn(CssPropertyType) -> CssProperty,
9227                    "none",
9228                ),
9229                (CssProperty::auto, "auto"),
9230                (CssProperty::initial, "initial"),
9231                (CssProperty::inherit, "inherit"),
9232            ] {
9233                let prop = ctor(t);
9234                assert_eq!(prop.value(), keyword, "{t:?} {keyword}");
9235                assert!(!prop.value().is_empty());
9236                assert_eq!(
9237                    prop.format_css(),
9238                    format!("{}: {keyword};", t.to_str()),
9239                    "{t:?} {keyword}"
9240                );
9241            }
9242        }
9243    }
9244
9245    #[test]
9246    fn format_css_does_not_panic_on_extreme_and_non_finite_numbers() {
9247        for px in [
9248            0.0,
9249            -0.0,
9250            1.0,
9251            -1.0,
9252            f32::MAX,
9253            f32::MIN,
9254            f32::MIN_POSITIVE,
9255            f32::EPSILON,
9256            f32::INFINITY,
9257            f32::NEG_INFINITY,
9258            f32::NAN,
9259        ] {
9260            let prop = font_size(px);
9261            let css = prop.format_css();
9262            assert!(!css.is_empty(), "empty css for font-size {px}");
9263            assert!(css.starts_with("font-size: "), "malformed: {css:?}");
9264            assert!(css.ends_with(';'), "malformed: {css:?}");
9265            assert_eq!(prop.get_type(), CssPropertyType::FontSize);
9266        }
9267    }
9268
9269    #[test]
9270    fn extreme_float_inputs_saturate_rather_than_wrap() {
9271        // FloatValue stores a fixed-point isize; `f32 as isize` saturates, so
9272        // huge magnitudes must clamp and NaN must land on a defined value.
9273        assert!(font_size_px_of(&font_size(f32::INFINITY)) > 0.0);
9274        assert!(font_size_px_of(&font_size(f32::NEG_INFINITY)) < 0.0);
9275        assert_eq!(font_size_px_of(&font_size(f32::NAN)), 0.0);
9276        assert_eq!(font_size_px_of(&font_size(0.0)), 0.0);
9277        assert_eq!(font_size_px_of(&font_size(16.0)), 16.0);
9278        assert_eq!(font_size_px_of(&font_size(-16.0)), -16.0);
9279    }
9280
9281    // ---- interpolate ---------------------------------------------------------
9282
9283    #[test]
9284    fn interpolate_at_and_beyond_the_endpoints() {
9285        let r = resolver();
9286        let a = font_size(10.0);
9287        let b = font_size(20.0);
9288
9289        assert_eq!(a.interpolate(&b, 0.0, &r), a, "t=0 must return self");
9290        assert_eq!(a.interpolate(&b, 1.0, &r), b, "t=1 must return other");
9291        assert_eq!(a.interpolate(&b, -0.0, &r), a);
9292        assert_eq!(a.interpolate(&b, -5.0, &r), a, "t<0 clamps to self");
9293        assert_eq!(a.interpolate(&b, 5.0, &r), b, "t>1 clamps to other");
9294        assert_eq!(a.interpolate(&b, f32::NEG_INFINITY, &r), a);
9295        assert_eq!(a.interpolate(&b, f32::INFINITY, &r), b);
9296        assert_eq!(a.interpolate(&b, f32::MIN, &r), a);
9297        assert_eq!(a.interpolate(&b, f32::MAX, &r), b);
9298    }
9299
9300    #[test]
9301    fn interpolate_midpoint_is_the_linear_average() {
9302        let r = resolver();
9303        let out = font_size(0.0).interpolate(&font_size(100.0), 0.5, &r);
9304        let px = font_size_px_of(&out);
9305        assert!(
9306            (px - 50.0).abs() < 1.0,
9307            "linear midpoint of 0px..100px should be ~50px, got {px}"
9308        );
9309    }
9310
9311    #[test]
9312    fn interpolate_nan_t_does_not_panic_and_keeps_the_property_type() {
9313        let r = resolver();
9314        let a = font_size(10.0);
9315        let b = font_size(20.0);
9316        // NaN fails both the `t <= 0.0` and `t >= 1.0` guards and survives
9317        // f32::clamp, so it reaches the per-property interpolators.
9318        let out = a.interpolate(&b, f32::NAN, &r);
9319        assert_eq!(out.get_type(), CssPropertyType::FontSize);
9320        assert!(!out.format_css().is_empty());
9321    }
9322
9323    #[test]
9324    fn interpolate_extreme_endpoints_do_not_panic() {
9325        let r = resolver();
9326        for (from, to) in [
9327            (f32::MAX, f32::MIN),
9328            (f32::MIN, f32::MAX),
9329            (f32::INFINITY, f32::NEG_INFINITY),
9330            (f32::NAN, 10.0),
9331            (10.0, f32::NAN),
9332            (0.0, 0.0),
9333        ] {
9334            for t in [0.25, 0.5, 0.75] {
9335                let out = font_size(from).interpolate(&font_size(to), t, &r);
9336                assert_eq!(out.get_type(), CssPropertyType::FontSize);
9337                assert!(!out.format_css().is_empty());
9338            }
9339        }
9340    }
9341
9342    #[test]
9343    fn interpolate_between_mismatched_types_falls_back_without_panic() {
9344        let r = resolver();
9345        let width = CssProperty::width(LayoutWidth::Px(PixelValue::px(10.0)));
9346        let height = CssProperty::height(LayoutHeight::Px(PixelValue::px(20.0)));
9347
9348        // Not animatable across types: snaps to the nearer endpoint.
9349        assert_eq!(width.interpolate(&height, 0.25, &r), width);
9350        assert_eq!(width.interpolate(&height, 0.75, &r), height);
9351        // NaN takes neither branch of `t > 0.5`, so it must fall back to self.
9352        assert_eq!(width.interpolate(&height, f32::NAN, &r), width);
9353    }
9354
9355    #[test]
9356    fn interpolate_keyword_operands_fall_back_to_defaults_without_panic() {
9357        let r = resolver();
9358        // `auto`/`inherit` carry no concrete value; interpolating them must not
9359        // unwrap a missing property.
9360        let auto = CssProperty::auto(CssPropertyType::FontSize);
9361        let inherit = CssProperty::inherit(CssPropertyType::FontSize);
9362        let exact = font_size(24.0);
9363
9364        for (a, b) in [
9365            (&auto, &exact),
9366            (&exact, &auto),
9367            (&inherit, &exact),
9368            (&auto, &inherit),
9369        ] {
9370            let out = a.interpolate(b, 0.5, &r);
9371            assert_eq!(out.get_type(), CssPropertyType::FontSize);
9372            assert!(!out.format_css().is_empty());
9373        }
9374    }
9375
9376    // ---- parse_css_property --------------------------------------------------
9377
9378    #[test]
9379    #[cfg(feature = "parser")]
9380    fn parse_css_property_keyword_shortcut_works_for_every_property_type() {
9381        // `initial` / `inherit` short-circuit before any key-specific parsing,
9382        // so they must succeed for all 180 types and keep the requested type.
9383        for t in CssPropertyType::iter() {
9384            for keyword in ["initial", "inherit"] {
9385                let parsed = parse_css_property(t, keyword)
9386                    .unwrap_or_else(|e| panic!("{}: {keyword} failed: {e}", t.to_str()));
9387                assert_eq!(parsed.get_type(), t, "{t:?} {keyword}");
9388                assert_eq!(parsed.value(), keyword);
9389            }
9390            // Surrounding whitespace is trimmed before the keyword match.
9391            let parsed = parse_css_property(t, "  \t initial \n ")
9392                .unwrap_or_else(|e| panic!("{}: padded initial failed: {e}", t.to_str()));
9393            assert_eq!(parsed, CssProperty::initial(t), "{t:?}");
9394        }
9395    }
9396
9397    #[test]
9398    #[cfg(feature = "parser")]
9399    fn parse_css_property_valid_minimal_positive_control() {
9400        let width = parse_css_property(CssPropertyType::Width, "100px").expect("100px is valid");
9401        assert_eq!(width.get_type(), CssPropertyType::Width);
9402        assert_eq!(width.value(), "100px");
9403        assert_eq!(width.format_css(), "width: 100px;");
9404
9405        let display =
9406            parse_css_property(CssPropertyType::Display, "flex").expect("flex is valid display");
9407        assert_eq!(display.get_type(), CssPropertyType::Display);
9408
9409        // text-overflow: full dispatch through parse_css_property -> typed CssProperty,
9410        // correct type mapping, and canonical serialization.
9411        let text_overflow = parse_css_property(CssPropertyType::TextOverflow, "ellipsis")
9412            .expect("ellipsis is valid text-overflow");
9413        assert_eq!(text_overflow.get_type(), CssPropertyType::TextOverflow);
9414        assert_eq!(
9415            text_overflow,
9416            CssProperty::TextOverflow(CssPropertyValue::Exact(StyleTextOverflow::Ellipsis))
9417        );
9418        assert_eq!(text_overflow.value(), "ellipsis");
9419        assert_eq!(text_overflow.format_css(), "text-overflow: ellipsis;");
9420        assert!(parse_css_property(CssPropertyType::TextOverflow, "bogus").is_err());
9421    }
9422
9423    #[test]
9424    #[cfg(feature = "parser")]
9425    fn parse_css_property_empty_and_whitespace_only_are_rejected() {
9426        for value in ["", " ", "\t", "\n", "   \t\n  "] {
9427            assert!(
9428                parse_css_property(CssPropertyType::Width, value).is_err(),
9429                "width: {value:?} should not parse"
9430            );
9431            assert!(
9432                parse_css_property(CssPropertyType::TextColor, value).is_err(),
9433                "color: {value:?} should not parse"
9434            );
9435        }
9436    }
9437
9438    #[test]
9439    #[cfg(feature = "parser")]
9440    fn parse_css_property_garbage_is_rejected_without_panicking() {
9441        for value in [
9442            "!!!",
9443            "not-a-value",
9444            "100pxx",
9445            "px100",
9446            "100 px",
9447            ";",
9448            "}",
9449            "100px;",
9450            "100px !important",
9451            "\0",
9452            "#gg0000",
9453            "rgb(",
9454            "rgb(1,2",
9455        ] {
9456            assert!(
9457                parse_css_property(CssPropertyType::Width, value).is_err()
9458                    || parse_css_property(CssPropertyType::TextColor, value).is_err(),
9459                "{value:?} parsed as both a width and a color"
9460            );
9461        }
9462        // Spot-check the ones that must be rejected by *both* parsers.
9463        for value in ["!!!", "not-a-value", "\0", ";"] {
9464            assert!(parse_css_property(CssPropertyType::Width, value).is_err());
9465            assert!(parse_css_property(CssPropertyType::TextColor, value).is_err());
9466        }
9467    }
9468
9469    #[test]
9470    #[cfg(feature = "parser")]
9471    fn parse_css_property_unicode_is_rejected_without_panicking() {
9472        for value in [
9473            "\u{1F600}",
9474            "100\u{0301}px",
9475            "\u{202E}100px",
9476            "100px",
9477            "100px\u{FEFF}",
9478            "红色",
9479        ] {
9480            // Must not panic; a multibyte slice must never be cut mid-codepoint.
9481            let _ = parse_css_property(CssPropertyType::Width, value).is_err();
9482            let _ = parse_css_property(CssPropertyType::TextColor, value).is_err();
9483            let _ = parse_css_property(CssPropertyType::FontFamily, value).is_ok();
9484        }
9485        assert!(parse_css_property(CssPropertyType::Width, "\u{1F600}").is_err());
9486    }
9487
9488    #[test]
9489    #[cfg(feature = "parser")]
9490    fn parse_css_property_boundary_numbers_do_not_panic() {
9491        for value in [
9492            "0",
9493            "0px",
9494            "-0px",
9495            "-1px",
9496            "2147483647px",
9497            "-2147483648px",
9498            "9223372036854775807px",
9499            "340282350000000000000000000000000000000px",
9500            "1e309px",
9501            "NaNpx",
9502            "infpx",
9503            "0.00000000000000000001px",
9504            "99999999999999999999999999999999999999999999px",
9505        ] {
9506            // The contract is "no panic, no overflow trap" — a saturating Ok or a
9507            // clean Err are both acceptable, a debug-overflow panic is not.
9508            let parsed = parse_css_property(CssPropertyType::Width, value);
9509            if let Ok(p) = parsed {
9510                assert_eq!(p.get_type(), CssPropertyType::Width, "{value:?}");
9511                assert!(!p.format_css().is_empty(), "{value:?}");
9512            }
9513        }
9514    }
9515
9516    #[test]
9517    #[cfg(feature = "parser")]
9518    fn parse_css_property_extremely_long_input_does_not_hang() {
9519        // Long *digit* runs stay at 100k: the float parser is the expensive part
9520        // and the point is to prove it terminates, not to benchmark it.
9521        let huge = "1".repeat(100_000);
9522        if let Ok(p) = parse_css_property(CssPropertyType::Width, &huge) {
9523            assert_eq!(p.get_type(), CssPropertyType::Width);
9524        }
9525        let huge_px = format!("{}px", "9".repeat(100_000));
9526        let _ = parse_css_property(CssPropertyType::Width, &huge_px);
9527
9528        // Pure garbage is rejected on the first byte, so a full megabyte is cheap.
9529        let huge_garbage = "z".repeat(1_000_000);
9530        assert!(parse_css_property(CssPropertyType::Width, &huge_garbage).is_err());
9531    }
9532
9533    #[test]
9534    #[cfg(feature = "parser")]
9535    fn parse_css_property_deeply_nested_calc_does_not_stack_overflow() {
9536        // parse_calc_expression is an iterative stack machine, not a recursive
9537        // descent parser, so deep nesting must stay on the heap.
9538        let depth = 10_000;
9539        let nested = format!("calc({}1px{})", "(".repeat(depth), ")".repeat(depth));
9540        let _ = parse_css_property(CssPropertyType::Width, &nested);
9541
9542        let unbalanced = format!("calc({})", "(".repeat(depth));
9543        let _ = parse_css_property(CssPropertyType::Width, &unbalanced);
9544    }
9545
9546    #[test]
9547    #[cfg(feature = "parser")]
9548    fn parse_css_property_leading_trailing_junk_is_handled_deterministically() {
9549        // Padding is trimmed...
9550        let padded = parse_css_property(CssPropertyType::Width, "  \t 100px \n ")
9551            .expect("surrounding whitespace should be trimmed");
9552        assert_eq!(padded.value(), "100px");
9553        assert_eq!(
9554            padded,
9555            parse_css_property(CssPropertyType::Width, "100px").unwrap()
9556        );
9557        // ...but embedded junk is not silently dropped.
9558        assert!(parse_css_property(CssPropertyType::Width, "100px;garbage").is_err());
9559        assert!(parse_css_property(CssPropertyType::Width, "garbage 100px").is_err());
9560    }
9561
9562    // ---- parse_combined_css_property ------------------------------------------
9563
9564    #[test]
9565    #[cfg(feature = "parser")]
9566    fn parse_combined_css_property_valid_minimal_positive_control() {
9567        let props = parse_combined_css_property(CombinedCssPropertyType::Margin, "10px")
9568            .expect("margin: 10px is valid");
9569        let types: Vec<CssPropertyType> = props.iter().map(CssProperty::get_type).collect();
9570        assert_eq!(
9571            types,
9572            vec![
9573                CssPropertyType::MarginTop,
9574                CssPropertyType::MarginBottom,
9575                CssPropertyType::MarginLeft,
9576                CssPropertyType::MarginRight,
9577            ]
9578        );
9579        for p in &props {
9580            assert_eq!(p.value(), "10px");
9581        }
9582    }
9583
9584    #[test]
9585    #[cfg(feature = "parser")]
9586    fn parse_combined_css_property_expands_every_shorthand_or_errors_cleanly() {
9587        // `initial` short-circuits ahead of every value parser, so all 27
9588        // shorthands must expand to a non-empty list of `initial` longhands.
9589        let map = get_css_key_map();
9590        for key in map.shorthands.values() {
9591            let props = parse_combined_css_property(*key, "initial")
9592                .unwrap_or_else(|e| panic!("{key:?}: initial failed: {e}"));
9593            assert!(
9594                !props.is_empty(),
9595                "{key:?} expanded to an empty property list"
9596            );
9597            for p in &props {
9598                assert_eq!(p.value(), "initial", "{key:?} -> {:?}", p.get_type());
9599                assert_eq!(*p, CssProperty::initial(p.get_type()), "{key:?}");
9600            }
9601        }
9602    }
9603
9604    #[test]
9605    #[cfg(feature = "parser")]
9606    fn parse_combined_css_property_empty_and_whitespace_are_rejected() {
9607        for value in ["", " ", "\t\n", "    "] {
9608            assert!(
9609                parse_combined_css_property(CombinedCssPropertyType::Margin, value).is_err(),
9610                "margin: {value:?} should not parse"
9611            );
9612            assert!(
9613                parse_combined_css_property(CombinedCssPropertyType::BorderRadius, value).is_err(),
9614                "border-radius: {value:?} should not parse"
9615            );
9616        }
9617    }
9618
9619    #[test]
9620    #[cfg(feature = "parser")]
9621    fn parse_combined_css_property_garbage_is_rejected_without_panicking() {
9622        for value in [
9623            "!!!",
9624            "not-a-value",
9625            "10pxx",
9626            ";",
9627            "\0",
9628            "10px 20px 30px 40px 50px",
9629        ] {
9630            assert!(
9631                parse_combined_css_property(CombinedCssPropertyType::Margin, value).is_err(),
9632                "margin: {value:?} should not parse"
9633            );
9634        }
9635    }
9636
9637    #[test]
9638    #[cfg(feature = "parser")]
9639    fn parse_combined_css_property_unicode_and_long_input_do_not_panic() {
9640        for value in ["\u{1F600}", "1\u{0301}0px", "10px", "红色"] {
9641            let _ = parse_combined_css_property(CombinedCssPropertyType::Margin, value).is_err();
9642            let _ =
9643                parse_combined_css_property(CombinedCssPropertyType::Background, value).is_err();
9644        }
9645        // The padding/margin parser parses every value before it counts them, so
9646        // 20k values already exercises the TooManyValues path without a long run.
9647        let many = "10px ".repeat(20_000);
9648        assert!(
9649            parse_combined_css_property(CombinedCssPropertyType::Margin, &many).is_err(),
9650            "20_000 margin values should be TooManyValues, not a panic"
9651        );
9652        let huge_garbage = "z".repeat(1_000_000);
9653        assert!(
9654            parse_combined_css_property(CombinedCssPropertyType::Margin, &huge_garbage).is_err()
9655        );
9656    }
9657
9658    #[test]
9659    #[cfg(feature = "parser")]
9660    fn parse_combined_css_property_nested_parens_do_not_stack_overflow() {
9661        let nested = format!("{}10px{}", "(".repeat(1_000), ")".repeat(1_000));
9662        let _ = parse_combined_css_property(CombinedCssPropertyType::Margin, &nested);
9663        let _ = parse_combined_css_property(CombinedCssPropertyType::Border, &nested);
9664    }
9665
9666    // ---- CssParsingError round-trip -------------------------------------------
9667
9668    #[test]
9669    #[cfg(feature = "parser")]
9670    fn parsing_error_survives_the_owned_round_trip() {
9671        let err = parse_css_property(CssPropertyType::Width, "definitely-not-a-width")
9672            .expect_err("garbage width must fail");
9673
9674        let owned = err.to_contained();
9675        let shared = owned.to_shared();
9676
9677        // to_contained/to_shared must preserve the error, not flatten it to a
9678        // generic variant: the rendered message is the observable contract.
9679        assert_eq!(format!("{err}"), format!("{shared}"));
9680        assert!(!format!("{err}").is_empty());
9681        // ...and the round-trip is idempotent.
9682        let owned_again = shared.to_contained();
9683        assert_eq!(format!("{}", owned_again.to_shared()), format!("{err}"));
9684    }
9685
9686    #[test]
9687    #[cfg(feature = "parser")]
9688    fn parsing_errors_round_trip_for_a_spread_of_property_kinds() {
9689        for t in [
9690            CssPropertyType::Width,
9691            CssPropertyType::TextColor,
9692            CssPropertyType::FontSize,
9693            CssPropertyType::Opacity,
9694            CssPropertyType::Transform,
9695            CssPropertyType::BackgroundContent,
9696        ] {
9697            let Err(err) = parse_css_property(t, "\u{1F600}not-valid\u{1F600}") else {
9698                continue;
9699            };
9700            let owned = err.to_contained();
9701            let round_tripped = owned.to_shared();
9702            assert_eq!(
9703                format!("{err}"),
9704                format!("{round_tripped}"),
9705                "{} error lost information in to_contained()",
9706                t.to_str()
9707            );
9708        }
9709    }
9710}