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