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            let parts: Vec<&str> = trimmed.split_whitespace().collect();
4224            let mut trim_val = None;
4225            let mut edge_val = None;
4226            for part in &parts {
4227                if let Ok(t) = parse_style_text_box_trim(part) {
4228                    trim_val = Some(t);
4229                } else if let Ok(e) = parse_style_text_box_edge(part) {
4230                    edge_val = Some(e);
4231                } else {
4232                    return Err(CssParsingError::InvalidValue(InvalidValueErr(value)));
4233                }
4234            }
4235            // Per spec: omitting trim defaults to "both" (not the initial "none")
4236            let trim = trim_val.unwrap_or(StyleTextBoxTrim::TrimBoth);
4237            // Per spec: omitting edge defaults to "auto" (the initial value)
4238            let edge = edge_val.unwrap_or(StyleTextBoxEdge::Auto);
4239            Ok(vec![
4240                CssProperty::TextBoxTrim(CssPropertyValue::Exact(trim)),
4241                CssProperty::TextBoxEdge(CssPropertyValue::Exact(edge)),
4242            ])
4243        }
4244        // +spec:writing-modes:798cca - inset-block shorthand: first value = start, second = end;
4245        // if omitted, second defaults to first. Maps to top/bottom in horizontal-tb.
4246        InsetBlock => {
4247            let parts: Vec<&str> = value.split_whitespace().collect();
4248            let start_val = parts
4249                .first()
4250                .ok_or(CssParsingError::InvalidValue(InvalidValueErr(value)))?;
4251            let end_val = parts.get(1).unwrap_or(start_val);
4252            let start = parse_layout_top(start_val)?;
4253            let end = parse_layout_bottom(end_val)?;
4254            Ok(vec![
4255                CssProperty::Top(start.into()),
4256                CssProperty::Bottom(end.into()),
4257            ])
4258        }
4259        // +spec:writing-modes:798cca - inset-inline shorthand: first value = start, second = end;
4260        // if omitted, second defaults to first. Maps to left/right in horizontal-tb.
4261        InsetInline => {
4262            let parts: Vec<&str> = value.split_whitespace().collect();
4263            let start_val = parts
4264                .first()
4265                .ok_or(CssParsingError::InvalidValue(InvalidValueErr(value)))?;
4266            let end_val = parts.get(1).unwrap_or(start_val);
4267            let start = parse_layout_left(start_val)?;
4268            let end = parse_layout_right(end_val)?;
4269            Ok(vec![
4270                CssProperty::Left(start.into()),
4271                CssProperty::Right(end.into()),
4272            ])
4273        }
4274    }
4275}
4276
4277// Re-add the From implementations for convenience
4278macro_rules! impl_from_css_prop {
4279    ($a:ident, $b:ident:: $enum_type:ident) => {
4280        impl From<$a> for $b {
4281            fn from(e: $a) -> Self {
4282                $b::$enum_type(CssPropertyValue::from(e))
4283            }
4284        }
4285    };
4286}
4287
4288impl_from_css_prop!(CaretColor, CssProperty::CaretColor);
4289impl_from_css_prop!(CaretWidth, CssProperty::CaretWidth);
4290impl_from_css_prop!(CaretAnimationDuration, CssProperty::CaretAnimationDuration);
4291impl_from_css_prop!(
4292    SelectionBackgroundColor,
4293    CssProperty::SelectionBackgroundColor
4294);
4295impl_from_css_prop!(SelectionColor, CssProperty::SelectionColor);
4296impl_from_css_prop!(SelectionRadius, CssProperty::SelectionRadius);
4297impl_from_css_prop!(StyleTextColor, CssProperty::TextColor);
4298impl_from_css_prop!(StyleFontSize, CssProperty::FontSize);
4299impl_from_css_prop!(StyleFontFamilyVec, CssProperty::FontFamily);
4300impl_from_css_prop!(StyleTextAlign, CssProperty::TextAlign);
4301impl_from_css_prop!(LayoutTextJustify, CssProperty::TextJustify);
4302impl_from_css_prop!(StyleVerticalAlign, CssProperty::VerticalAlign);
4303impl_from_css_prop!(StyleLetterSpacing, CssProperty::LetterSpacing);
4304impl_from_css_prop!(StyleTextIndent, CssProperty::TextIndent);
4305impl_from_css_prop!(StyleInitialLetter, CssProperty::InitialLetter);
4306impl_from_css_prop!(StyleLineClamp, CssProperty::LineClamp);
4307impl_from_css_prop!(StyleHangingPunctuation, CssProperty::HangingPunctuation);
4308impl_from_css_prop!(StyleTextCombineUpright, CssProperty::TextCombineUpright);
4309impl_from_css_prop!(StyleUnicodeBidi, CssProperty::UnicodeBidi);
4310impl_from_css_prop!(StyleTextBoxTrim, CssProperty::TextBoxTrim);
4311impl_from_css_prop!(StyleTextBoxEdge, CssProperty::TextBoxEdge);
4312impl_from_css_prop!(StyleDominantBaseline, CssProperty::DominantBaseline);
4313impl_from_css_prop!(StyleAlignmentBaseline, CssProperty::AlignmentBaseline);
4314impl_from_css_prop!(StyleBaselineSource, CssProperty::BaselineSource);
4315impl_from_css_prop!(StyleLineFitEdge, CssProperty::LineFitEdge);
4316impl_from_css_prop!(StyleInitialLetterAlign, CssProperty::InitialLetterAlign);
4317impl_from_css_prop!(StyleInitialLetterWrap, CssProperty::InitialLetterWrap);
4318impl_from_css_prop!(StyleScrollbarGutter, CssProperty::ScrollbarGutter);
4319impl_from_css_prop!(StyleOverflowClipMargin, CssProperty::OverflowClipMargin);
4320impl_from_css_prop!(StyleClipRect, CssProperty::Clip);
4321impl_from_css_prop!(StyleExclusionMargin, CssProperty::ExclusionMargin);
4322impl_from_css_prop!(StyleHyphenationLanguage, CssProperty::HyphenationLanguage);
4323impl_from_css_prop!(StyleLineHeight, CssProperty::LineHeight);
4324impl_from_css_prop!(StyleWordSpacing, CssProperty::WordSpacing);
4325impl_from_css_prop!(StyleTabSize, CssProperty::TabSize);
4326impl_from_css_prop!(StyleCursor, CssProperty::Cursor);
4327impl_from_css_prop!(LayoutDisplay, CssProperty::Display);
4328impl_from_css_prop!(LayoutFloat, CssProperty::Float);
4329impl_from_css_prop!(LayoutBoxSizing, CssProperty::BoxSizing);
4330impl_from_css_prop!(LayoutWidth, CssProperty::Width);
4331impl_from_css_prop!(LayoutHeight, CssProperty::Height);
4332impl_from_css_prop!(LayoutMinWidth, CssProperty::MinWidth);
4333impl_from_css_prop!(LayoutMinHeight, CssProperty::MinHeight);
4334impl_from_css_prop!(LayoutMaxWidth, CssProperty::MaxWidth);
4335impl_from_css_prop!(LayoutMaxHeight, CssProperty::MaxHeight);
4336impl_from_css_prop!(LayoutPosition, CssProperty::Position);
4337impl_from_css_prop!(LayoutTop, CssProperty::Top);
4338impl_from_css_prop!(LayoutRight, CssProperty::Right);
4339impl_from_css_prop!(LayoutLeft, CssProperty::Left);
4340impl_from_css_prop!(LayoutInsetBottom, CssProperty::Bottom);
4341impl_from_css_prop!(LayoutFlexWrap, CssProperty::FlexWrap);
4342impl_from_css_prop!(LayoutFlexDirection, CssProperty::FlexDirection);
4343impl_from_css_prop!(LayoutFlexGrow, CssProperty::FlexGrow);
4344impl_from_css_prop!(LayoutFlexShrink, CssProperty::FlexShrink);
4345impl_from_css_prop!(LayoutFlexBasis, CssProperty::FlexBasis);
4346impl_from_css_prop!(LayoutJustifyContent, CssProperty::JustifyContent);
4347impl_from_css_prop!(LayoutAlignItems, CssProperty::AlignItems);
4348impl_from_css_prop!(LayoutAlignContent, CssProperty::AlignContent);
4349impl_from_css_prop!(LayoutColumnGap, CssProperty::ColumnGap);
4350impl_from_css_prop!(LayoutRowGap, CssProperty::RowGap);
4351impl_from_css_prop!(LayoutGridAutoFlow, CssProperty::GridAutoFlow);
4352impl_from_css_prop!(LayoutJustifySelf, CssProperty::JustifySelf);
4353impl_from_css_prop!(LayoutJustifyItems, CssProperty::JustifyItems);
4354impl_from_css_prop!(LayoutGap, CssProperty::Gap);
4355impl_from_css_prop!(LayoutAlignSelf, CssProperty::AlignSelf);
4356impl_from_css_prop!(LayoutWritingMode, CssProperty::WritingMode);
4357impl_from_css_prop!(LayoutClear, CssProperty::Clear);
4358
4359// BackgroundContent uses the standard From pattern
4360impl_from_css_prop!(StyleBackgroundContentVec, CssProperty::BackgroundContent);
4361
4362impl_from_css_prop!(StyleBackgroundPositionVec, CssProperty::BackgroundPosition);
4363impl_from_css_prop!(StyleBackgroundSizeVec, CssProperty::BackgroundSize);
4364impl_from_css_prop!(StyleBackgroundRepeatVec, CssProperty::BackgroundRepeat);
4365impl_from_css_prop!(LayoutPaddingTop, CssProperty::PaddingTop);
4366impl_from_css_prop!(LayoutPaddingLeft, CssProperty::PaddingLeft);
4367impl_from_css_prop!(LayoutPaddingRight, CssProperty::PaddingRight);
4368impl_from_css_prop!(LayoutPaddingBottom, CssProperty::PaddingBottom);
4369impl_from_css_prop!(LayoutPaddingInlineStart, CssProperty::PaddingInlineStart);
4370impl_from_css_prop!(LayoutPaddingInlineEnd, CssProperty::PaddingInlineEnd);
4371impl_from_css_prop!(LayoutMarginTop, CssProperty::MarginTop);
4372impl_from_css_prop!(LayoutMarginLeft, CssProperty::MarginLeft);
4373impl_from_css_prop!(LayoutMarginRight, CssProperty::MarginRight);
4374impl_from_css_prop!(LayoutMarginBottom, CssProperty::MarginBottom);
4375impl_from_css_prop!(StyleBorderTopLeftRadius, CssProperty::BorderTopLeftRadius);
4376impl_from_css_prop!(StyleBorderTopRightRadius, CssProperty::BorderTopRightRadius);
4377impl_from_css_prop!(
4378    StyleBorderBottomLeftRadius,
4379    CssProperty::BorderBottomLeftRadius
4380);
4381impl_from_css_prop!(
4382    StyleBorderBottomRightRadius,
4383    CssProperty::BorderBottomRightRadius
4384);
4385impl_from_css_prop!(StyleBorderTopColor, CssProperty::BorderTopColor);
4386impl_from_css_prop!(StyleBorderRightColor, CssProperty::BorderRightColor);
4387impl_from_css_prop!(StyleBorderLeftColor, CssProperty::BorderLeftColor);
4388impl_from_css_prop!(StyleBorderBottomColor, CssProperty::BorderBottomColor);
4389impl_from_css_prop!(StyleBorderTopStyle, CssProperty::BorderTopStyle);
4390impl_from_css_prop!(StyleBorderRightStyle, CssProperty::BorderRightStyle);
4391impl_from_css_prop!(StyleBorderLeftStyle, CssProperty::BorderLeftStyle);
4392impl_from_css_prop!(StyleBorderBottomStyle, CssProperty::BorderBottomStyle);
4393impl_from_css_prop!(LayoutBorderTopWidth, CssProperty::BorderTopWidth);
4394impl_from_css_prop!(LayoutBorderRightWidth, CssProperty::BorderRightWidth);
4395impl_from_css_prop!(LayoutBorderLeftWidth, CssProperty::BorderLeftWidth);
4396impl_from_css_prop!(LayoutBorderBottomWidth, CssProperty::BorderBottomWidth);
4397impl_from_css_prop!(LayoutScrollbarWidth, CssProperty::ScrollbarWidth);
4398impl_from_css_prop!(StyleScrollbarColor, CssProperty::ScrollbarColor);
4399impl_from_css_prop!(ScrollbarVisibilityMode, CssProperty::ScrollbarVisibility);
4400impl_from_css_prop!(ScrollbarFadeDelay, CssProperty::ScrollbarFadeDelay);
4401impl_from_css_prop!(ScrollbarFadeDuration, CssProperty::ScrollbarFadeDuration);
4402impl_from_css_prop!(StyleOpacity, CssProperty::Opacity);
4403impl_from_css_prop!(StyleVisibility, CssProperty::Visibility);
4404impl_from_css_prop!(StyleTransformVec, CssProperty::Transform);
4405impl_from_css_prop!(StyleTransformOrigin, CssProperty::TransformOrigin);
4406impl_from_css_prop!(StylePerspectiveOrigin, CssProperty::PerspectiveOrigin);
4407impl_from_css_prop!(StyleBackfaceVisibility, CssProperty::BackfaceVisibility);
4408impl_from_css_prop!(StyleMixBlendMode, CssProperty::MixBlendMode);
4409impl_from_css_prop!(StyleHyphens, CssProperty::Hyphens);
4410impl_from_css_prop!(StyleWordBreak, CssProperty::WordBreak);
4411impl_from_css_prop!(StyleOverflowWrap, CssProperty::OverflowWrap);
4412impl_from_css_prop!(StyleLineBreak, CssProperty::LineBreak);
4413impl_from_css_prop!(StyleTextOverflow, CssProperty::TextOverflow);
4414impl_from_css_prop!(StyleObjectFit, CssProperty::ObjectFit);
4415impl_from_css_prop!(StyleObjectPosition, CssProperty::ObjectPosition);
4416impl_from_css_prop!(StyleAspectRatio, CssProperty::AspectRatio);
4417impl_from_css_prop!(StyleTextOrientation, CssProperty::TextOrientation);
4418impl_from_css_prop!(StyleTextAlignLast, CssProperty::TextAlignLast);
4419impl_from_css_prop!(StyleTextTransform, CssProperty::TextTransform);
4420impl_from_css_prop!(StyleDirection, CssProperty::Direction);
4421impl_from_css_prop!(StyleWhiteSpace, CssProperty::WhiteSpace);
4422impl_from_css_prop!(PageBreak, CssProperty::BreakBefore);
4423impl_from_css_prop!(BreakInside, CssProperty::BreakInside);
4424impl_from_css_prop!(Widows, CssProperty::Widows);
4425impl_from_css_prop!(Orphans, CssProperty::Orphans);
4426impl_from_css_prop!(BoxDecorationBreak, CssProperty::BoxDecorationBreak);
4427impl_from_css_prop!(ColumnCount, CssProperty::ColumnCount);
4428impl_from_css_prop!(ColumnWidth, CssProperty::ColumnWidth);
4429impl_from_css_prop!(ColumnSpan, CssProperty::ColumnSpan);
4430impl_from_css_prop!(ColumnFill, CssProperty::ColumnFill);
4431impl_from_css_prop!(ColumnRuleWidth, CssProperty::ColumnRuleWidth);
4432impl_from_css_prop!(ColumnRuleStyle, CssProperty::ColumnRuleStyle);
4433impl_from_css_prop!(ColumnRuleColor, CssProperty::ColumnRuleColor);
4434impl_from_css_prop!(FlowInto, CssProperty::FlowInto);
4435impl_from_css_prop!(FlowFrom, CssProperty::FlowFrom);
4436impl_from_css_prop!(ShapeOutside, CssProperty::ShapeOutside);
4437impl_from_css_prop!(ShapeInside, CssProperty::ShapeInside);
4438impl_from_css_prop!(ClipPath, CssProperty::ClipPath);
4439impl_from_css_prop!(ShapeMargin, CssProperty::ShapeMargin);
4440impl_from_css_prop!(ShapeImageThreshold, CssProperty::ShapeImageThreshold);
4441impl_from_css_prop!(Content, CssProperty::Content);
4442impl_from_css_prop!(CounterReset, CssProperty::CounterReset);
4443impl_from_css_prop!(CounterIncrement, CssProperty::CounterIncrement);
4444impl_from_css_prop!(StyleListStyleType, CssProperty::ListStyleType);
4445impl_from_css_prop!(StyleListStylePosition, CssProperty::ListStylePosition);
4446impl_from_css_prop!(StringSet, CssProperty::StringSet);
4447impl_from_css_prop!(LayoutTableLayout, CssProperty::TableLayout);
4448impl_from_css_prop!(StyleBorderCollapse, CssProperty::BorderCollapse);
4449impl_from_css_prop!(LayoutBorderSpacing, CssProperty::BorderSpacing);
4450impl_from_css_prop!(StyleCaptionSide, CssProperty::CaptionSide);
4451impl_from_css_prop!(StyleEmptyCells, CssProperty::EmptyCells);
4452
4453impl CssProperty {
4454    #[must_use] pub const fn key(&self) -> &'static str {
4455        self.get_type().to_str()
4456    }
4457
4458    // Every arm delegates to `v.get_css_value_fmt()`, but each `v` is a different
4459    // `CssPropertyValue<T>` — the identical bodies cannot merge into one or-pattern
4460    // (mismatched binding types), so clippy::match_same_arms is a false positive here.
4461    #[allow(clippy::match_same_arms)]
4462    #[allow(clippy::too_many_lines)] // large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
4463    #[must_use] pub fn value(&self) -> String {
4464        match self {
4465            Self::CaretColor(v) => v.get_css_value_fmt(),
4466            Self::CaretWidth(v) => v.get_css_value_fmt(),
4467            Self::CaretAnimationDuration(v) => v.get_css_value_fmt(),
4468            Self::SelectionBackgroundColor(v) => v.get_css_value_fmt(),
4469            Self::SelectionColor(v) => v.get_css_value_fmt(),
4470            Self::SelectionRadius(v) => v.get_css_value_fmt(),
4471            Self::TextJustify(v) => v.get_css_value_fmt(),
4472            Self::TextColor(v) => v.get_css_value_fmt(),
4473            Self::FontSize(v) => v.get_css_value_fmt(),
4474            Self::FontFamily(v) => v.get_css_value_fmt(),
4475            Self::TextAlign(v) => v.get_css_value_fmt(),
4476            Self::LetterSpacing(v) => v.get_css_value_fmt(),
4477            Self::TextIndent(v) => v.get_css_value_fmt(),
4478            Self::InitialLetter(v) => v.get_css_value_fmt(),
4479            Self::LineClamp(v) => v.get_css_value_fmt(),
4480            Self::HangingPunctuation(v) => v.get_css_value_fmt(),
4481            Self::TextCombineUpright(v) => v.get_css_value_fmt(),
4482            Self::UnicodeBidi(v) => v.get_css_value_fmt(),
4483            Self::TextBoxTrim(v) => v.get_css_value_fmt(),
4484            Self::TextBoxEdge(v) => v.get_css_value_fmt(),
4485            Self::DominantBaseline(v) => v.get_css_value_fmt(),
4486            Self::AlignmentBaseline(v) => v.get_css_value_fmt(),
4487            Self::BaselineSource(v) => v.get_css_value_fmt(),
4488            Self::LineFitEdge(v) => v.get_css_value_fmt(),
4489            Self::InitialLetterAlign(v) => v.get_css_value_fmt(),
4490            Self::InitialLetterWrap(v) => v.get_css_value_fmt(),
4491            Self::ScrollbarGutter(v) => v.get_css_value_fmt(),
4492            Self::OverflowClipMargin(v) => v.get_css_value_fmt(),
4493            Self::Clip(v) => v.get_css_value_fmt(),
4494            Self::ExclusionMargin(v) => v.get_css_value_fmt(),
4495            Self::HyphenationLanguage(v) => v.get_css_value_fmt(),
4496            Self::LineHeight(v) => v.get_css_value_fmt(),
4497            Self::WordSpacing(v) => v.get_css_value_fmt(),
4498            Self::TabSize(v) => v.get_css_value_fmt(),
4499            Self::Cursor(v) => v.get_css_value_fmt(),
4500            Self::Display(v) => v.get_css_value_fmt(),
4501            Self::Float(v) => v.get_css_value_fmt(),
4502            Self::BoxSizing(v) => v.get_css_value_fmt(),
4503            Self::Width(v) => v.get_css_value_fmt(),
4504            Self::Height(v) => v.get_css_value_fmt(),
4505            Self::MinWidth(v) => v.get_css_value_fmt(),
4506            Self::MinHeight(v) => v.get_css_value_fmt(),
4507            Self::MaxWidth(v) => v.get_css_value_fmt(),
4508            Self::MaxHeight(v) => v.get_css_value_fmt(),
4509            Self::Position(v) => v.get_css_value_fmt(),
4510            Self::Top(v) => v.get_css_value_fmt(),
4511            Self::Right(v) => v.get_css_value_fmt(),
4512            Self::Left(v) => v.get_css_value_fmt(),
4513            Self::Bottom(v) => v.get_css_value_fmt(),
4514            Self::ZIndex(v) => v.get_css_value_fmt(),
4515            Self::FlexWrap(v) => v.get_css_value_fmt(),
4516            Self::FlexDirection(v) => v.get_css_value_fmt(),
4517            Self::FlexGrow(v) => v.get_css_value_fmt(),
4518            Self::FlexShrink(v) => v.get_css_value_fmt(),
4519            Self::FlexBasis(v) => v.get_css_value_fmt(),
4520            Self::JustifyContent(v) => v.get_css_value_fmt(),
4521            Self::AlignItems(v) => v.get_css_value_fmt(),
4522            Self::AlignContent(v) => v.get_css_value_fmt(),
4523            Self::ColumnGap(v) => v.get_css_value_fmt(),
4524            Self::RowGap(v) => v.get_css_value_fmt(),
4525            Self::GridTemplateColumns(v) => v.get_css_value_fmt(),
4526            Self::GridTemplateRows(v) => v.get_css_value_fmt(),
4527            Self::GridAutoFlow(v) => v.get_css_value_fmt(),
4528            Self::JustifySelf(v) => v.get_css_value_fmt(),
4529            Self::JustifyItems(v) => v.get_css_value_fmt(),
4530            Self::Gap(v) => v.get_css_value_fmt(),
4531            Self::GridGap(v) => v.get_css_value_fmt(),
4532            Self::AlignSelf(v) => v.get_css_value_fmt(),
4533            Self::Font(v) => v.get_css_value_fmt(),
4534            Self::GridAutoColumns(v) => v.get_css_value_fmt(),
4535            Self::GridAutoRows(v) => v.get_css_value_fmt(),
4536            Self::GridColumn(v) => v.get_css_value_fmt(),
4537            Self::GridRow(v) => v.get_css_value_fmt(),
4538            Self::GridTemplateAreas(v) => v.get_css_value_fmt(),
4539            Self::WritingMode(v) => v.get_css_value_fmt(),
4540            Self::Clear(v) => v.get_css_value_fmt(),
4541            Self::BackgroundContent(v) => v.get_css_value_fmt(),
4542            Self::BackgroundPosition(v) => v.get_css_value_fmt(),
4543            Self::BackgroundSize(v) => v.get_css_value_fmt(),
4544            Self::BackgroundRepeat(v) => v.get_css_value_fmt(),
4545            Self::OverflowX(v) => v.get_css_value_fmt(),
4546            Self::OverflowY(v) => v.get_css_value_fmt(),
4547            Self::OverflowBlock(v) => v.get_css_value_fmt(),
4548            Self::OverflowInline(v) => v.get_css_value_fmt(),
4549            Self::PaddingTop(v) => v.get_css_value_fmt(),
4550            Self::PaddingLeft(v) => v.get_css_value_fmt(),
4551            Self::PaddingRight(v) => v.get_css_value_fmt(),
4552            Self::PaddingBottom(v) => v.get_css_value_fmt(),
4553            Self::PaddingInlineStart(v) => v.get_css_value_fmt(),
4554            Self::PaddingInlineEnd(v) => v.get_css_value_fmt(),
4555            Self::MarginTop(v) => v.get_css_value_fmt(),
4556            Self::MarginLeft(v) => v.get_css_value_fmt(),
4557            Self::MarginRight(v) => v.get_css_value_fmt(),
4558            Self::MarginBottom(v) => v.get_css_value_fmt(),
4559            Self::BorderTopLeftRadius(v) => v.get_css_value_fmt(),
4560            Self::BorderTopRightRadius(v) => v.get_css_value_fmt(),
4561            Self::BorderBottomLeftRadius(v) => v.get_css_value_fmt(),
4562            Self::BorderBottomRightRadius(v) => v.get_css_value_fmt(),
4563            Self::BorderTopColor(v) => v.get_css_value_fmt(),
4564            Self::BorderRightColor(v) => v.get_css_value_fmt(),
4565            Self::BorderLeftColor(v) => v.get_css_value_fmt(),
4566            Self::BorderBottomColor(v) => v.get_css_value_fmt(),
4567            Self::BorderTopStyle(v) => v.get_css_value_fmt(),
4568            Self::BorderRightStyle(v) => v.get_css_value_fmt(),
4569            Self::BorderLeftStyle(v) => v.get_css_value_fmt(),
4570            Self::BorderBottomStyle(v) => v.get_css_value_fmt(),
4571            Self::BorderTopWidth(v) => v.get_css_value_fmt(),
4572            Self::BorderRightWidth(v) => v.get_css_value_fmt(),
4573            Self::BorderLeftWidth(v) => v.get_css_value_fmt(),
4574            Self::BorderBottomWidth(v) => v.get_css_value_fmt(),
4575            Self::BoxShadowLeft(v) => v.get_css_value_fmt(),
4576            Self::BoxShadowRight(v) => v.get_css_value_fmt(),
4577            Self::BoxShadowTop(v) => v.get_css_value_fmt(),
4578            Self::BoxShadowBottom(v) => v.get_css_value_fmt(),
4579            Self::ScrollbarTrack(v) => v.get_css_value_fmt(),
4580            Self::ScrollbarThumb(v) => v.get_css_value_fmt(),
4581            Self::ScrollbarButton(v) => v.get_css_value_fmt(),
4582            Self::ScrollbarCorner(v) => v.get_css_value_fmt(),
4583            Self::ScrollbarResizer(v) => v.get_css_value_fmt(),
4584            Self::ScrollbarWidth(v) => v.get_css_value_fmt(),
4585            Self::ScrollbarColor(v) => v.get_css_value_fmt(),
4586            Self::ScrollbarVisibility(v) => v.get_css_value_fmt(),
4587            Self::ScrollbarFadeDelay(v) => v.get_css_value_fmt(),
4588            Self::ScrollbarFadeDuration(v) => v.get_css_value_fmt(),
4589            Self::Opacity(v) => v.get_css_value_fmt(),
4590            Self::Visibility(v) => v.get_css_value_fmt(),
4591            Self::Transform(v) => v.get_css_value_fmt(),
4592            Self::TransformOrigin(v) => v.get_css_value_fmt(),
4593            Self::PerspectiveOrigin(v) => v.get_css_value_fmt(),
4594            Self::BackfaceVisibility(v) => v.get_css_value_fmt(),
4595            Self::MixBlendMode(v) => v.get_css_value_fmt(),
4596            Self::Filter(v) => v.get_css_value_fmt(),
4597            Self::BackdropFilter(v) => v.get_css_value_fmt(),
4598            Self::TextShadow(v) => v.get_css_value_fmt(),
4599            Self::Hyphens(v) => v.get_css_value_fmt(),
4600            Self::WordBreak(v) => v.get_css_value_fmt(),
4601            Self::OverflowWrap(v) => v.get_css_value_fmt(),
4602            Self::LineBreak(v) => v.get_css_value_fmt(),
4603            Self::TextOverflow(v) => v.get_css_value_fmt(),
4604            Self::ObjectFit(v) => v.get_css_value_fmt(),
4605            Self::ObjectPosition(v) => v.get_css_value_fmt(),
4606            Self::AspectRatio(v) => v.get_css_value_fmt(),
4607            Self::TextOrientation(v) => v.get_css_value_fmt(),
4608            Self::TextAlignLast(v) => v.get_css_value_fmt(),
4609            Self::TextTransform(v) => v.get_css_value_fmt(),
4610            Self::Direction(v) => v.get_css_value_fmt(),
4611            Self::UserSelect(v) => v.get_css_value_fmt(),
4612            Self::TextDecoration(v) => v.get_css_value_fmt(),
4613            Self::WhiteSpace(v) => v.get_css_value_fmt(),
4614            Self::BreakBefore(v) => v.get_css_value_fmt(),
4615            Self::BreakAfter(v) => v.get_css_value_fmt(),
4616            Self::BreakInside(v) => v.get_css_value_fmt(),
4617            Self::Orphans(v) => v.get_css_value_fmt(),
4618            Self::Widows(v) => v.get_css_value_fmt(),
4619            Self::BoxDecorationBreak(v) => v.get_css_value_fmt(),
4620            Self::ColumnCount(v) => v.get_css_value_fmt(),
4621            Self::ColumnWidth(v) => v.get_css_value_fmt(),
4622            Self::ColumnSpan(v) => v.get_css_value_fmt(),
4623            Self::ColumnFill(v) => v.get_css_value_fmt(),
4624            Self::ColumnRuleWidth(v) => v.get_css_value_fmt(),
4625            Self::ColumnRuleStyle(v) => v.get_css_value_fmt(),
4626            Self::ColumnRuleColor(v) => v.get_css_value_fmt(),
4627            Self::FlowInto(v) => v.get_css_value_fmt(),
4628            Self::FlowFrom(v) => v.get_css_value_fmt(),
4629            Self::ShapeOutside(v) => v.get_css_value_fmt(),
4630            Self::ShapeInside(v) => v.get_css_value_fmt(),
4631            Self::ClipPath(v) => v.get_css_value_fmt(),
4632            Self::ShapeMargin(v) => v.get_css_value_fmt(),
4633            Self::ShapeImageThreshold(v) => v.get_css_value_fmt(),
4634            Self::Content(v) => v.get_css_value_fmt(),
4635            Self::CounterReset(v) => v.get_css_value_fmt(),
4636            Self::CounterIncrement(v) => v.get_css_value_fmt(),
4637            Self::ListStyleType(v) => v.get_css_value_fmt(),
4638            Self::ListStylePosition(v) => v.get_css_value_fmt(),
4639            Self::StringSet(v) => v.get_css_value_fmt(),
4640            Self::TableLayout(v) => v.get_css_value_fmt(),
4641            Self::BorderCollapse(v) => v.get_css_value_fmt(),
4642            Self::BorderSpacing(v) => v.get_css_value_fmt(),
4643            Self::CaptionSide(v) => v.get_css_value_fmt(),
4644            Self::EmptyCells(v) => v.get_css_value_fmt(),
4645            Self::FontWeight(v) => v.get_css_value_fmt(),
4646            Self::FontStyle(v) => v.get_css_value_fmt(),
4647            Self::VerticalAlign(v) => v.get_css_value_fmt(),
4648        }
4649    }
4650
4651    #[must_use] pub fn format_css(&self) -> String {
4652        format!("{}: {};", self.key(), self.value())
4653    }
4654
4655    #[allow(clippy::too_many_lines)] // large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
4656    #[must_use] pub fn interpolate(
4657        &self,
4658        other: &Self,
4659        t: f32,
4660        interpolate_resolver: &InterpolateResolver,
4661    ) -> Self {
4662        if t <= 0.0 {
4663            return self.clone();
4664        } else if t >= 1.0 {
4665            return other.clone();
4666        }
4667
4668        // Map from linear interpolation function to Easing curve
4669        let t: f32 = interpolate_resolver.interpolate_func.evaluate(f64::from(t));
4670
4671        let t = t.clamp(0.0, 1.0);
4672
4673        match (self, other) {
4674            (Self::TextColor(col_start), Self::TextColor(col_end)) => {
4675                let col_start = col_start.get_property().copied().unwrap_or_default();
4676                let col_end = col_end.get_property().copied().unwrap_or_default();
4677                Self::text_color(col_start.interpolate(&col_end, t))
4678            }
4679            (Self::FontSize(fs_start), Self::FontSize(fs_end)) => {
4680                let fs_start = fs_start.get_property().copied().unwrap_or_default();
4681                let fs_end = fs_end.get_property().copied().unwrap_or_default();
4682                Self::font_size(fs_start.interpolate(&fs_end, t))
4683            }
4684            (Self::LetterSpacing(ls_start), Self::LetterSpacing(ls_end)) => {
4685                let ls_start = ls_start.get_property().copied().unwrap_or_default();
4686                let ls_end = ls_end.get_property().copied().unwrap_or_default();
4687                Self::letter_spacing(ls_start.interpolate(&ls_end, t))
4688            }
4689            (Self::TextIndent(ti_start), Self::TextIndent(ti_end)) => {
4690                let ti_start = ti_start.get_property().copied().unwrap_or_default();
4691                let ti_end = ti_end.get_property().copied().unwrap_or_default();
4692                Self::text_indent(ti_start.interpolate(&ti_end, t))
4693            }
4694            (Self::LineHeight(lh_start), Self::LineHeight(lh_end)) => {
4695                let lh_start = lh_start.get_property().copied().unwrap_or_default();
4696                let lh_end = lh_end.get_property().copied().unwrap_or_default();
4697                Self::line_height(lh_start.interpolate(&lh_end, t))
4698            }
4699            (Self::WordSpacing(ws_start), Self::WordSpacing(ws_end)) => {
4700                let ws_start = ws_start.get_property().copied().unwrap_or_default();
4701                let ws_end = ws_end.get_property().copied().unwrap_or_default();
4702                Self::word_spacing(ws_start.interpolate(&ws_end, t))
4703            }
4704            (Self::TabSize(tw_start), Self::TabSize(tw_end)) => {
4705                let tw_start = tw_start.get_property().copied().unwrap_or_default();
4706                let tw_end = tw_end.get_property().copied().unwrap_or_default();
4707                Self::tab_size(tw_start.interpolate(&tw_end, t))
4708            }
4709            (Self::Width(start), Self::Width(end)) => {
4710                let start =
4711                    start
4712                        .get_property()
4713                        .cloned()
4714                        .unwrap_or(LayoutWidth::Px(PixelValue::px(
4715                            interpolate_resolver.current_rect_width,
4716                        )));
4717                let end = end.get_property().cloned().unwrap_or_default();
4718                Self::Width(CssPropertyValue::Exact(start.interpolate(&end, t)))
4719            }
4720            (Self::Height(start), Self::Height(end)) => {
4721                let start =
4722                    start
4723                        .get_property()
4724                        .cloned()
4725                        .unwrap_or(LayoutHeight::Px(PixelValue::px(
4726                            interpolate_resolver.current_rect_height,
4727                        )));
4728                let end = end.get_property().cloned().unwrap_or_default();
4729                Self::Height(CssPropertyValue::Exact(start.interpolate(&end, t)))
4730            }
4731            (Self::MinWidth(start), Self::MinWidth(end)) => {
4732                let start = start.get_property().copied().unwrap_or_default();
4733                let end = end.get_property().copied().unwrap_or_default();
4734                Self::MinWidth(CssPropertyValue::Exact(start.interpolate(&end, t)))
4735            }
4736            (Self::MinHeight(start), Self::MinHeight(end)) => {
4737                let start = start.get_property().copied().unwrap_or_default();
4738                let end = end.get_property().copied().unwrap_or_default();
4739                Self::MinHeight(CssPropertyValue::Exact(start.interpolate(&end, t)))
4740            }
4741            (Self::MaxWidth(start), Self::MaxWidth(end)) => {
4742                let start = start.get_property().copied().unwrap_or_default();
4743                let end = end.get_property().copied().unwrap_or_default();
4744                Self::MaxWidth(CssPropertyValue::Exact(start.interpolate(&end, t)))
4745            }
4746            (Self::MaxHeight(start), Self::MaxHeight(end)) => {
4747                let start = start.get_property().copied().unwrap_or_default();
4748                let end = end.get_property().copied().unwrap_or_default();
4749                Self::MaxHeight(CssPropertyValue::Exact(start.interpolate(&end, t)))
4750            }
4751            (Self::Top(start), Self::Top(end)) => {
4752                let start = start.get_property().copied().unwrap_or_default();
4753                let end = end.get_property().copied().unwrap_or_default();
4754                Self::Top(CssPropertyValue::Exact(start.interpolate(&end, t)))
4755            }
4756            (Self::Right(start), Self::Right(end)) => {
4757                let start = start.get_property().copied().unwrap_or_default();
4758                let end = end.get_property().copied().unwrap_or_default();
4759                Self::Right(CssPropertyValue::Exact(start.interpolate(&end, t)))
4760            }
4761            (Self::Left(start), Self::Left(end)) => {
4762                let start = start.get_property().copied().unwrap_or_default();
4763                let end = end.get_property().copied().unwrap_or_default();
4764                Self::Left(CssPropertyValue::Exact(start.interpolate(&end, t)))
4765            }
4766            (Self::Bottom(start), Self::Bottom(end)) => {
4767                let start = start.get_property().copied().unwrap_or_default();
4768                let end = end.get_property().copied().unwrap_or_default();
4769                Self::Bottom(CssPropertyValue::Exact(start.interpolate(&end, t)))
4770            }
4771            (Self::FlexGrow(start), Self::FlexGrow(end)) => {
4772                let start = start.get_property().copied().unwrap_or_default();
4773                let end = end.get_property().copied().unwrap_or_default();
4774                Self::FlexGrow(CssPropertyValue::Exact(start.interpolate(&end, t)))
4775            }
4776            (Self::FlexShrink(start), Self::FlexShrink(end)) => {
4777                let start = start.get_property().copied().unwrap_or_default();
4778                let end = end.get_property().copied().unwrap_or_default();
4779                Self::FlexShrink(CssPropertyValue::Exact(start.interpolate(&end, t)))
4780            }
4781            (Self::PaddingTop(start), Self::PaddingTop(end)) => {
4782                let start = start.get_property().copied().unwrap_or_default();
4783                let end = end.get_property().copied().unwrap_or_default();
4784                Self::PaddingTop(CssPropertyValue::Exact(start.interpolate(&end, t)))
4785            }
4786            (Self::PaddingLeft(start), Self::PaddingLeft(end)) => {
4787                let start = start.get_property().copied().unwrap_or_default();
4788                let end = end.get_property().copied().unwrap_or_default();
4789                Self::PaddingLeft(CssPropertyValue::Exact(start.interpolate(&end, t)))
4790            }
4791            (Self::PaddingRight(start), Self::PaddingRight(end)) => {
4792                let start = start.get_property().copied().unwrap_or_default();
4793                let end = end.get_property().copied().unwrap_or_default();
4794                Self::PaddingRight(CssPropertyValue::Exact(start.interpolate(&end, t)))
4795            }
4796            (Self::PaddingBottom(start), Self::PaddingBottom(end)) => {
4797                let start = start.get_property().copied().unwrap_or_default();
4798                let end = end.get_property().copied().unwrap_or_default();
4799                Self::PaddingBottom(CssPropertyValue::Exact(start.interpolate(&end, t)))
4800            }
4801            (Self::MarginTop(start), Self::MarginTop(end)) => {
4802                let start = start.get_property().copied().unwrap_or_default();
4803                let end = end.get_property().copied().unwrap_or_default();
4804                Self::MarginTop(CssPropertyValue::Exact(start.interpolate(&end, t)))
4805            }
4806            (Self::MarginLeft(start), Self::MarginLeft(end)) => {
4807                let start = start.get_property().copied().unwrap_or_default();
4808                let end = end.get_property().copied().unwrap_or_default();
4809                Self::MarginLeft(CssPropertyValue::Exact(start.interpolate(&end, t)))
4810            }
4811            (Self::MarginRight(start), Self::MarginRight(end)) => {
4812                let start = start.get_property().copied().unwrap_or_default();
4813                let end = end.get_property().copied().unwrap_or_default();
4814                Self::MarginRight(CssPropertyValue::Exact(start.interpolate(&end, t)))
4815            }
4816            (Self::MarginBottom(start), Self::MarginBottom(end)) => {
4817                let start = start.get_property().copied().unwrap_or_default();
4818                let end = end.get_property().copied().unwrap_or_default();
4819                Self::MarginBottom(CssPropertyValue::Exact(start.interpolate(&end, t)))
4820            }
4821            (Self::BorderTopLeftRadius(start), Self::BorderTopLeftRadius(end)) => {
4822                let start = start.get_property().copied().unwrap_or_default();
4823                let end = end.get_property().copied().unwrap_or_default();
4824                Self::BorderTopLeftRadius(CssPropertyValue::Exact(
4825                    start.interpolate(&end, t),
4826                ))
4827            }
4828            (Self::BorderTopRightRadius(start), Self::BorderTopRightRadius(end)) => {
4829                let start = start.get_property().copied().unwrap_or_default();
4830                let end = end.get_property().copied().unwrap_or_default();
4831                Self::BorderTopRightRadius(CssPropertyValue::Exact(
4832                    start.interpolate(&end, t),
4833                ))
4834            }
4835            (
4836                Self::BorderBottomLeftRadius(start),
4837                Self::BorderBottomLeftRadius(end),
4838            ) => {
4839                let start = start.get_property().copied().unwrap_or_default();
4840                let end = end.get_property().copied().unwrap_or_default();
4841                Self::BorderBottomLeftRadius(CssPropertyValue::Exact(
4842                    start.interpolate(&end, t),
4843                ))
4844            }
4845            (
4846                Self::BorderBottomRightRadius(start),
4847                Self::BorderBottomRightRadius(end),
4848            ) => {
4849                let start = start.get_property().copied().unwrap_or_default();
4850                let end = end.get_property().copied().unwrap_or_default();
4851                Self::BorderBottomRightRadius(CssPropertyValue::Exact(
4852                    start.interpolate(&end, t),
4853                ))
4854            }
4855            (Self::BorderTopColor(start), Self::BorderTopColor(end)) => {
4856                let start = start.get_property().copied().unwrap_or_default();
4857                let end = end.get_property().copied().unwrap_or_default();
4858                Self::BorderTopColor(CssPropertyValue::Exact(start.interpolate(&end, t)))
4859            }
4860            (Self::BorderRightColor(start), Self::BorderRightColor(end)) => {
4861                let start = start.get_property().copied().unwrap_or_default();
4862                let end = end.get_property().copied().unwrap_or_default();
4863                Self::BorderRightColor(CssPropertyValue::Exact(start.interpolate(&end, t)))
4864            }
4865            (Self::BorderLeftColor(start), Self::BorderLeftColor(end)) => {
4866                let start = start.get_property().copied().unwrap_or_default();
4867                let end = end.get_property().copied().unwrap_or_default();
4868                Self::BorderLeftColor(CssPropertyValue::Exact(start.interpolate(&end, t)))
4869            }
4870            (Self::BorderBottomColor(start), Self::BorderBottomColor(end)) => {
4871                let start = start.get_property().copied().unwrap_or_default();
4872                let end = end.get_property().copied().unwrap_or_default();
4873                Self::BorderBottomColor(CssPropertyValue::Exact(start.interpolate(&end, t)))
4874            }
4875            (Self::BorderTopWidth(start), Self::BorderTopWidth(end)) => {
4876                let start = start.get_property().copied().unwrap_or_default();
4877                let end = end.get_property().copied().unwrap_or_default();
4878                Self::BorderTopWidth(CssPropertyValue::Exact(start.interpolate(&end, t)))
4879            }
4880            (Self::BorderRightWidth(start), Self::BorderRightWidth(end)) => {
4881                let start = start.get_property().copied().unwrap_or_default();
4882                let end = end.get_property().copied().unwrap_or_default();
4883                Self::BorderRightWidth(CssPropertyValue::Exact(start.interpolate(&end, t)))
4884            }
4885            (Self::BorderLeftWidth(start), Self::BorderLeftWidth(end)) => {
4886                let start = start.get_property().copied().unwrap_or_default();
4887                let end = end.get_property().copied().unwrap_or_default();
4888                Self::BorderLeftWidth(CssPropertyValue::Exact(start.interpolate(&end, t)))
4889            }
4890            (Self::BorderBottomWidth(start), Self::BorderBottomWidth(end)) => {
4891                let start = start.get_property().copied().unwrap_or_default();
4892                let end = end.get_property().copied().unwrap_or_default();
4893                Self::BorderBottomWidth(CssPropertyValue::Exact(start.interpolate(&end, t)))
4894            }
4895            (Self::Opacity(start), Self::Opacity(end)) => {
4896                let start = start.get_property().copied().unwrap_or_default();
4897                let end = end.get_property().copied().unwrap_or_default();
4898                Self::Opacity(CssPropertyValue::Exact(start.interpolate(&end, t)))
4899            }
4900            (Self::TransformOrigin(start), Self::TransformOrigin(end)) => {
4901                let start = start.get_property().copied().unwrap_or_default();
4902                let end = end.get_property().copied().unwrap_or_default();
4903                Self::TransformOrigin(CssPropertyValue::Exact(start.interpolate(&end, t)))
4904            }
4905            (Self::PerspectiveOrigin(start), Self::PerspectiveOrigin(end)) => {
4906                let start = start.get_property().copied().unwrap_or_default();
4907                let end = end.get_property().copied().unwrap_or_default();
4908                Self::PerspectiveOrigin(CssPropertyValue::Exact(start.interpolate(&end, t)))
4909            }
4910            /*
4911            animate transform:
4912            CssProperty::Transform(CssPropertyValue<StyleTransformVec>),
4913
4914            animate box shadow:
4915            CssProperty::BoxShadowLeft(CssPropertyValue<StyleBoxShadow>),
4916            CssProperty::BoxShadowRight(CssPropertyValue<StyleBoxShadow>),
4917            CssProperty::BoxShadowTop(CssPropertyValue<StyleBoxShadow>),
4918            CssProperty::BoxShadowBottom(CssPropertyValue<StyleBoxShadow>),
4919
4920            animate background:
4921            CssProperty::BackgroundContent(CssPropertyValue<StyleBackgroundContentVec>),
4922            CssProperty::BackgroundPosition(CssPropertyValue<StyleBackgroundPositionVec>),
4923            CssProperty::BackgroundSize(CssPropertyValue<StyleBackgroundSizeVec>),
4924            */
4925            (_, _) => {
4926                // not animatable, fallback
4927                if t > 0.5 {
4928                    other.clone()
4929                } else {
4930                    self.clone()
4931                }
4932            }
4933        }
4934    }
4935
4936    /// Return the type (key) of this property as a statically typed enum
4937    #[allow(clippy::too_many_lines)] // large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
4938    #[must_use] pub const fn get_type(&self) -> CssPropertyType {
4939        match &self {
4940            Self::CaretColor(_) => CssPropertyType::CaretColor,
4941            Self::CaretWidth(_) => CssPropertyType::CaretWidth,
4942            Self::CaretAnimationDuration(_) => CssPropertyType::CaretAnimationDuration,
4943            Self::SelectionBackgroundColor(_) => CssPropertyType::SelectionBackgroundColor,
4944            Self::SelectionColor(_) => CssPropertyType::SelectionColor,
4945            Self::SelectionRadius(_) => CssPropertyType::SelectionRadius,
4946
4947            Self::TextJustify(_) => CssPropertyType::TextJustify,
4948            Self::TextColor(_) => CssPropertyType::TextColor,
4949            Self::FontSize(_) => CssPropertyType::FontSize,
4950            Self::FontFamily(_) => CssPropertyType::FontFamily,
4951            Self::FontWeight(_) => CssPropertyType::FontWeight,
4952            Self::FontStyle(_) => CssPropertyType::FontStyle,
4953            Self::TextAlign(_) => CssPropertyType::TextAlign,
4954            Self::VerticalAlign(_) => CssPropertyType::VerticalAlign,
4955            Self::LetterSpacing(_) => CssPropertyType::LetterSpacing,
4956            Self::TextIndent(_) => CssPropertyType::TextIndent,
4957            Self::InitialLetter(_) => CssPropertyType::InitialLetter,
4958            Self::LineClamp(_) => CssPropertyType::LineClamp,
4959            Self::HangingPunctuation(_) => CssPropertyType::HangingPunctuation,
4960            Self::TextCombineUpright(_) => CssPropertyType::TextCombineUpright,
4961            Self::UnicodeBidi(_) => CssPropertyType::UnicodeBidi,
4962            Self::TextBoxTrim(_) => CssPropertyType::TextBoxTrim,
4963            Self::TextBoxEdge(_) => CssPropertyType::TextBoxEdge,
4964            Self::DominantBaseline(_) => CssPropertyType::DominantBaseline,
4965            Self::AlignmentBaseline(_) => CssPropertyType::AlignmentBaseline,
4966            Self::BaselineSource(_) => CssPropertyType::BaselineSource,
4967            Self::LineFitEdge(_) => CssPropertyType::LineFitEdge,
4968            Self::InitialLetterAlign(_) => CssPropertyType::InitialLetterAlign,
4969            Self::InitialLetterWrap(_) => CssPropertyType::InitialLetterWrap,
4970            Self::ScrollbarGutter(_) => CssPropertyType::ScrollbarGutter,
4971            Self::OverflowClipMargin(_) => CssPropertyType::OverflowClipMargin,
4972            Self::Clip(_) => CssPropertyType::Clip,
4973            Self::ExclusionMargin(_) => CssPropertyType::ExclusionMargin,
4974            Self::HyphenationLanguage(_) => CssPropertyType::HyphenationLanguage,
4975            Self::LineHeight(_) => CssPropertyType::LineHeight,
4976            Self::WordSpacing(_) => CssPropertyType::WordSpacing,
4977            Self::TabSize(_) => CssPropertyType::TabSize,
4978            Self::Cursor(_) => CssPropertyType::Cursor,
4979            Self::Display(_) => CssPropertyType::Display,
4980            Self::Float(_) => CssPropertyType::Float,
4981            Self::BoxSizing(_) => CssPropertyType::BoxSizing,
4982            Self::Width(_) => CssPropertyType::Width,
4983            Self::Height(_) => CssPropertyType::Height,
4984            Self::MinWidth(_) => CssPropertyType::MinWidth,
4985            Self::MinHeight(_) => CssPropertyType::MinHeight,
4986            Self::MaxWidth(_) => CssPropertyType::MaxWidth,
4987            Self::MaxHeight(_) => CssPropertyType::MaxHeight,
4988            Self::Position(_) => CssPropertyType::Position,
4989            Self::Top(_) => CssPropertyType::Top,
4990            Self::Right(_) => CssPropertyType::Right,
4991            Self::Left(_) => CssPropertyType::Left,
4992            Self::Bottom(_) => CssPropertyType::Bottom,
4993            Self::ZIndex(_) => CssPropertyType::ZIndex,
4994            Self::FlexWrap(_) => CssPropertyType::FlexWrap,
4995            Self::FlexDirection(_) => CssPropertyType::FlexDirection,
4996            Self::FlexGrow(_) => CssPropertyType::FlexGrow,
4997            Self::FlexShrink(_) => CssPropertyType::FlexShrink,
4998            Self::FlexBasis(_) => CssPropertyType::FlexBasis,
4999            Self::JustifyContent(_) => CssPropertyType::JustifyContent,
5000            Self::AlignItems(_) => CssPropertyType::AlignItems,
5001            Self::AlignContent(_) => CssPropertyType::AlignContent,
5002            Self::ColumnGap(_) => CssPropertyType::ColumnGap,
5003            Self::RowGap(_) => CssPropertyType::RowGap,
5004            Self::GridTemplateColumns(_) => CssPropertyType::GridTemplateColumns,
5005            Self::GridTemplateRows(_) => CssPropertyType::GridTemplateRows,
5006            Self::GridAutoColumns(_) => CssPropertyType::GridAutoColumns,
5007            Self::GridAutoRows(_) => CssPropertyType::GridAutoRows,
5008            Self::GridColumn(_) => CssPropertyType::GridColumn,
5009            Self::GridAutoFlow(_) => CssPropertyType::GridAutoFlow,
5010            Self::JustifySelf(_) => CssPropertyType::JustifySelf,
5011            Self::JustifyItems(_) => CssPropertyType::JustifyItems,
5012            Self::Gap(_) => CssPropertyType::Gap,
5013            Self::GridGap(_) => CssPropertyType::GridGap,
5014            Self::AlignSelf(_) => CssPropertyType::AlignSelf,
5015            Self::Font(_) => CssPropertyType::Font,
5016            Self::GridRow(_) => CssPropertyType::GridRow,
5017            Self::GridTemplateAreas(_) => CssPropertyType::GridTemplateAreas,
5018            Self::WritingMode(_) => CssPropertyType::WritingMode,
5019            Self::Clear(_) => CssPropertyType::Clear,
5020            Self::BackgroundContent(_) => CssPropertyType::BackgroundContent,
5021            Self::BackgroundPosition(_) => CssPropertyType::BackgroundPosition,
5022            Self::BackgroundSize(_) => CssPropertyType::BackgroundSize,
5023            Self::BackgroundRepeat(_) => CssPropertyType::BackgroundRepeat,
5024            Self::OverflowX(_) => CssPropertyType::OverflowX,
5025            Self::OverflowY(_) => CssPropertyType::OverflowY,
5026            Self::OverflowBlock(_) => CssPropertyType::OverflowBlock,
5027            Self::OverflowInline(_) => CssPropertyType::OverflowInline,
5028            Self::PaddingTop(_) => CssPropertyType::PaddingTop,
5029            Self::PaddingLeft(_) => CssPropertyType::PaddingLeft,
5030            Self::PaddingRight(_) => CssPropertyType::PaddingRight,
5031            Self::PaddingBottom(_) => CssPropertyType::PaddingBottom,
5032            Self::PaddingInlineStart(_) => CssPropertyType::PaddingInlineStart,
5033            Self::PaddingInlineEnd(_) => CssPropertyType::PaddingInlineEnd,
5034            Self::MarginTop(_) => CssPropertyType::MarginTop,
5035            Self::MarginLeft(_) => CssPropertyType::MarginLeft,
5036            Self::MarginRight(_) => CssPropertyType::MarginRight,
5037            Self::MarginBottom(_) => CssPropertyType::MarginBottom,
5038            Self::BorderTopLeftRadius(_) => CssPropertyType::BorderTopLeftRadius,
5039            Self::BorderTopRightRadius(_) => CssPropertyType::BorderTopRightRadius,
5040            Self::BorderBottomLeftRadius(_) => CssPropertyType::BorderBottomLeftRadius,
5041            Self::BorderBottomRightRadius(_) => CssPropertyType::BorderBottomRightRadius,
5042            Self::BorderTopColor(_) => CssPropertyType::BorderTopColor,
5043            Self::BorderRightColor(_) => CssPropertyType::BorderRightColor,
5044            Self::BorderLeftColor(_) => CssPropertyType::BorderLeftColor,
5045            Self::BorderBottomColor(_) => CssPropertyType::BorderBottomColor,
5046            Self::BorderTopStyle(_) => CssPropertyType::BorderTopStyle,
5047            Self::BorderRightStyle(_) => CssPropertyType::BorderRightStyle,
5048            Self::BorderLeftStyle(_) => CssPropertyType::BorderLeftStyle,
5049            Self::BorderBottomStyle(_) => CssPropertyType::BorderBottomStyle,
5050            Self::BorderTopWidth(_) => CssPropertyType::BorderTopWidth,
5051            Self::BorderRightWidth(_) => CssPropertyType::BorderRightWidth,
5052            Self::BorderLeftWidth(_) => CssPropertyType::BorderLeftWidth,
5053            Self::BorderBottomWidth(_) => CssPropertyType::BorderBottomWidth,
5054            Self::BoxShadowLeft(_) => CssPropertyType::BoxShadowLeft,
5055            Self::BoxShadowRight(_) => CssPropertyType::BoxShadowRight,
5056            Self::BoxShadowTop(_) => CssPropertyType::BoxShadowTop,
5057            Self::BoxShadowBottom(_) => CssPropertyType::BoxShadowBottom,
5058            Self::ScrollbarTrack(_) => CssPropertyType::ScrollbarTrack,
5059            Self::ScrollbarThumb(_) => CssPropertyType::ScrollbarThumb,
5060            Self::ScrollbarButton(_) => CssPropertyType::ScrollbarButton,
5061            Self::ScrollbarCorner(_) => CssPropertyType::ScrollbarCorner,
5062            Self::ScrollbarResizer(_) => CssPropertyType::ScrollbarResizer,
5063            Self::ScrollbarWidth(_) => CssPropertyType::ScrollbarWidth,
5064            Self::ScrollbarColor(_) => CssPropertyType::ScrollbarColor,
5065            Self::ScrollbarVisibility(_) => CssPropertyType::ScrollbarVisibility,
5066            Self::ScrollbarFadeDelay(_) => CssPropertyType::ScrollbarFadeDelay,
5067            Self::ScrollbarFadeDuration(_) => CssPropertyType::ScrollbarFadeDuration,
5068            Self::Opacity(_) => CssPropertyType::Opacity,
5069            Self::Visibility(_) => CssPropertyType::Visibility,
5070            Self::Transform(_) => CssPropertyType::Transform,
5071            Self::PerspectiveOrigin(_) => CssPropertyType::PerspectiveOrigin,
5072            Self::TransformOrigin(_) => CssPropertyType::TransformOrigin,
5073            Self::BackfaceVisibility(_) => CssPropertyType::BackfaceVisibility,
5074            Self::MixBlendMode(_) => CssPropertyType::MixBlendMode,
5075            Self::Filter(_) => CssPropertyType::Filter,
5076            Self::BackdropFilter(_) => CssPropertyType::BackdropFilter,
5077            Self::TextShadow(_) => CssPropertyType::TextShadow,
5078            Self::WhiteSpace(_) => CssPropertyType::WhiteSpace,
5079            Self::Hyphens(_) => CssPropertyType::Hyphens,
5080            Self::WordBreak(_) => CssPropertyType::WordBreak,
5081            Self::OverflowWrap(_) => CssPropertyType::OverflowWrap,
5082            Self::LineBreak(_) => CssPropertyType::LineBreak,
5083            Self::TextOverflow(_) => CssPropertyType::TextOverflow,
5084            Self::ObjectFit(_) => CssPropertyType::ObjectFit,
5085            Self::ObjectPosition(_) => CssPropertyType::ObjectPosition,
5086            Self::AspectRatio(_) => CssPropertyType::AspectRatio,
5087            Self::TextOrientation(_) => CssPropertyType::TextOrientation,
5088            Self::TextAlignLast(_) => CssPropertyType::TextAlignLast,
5089            Self::TextTransform(_) => CssPropertyType::TextTransform,
5090            Self::Direction(_) => CssPropertyType::Direction,
5091            Self::UserSelect(_) => CssPropertyType::UserSelect,
5092            Self::TextDecoration(_) => CssPropertyType::TextDecoration,
5093            Self::BreakBefore(_) => CssPropertyType::BreakBefore,
5094            Self::BreakAfter(_) => CssPropertyType::BreakAfter,
5095            Self::BreakInside(_) => CssPropertyType::BreakInside,
5096            Self::Orphans(_) => CssPropertyType::Orphans,
5097            Self::Widows(_) => CssPropertyType::Widows,
5098            Self::BoxDecorationBreak(_) => CssPropertyType::BoxDecorationBreak,
5099            Self::ColumnCount(_) => CssPropertyType::ColumnCount,
5100            Self::ColumnWidth(_) => CssPropertyType::ColumnWidth,
5101            Self::ColumnSpan(_) => CssPropertyType::ColumnSpan,
5102            Self::ColumnFill(_) => CssPropertyType::ColumnFill,
5103            Self::ColumnRuleWidth(_) => CssPropertyType::ColumnRuleWidth,
5104            Self::ColumnRuleStyle(_) => CssPropertyType::ColumnRuleStyle,
5105            Self::ColumnRuleColor(_) => CssPropertyType::ColumnRuleColor,
5106            Self::FlowInto(_) => CssPropertyType::FlowInto,
5107            Self::FlowFrom(_) => CssPropertyType::FlowFrom,
5108            Self::ShapeOutside(_) => CssPropertyType::ShapeOutside,
5109            Self::ShapeInside(_) => CssPropertyType::ShapeInside,
5110            Self::ClipPath(_) => CssPropertyType::ClipPath,
5111            Self::ShapeMargin(_) => CssPropertyType::ShapeMargin,
5112            Self::ShapeImageThreshold(_) => CssPropertyType::ShapeImageThreshold,
5113            Self::Content(_) => CssPropertyType::Content,
5114            Self::CounterReset(_) => CssPropertyType::CounterReset,
5115            Self::CounterIncrement(_) => CssPropertyType::CounterIncrement,
5116            Self::ListStyleType(_) => CssPropertyType::ListStyleType,
5117            Self::ListStylePosition(_) => CssPropertyType::ListStylePosition,
5118            Self::StringSet(_) => CssPropertyType::StringSet,
5119            Self::TableLayout(_) => CssPropertyType::TableLayout,
5120            Self::BorderCollapse(_) => CssPropertyType::BorderCollapse,
5121            Self::BorderSpacing(_) => CssPropertyType::BorderSpacing,
5122            Self::CaptionSide(_) => CssPropertyType::CaptionSide,
5123            Self::EmptyCells(_) => CssPropertyType::EmptyCells,
5124        }
5125    }
5126
5127    // const constructors for easier API access
5128
5129    #[must_use] pub const fn none(prop_type: CssPropertyType) -> Self {
5130        css_property_from_type!(prop_type, None)
5131    }
5132    #[must_use] pub const fn auto(prop_type: CssPropertyType) -> Self {
5133        css_property_from_type!(prop_type, Auto)
5134    }
5135    #[must_use] pub const fn initial(prop_type: CssPropertyType) -> Self {
5136        css_property_from_type!(prop_type, Initial)
5137    }
5138    #[must_use] pub const fn inherit(prop_type: CssPropertyType) -> Self {
5139        css_property_from_type!(prop_type, Inherit)
5140    }
5141
5142    #[must_use] pub const fn text_color(input: StyleTextColor) -> Self {
5143        Self::TextColor(CssPropertyValue::Exact(input))
5144    }
5145    #[must_use] pub const fn font_size(input: StyleFontSize) -> Self {
5146        Self::FontSize(CssPropertyValue::Exact(input))
5147    }
5148    #[must_use] pub const fn font_family(input: StyleFontFamilyVec) -> Self {
5149        Self::FontFamily(CssPropertyValue::Exact(input))
5150    }
5151    #[must_use] pub const fn font_weight(input: StyleFontWeight) -> Self {
5152        Self::FontWeight(CssPropertyValue::Exact(input))
5153    }
5154    #[must_use] pub const fn font_style(input: StyleFontStyle) -> Self {
5155        Self::FontStyle(CssPropertyValue::Exact(input))
5156    }
5157    #[must_use] pub const fn text_align(input: StyleTextAlign) -> Self {
5158        Self::TextAlign(CssPropertyValue::Exact(input))
5159    }
5160    #[must_use] pub const fn text_justify(input: LayoutTextJustify) -> Self {
5161        Self::TextJustify(CssPropertyValue::Exact(input))
5162    }
5163    #[must_use] pub const fn vertical_align(input: StyleVerticalAlign) -> Self {
5164        Self::VerticalAlign(CssPropertyValue::Exact(input))
5165    }
5166    #[must_use] pub const fn letter_spacing(input: StyleLetterSpacing) -> Self {
5167        Self::LetterSpacing(CssPropertyValue::Exact(input))
5168    }
5169    #[must_use] pub const fn text_indent(input: StyleTextIndent) -> Self {
5170        Self::TextIndent(CssPropertyValue::Exact(input))
5171    }
5172    #[must_use] pub const fn line_height(input: StyleLineHeight) -> Self {
5173        Self::LineHeight(CssPropertyValue::Exact(input))
5174    }
5175    #[must_use] pub const fn word_spacing(input: StyleWordSpacing) -> Self {
5176        Self::WordSpacing(CssPropertyValue::Exact(input))
5177    }
5178    #[must_use] pub const fn tab_size(input: StyleTabSize) -> Self {
5179        Self::TabSize(CssPropertyValue::Exact(input))
5180    }
5181    #[must_use] pub const fn cursor(input: StyleCursor) -> Self {
5182        Self::Cursor(CssPropertyValue::Exact(input))
5183    }
5184    #[must_use] pub const fn user_select(input: StyleUserSelect) -> Self {
5185        Self::UserSelect(CssPropertyValue::Exact(input))
5186    }
5187    #[must_use] pub const fn text_decoration(input: StyleTextDecoration) -> Self {
5188        Self::TextDecoration(CssPropertyValue::Exact(input))
5189    }
5190    #[must_use] pub const fn display(input: LayoutDisplay) -> Self {
5191        Self::Display(CssPropertyValue::Exact(input))
5192    }
5193    #[must_use] pub const fn box_sizing(input: LayoutBoxSizing) -> Self {
5194        Self::BoxSizing(CssPropertyValue::Exact(input))
5195    }
5196    #[must_use] pub const fn width(input: LayoutWidth) -> Self {
5197        Self::Width(CssPropertyValue::Exact(input))
5198    }
5199    #[must_use] pub const fn height(input: LayoutHeight) -> Self {
5200        Self::Height(CssPropertyValue::Exact(input))
5201    }
5202    #[must_use] pub const fn min_width(input: LayoutMinWidth) -> Self {
5203        Self::MinWidth(CssPropertyValue::Exact(input))
5204    }
5205    #[must_use] pub const fn caret_color(input: CaretColor) -> Self {
5206        Self::CaretColor(CssPropertyValue::Exact(input))
5207    }
5208    #[must_use] pub const fn caret_width(input: CaretWidth) -> Self {
5209        Self::CaretWidth(CssPropertyValue::Exact(input))
5210    }
5211    #[must_use] pub const fn caret_animation_duration(input: CaretAnimationDuration) -> Self {
5212        Self::CaretAnimationDuration(CssPropertyValue::Exact(input))
5213    }
5214    #[must_use] pub const fn selection_background_color(input: SelectionBackgroundColor) -> Self {
5215        Self::SelectionBackgroundColor(CssPropertyValue::Exact(input))
5216    }
5217    #[must_use] pub const fn selection_color(input: SelectionColor) -> Self {
5218        Self::SelectionColor(CssPropertyValue::Exact(input))
5219    }
5220    #[must_use] pub const fn min_height(input: LayoutMinHeight) -> Self {
5221        Self::MinHeight(CssPropertyValue::Exact(input))
5222    }
5223    #[must_use] pub const fn max_width(input: LayoutMaxWidth) -> Self {
5224        Self::MaxWidth(CssPropertyValue::Exact(input))
5225    }
5226    #[must_use] pub const fn max_height(input: LayoutMaxHeight) -> Self {
5227        Self::MaxHeight(CssPropertyValue::Exact(input))
5228    }
5229    #[must_use] pub const fn position(input: LayoutPosition) -> Self {
5230        Self::Position(CssPropertyValue::Exact(input))
5231    }
5232    #[must_use] pub const fn top(input: LayoutTop) -> Self {
5233        Self::Top(CssPropertyValue::Exact(input))
5234    }
5235    #[must_use] pub const fn right(input: LayoutRight) -> Self {
5236        Self::Right(CssPropertyValue::Exact(input))
5237    }
5238    #[must_use] pub const fn left(input: LayoutLeft) -> Self {
5239        Self::Left(CssPropertyValue::Exact(input))
5240    }
5241    #[must_use] pub const fn bottom(input: LayoutInsetBottom) -> Self {
5242        Self::Bottom(CssPropertyValue::Exact(input))
5243    }
5244    #[must_use] pub const fn z_index(input: LayoutZIndex) -> Self {
5245        Self::ZIndex(CssPropertyValue::Exact(input))
5246    }
5247    #[must_use] pub const fn flex_wrap(input: LayoutFlexWrap) -> Self {
5248        Self::FlexWrap(CssPropertyValue::Exact(input))
5249    }
5250    #[must_use] pub const fn flex_direction(input: LayoutFlexDirection) -> Self {
5251        Self::FlexDirection(CssPropertyValue::Exact(input))
5252    }
5253    #[must_use] pub const fn flex_grow(input: LayoutFlexGrow) -> Self {
5254        Self::FlexGrow(CssPropertyValue::Exact(input))
5255    }
5256    #[must_use] pub const fn flex_shrink(input: LayoutFlexShrink) -> Self {
5257        Self::FlexShrink(CssPropertyValue::Exact(input))
5258    }
5259    #[must_use] pub const fn justify_content(input: LayoutJustifyContent) -> Self {
5260        Self::JustifyContent(CssPropertyValue::Exact(input))
5261    }
5262    #[must_use] pub const fn grid_auto_flow(input: LayoutGridAutoFlow) -> Self {
5263        Self::GridAutoFlow(CssPropertyValue::Exact(input))
5264    }
5265    #[must_use] pub const fn justify_self(input: LayoutJustifySelf) -> Self {
5266        Self::JustifySelf(CssPropertyValue::Exact(input))
5267    }
5268    #[must_use] pub const fn justify_items(input: LayoutJustifyItems) -> Self {
5269        Self::JustifyItems(CssPropertyValue::Exact(input))
5270    }
5271    #[must_use] pub const fn gap(input: LayoutGap) -> Self {
5272        Self::Gap(CssPropertyValue::Exact(input))
5273    }
5274    #[must_use] pub const fn grid_gap(input: LayoutGap) -> Self {
5275        Self::GridGap(CssPropertyValue::Exact(input))
5276    }
5277    #[must_use] pub const fn align_self(input: LayoutAlignSelf) -> Self {
5278        Self::AlignSelf(CssPropertyValue::Exact(input))
5279    }
5280    #[must_use] pub const fn font(input: StyleFontFamilyVec) -> Self {
5281        Self::Font(StyleFontValue::Exact(input))
5282    }
5283    #[must_use] pub const fn align_items(input: LayoutAlignItems) -> Self {
5284        Self::AlignItems(CssPropertyValue::Exact(input))
5285    }
5286    #[must_use] pub const fn align_content(input: LayoutAlignContent) -> Self {
5287        Self::AlignContent(CssPropertyValue::Exact(input))
5288    }
5289    #[must_use] pub const fn background_content(input: StyleBackgroundContentVec) -> Self {
5290        Self::BackgroundContent(CssPropertyValue::Exact(input))
5291    }
5292    #[must_use] pub const fn background_position(input: StyleBackgroundPositionVec) -> Self {
5293        Self::BackgroundPosition(CssPropertyValue::Exact(input))
5294    }
5295    #[must_use] pub const fn background_size(input: StyleBackgroundSizeVec) -> Self {
5296        Self::BackgroundSize(CssPropertyValue::Exact(input))
5297    }
5298    #[must_use] pub const fn background_repeat(input: StyleBackgroundRepeatVec) -> Self {
5299        Self::BackgroundRepeat(CssPropertyValue::Exact(input))
5300    }
5301    #[must_use] pub const fn overflow_x(input: LayoutOverflow) -> Self {
5302        Self::OverflowX(CssPropertyValue::Exact(input))
5303    }
5304    #[must_use] pub const fn overflow_y(input: LayoutOverflow) -> Self {
5305        Self::OverflowY(CssPropertyValue::Exact(input))
5306    }
5307    #[must_use] pub const fn overflow_block(input: LayoutOverflow) -> Self {
5308        Self::OverflowBlock(CssPropertyValue::Exact(input))
5309    }
5310    #[must_use] pub const fn overflow_inline(input: LayoutOverflow) -> Self {
5311        Self::OverflowInline(CssPropertyValue::Exact(input))
5312    }
5313    #[must_use] pub const fn padding_top(input: LayoutPaddingTop) -> Self {
5314        Self::PaddingTop(CssPropertyValue::Exact(input))
5315    }
5316    #[must_use] pub const fn padding_left(input: LayoutPaddingLeft) -> Self {
5317        Self::PaddingLeft(CssPropertyValue::Exact(input))
5318    }
5319    #[must_use] pub const fn padding_right(input: LayoutPaddingRight) -> Self {
5320        Self::PaddingRight(CssPropertyValue::Exact(input))
5321    }
5322    #[must_use] pub const fn padding_bottom(input: LayoutPaddingBottom) -> Self {
5323        Self::PaddingBottom(CssPropertyValue::Exact(input))
5324    }
5325    #[must_use] pub const fn margin_top(input: LayoutMarginTop) -> Self {
5326        Self::MarginTop(CssPropertyValue::Exact(input))
5327    }
5328    #[must_use] pub const fn margin_left(input: LayoutMarginLeft) -> Self {
5329        Self::MarginLeft(CssPropertyValue::Exact(input))
5330    }
5331    #[must_use] pub const fn margin_right(input: LayoutMarginRight) -> Self {
5332        Self::MarginRight(CssPropertyValue::Exact(input))
5333    }
5334    #[must_use] pub const fn margin_bottom(input: LayoutMarginBottom) -> Self {
5335        Self::MarginBottom(CssPropertyValue::Exact(input))
5336    }
5337    #[must_use] pub const fn border_top_left_radius(input: StyleBorderTopLeftRadius) -> Self {
5338        Self::BorderTopLeftRadius(CssPropertyValue::Exact(input))
5339    }
5340    #[must_use] pub const fn border_top_right_radius(input: StyleBorderTopRightRadius) -> Self {
5341        Self::BorderTopRightRadius(CssPropertyValue::Exact(input))
5342    }
5343    #[must_use] pub const fn border_bottom_left_radius(input: StyleBorderBottomLeftRadius) -> Self {
5344        Self::BorderBottomLeftRadius(CssPropertyValue::Exact(input))
5345    }
5346    #[must_use] pub const fn border_bottom_right_radius(input: StyleBorderBottomRightRadius) -> Self {
5347        Self::BorderBottomRightRadius(CssPropertyValue::Exact(input))
5348    }
5349    #[must_use] pub const fn border_top_color(input: StyleBorderTopColor) -> Self {
5350        Self::BorderTopColor(CssPropertyValue::Exact(input))
5351    }
5352    #[must_use] pub const fn border_right_color(input: StyleBorderRightColor) -> Self {
5353        Self::BorderRightColor(CssPropertyValue::Exact(input))
5354    }
5355    #[must_use] pub const fn border_left_color(input: StyleBorderLeftColor) -> Self {
5356        Self::BorderLeftColor(CssPropertyValue::Exact(input))
5357    }
5358    #[must_use] pub const fn border_bottom_color(input: StyleBorderBottomColor) -> Self {
5359        Self::BorderBottomColor(CssPropertyValue::Exact(input))
5360    }
5361    #[must_use] pub const fn border_top_style(input: StyleBorderTopStyle) -> Self {
5362        Self::BorderTopStyle(CssPropertyValue::Exact(input))
5363    }
5364    #[must_use] pub const fn border_right_style(input: StyleBorderRightStyle) -> Self {
5365        Self::BorderRightStyle(CssPropertyValue::Exact(input))
5366    }
5367    #[must_use] pub const fn border_left_style(input: StyleBorderLeftStyle) -> Self {
5368        Self::BorderLeftStyle(CssPropertyValue::Exact(input))
5369    }
5370    #[must_use] pub const fn border_bottom_style(input: StyleBorderBottomStyle) -> Self {
5371        Self::BorderBottomStyle(CssPropertyValue::Exact(input))
5372    }
5373    #[must_use] pub const fn border_top_width(input: LayoutBorderTopWidth) -> Self {
5374        Self::BorderTopWidth(CssPropertyValue::Exact(input))
5375    }
5376    #[must_use] pub const fn border_right_width(input: LayoutBorderRightWidth) -> Self {
5377        Self::BorderRightWidth(CssPropertyValue::Exact(input))
5378    }
5379    #[must_use] pub const fn border_left_width(input: LayoutBorderLeftWidth) -> Self {
5380        Self::BorderLeftWidth(CssPropertyValue::Exact(input))
5381    }
5382    #[must_use] pub const fn border_bottom_width(input: LayoutBorderBottomWidth) -> Self {
5383        Self::BorderBottomWidth(CssPropertyValue::Exact(input))
5384    }
5385    #[must_use] pub fn box_shadow_left(input: StyleBoxShadow) -> Self {
5386        Self::BoxShadowLeft(CssPropertyValue::Exact(BoxOrStatic::heap(input)))
5387    }
5388    #[must_use] pub fn box_shadow_right(input: StyleBoxShadow) -> Self {
5389        Self::BoxShadowRight(CssPropertyValue::Exact(BoxOrStatic::heap(input)))
5390    }
5391    #[must_use] pub fn box_shadow_top(input: StyleBoxShadow) -> Self {
5392        Self::BoxShadowTop(CssPropertyValue::Exact(BoxOrStatic::heap(input)))
5393    }
5394    #[must_use] pub fn box_shadow_bottom(input: StyleBoxShadow) -> Self {
5395        Self::BoxShadowBottom(CssPropertyValue::Exact(BoxOrStatic::heap(input)))
5396    }
5397    #[must_use] pub const fn opacity(input: StyleOpacity) -> Self {
5398        Self::Opacity(CssPropertyValue::Exact(input))
5399    }
5400    #[must_use] pub const fn visibility(input: StyleVisibility) -> Self {
5401        Self::Visibility(CssPropertyValue::Exact(input))
5402    }
5403    #[must_use] pub const fn transform(input: StyleTransformVec) -> Self {
5404        Self::Transform(CssPropertyValue::Exact(input))
5405    }
5406    #[must_use] pub const fn transform_origin(input: StyleTransformOrigin) -> Self {
5407        Self::TransformOrigin(CssPropertyValue::Exact(input))
5408    }
5409    #[must_use] pub const fn perspective_origin(input: StylePerspectiveOrigin) -> Self {
5410        Self::PerspectiveOrigin(CssPropertyValue::Exact(input))
5411    }
5412    #[must_use] pub const fn backface_visibility(input: StyleBackfaceVisibility) -> Self {
5413        Self::BackfaceVisibility(CssPropertyValue::Exact(input))
5414    }
5415
5416    // New DTP const fn constructors
5417    #[must_use] pub const fn break_before(input: PageBreak) -> Self {
5418        Self::BreakBefore(CssPropertyValue::Exact(input))
5419    }
5420    #[must_use] pub const fn break_after(input: PageBreak) -> Self {
5421        Self::BreakAfter(CssPropertyValue::Exact(input))
5422    }
5423    #[must_use] pub const fn break_inside(input: BreakInside) -> Self {
5424        Self::BreakInside(CssPropertyValue::Exact(input))
5425    }
5426    #[must_use] pub const fn orphans(input: Orphans) -> Self {
5427        Self::Orphans(CssPropertyValue::Exact(input))
5428    }
5429    #[must_use] pub const fn widows(input: Widows) -> Self {
5430        Self::Widows(CssPropertyValue::Exact(input))
5431    }
5432    #[must_use] pub const fn box_decoration_break(input: BoxDecorationBreak) -> Self {
5433        Self::BoxDecorationBreak(CssPropertyValue::Exact(input))
5434    }
5435    #[must_use] pub const fn column_count(input: ColumnCount) -> Self {
5436        Self::ColumnCount(CssPropertyValue::Exact(input))
5437    }
5438    #[must_use] pub const fn column_width(input: ColumnWidth) -> Self {
5439        Self::ColumnWidth(CssPropertyValue::Exact(input))
5440    }
5441    #[must_use] pub const fn column_span(input: ColumnSpan) -> Self {
5442        Self::ColumnSpan(CssPropertyValue::Exact(input))
5443    }
5444    #[must_use] pub const fn column_fill(input: ColumnFill) -> Self {
5445        Self::ColumnFill(CssPropertyValue::Exact(input))
5446    }
5447    #[must_use] pub const fn column_rule_width(input: ColumnRuleWidth) -> Self {
5448        Self::ColumnRuleWidth(CssPropertyValue::Exact(input))
5449    }
5450    #[must_use] pub const fn column_rule_style(input: ColumnRuleStyle) -> Self {
5451        Self::ColumnRuleStyle(CssPropertyValue::Exact(input))
5452    }
5453    #[must_use] pub const fn column_rule_color(input: ColumnRuleColor) -> Self {
5454        Self::ColumnRuleColor(CssPropertyValue::Exact(input))
5455    }
5456    #[must_use] pub const fn flow_into(input: FlowInto) -> Self {
5457        Self::FlowInto(CssPropertyValue::Exact(input))
5458    }
5459    #[must_use] pub const fn flow_from(input: FlowFrom) -> Self {
5460        Self::FlowFrom(CssPropertyValue::Exact(input))
5461    }
5462    #[must_use] pub const fn shape_outside(input: ShapeOutside) -> Self {
5463        Self::ShapeOutside(CssPropertyValue::Exact(input))
5464    }
5465    #[must_use] pub const fn shape_inside(input: ShapeInside) -> Self {
5466        Self::ShapeInside(CssPropertyValue::Exact(input))
5467    }
5468    #[must_use] pub const fn clip_path(input: ClipPath) -> Self {
5469        Self::ClipPath(CssPropertyValue::Exact(input))
5470    }
5471    #[must_use] pub const fn shape_margin(input: ShapeMargin) -> Self {
5472        Self::ShapeMargin(CssPropertyValue::Exact(input))
5473    }
5474    #[must_use] pub const fn shape_image_threshold(input: ShapeImageThreshold) -> Self {
5475        Self::ShapeImageThreshold(CssPropertyValue::Exact(input))
5476    }
5477    #[must_use] pub const fn content(input: Content) -> Self {
5478        Self::Content(CssPropertyValue::Exact(input))
5479    }
5480    #[must_use] pub const fn counter_reset(input: CounterReset) -> Self {
5481        Self::CounterReset(CssPropertyValue::Exact(input))
5482    }
5483    #[must_use] pub const fn counter_increment(input: CounterIncrement) -> Self {
5484        Self::CounterIncrement(CssPropertyValue::Exact(input))
5485    }
5486    #[must_use] pub const fn list_style_type(input: StyleListStyleType) -> Self {
5487        Self::ListStyleType(CssPropertyValue::Exact(input))
5488    }
5489    #[must_use] pub const fn list_style_position(input: StyleListStylePosition) -> Self {
5490        Self::ListStylePosition(CssPropertyValue::Exact(input))
5491    }
5492    #[must_use] pub const fn string_set(input: StringSet) -> Self {
5493        Self::StringSet(CssPropertyValue::Exact(input))
5494    }
5495    #[must_use] pub const fn table_layout(input: LayoutTableLayout) -> Self {
5496        Self::TableLayout(CssPropertyValue::Exact(input))
5497    }
5498    #[must_use] pub const fn border_collapse(input: StyleBorderCollapse) -> Self {
5499        Self::BorderCollapse(CssPropertyValue::Exact(input))
5500    }
5501    #[must_use] pub const fn border_spacing(input: LayoutBorderSpacing) -> Self {
5502        Self::BorderSpacing(CssPropertyValue::Exact(input))
5503    }
5504    #[must_use] pub const fn caption_side(input: StyleCaptionSide) -> Self {
5505        Self::CaptionSide(CssPropertyValue::Exact(input))
5506    }
5507    #[must_use] pub const fn empty_cells(input: StyleEmptyCells) -> Self {
5508        Self::EmptyCells(CssPropertyValue::Exact(input))
5509    }
5510
5511    #[must_use] pub const fn as_z_index(&self) -> Option<&LayoutZIndexValue> {
5512        match self {
5513            Self::ZIndex(f) => Some(f),
5514            _ => None,
5515        }
5516    }
5517
5518    #[must_use] pub const fn as_flex_basis(&self) -> Option<&LayoutFlexBasisValue> {
5519        match self {
5520            Self::FlexBasis(f) => Some(f),
5521            _ => None,
5522        }
5523    }
5524
5525    #[must_use] pub const fn as_column_gap(&self) -> Option<&LayoutColumnGapValue> {
5526        match self {
5527            Self::ColumnGap(f) => Some(f),
5528            _ => None,
5529        }
5530    }
5531
5532    #[must_use] pub const fn as_row_gap(&self) -> Option<&LayoutRowGapValue> {
5533        match self {
5534            Self::RowGap(f) => Some(f),
5535            _ => None,
5536        }
5537    }
5538
5539    #[must_use] pub const fn as_grid_template_columns(&self) -> Option<&LayoutGridTemplateColumnsValue> {
5540        match self {
5541            Self::GridTemplateColumns(f) => Some(f),
5542            _ => None,
5543        }
5544    }
5545
5546    #[must_use] pub const fn as_grid_template_rows(&self) -> Option<&LayoutGridTemplateRowsValue> {
5547        match self {
5548            Self::GridTemplateRows(f) => Some(f),
5549            _ => None,
5550        }
5551    }
5552
5553    #[must_use] pub const fn as_grid_auto_columns(&self) -> Option<&LayoutGridAutoColumnsValue> {
5554        match self {
5555            Self::GridAutoColumns(f) => Some(f),
5556            _ => None,
5557        }
5558    }
5559
5560    #[must_use] pub const fn as_grid_auto_rows(&self) -> Option<&LayoutGridAutoRowsValue> {
5561        match self {
5562            Self::GridAutoRows(f) => Some(f),
5563            _ => None,
5564        }
5565    }
5566
5567    #[must_use] pub const fn as_grid_column(&self) -> Option<&LayoutGridColumnValue> {
5568        match self {
5569            Self::GridColumn(f) => Some(f),
5570            _ => None,
5571        }
5572    }
5573
5574    #[must_use] pub const fn as_grid_row(&self) -> Option<&LayoutGridRowValue> {
5575        match self {
5576            Self::GridRow(f) => Some(f),
5577            _ => None,
5578        }
5579    }
5580
5581    #[must_use] pub const fn as_writing_mode(&self) -> Option<&LayoutWritingModeValue> {
5582        match self {
5583            Self::WritingMode(f) => Some(f),
5584            _ => None,
5585        }
5586    }
5587
5588    #[must_use] pub const fn as_clear(&self) -> Option<&LayoutClearValue> {
5589        match self {
5590            Self::Clear(f) => Some(f),
5591            _ => None,
5592        }
5593    }
5594
5595    #[must_use] pub const fn as_scrollbar_track(&self) -> Option<&StyleBackgroundContentValue> {
5596        match self {
5597            Self::ScrollbarTrack(f) => Some(f),
5598            _ => None,
5599        }
5600    }
5601
5602    #[must_use] pub const fn as_scrollbar_thumb(&self) -> Option<&StyleBackgroundContentValue> {
5603        match self {
5604            Self::ScrollbarThumb(f) => Some(f),
5605            _ => None,
5606        }
5607    }
5608
5609    #[must_use] pub const fn as_scrollbar_button(&self) -> Option<&StyleBackgroundContentValue> {
5610        match self {
5611            Self::ScrollbarButton(f) => Some(f),
5612            _ => None,
5613        }
5614    }
5615
5616    #[must_use] pub const fn as_scrollbar_corner(&self) -> Option<&StyleBackgroundContentValue> {
5617        match self {
5618            Self::ScrollbarCorner(f) => Some(f),
5619            _ => None,
5620        }
5621    }
5622
5623    #[must_use] pub const fn as_scrollbar_resizer(&self) -> Option<&StyleBackgroundContentValue> {
5624        match self {
5625            Self::ScrollbarResizer(f) => Some(f),
5626            _ => None,
5627        }
5628    }
5629
5630    #[must_use] pub const fn as_visibility(&self) -> Option<&StyleVisibilityValue> {
5631        match self {
5632            Self::Visibility(f) => Some(f),
5633            _ => None,
5634        }
5635    }
5636
5637    #[must_use] pub const fn as_background_content(&self) -> Option<&StyleBackgroundContentVecValue> {
5638        match self {
5639            Self::BackgroundContent(f) => Some(f),
5640            _ => None,
5641        }
5642    }
5643    #[must_use] pub const fn as_text_justify(&self) -> Option<&LayoutTextJustifyValue> {
5644        match self {
5645            Self::TextJustify(f) => Some(f),
5646            _ => None,
5647        }
5648    }
5649    #[must_use] pub const fn as_caret_color(&self) -> Option<&CaretColorValue> {
5650        match self {
5651            Self::CaretColor(f) => Some(f),
5652            _ => None,
5653        }
5654    }
5655    #[must_use] pub const fn as_caret_width(&self) -> Option<&CaretWidthValue> {
5656        match self {
5657            Self::CaretWidth(f) => Some(f),
5658            _ => None,
5659        }
5660    }
5661    #[must_use] pub const fn as_caret_animation_duration(&self) -> Option<&CaretAnimationDurationValue> {
5662        match self {
5663            Self::CaretAnimationDuration(f) => Some(f),
5664            _ => None,
5665        }
5666    }
5667    #[must_use] pub const fn as_selection_background_color(&self) -> Option<&SelectionBackgroundColorValue> {
5668        match self {
5669            Self::SelectionBackgroundColor(f) => Some(f),
5670            _ => None,
5671        }
5672    }
5673    #[must_use] pub const fn as_selection_color(&self) -> Option<&SelectionColorValue> {
5674        match self {
5675            Self::SelectionColor(f) => Some(f),
5676            _ => None,
5677        }
5678    }
5679    #[must_use] pub const fn as_selection_radius(&self) -> Option<&SelectionRadiusValue> {
5680        match self {
5681            Self::SelectionRadius(f) => Some(f),
5682            _ => None,
5683        }
5684    }
5685    #[must_use] pub const fn as_background_position(&self) -> Option<&StyleBackgroundPositionVecValue> {
5686        match self {
5687            Self::BackgroundPosition(f) => Some(f),
5688            _ => None,
5689        }
5690    }
5691    #[must_use] pub const fn as_background_size(&self) -> Option<&StyleBackgroundSizeVecValue> {
5692        match self {
5693            Self::BackgroundSize(f) => Some(f),
5694            _ => None,
5695        }
5696    }
5697    #[must_use] pub const fn as_background_repeat(&self) -> Option<&StyleBackgroundRepeatVecValue> {
5698        match self {
5699            Self::BackgroundRepeat(f) => Some(f),
5700            _ => None,
5701        }
5702    }
5703
5704    #[must_use] pub const fn as_grid_auto_flow(&self) -> Option<&LayoutGridAutoFlowValue> {
5705        match self {
5706            Self::GridAutoFlow(f) => Some(f),
5707            _ => None,
5708        }
5709    }
5710    #[must_use] pub const fn as_justify_self(&self) -> Option<&LayoutJustifySelfValue> {
5711        match self {
5712            Self::JustifySelf(f) => Some(f),
5713            _ => None,
5714        }
5715    }
5716    #[must_use] pub const fn as_justify_items(&self) -> Option<&LayoutJustifyItemsValue> {
5717        match self {
5718            Self::JustifyItems(f) => Some(f),
5719            _ => None,
5720        }
5721    }
5722    #[must_use] pub const fn as_gap(&self) -> Option<&LayoutGapValue> {
5723        match self {
5724            Self::Gap(f) => Some(f),
5725            _ => None,
5726        }
5727    }
5728    #[must_use] pub const fn as_grid_gap(&self) -> Option<&LayoutGapValue> {
5729        match self {
5730            Self::GridGap(f) => Some(f),
5731            _ => None,
5732        }
5733    }
5734    #[must_use] pub const fn as_align_self(&self) -> Option<&LayoutAlignSelfValue> {
5735        match self {
5736            Self::AlignSelf(f) => Some(f),
5737            _ => None,
5738        }
5739    }
5740    #[must_use] pub const fn as_font(&self) -> Option<&StyleFontValue> {
5741        match self {
5742            Self::Font(f) => Some(f),
5743            _ => None,
5744        }
5745    }
5746    #[must_use] pub const fn as_font_size(&self) -> Option<&StyleFontSizeValue> {
5747        match self {
5748            Self::FontSize(f) => Some(f),
5749            _ => None,
5750        }
5751    }
5752    #[must_use] pub const fn as_font_family(&self) -> Option<&StyleFontFamilyVecValue> {
5753        match self {
5754            Self::FontFamily(f) => Some(f),
5755            _ => None,
5756        }
5757    }
5758    #[must_use] pub const fn as_font_weight(&self) -> Option<&StyleFontWeightValue> {
5759        match self {
5760            Self::FontWeight(f) => Some(f),
5761            _ => None,
5762        }
5763    }
5764    #[must_use] pub const fn as_font_style(&self) -> Option<&StyleFontStyleValue> {
5765        match self {
5766            Self::FontStyle(f) => Some(f),
5767            _ => None,
5768        }
5769    }
5770    #[must_use] pub const fn as_text_color(&self) -> Option<&StyleTextColorValue> {
5771        match self {
5772            Self::TextColor(f) => Some(f),
5773            _ => None,
5774        }
5775    }
5776    #[must_use] pub const fn as_text_align(&self) -> Option<&StyleTextAlignValue> {
5777        match self {
5778            Self::TextAlign(f) => Some(f),
5779            _ => None,
5780        }
5781    }
5782    #[must_use] pub const fn as_vertical_align(&self) -> Option<&StyleVerticalAlignValue> {
5783        match self {
5784            Self::VerticalAlign(f) => Some(f),
5785            _ => None,
5786        }
5787    }
5788    #[must_use] pub const fn as_line_height(&self) -> Option<&StyleLineHeightValue> {
5789        match self {
5790            Self::LineHeight(f) => Some(f),
5791            _ => None,
5792        }
5793    }
5794    #[must_use] pub const fn as_text_indent(&self) -> Option<&StyleTextIndentValue> {
5795        match self {
5796            Self::TextIndent(f) => Some(f),
5797            _ => None,
5798        }
5799    }
5800    #[must_use] pub const fn as_initial_letter(&self) -> Option<&StyleInitialLetterValue> {
5801        match self {
5802            Self::InitialLetter(f) => Some(f),
5803            _ => None,
5804        }
5805    }
5806    #[must_use] pub const fn as_line_clamp(&self) -> Option<&StyleLineClampValue> {
5807        match self {
5808            Self::LineClamp(f) => Some(f),
5809            _ => None,
5810        }
5811    }
5812    #[must_use] pub const fn as_hanging_punctuation(&self) -> Option<&StyleHangingPunctuationValue> {
5813        match self {
5814            Self::HangingPunctuation(f) => Some(f),
5815            _ => None,
5816        }
5817    }
5818    #[must_use] pub const fn as_text_combine_upright(&self) -> Option<&StyleTextCombineUprightValue> {
5819        match self {
5820            Self::TextCombineUpright(f) => Some(f),
5821            _ => None,
5822        }
5823    }
5824    #[must_use] pub const fn as_unicode_bidi(&self) -> Option<&StyleUnicodeBidiValue> {
5825        match self {
5826            Self::UnicodeBidi(f) => Some(f),
5827            _ => None,
5828        }
5829    }
5830    #[must_use] pub const fn as_text_box_trim(&self) -> Option<&StyleTextBoxTrimValue> {
5831        match self {
5832            Self::TextBoxTrim(f) => Some(f),
5833            _ => None,
5834        }
5835    }
5836    #[must_use] pub const fn as_text_box_edge(&self) -> Option<&StyleTextBoxEdgeValue> {
5837        match self {
5838            Self::TextBoxEdge(f) => Some(f),
5839            _ => None,
5840        }
5841    }
5842    #[must_use] pub const fn as_dominant_baseline(&self) -> Option<&StyleDominantBaselineValue> {
5843        match self {
5844            Self::DominantBaseline(f) => Some(f),
5845            _ => None,
5846        }
5847    }
5848    #[must_use] pub const fn as_alignment_baseline(&self) -> Option<&StyleAlignmentBaselineValue> {
5849        match self {
5850            Self::AlignmentBaseline(f) => Some(f),
5851            _ => None,
5852        }
5853    }
5854    #[must_use] pub const fn as_baseline_source(&self) -> Option<&StyleBaselineSourceValue> {
5855        match self {
5856            Self::BaselineSource(f) => Some(f),
5857            _ => None,
5858        }
5859    }
5860    #[must_use] pub const fn as_line_fit_edge(&self) -> Option<&StyleLineFitEdgeValue> {
5861        match self {
5862            Self::LineFitEdge(f) => Some(f),
5863            _ => None,
5864        }
5865    }
5866    #[must_use] pub const fn as_initial_letter_align(&self) -> Option<&StyleInitialLetterAlignValue> {
5867        match self {
5868            Self::InitialLetterAlign(f) => Some(f),
5869            _ => None,
5870        }
5871    }
5872    #[must_use] pub const fn as_initial_letter_wrap(&self) -> Option<&StyleInitialLetterWrapValue> {
5873        match self {
5874            Self::InitialLetterWrap(f) => Some(f),
5875            _ => None,
5876        }
5877    }
5878    #[must_use] pub const fn as_scrollbar_gutter(&self) -> Option<&StyleScrollbarGutterValue> {
5879        match self {
5880            Self::ScrollbarGutter(f) => Some(f),
5881            _ => None,
5882        }
5883    }
5884    #[must_use] pub const fn as_overflow_clip_margin(&self) -> Option<&StyleOverflowClipMarginValue> {
5885        match self {
5886            Self::OverflowClipMargin(f) => Some(f),
5887            _ => None,
5888        }
5889    }
5890    #[must_use] pub const fn as_clip(&self) -> Option<&StyleClipRectValue> {
5891        match self {
5892            Self::Clip(f) => Some(f),
5893            _ => None,
5894        }
5895    }
5896    #[must_use] pub const fn as_exclusion_margin(&self) -> Option<&StyleExclusionMarginValue> {
5897        match self {
5898            Self::ExclusionMargin(f) => Some(f),
5899            _ => None,
5900        }
5901    }
5902    #[must_use] pub const fn as_hyphenation_language(&self) -> Option<&StyleHyphenationLanguageValue> {
5903        match self {
5904            Self::HyphenationLanguage(f) => Some(f),
5905            _ => None,
5906        }
5907    }
5908    #[must_use] pub const fn as_letter_spacing(&self) -> Option<&StyleLetterSpacingValue> {
5909        match self {
5910            Self::LetterSpacing(f) => Some(f),
5911            _ => None,
5912        }
5913    }
5914    #[must_use] pub const fn as_word_spacing(&self) -> Option<&StyleWordSpacingValue> {
5915        match self {
5916            Self::WordSpacing(f) => Some(f),
5917            _ => None,
5918        }
5919    }
5920    #[must_use] pub const fn as_tab_size(&self) -> Option<&StyleTabSizeValue> {
5921        match self {
5922            Self::TabSize(f) => Some(f),
5923            _ => None,
5924        }
5925    }
5926    #[must_use] pub const fn as_cursor(&self) -> Option<&StyleCursorValue> {
5927        match self {
5928            Self::Cursor(f) => Some(f),
5929            _ => None,
5930        }
5931    }
5932    #[must_use] pub const fn as_box_shadow_left(&self) -> Option<&StyleBoxShadowValue> {
5933        match self {
5934            Self::BoxShadowLeft(f) => Some(f),
5935            _ => None,
5936        }
5937    }
5938    #[must_use] pub const fn as_box_shadow_right(&self) -> Option<&StyleBoxShadowValue> {
5939        match self {
5940            Self::BoxShadowRight(f) => Some(f),
5941            _ => None,
5942        }
5943    }
5944    #[must_use] pub const fn as_box_shadow_top(&self) -> Option<&StyleBoxShadowValue> {
5945        match self {
5946            Self::BoxShadowTop(f) => Some(f),
5947            _ => None,
5948        }
5949    }
5950    #[must_use] pub const fn as_box_shadow_bottom(&self) -> Option<&StyleBoxShadowValue> {
5951        match self {
5952            Self::BoxShadowBottom(f) => Some(f),
5953            _ => None,
5954        }
5955    }
5956    #[must_use] pub const fn as_border_top_color(&self) -> Option<&StyleBorderTopColorValue> {
5957        match self {
5958            Self::BorderTopColor(f) => Some(f),
5959            _ => None,
5960        }
5961    }
5962    #[must_use] pub const fn as_border_left_color(&self) -> Option<&StyleBorderLeftColorValue> {
5963        match self {
5964            Self::BorderLeftColor(f) => Some(f),
5965            _ => None,
5966        }
5967    }
5968    #[must_use] pub const fn as_border_right_color(&self) -> Option<&StyleBorderRightColorValue> {
5969        match self {
5970            Self::BorderRightColor(f) => Some(f),
5971            _ => None,
5972        }
5973    }
5974    #[must_use] pub const fn as_border_bottom_color(&self) -> Option<&StyleBorderBottomColorValue> {
5975        match self {
5976            Self::BorderBottomColor(f) => Some(f),
5977            _ => None,
5978        }
5979    }
5980    #[must_use] pub const fn as_border_top_style(&self) -> Option<&StyleBorderTopStyleValue> {
5981        match self {
5982            Self::BorderTopStyle(f) => Some(f),
5983            _ => None,
5984        }
5985    }
5986    #[must_use] pub const fn as_border_left_style(&self) -> Option<&StyleBorderLeftStyleValue> {
5987        match self {
5988            Self::BorderLeftStyle(f) => Some(f),
5989            _ => None,
5990        }
5991    }
5992    #[must_use] pub const fn as_border_right_style(&self) -> Option<&StyleBorderRightStyleValue> {
5993        match self {
5994            Self::BorderRightStyle(f) => Some(f),
5995            _ => None,
5996        }
5997    }
5998    #[must_use] pub const fn as_border_bottom_style(&self) -> Option<&StyleBorderBottomStyleValue> {
5999        match self {
6000            Self::BorderBottomStyle(f) => Some(f),
6001            _ => None,
6002        }
6003    }
6004    #[must_use] pub const fn as_border_top_left_radius(&self) -> Option<&StyleBorderTopLeftRadiusValue> {
6005        match self {
6006            Self::BorderTopLeftRadius(f) => Some(f),
6007            _ => None,
6008        }
6009    }
6010    #[must_use] pub const fn as_border_top_right_radius(&self) -> Option<&StyleBorderTopRightRadiusValue> {
6011        match self {
6012            Self::BorderTopRightRadius(f) => Some(f),
6013            _ => None,
6014        }
6015    }
6016    #[must_use] pub const fn as_border_bottom_left_radius(&self) -> Option<&StyleBorderBottomLeftRadiusValue> {
6017        match self {
6018            Self::BorderBottomLeftRadius(f) => Some(f),
6019            _ => None,
6020        }
6021    }
6022    #[must_use] pub const fn as_border_bottom_right_radius(
6023        &self,
6024    ) -> Option<&StyleBorderBottomRightRadiusValue> {
6025        match self {
6026            Self::BorderBottomRightRadius(f) => Some(f),
6027            _ => None,
6028        }
6029    }
6030    #[must_use] pub const fn as_opacity(&self) -> Option<&StyleOpacityValue> {
6031        match self {
6032            Self::Opacity(f) => Some(f),
6033            _ => None,
6034        }
6035    }
6036    #[must_use] pub const fn as_transform(&self) -> Option<&StyleTransformVecValue> {
6037        match self {
6038            Self::Transform(f) => Some(f),
6039            _ => None,
6040        }
6041    }
6042    #[must_use] pub const fn as_transform_origin(&self) -> Option<&StyleTransformOriginValue> {
6043        match self {
6044            Self::TransformOrigin(f) => Some(f),
6045            _ => None,
6046        }
6047    }
6048    #[must_use] pub const fn as_perspective_origin(&self) -> Option<&StylePerspectiveOriginValue> {
6049        match self {
6050            Self::PerspectiveOrigin(f) => Some(f),
6051            _ => None,
6052        }
6053    }
6054    #[must_use] pub const fn as_backface_visibility(&self) -> Option<&StyleBackfaceVisibilityValue> {
6055        match self {
6056            Self::BackfaceVisibility(f) => Some(f),
6057            _ => None,
6058        }
6059    }
6060    #[must_use] pub const fn as_mix_blend_mode(&self) -> Option<&StyleMixBlendModeValue> {
6061        match self {
6062            Self::MixBlendMode(f) => Some(f),
6063            _ => None,
6064        }
6065    }
6066    #[must_use] pub const fn as_filter(&self) -> Option<&StyleFilterVecValue> {
6067        match self {
6068            Self::Filter(f) => Some(f),
6069            _ => None,
6070        }
6071    }
6072    #[must_use] pub const fn as_backdrop_filter(&self) -> Option<&StyleFilterVecValue> {
6073        match self {
6074            Self::BackdropFilter(f) => Some(f),
6075            _ => None,
6076        }
6077    }
6078    #[must_use] pub const fn as_text_shadow(&self) -> Option<&StyleBoxShadowValue> {
6079        match self {
6080            Self::TextShadow(f) => Some(f),
6081            _ => None,
6082        }
6083    }
6084
6085    // functions that downcast to the concrete CSS type (layout)
6086
6087    #[must_use] pub const fn as_display(&self) -> Option<&LayoutDisplayValue> {
6088        match self {
6089            Self::Display(f) => Some(f),
6090            _ => None,
6091        }
6092    }
6093    #[must_use] pub const fn as_float(&self) -> Option<&LayoutFloatValue> {
6094        match self {
6095            Self::Float(f) => Some(f),
6096            _ => None,
6097        }
6098    }
6099    #[must_use] pub const fn as_box_sizing(&self) -> Option<&LayoutBoxSizingValue> {
6100        match self {
6101            Self::BoxSizing(f) => Some(f),
6102            _ => None,
6103        }
6104    }
6105    #[must_use] pub const fn as_width(&self) -> Option<&LayoutWidthValue> {
6106        match self {
6107            Self::Width(f) => Some(f),
6108            _ => None,
6109        }
6110    }
6111    #[must_use] pub const fn as_height(&self) -> Option<&LayoutHeightValue> {
6112        match self {
6113            Self::Height(f) => Some(f),
6114            _ => None,
6115        }
6116    }
6117    #[must_use] pub const fn as_min_width(&self) -> Option<&LayoutMinWidthValue> {
6118        match self {
6119            Self::MinWidth(f) => Some(f),
6120            _ => None,
6121        }
6122    }
6123    #[must_use] pub const fn as_min_height(&self) -> Option<&LayoutMinHeightValue> {
6124        match self {
6125            Self::MinHeight(f) => Some(f),
6126            _ => None,
6127        }
6128    }
6129    #[must_use] pub const fn as_max_width(&self) -> Option<&LayoutMaxWidthValue> {
6130        match self {
6131            Self::MaxWidth(f) => Some(f),
6132            _ => None,
6133        }
6134    }
6135    #[must_use] pub const fn as_max_height(&self) -> Option<&LayoutMaxHeightValue> {
6136        match self {
6137            Self::MaxHeight(f) => Some(f),
6138            _ => None,
6139        }
6140    }
6141    #[must_use] pub const fn as_position(&self) -> Option<&LayoutPositionValue> {
6142        match self {
6143            Self::Position(f) => Some(f),
6144            _ => None,
6145        }
6146    }
6147    #[must_use] pub const fn as_top(&self) -> Option<&LayoutTopValue> {
6148        match self {
6149            Self::Top(f) => Some(f),
6150            _ => None,
6151        }
6152    }
6153    #[must_use] pub const fn as_bottom(&self) -> Option<&LayoutInsetBottomValue> {
6154        match self {
6155            Self::Bottom(f) => Some(f),
6156            _ => None,
6157        }
6158    }
6159    #[must_use] pub const fn as_right(&self) -> Option<&LayoutRightValue> {
6160        match self {
6161            Self::Right(f) => Some(f),
6162            _ => None,
6163        }
6164    }
6165    #[must_use] pub const fn as_left(&self) -> Option<&LayoutLeftValue> {
6166        match self {
6167            Self::Left(f) => Some(f),
6168            _ => None,
6169        }
6170    }
6171    #[must_use] pub const fn as_padding_top(&self) -> Option<&LayoutPaddingTopValue> {
6172        match self {
6173            Self::PaddingTop(f) => Some(f),
6174            _ => None,
6175        }
6176    }
6177    #[must_use] pub const fn as_padding_bottom(&self) -> Option<&LayoutPaddingBottomValue> {
6178        match self {
6179            Self::PaddingBottom(f) => Some(f),
6180            _ => None,
6181        }
6182    }
6183    #[must_use] pub const fn as_padding_left(&self) -> Option<&LayoutPaddingLeftValue> {
6184        match self {
6185            Self::PaddingLeft(f) => Some(f),
6186            _ => None,
6187        }
6188    }
6189    #[must_use] pub const fn as_padding_right(&self) -> Option<&LayoutPaddingRightValue> {
6190        match self {
6191            Self::PaddingRight(f) => Some(f),
6192            _ => None,
6193        }
6194    }
6195    #[must_use] pub const fn as_margin_top(&self) -> Option<&LayoutMarginTopValue> {
6196        match self {
6197            Self::MarginTop(f) => Some(f),
6198            _ => None,
6199        }
6200    }
6201    #[must_use] pub const fn as_margin_bottom(&self) -> Option<&LayoutMarginBottomValue> {
6202        match self {
6203            Self::MarginBottom(f) => Some(f),
6204            _ => None,
6205        }
6206    }
6207    #[must_use] pub const fn as_margin_left(&self) -> Option<&LayoutMarginLeftValue> {
6208        match self {
6209            Self::MarginLeft(f) => Some(f),
6210            _ => None,
6211        }
6212    }
6213    #[must_use] pub const fn as_margin_right(&self) -> Option<&LayoutMarginRightValue> {
6214        match self {
6215            Self::MarginRight(f) => Some(f),
6216            _ => None,
6217        }
6218    }
6219    #[must_use] pub const fn as_border_top_width(&self) -> Option<&LayoutBorderTopWidthValue> {
6220        match self {
6221            Self::BorderTopWidth(f) => Some(f),
6222            _ => None,
6223        }
6224    }
6225    #[must_use] pub const fn as_border_left_width(&self) -> Option<&LayoutBorderLeftWidthValue> {
6226        match self {
6227            Self::BorderLeftWidth(f) => Some(f),
6228            _ => None,
6229        }
6230    }
6231    #[must_use] pub const fn as_border_right_width(&self) -> Option<&LayoutBorderRightWidthValue> {
6232        match self {
6233            Self::BorderRightWidth(f) => Some(f),
6234            _ => None,
6235        }
6236    }
6237    #[must_use] pub const fn as_border_bottom_width(&self) -> Option<&LayoutBorderBottomWidthValue> {
6238        match self {
6239            Self::BorderBottomWidth(f) => Some(f),
6240            _ => None,
6241        }
6242    }
6243    #[must_use] pub const fn as_overflow_x(&self) -> Option<&LayoutOverflowValue> {
6244        match self {
6245            Self::OverflowX(f) => Some(f),
6246            _ => None,
6247        }
6248    }
6249    #[must_use] pub const fn as_overflow_y(&self) -> Option<&LayoutOverflowValue> {
6250        match self {
6251            Self::OverflowY(f) => Some(f),
6252            _ => None,
6253        }
6254    }
6255    #[must_use] pub const fn as_overflow_block(&self) -> Option<&LayoutOverflowValue> {
6256        match self {
6257            Self::OverflowBlock(f) => Some(f),
6258            _ => None,
6259        }
6260    }
6261    #[must_use] pub const fn as_overflow_inline(&self) -> Option<&LayoutOverflowValue> {
6262        match self {
6263            Self::OverflowInline(f) => Some(f),
6264            _ => None,
6265        }
6266    }
6267    #[must_use] pub const fn as_flex_direction(&self) -> Option<&LayoutFlexDirectionValue> {
6268        match self {
6269            Self::FlexDirection(f) => Some(f),
6270            _ => None,
6271        }
6272    }
6273    #[must_use] pub const fn as_direction(&self) -> Option<&StyleDirectionValue> {
6274        match self {
6275            Self::Direction(f) => Some(f),
6276            _ => None,
6277        }
6278    }
6279    #[must_use] pub const fn as_user_select(&self) -> Option<&StyleUserSelectValue> {
6280        match self {
6281            Self::UserSelect(f) => Some(f),
6282            _ => None,
6283        }
6284    }
6285    #[must_use] pub const fn as_text_decoration(&self) -> Option<&StyleTextDecorationValue> {
6286        match self {
6287            Self::TextDecoration(f) => Some(f),
6288            _ => None,
6289        }
6290    }
6291    #[must_use] pub const fn as_hyphens(&self) -> Option<&StyleHyphensValue> {
6292        match self {
6293            Self::Hyphens(f) => Some(f),
6294            _ => None,
6295        }
6296    }
6297    #[must_use] pub const fn as_word_break(&self) -> Option<&StyleWordBreakValue> {
6298        match self {
6299            Self::WordBreak(f) => Some(f),
6300            _ => None,
6301        }
6302    }
6303    #[must_use] pub const fn as_overflow_wrap(&self) -> Option<&StyleOverflowWrapValue> {
6304        match self {
6305            Self::OverflowWrap(f) => Some(f),
6306            _ => None,
6307        }
6308    }
6309    #[must_use] pub const fn as_line_break(&self) -> Option<&StyleLineBreakValue> {
6310        match self {
6311            Self::LineBreak(f) => Some(f),
6312            _ => None,
6313        }
6314    }
6315    #[must_use] pub const fn as_object_fit(&self) -> Option<&StyleObjectFitValue> {
6316        match self {
6317            Self::ObjectFit(f) => Some(f),
6318            _ => None,
6319        }
6320    }
6321    #[must_use] pub const fn as_text_overflow(&self) -> Option<&StyleTextOverflowValue> {
6322        match self {
6323            Self::TextOverflow(f) => Some(f),
6324            _ => None,
6325        }
6326    }
6327    #[must_use] pub const fn as_object_position(&self) -> Option<&StyleObjectPositionValue> {
6328        match self {
6329            Self::ObjectPosition(f) => Some(f),
6330            _ => None,
6331        }
6332    }
6333    #[must_use] pub const fn as_aspect_ratio(&self) -> Option<&StyleAspectRatioValue> {
6334        match self {
6335            Self::AspectRatio(f) => Some(f),
6336            _ => None,
6337        }
6338    }
6339    #[must_use] pub const fn as_text_orientation(&self) -> Option<&StyleTextOrientationValue> {
6340        match self {
6341            Self::TextOrientation(f) => Some(f),
6342            _ => None,
6343        }
6344    }
6345    #[must_use] pub const fn as_text_transform(&self) -> Option<&StyleTextTransformValue> {
6346        match self {
6347            Self::TextTransform(f) => Some(f),
6348            _ => None,
6349        }
6350    }
6351    #[must_use] pub const fn as_text_align_last(&self) -> Option<&StyleTextAlignLastValue> {
6352        match self {
6353            Self::TextAlignLast(f) => Some(f),
6354            _ => None,
6355        }
6356    }
6357    #[must_use] pub const fn as_white_space(&self) -> Option<&StyleWhiteSpaceValue> {
6358        match self {
6359            Self::WhiteSpace(f) => Some(f),
6360            _ => None,
6361        }
6362    }
6363    #[must_use] pub const fn as_flex_wrap(&self) -> Option<&LayoutFlexWrapValue> {
6364        match self {
6365            Self::FlexWrap(f) => Some(f),
6366            _ => None,
6367        }
6368    }
6369    #[must_use] pub const fn as_flex_grow(&self) -> Option<&LayoutFlexGrowValue> {
6370        match self {
6371            Self::FlexGrow(f) => Some(f),
6372            _ => None,
6373        }
6374    }
6375    #[must_use] pub const fn as_flex_shrink(&self) -> Option<&LayoutFlexShrinkValue> {
6376        match self {
6377            Self::FlexShrink(f) => Some(f),
6378            _ => None,
6379        }
6380    }
6381    #[must_use] pub const fn as_justify_content(&self) -> Option<&LayoutJustifyContentValue> {
6382        match self {
6383            Self::JustifyContent(f) => Some(f),
6384            _ => None,
6385        }
6386    }
6387    #[must_use] pub const fn as_align_items(&self) -> Option<&LayoutAlignItemsValue> {
6388        match self {
6389            Self::AlignItems(f) => Some(f),
6390            _ => None,
6391        }
6392    }
6393    #[must_use] pub const fn as_align_content(&self) -> Option<&LayoutAlignContentValue> {
6394        match self {
6395            Self::AlignContent(f) => Some(f),
6396            _ => None,
6397        }
6398    }
6399    #[must_use] pub const fn as_break_before(&self) -> Option<&PageBreakValue> {
6400        match self {
6401            Self::BreakBefore(f) => Some(f),
6402            _ => None,
6403        }
6404    }
6405    #[must_use] pub const fn as_break_after(&self) -> Option<&PageBreakValue> {
6406        match self {
6407            Self::BreakAfter(f) => Some(f),
6408            _ => None,
6409        }
6410    }
6411    #[must_use] pub const fn as_break_inside(&self) -> Option<&BreakInsideValue> {
6412        match self {
6413            Self::BreakInside(f) => Some(f),
6414            _ => None,
6415        }
6416    }
6417    #[must_use] pub const fn as_orphans(&self) -> Option<&OrphansValue> {
6418        match self {
6419            Self::Orphans(f) => Some(f),
6420            _ => None,
6421        }
6422    }
6423    #[must_use] pub const fn as_widows(&self) -> Option<&WidowsValue> {
6424        match self {
6425            Self::Widows(f) => Some(f),
6426            _ => None,
6427        }
6428    }
6429    #[must_use] pub const fn as_box_decoration_break(&self) -> Option<&BoxDecorationBreakValue> {
6430        match self {
6431            Self::BoxDecorationBreak(f) => Some(f),
6432            _ => None,
6433        }
6434    }
6435    #[must_use] pub const fn as_column_count(&self) -> Option<&ColumnCountValue> {
6436        match self {
6437            Self::ColumnCount(f) => Some(f),
6438            _ => None,
6439        }
6440    }
6441    #[must_use] pub const fn as_column_width(&self) -> Option<&ColumnWidthValue> {
6442        match self {
6443            Self::ColumnWidth(f) => Some(f),
6444            _ => None,
6445        }
6446    }
6447    #[must_use] pub const fn as_column_span(&self) -> Option<&ColumnSpanValue> {
6448        match self {
6449            Self::ColumnSpan(f) => Some(f),
6450            _ => None,
6451        }
6452    }
6453    #[must_use] pub const fn as_column_fill(&self) -> Option<&ColumnFillValue> {
6454        match self {
6455            Self::ColumnFill(f) => Some(f),
6456            _ => None,
6457        }
6458    }
6459    #[must_use] pub const fn as_column_rule_width(&self) -> Option<&ColumnRuleWidthValue> {
6460        match self {
6461            Self::ColumnRuleWidth(f) => Some(f),
6462            _ => None,
6463        }
6464    }
6465    #[must_use] pub const fn as_column_rule_style(&self) -> Option<&ColumnRuleStyleValue> {
6466        match self {
6467            Self::ColumnRuleStyle(f) => Some(f),
6468            _ => None,
6469        }
6470    }
6471    #[must_use] pub const fn as_column_rule_color(&self) -> Option<&ColumnRuleColorValue> {
6472        match self {
6473            Self::ColumnRuleColor(f) => Some(f),
6474            _ => None,
6475        }
6476    }
6477    #[must_use] pub const fn as_flow_into(&self) -> Option<&FlowIntoValue> {
6478        match self {
6479            Self::FlowInto(f) => Some(f),
6480            _ => None,
6481        }
6482    }
6483    #[must_use] pub const fn as_flow_from(&self) -> Option<&FlowFromValue> {
6484        match self {
6485            Self::FlowFrom(f) => Some(f),
6486            _ => None,
6487        }
6488    }
6489    #[must_use] pub const fn as_shape_outside(&self) -> Option<&ShapeOutsideValue> {
6490        match self {
6491            Self::ShapeOutside(f) => Some(f),
6492            _ => None,
6493        }
6494    }
6495    #[must_use] pub const fn as_shape_inside(&self) -> Option<&ShapeInsideValue> {
6496        match self {
6497            Self::ShapeInside(f) => Some(f),
6498            _ => None,
6499        }
6500    }
6501    #[must_use] pub const fn as_clip_path(&self) -> Option<&ClipPathValue> {
6502        match self {
6503            Self::ClipPath(f) => Some(f),
6504            _ => None,
6505        }
6506    }
6507    #[must_use] pub const fn as_shape_margin(&self) -> Option<&ShapeMarginValue> {
6508        match self {
6509            Self::ShapeMargin(f) => Some(f),
6510            _ => None,
6511        }
6512    }
6513    #[must_use] pub const fn as_shape_image_threshold(&self) -> Option<&ShapeImageThresholdValue> {
6514        match self {
6515            Self::ShapeImageThreshold(f) => Some(f),
6516            _ => None,
6517        }
6518    }
6519    #[must_use] pub const fn as_content(&self) -> Option<&ContentValue> {
6520        match self {
6521            Self::Content(f) => Some(f),
6522            _ => None,
6523        }
6524    }
6525    #[must_use] pub const fn as_counter_reset(&self) -> Option<&CounterResetValue> {
6526        match self {
6527            Self::CounterReset(f) => Some(f),
6528            _ => None,
6529        }
6530    }
6531    #[must_use] pub const fn as_counter_increment(&self) -> Option<&CounterIncrementValue> {
6532        match self {
6533            Self::CounterIncrement(f) => Some(f),
6534            _ => None,
6535        }
6536    }
6537    #[must_use] pub const fn as_list_style_type(&self) -> Option<&StyleListStyleTypeValue> {
6538        match self {
6539            Self::ListStyleType(f) => Some(f),
6540            _ => None,
6541        }
6542    }
6543    #[must_use] pub const fn as_list_style_position(&self) -> Option<&StyleListStylePositionValue> {
6544        match self {
6545            Self::ListStylePosition(f) => Some(f),
6546            _ => None,
6547        }
6548    }
6549    #[must_use] pub const fn as_string_set(&self) -> Option<&StringSetValue> {
6550        match self {
6551            Self::StringSet(f) => Some(f),
6552            _ => None,
6553        }
6554    }
6555    #[must_use] pub const fn as_table_layout(&self) -> Option<&LayoutTableLayoutValue> {
6556        match self {
6557            Self::TableLayout(f) => Some(f),
6558            _ => None,
6559        }
6560    }
6561    #[must_use] pub const fn as_border_collapse(&self) -> Option<&StyleBorderCollapseValue> {
6562        match self {
6563            Self::BorderCollapse(f) => Some(f),
6564            _ => None,
6565        }
6566    }
6567    #[must_use] pub const fn as_border_spacing(&self) -> Option<&LayoutBorderSpacingValue> {
6568        match self {
6569            Self::BorderSpacing(f) => Some(f),
6570            _ => None,
6571        }
6572    }
6573    #[must_use] pub const fn as_caption_side(&self) -> Option<&StyleCaptionSideValue> {
6574        match self {
6575            Self::CaptionSide(f) => Some(f),
6576            _ => None,
6577        }
6578    }
6579    #[must_use] pub const fn as_empty_cells(&self) -> Option<&StyleEmptyCellsValue> {
6580        match self {
6581            Self::EmptyCells(f) => Some(f),
6582            _ => None,
6583        }
6584    }
6585
6586    #[must_use] pub const fn as_scrollbar_width(&self) -> Option<&LayoutScrollbarWidthValue> {
6587        match self {
6588            Self::ScrollbarWidth(f) => Some(f),
6589            _ => None,
6590        }
6591    }
6592    #[must_use] pub const fn as_scrollbar_color(&self) -> Option<&StyleScrollbarColorValue> {
6593        match self {
6594            Self::ScrollbarColor(f) => Some(f),
6595            _ => None,
6596        }
6597    }
6598
6599    #[must_use] pub const fn as_scrollbar_visibility(&self) -> Option<&ScrollbarVisibilityModeValue> {
6600        match self {
6601            Self::ScrollbarVisibility(f) => Some(f),
6602            _ => None,
6603        }
6604    }
6605
6606    #[must_use] pub const fn as_scrollbar_fade_delay(&self) -> Option<&ScrollbarFadeDelayValue> {
6607        match self {
6608            Self::ScrollbarFadeDelay(f) => Some(f),
6609            _ => None,
6610        }
6611    }
6612
6613    #[must_use] pub const fn as_scrollbar_fade_duration(&self) -> Option<&ScrollbarFadeDurationValue> {
6614        match self {
6615            Self::ScrollbarFadeDuration(f) => Some(f),
6616            _ => None,
6617        }
6618    }
6619
6620    // Cross-type dispatch: each `c` is a different `CssPropertyValue<T>`, so the
6621    // identical `c.is_initial()` bodies can't merge (clippy::match_same_arms FP).
6622    #[allow(clippy::match_same_arms)]
6623    #[allow(clippy::too_many_lines)] // large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
6624    #[must_use] pub const fn is_initial(&self) -> bool {
6625        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};
6626        match self {
6627            CaretColor(c) => c.is_initial(),
6628            CaretWidth(c) => c.is_initial(),
6629            CaretAnimationDuration(c) => c.is_initial(),
6630            SelectionBackgroundColor(c) => c.is_initial(),
6631            SelectionColor(c) => c.is_initial(),
6632            SelectionRadius(c) => c.is_initial(),
6633            TextJustify(c) => c.is_initial(),
6634            TextColor(c) => c.is_initial(),
6635            FontSize(c) => c.is_initial(),
6636            FontFamily(c) => c.is_initial(),
6637            TextAlign(c) => c.is_initial(),
6638            LetterSpacing(c) => c.is_initial(),
6639            TextIndent(c) => c.is_initial(),
6640            InitialLetter(c) => c.is_initial(),
6641            LineClamp(c) => c.is_initial(),
6642            HangingPunctuation(c) => c.is_initial(),
6643            TextCombineUpright(c) => c.is_initial(),
6644            UnicodeBidi(c) => c.is_initial(),
6645            TextBoxTrim(c) => c.is_initial(),
6646            TextBoxEdge(c) => c.is_initial(),
6647            DominantBaseline(c) => c.is_initial(),
6648            AlignmentBaseline(c) => c.is_initial(),
6649            BaselineSource(c) => c.is_initial(),
6650            LineFitEdge(c) => c.is_initial(),
6651            InitialLetterAlign(c) => c.is_initial(),
6652            InitialLetterWrap(c) => c.is_initial(),
6653            ScrollbarGutter(c) => c.is_initial(),
6654            OverflowClipMargin(c) => c.is_initial(),
6655            Clip(c) => c.is_initial(),
6656            ExclusionMargin(c) => c.is_initial(),
6657            HyphenationLanguage(c) => c.is_initial(),
6658            LineHeight(c) => c.is_initial(),
6659            WordSpacing(c) => c.is_initial(),
6660            TabSize(c) => c.is_initial(),
6661            Cursor(c) => c.is_initial(),
6662            Display(c) => c.is_initial(),
6663            Float(c) => c.is_initial(),
6664            BoxSizing(c) => c.is_initial(),
6665            Width(c) => c.is_initial(),
6666            Height(c) => c.is_initial(),
6667            MinWidth(c) => c.is_initial(),
6668            MinHeight(c) => c.is_initial(),
6669            MaxWidth(c) => c.is_initial(),
6670            MaxHeight(c) => c.is_initial(),
6671            Position(c) => c.is_initial(),
6672            Top(c) => c.is_initial(),
6673            Right(c) => c.is_initial(),
6674            Left(c) => c.is_initial(),
6675            Bottom(c) => c.is_initial(),
6676            ZIndex(c) => c.is_initial(),
6677            FlexWrap(c) => c.is_initial(),
6678            FlexDirection(c) => c.is_initial(),
6679            FlexGrow(c) => c.is_initial(),
6680            FlexShrink(c) => c.is_initial(),
6681            FlexBasis(c) => c.is_initial(),
6682            JustifyContent(c) => c.is_initial(),
6683            AlignItems(c) => c.is_initial(),
6684            AlignContent(c) => c.is_initial(),
6685            ColumnGap(c) => c.is_initial(),
6686            RowGap(c) => c.is_initial(),
6687            GridTemplateColumns(c) => c.is_initial(),
6688            GridTemplateRows(c) => c.is_initial(),
6689            GridAutoFlow(c) => c.is_initial(),
6690            JustifySelf(c) => c.is_initial(),
6691            JustifyItems(c) => c.is_initial(),
6692            Gap(c) => c.is_initial(),
6693            GridGap(c) => c.is_initial(),
6694            AlignSelf(c) => c.is_initial(),
6695            Font(c) => c.is_initial(),
6696            GridAutoColumns(c) => c.is_initial(),
6697            GridAutoRows(c) => c.is_initial(),
6698            GridColumn(c) => c.is_initial(),
6699            GridRow(c) => c.is_initial(),
6700            GridTemplateAreas(c) => c.is_initial(),
6701            WritingMode(c) => c.is_initial(),
6702            Clear(c) => c.is_initial(),
6703            BackgroundContent(c) => c.is_initial(),
6704            BackgroundPosition(c) => c.is_initial(),
6705            BackgroundSize(c) => c.is_initial(),
6706            BackgroundRepeat(c) => c.is_initial(),
6707            OverflowX(c) => c.is_initial(),
6708            OverflowY(c) => c.is_initial(),
6709            OverflowBlock(c) => c.is_initial(),
6710            OverflowInline(c) => c.is_initial(),
6711            PaddingTop(c) => c.is_initial(),
6712            PaddingLeft(c) => c.is_initial(),
6713            PaddingRight(c) => c.is_initial(),
6714            PaddingBottom(c) => c.is_initial(),
6715            PaddingInlineStart(c) => c.is_initial(),
6716            PaddingInlineEnd(c) => c.is_initial(),
6717            MarginTop(c) => c.is_initial(),
6718            MarginLeft(c) => c.is_initial(),
6719            MarginRight(c) => c.is_initial(),
6720            MarginBottom(c) => c.is_initial(),
6721            BorderTopLeftRadius(c) => c.is_initial(),
6722            BorderTopRightRadius(c) => c.is_initial(),
6723            BorderBottomLeftRadius(c) => c.is_initial(),
6724            BorderBottomRightRadius(c) => c.is_initial(),
6725            BorderTopColor(c) => c.is_initial(),
6726            BorderRightColor(c) => c.is_initial(),
6727            BorderLeftColor(c) => c.is_initial(),
6728            BorderBottomColor(c) => c.is_initial(),
6729            BorderTopStyle(c) => c.is_initial(),
6730            BorderRightStyle(c) => c.is_initial(),
6731            BorderLeftStyle(c) => c.is_initial(),
6732            BorderBottomStyle(c) => c.is_initial(),
6733            BorderTopWidth(c) => c.is_initial(),
6734            BorderRightWidth(c) => c.is_initial(),
6735            BorderLeftWidth(c) => c.is_initial(),
6736            BorderBottomWidth(c) => c.is_initial(),
6737            BoxShadowLeft(c) => c.is_initial(),
6738            BoxShadowRight(c) => c.is_initial(),
6739            BoxShadowTop(c) => c.is_initial(),
6740            BoxShadowBottom(c) => c.is_initial(),
6741            ScrollbarTrack(c) => c.is_initial(),
6742            ScrollbarThumb(c) => c.is_initial(),
6743            ScrollbarButton(c) => c.is_initial(),
6744            ScrollbarCorner(c) => c.is_initial(),
6745            ScrollbarResizer(c) => c.is_initial(),
6746            ScrollbarWidth(c) => c.is_initial(),
6747            ScrollbarColor(c) => c.is_initial(),
6748            ScrollbarVisibility(c) => c.is_initial(),
6749            ScrollbarFadeDelay(c) => c.is_initial(),
6750            ScrollbarFadeDuration(c) => c.is_initial(),
6751            Opacity(c) => c.is_initial(),
6752            Visibility(c) => c.is_initial(),
6753            Transform(c) => c.is_initial(),
6754            TransformOrigin(c) => c.is_initial(),
6755            PerspectiveOrigin(c) => c.is_initial(),
6756            BackfaceVisibility(c) => c.is_initial(),
6757            MixBlendMode(c) => c.is_initial(),
6758            Filter(c) => c.is_initial(),
6759            BackdropFilter(c) => c.is_initial(),
6760            TextShadow(c) => c.is_initial(),
6761            WhiteSpace(c) => c.is_initial(),
6762            Direction(c) => c.is_initial(),
6763            UserSelect(c) => c.is_initial(),
6764            TextDecoration(c) => c.is_initial(),
6765            Hyphens(c) => c.is_initial(),
6766            WordBreak(c) => c.is_initial(),
6767            OverflowWrap(c) => c.is_initial(),
6768            LineBreak(c) => c.is_initial(),
6769            TextOverflow(c) => c.is_initial(),
6770            ObjectFit(c) => c.is_initial(),
6771            ObjectPosition(c) => c.is_initial(),
6772            AspectRatio(c) => c.is_initial(),
6773            TextOrientation(c) => c.is_initial(),
6774            TextAlignLast(c) => c.is_initial(),
6775            TextTransform(c) => c.is_initial(),
6776            BreakBefore(c) => c.is_initial(),
6777            BreakAfter(c) => c.is_initial(),
6778            BreakInside(c) => c.is_initial(),
6779            Orphans(c) => c.is_initial(),
6780            Widows(c) => c.is_initial(),
6781            BoxDecorationBreak(c) => c.is_initial(),
6782            ColumnCount(c) => c.is_initial(),
6783            ColumnWidth(c) => c.is_initial(),
6784            ColumnSpan(c) => c.is_initial(),
6785            ColumnFill(c) => c.is_initial(),
6786            ColumnRuleWidth(c) => c.is_initial(),
6787            ColumnRuleStyle(c) => c.is_initial(),
6788            ColumnRuleColor(c) => c.is_initial(),
6789            FlowInto(c) => c.is_initial(),
6790            FlowFrom(c) => c.is_initial(),
6791            ShapeOutside(c) => c.is_initial(),
6792            ShapeInside(c) => c.is_initial(),
6793            ClipPath(c) => c.is_initial(),
6794            ShapeMargin(c) => c.is_initial(),
6795            ShapeImageThreshold(c) => c.is_initial(),
6796            Content(c) => c.is_initial(),
6797            CounterReset(c) => c.is_initial(),
6798            CounterIncrement(c) => c.is_initial(),
6799            ListStyleType(c) => c.is_initial(),
6800            ListStylePosition(c) => c.is_initial(),
6801            StringSet(c) => c.is_initial(),
6802            TableLayout(c) => c.is_initial(),
6803            BorderCollapse(c) => c.is_initial(),
6804            BorderSpacing(c) => c.is_initial(),
6805            CaptionSide(c) => c.is_initial(),
6806            EmptyCells(c) => c.is_initial(),
6807            FontWeight(c) => c.is_initial(),
6808            FontStyle(c) => c.is_initial(),
6809            VerticalAlign(c) => c.is_initial(),
6810        }
6811    }
6812
6813    #[must_use] pub const fn const_none(prop_type: CssPropertyType) -> Self {
6814        css_property_from_type!(prop_type, None)
6815    }
6816    #[must_use] pub const fn const_auto(prop_type: CssPropertyType) -> Self {
6817        css_property_from_type!(prop_type, Auto)
6818    }
6819    #[must_use] pub const fn const_initial(prop_type: CssPropertyType) -> Self {
6820        css_property_from_type!(prop_type, Initial)
6821    }
6822    #[must_use] pub const fn const_inherit(prop_type: CssPropertyType) -> Self {
6823        css_property_from_type!(prop_type, Inherit)
6824    }
6825
6826    #[must_use] pub const fn const_text_color(input: StyleTextColor) -> Self {
6827        Self::TextColor(StyleTextColorValue::Exact(input))
6828    }
6829    #[must_use] pub const fn const_font_size(input: StyleFontSize) -> Self {
6830        Self::FontSize(StyleFontSizeValue::Exact(input))
6831    }
6832    #[must_use] pub const fn const_font_family(input: StyleFontFamilyVec) -> Self {
6833        Self::FontFamily(StyleFontFamilyVecValue::Exact(input))
6834    }
6835    #[must_use] pub const fn const_text_align(input: StyleTextAlign) -> Self {
6836        Self::TextAlign(StyleTextAlignValue::Exact(input))
6837    }
6838    #[must_use] pub const fn const_vertical_align(input: StyleVerticalAlign) -> Self {
6839        Self::VerticalAlign(StyleVerticalAlignValue::Exact(input))
6840    }
6841    #[must_use] pub const fn const_letter_spacing(input: StyleLetterSpacing) -> Self {
6842        Self::LetterSpacing(StyleLetterSpacingValue::Exact(input))
6843    }
6844    #[must_use] pub const fn const_text_indent(input: StyleTextIndent) -> Self {
6845        Self::TextIndent(StyleTextIndentValue::Exact(input))
6846    }
6847    #[must_use] pub const fn const_line_height(input: StyleLineHeight) -> Self {
6848        Self::LineHeight(StyleLineHeightValue::Exact(input))
6849    }
6850    #[must_use] pub const fn const_word_spacing(input: StyleWordSpacing) -> Self {
6851        Self::WordSpacing(StyleWordSpacingValue::Exact(input))
6852    }
6853    #[must_use] pub const fn const_tab_size(input: StyleTabSize) -> Self {
6854        Self::TabSize(StyleTabSizeValue::Exact(input))
6855    }
6856    #[must_use] pub const fn const_cursor(input: StyleCursor) -> Self {
6857        Self::Cursor(StyleCursorValue::Exact(input))
6858    }
6859    #[must_use] pub const fn const_display(input: LayoutDisplay) -> Self {
6860        Self::Display(LayoutDisplayValue::Exact(input))
6861    }
6862    #[must_use] pub const fn const_float(input: LayoutFloat) -> Self {
6863        Self::Float(LayoutFloatValue::Exact(input))
6864    }
6865    #[must_use] pub const fn const_box_sizing(input: LayoutBoxSizing) -> Self {
6866        Self::BoxSizing(LayoutBoxSizingValue::Exact(input))
6867    }
6868    #[must_use] pub const fn const_width(input: LayoutWidth) -> Self {
6869        Self::Width(LayoutWidthValue::Exact(input))
6870    }
6871    #[must_use] pub const fn const_height(input: LayoutHeight) -> Self {
6872        Self::Height(LayoutHeightValue::Exact(input))
6873    }
6874    #[must_use] pub const fn const_min_width(input: LayoutMinWidth) -> Self {
6875        Self::MinWidth(LayoutMinWidthValue::Exact(input))
6876    }
6877    #[must_use] pub const fn const_min_height(input: LayoutMinHeight) -> Self {
6878        Self::MinHeight(LayoutMinHeightValue::Exact(input))
6879    }
6880    #[must_use] pub const fn const_max_width(input: LayoutMaxWidth) -> Self {
6881        Self::MaxWidth(LayoutMaxWidthValue::Exact(input))
6882    }
6883    #[must_use] pub const fn const_max_height(input: LayoutMaxHeight) -> Self {
6884        Self::MaxHeight(LayoutMaxHeightValue::Exact(input))
6885    }
6886    #[must_use] pub const fn const_position(input: LayoutPosition) -> Self {
6887        Self::Position(LayoutPositionValue::Exact(input))
6888    }
6889    #[must_use] pub const fn const_top(input: LayoutTop) -> Self {
6890        Self::Top(LayoutTopValue::Exact(input))
6891    }
6892    #[must_use] pub const fn const_right(input: LayoutRight) -> Self {
6893        Self::Right(LayoutRightValue::Exact(input))
6894    }
6895    #[must_use] pub const fn const_left(input: LayoutLeft) -> Self {
6896        Self::Left(LayoutLeftValue::Exact(input))
6897    }
6898    #[must_use] pub const fn const_bottom(input: LayoutInsetBottom) -> Self {
6899        Self::Bottom(LayoutInsetBottomValue::Exact(input))
6900    }
6901    #[must_use] pub const fn const_flex_wrap(input: LayoutFlexWrap) -> Self {
6902        Self::FlexWrap(LayoutFlexWrapValue::Exact(input))
6903    }
6904    #[must_use] pub const fn const_flex_direction(input: LayoutFlexDirection) -> Self {
6905        Self::FlexDirection(LayoutFlexDirectionValue::Exact(input))
6906    }
6907    #[must_use] pub const fn const_flex_grow(input: LayoutFlexGrow) -> Self {
6908        Self::FlexGrow(LayoutFlexGrowValue::Exact(input))
6909    }
6910    #[must_use] pub const fn const_flex_shrink(input: LayoutFlexShrink) -> Self {
6911        Self::FlexShrink(LayoutFlexShrinkValue::Exact(input))
6912    }
6913    #[must_use] pub const fn const_justify_content(input: LayoutJustifyContent) -> Self {
6914        Self::JustifyContent(LayoutJustifyContentValue::Exact(input))
6915    }
6916    #[must_use] pub const fn const_align_items(input: LayoutAlignItems) -> Self {
6917        Self::AlignItems(LayoutAlignItemsValue::Exact(input))
6918    }
6919    #[must_use] pub const fn const_align_content(input: LayoutAlignContent) -> Self {
6920        Self::AlignContent(LayoutAlignContentValue::Exact(input))
6921    }
6922    #[must_use] pub const fn const_background_content(input: StyleBackgroundContentVec) -> Self {
6923        Self::BackgroundContent(StyleBackgroundContentVecValue::Exact(input))
6924    }
6925    #[must_use] pub const fn const_background_position(input: StyleBackgroundPositionVec) -> Self {
6926        Self::BackgroundPosition(StyleBackgroundPositionVecValue::Exact(input))
6927    }
6928    #[must_use] pub const fn const_background_size(input: StyleBackgroundSizeVec) -> Self {
6929        Self::BackgroundSize(StyleBackgroundSizeVecValue::Exact(input))
6930    }
6931    #[must_use] pub const fn const_background_repeat(input: StyleBackgroundRepeatVec) -> Self {
6932        Self::BackgroundRepeat(StyleBackgroundRepeatVecValue::Exact(input))
6933    }
6934    #[must_use] pub const fn const_overflow_x(input: LayoutOverflow) -> Self {
6935        Self::OverflowX(LayoutOverflowValue::Exact(input))
6936    }
6937    #[must_use] pub const fn const_overflow_y(input: LayoutOverflow) -> Self {
6938        Self::OverflowY(LayoutOverflowValue::Exact(input))
6939    }
6940    #[must_use] pub const fn const_overflow_block(input: LayoutOverflow) -> Self {
6941        Self::OverflowBlock(LayoutOverflowValue::Exact(input))
6942    }
6943    #[must_use] pub const fn const_overflow_inline(input: LayoutOverflow) -> Self {
6944        Self::OverflowInline(LayoutOverflowValue::Exact(input))
6945    }
6946    #[must_use] pub const fn const_padding_top(input: LayoutPaddingTop) -> Self {
6947        Self::PaddingTop(LayoutPaddingTopValue::Exact(input))
6948    }
6949    #[must_use] pub const fn const_padding_left(input: LayoutPaddingLeft) -> Self {
6950        Self::PaddingLeft(LayoutPaddingLeftValue::Exact(input))
6951    }
6952    #[must_use] pub const fn const_padding_right(input: LayoutPaddingRight) -> Self {
6953        Self::PaddingRight(LayoutPaddingRightValue::Exact(input))
6954    }
6955    #[must_use] pub const fn const_padding_bottom(input: LayoutPaddingBottom) -> Self {
6956        Self::PaddingBottom(LayoutPaddingBottomValue::Exact(input))
6957    }
6958    #[must_use] pub const fn const_margin_top(input: LayoutMarginTop) -> Self {
6959        Self::MarginTop(LayoutMarginTopValue::Exact(input))
6960    }
6961    #[must_use] pub const fn const_margin_left(input: LayoutMarginLeft) -> Self {
6962        Self::MarginLeft(LayoutMarginLeftValue::Exact(input))
6963    }
6964    #[must_use] pub const fn const_margin_right(input: LayoutMarginRight) -> Self {
6965        Self::MarginRight(LayoutMarginRightValue::Exact(input))
6966    }
6967    #[must_use] pub const fn const_margin_bottom(input: LayoutMarginBottom) -> Self {
6968        Self::MarginBottom(LayoutMarginBottomValue::Exact(input))
6969    }
6970    #[must_use] pub const fn const_border_top_left_radius(input: StyleBorderTopLeftRadius) -> Self {
6971        Self::BorderTopLeftRadius(StyleBorderTopLeftRadiusValue::Exact(input))
6972    }
6973    #[must_use] pub const fn const_border_top_right_radius(input: StyleBorderTopRightRadius) -> Self {
6974        Self::BorderTopRightRadius(StyleBorderTopRightRadiusValue::Exact(input))
6975    }
6976    #[must_use] pub const fn const_border_bottom_left_radius(input: StyleBorderBottomLeftRadius) -> Self {
6977        Self::BorderBottomLeftRadius(StyleBorderBottomLeftRadiusValue::Exact(input))
6978    }
6979    #[must_use] pub const fn const_border_bottom_right_radius(input: StyleBorderBottomRightRadius) -> Self {
6980        Self::BorderBottomRightRadius(StyleBorderBottomRightRadiusValue::Exact(input))
6981    }
6982    #[must_use] pub const fn const_border_top_color(input: StyleBorderTopColor) -> Self {
6983        Self::BorderTopColor(StyleBorderTopColorValue::Exact(input))
6984    }
6985    #[must_use] pub const fn const_border_right_color(input: StyleBorderRightColor) -> Self {
6986        Self::BorderRightColor(StyleBorderRightColorValue::Exact(input))
6987    }
6988    #[must_use] pub const fn const_border_left_color(input: StyleBorderLeftColor) -> Self {
6989        Self::BorderLeftColor(StyleBorderLeftColorValue::Exact(input))
6990    }
6991    #[must_use] pub const fn const_border_bottom_color(input: StyleBorderBottomColor) -> Self {
6992        Self::BorderBottomColor(StyleBorderBottomColorValue::Exact(input))
6993    }
6994    #[must_use] pub const fn const_border_top_style(input: StyleBorderTopStyle) -> Self {
6995        Self::BorderTopStyle(StyleBorderTopStyleValue::Exact(input))
6996    }
6997    #[must_use] pub const fn const_border_right_style(input: StyleBorderRightStyle) -> Self {
6998        Self::BorderRightStyle(StyleBorderRightStyleValue::Exact(input))
6999    }
7000    #[must_use] pub const fn const_border_left_style(input: StyleBorderLeftStyle) -> Self {
7001        Self::BorderLeftStyle(StyleBorderLeftStyleValue::Exact(input))
7002    }
7003    #[must_use] pub const fn const_border_bottom_style(input: StyleBorderBottomStyle) -> Self {
7004        Self::BorderBottomStyle(StyleBorderBottomStyleValue::Exact(input))
7005    }
7006    #[must_use] pub const fn const_border_top_width(input: LayoutBorderTopWidth) -> Self {
7007        Self::BorderTopWidth(LayoutBorderTopWidthValue::Exact(input))
7008    }
7009    #[must_use] pub const fn const_border_right_width(input: LayoutBorderRightWidth) -> Self {
7010        Self::BorderRightWidth(LayoutBorderRightWidthValue::Exact(input))
7011    }
7012    #[must_use] pub const fn const_border_left_width(input: LayoutBorderLeftWidth) -> Self {
7013        Self::BorderLeftWidth(LayoutBorderLeftWidthValue::Exact(input))
7014    }
7015    #[must_use] pub const fn const_border_bottom_width(input: LayoutBorderBottomWidth) -> Self {
7016        Self::BorderBottomWidth(LayoutBorderBottomWidthValue::Exact(input))
7017    }
7018    #[must_use] pub fn const_box_shadow_left(input: StyleBoxShadow) -> Self {
7019        Self::BoxShadowLeft(StyleBoxShadowValue::Exact(BoxOrStatic::heap(input)))
7020    }
7021    #[must_use] pub fn const_box_shadow_right(input: StyleBoxShadow) -> Self {
7022        Self::BoxShadowRight(StyleBoxShadowValue::Exact(BoxOrStatic::heap(input)))
7023    }
7024    #[must_use] pub fn const_box_shadow_top(input: StyleBoxShadow) -> Self {
7025        Self::BoxShadowTop(StyleBoxShadowValue::Exact(BoxOrStatic::heap(input)))
7026    }
7027    #[must_use] pub fn const_box_shadow_bottom(input: StyleBoxShadow) -> Self {
7028        Self::BoxShadowBottom(StyleBoxShadowValue::Exact(BoxOrStatic::heap(input)))
7029    }
7030    #[must_use] pub const fn const_opacity(input: StyleOpacity) -> Self {
7031        Self::Opacity(StyleOpacityValue::Exact(input))
7032    }
7033    #[must_use] pub const fn const_transform(input: StyleTransformVec) -> Self {
7034        Self::Transform(StyleTransformVecValue::Exact(input))
7035    }
7036    #[must_use] pub const fn const_transform_origin(input: StyleTransformOrigin) -> Self {
7037        Self::TransformOrigin(StyleTransformOriginValue::Exact(input))
7038    }
7039    #[must_use] pub const fn const_perspective_origin(input: StylePerspectiveOrigin) -> Self {
7040        Self::PerspectiveOrigin(StylePerspectiveOriginValue::Exact(input))
7041    }
7042    #[must_use] pub const fn const_backface_visibility(input: StyleBackfaceVisibility) -> Self {
7043        Self::BackfaceVisibility(StyleBackfaceVisibilityValue::Exact(input))
7044    }
7045    #[must_use] pub const fn const_break_before(input: PageBreak) -> Self {
7046        Self::BreakBefore(PageBreakValue::Exact(input))
7047    }
7048    #[must_use] pub const fn const_break_after(input: PageBreak) -> Self {
7049        Self::BreakAfter(PageBreakValue::Exact(input))
7050    }
7051    #[must_use] pub const fn const_break_inside(input: BreakInside) -> Self {
7052        Self::BreakInside(BreakInsideValue::Exact(input))
7053    }
7054    #[must_use] pub const fn const_orphans(input: Orphans) -> Self {
7055        Self::Orphans(OrphansValue::Exact(input))
7056    }
7057    #[must_use] pub const fn const_widows(input: Widows) -> Self {
7058        Self::Widows(WidowsValue::Exact(input))
7059    }
7060    #[must_use] pub const fn const_box_decoration_break(input: BoxDecorationBreak) -> Self {
7061        Self::BoxDecorationBreak(BoxDecorationBreakValue::Exact(input))
7062    }
7063    #[must_use] pub const fn const_column_count(input: ColumnCount) -> Self {
7064        Self::ColumnCount(ColumnCountValue::Exact(input))
7065    }
7066    #[must_use] pub const fn const_column_width(input: ColumnWidth) -> Self {
7067        Self::ColumnWidth(ColumnWidthValue::Exact(input))
7068    }
7069    #[must_use] pub const fn const_column_span(input: ColumnSpan) -> Self {
7070        Self::ColumnSpan(ColumnSpanValue::Exact(input))
7071    }
7072    #[must_use] pub const fn const_column_fill(input: ColumnFill) -> Self {
7073        Self::ColumnFill(ColumnFillValue::Exact(input))
7074    }
7075    #[must_use] pub const fn const_column_rule_width(input: ColumnRuleWidth) -> Self {
7076        Self::ColumnRuleWidth(ColumnRuleWidthValue::Exact(input))
7077    }
7078    #[must_use] pub const fn const_column_rule_style(input: ColumnRuleStyle) -> Self {
7079        Self::ColumnRuleStyle(ColumnRuleStyleValue::Exact(input))
7080    }
7081    #[must_use] pub const fn const_column_rule_color(input: ColumnRuleColor) -> Self {
7082        Self::ColumnRuleColor(ColumnRuleColorValue::Exact(input))
7083    }
7084    #[must_use] pub const fn const_flow_into(input: FlowInto) -> Self {
7085        Self::FlowInto(FlowIntoValue::Exact(input))
7086    }
7087    #[must_use] pub const fn const_flow_from(input: FlowFrom) -> Self {
7088        Self::FlowFrom(FlowFromValue::Exact(input))
7089    }
7090    #[must_use] pub const fn const_shape_outside(input: ShapeOutside) -> Self {
7091        Self::ShapeOutside(ShapeOutsideValue::Exact(input))
7092    }
7093    #[must_use] pub const fn const_shape_inside(input: ShapeInside) -> Self {
7094        Self::ShapeInside(ShapeInsideValue::Exact(input))
7095    }
7096    #[must_use] pub const fn const_clip_path(input: ClipPath) -> Self {
7097        Self::ClipPath(ClipPathValue::Exact(input))
7098    }
7099    #[must_use] pub const fn const_shape_margin(input: ShapeMargin) -> Self {
7100        Self::ShapeMargin(ShapeMarginValue::Exact(input))
7101    }
7102    #[must_use] pub const fn const_shape_image_threshold(input: ShapeImageThreshold) -> Self {
7103        Self::ShapeImageThreshold(ShapeImageThresholdValue::Exact(input))
7104    }
7105    #[must_use] pub const fn const_content(input: Content) -> Self {
7106        Self::Content(ContentValue::Exact(input))
7107    }
7108    #[must_use] pub const fn const_counter_reset(input: CounterReset) -> Self {
7109        Self::CounterReset(CounterResetValue::Exact(input))
7110    }
7111    #[must_use] pub const fn const_counter_increment(input: CounterIncrement) -> Self {
7112        Self::CounterIncrement(CounterIncrementValue::Exact(input))
7113    }
7114    #[must_use] pub const fn const_list_style_type(input: StyleListStyleType) -> Self {
7115        Self::ListStyleType(StyleListStyleTypeValue::Exact(input))
7116    }
7117    #[must_use] pub const fn const_list_style_position(input: StyleListStylePosition) -> Self {
7118        Self::ListStylePosition(StyleListStylePositionValue::Exact(input))
7119    }
7120    #[must_use] pub const fn const_string_set(input: StringSet) -> Self {
7121        Self::StringSet(StringSetValue::Exact(input))
7122    }
7123    #[must_use] pub const fn const_table_layout(input: LayoutTableLayout) -> Self {
7124        Self::TableLayout(LayoutTableLayoutValue::Exact(input))
7125    }
7126    #[must_use] pub const fn const_border_collapse(input: StyleBorderCollapse) -> Self {
7127        Self::BorderCollapse(StyleBorderCollapseValue::Exact(input))
7128    }
7129    #[must_use] pub const fn const_border_spacing(input: LayoutBorderSpacing) -> Self {
7130        Self::BorderSpacing(LayoutBorderSpacingValue::Exact(input))
7131    }
7132    #[must_use] pub const fn const_caption_side(input: StyleCaptionSide) -> Self {
7133        Self::CaptionSide(StyleCaptionSideValue::Exact(input))
7134    }
7135    #[must_use] pub const fn const_empty_cells(input: StyleEmptyCells) -> Self {
7136        Self::EmptyCells(StyleEmptyCellsValue::Exact(input))
7137    }
7138}
7139
7140// Cross-type dispatch over CssProperty variants; identical format! bodies bind
7141// different value types and can't merge (clippy::match_same_arms false positive).
7142#[allow(clippy::match_same_arms)]
7143#[allow(clippy::too_many_lines)] // large but cohesive: single-purpose CSS parser/formatter/dispatch table (one branch per property/variant)
7144#[must_use] pub fn format_static_css_prop(prop: &CssProperty, tabs: usize) -> String {
7145    match prop {
7146        CssProperty::CaretColor(p) => format!(
7147            "CssProperty::CaretColor({})",
7148            print_css_property_value(p, tabs, "CaretColor")
7149        ),
7150        CssProperty::CaretWidth(p) => format!(
7151            "CssProperty::CaretWidth({})",
7152            print_css_property_value(p, tabs, "CaretWidth")
7153        ),
7154        CssProperty::CaretAnimationDuration(p) => format!(
7155            "CssProperty::CaretAnimationDuration({})",
7156            print_css_property_value(p, tabs, "CaretAnimationDuration")
7157        ),
7158        CssProperty::SelectionBackgroundColor(p) => format!(
7159            "CssProperty::SelectionBackgroundColor({})",
7160            print_css_property_value(p, tabs, "SelectionBackgroundColor")
7161        ),
7162        CssProperty::SelectionColor(p) => format!(
7163            "CssProperty::SelectionColor({})",
7164            print_css_property_value(p, tabs, "SelectionColor")
7165        ),
7166        CssProperty::SelectionRadius(p) => format!(
7167            "CssProperty::SelectionRadius({})",
7168            print_css_property_value(p, tabs, "SelectionRadius")
7169        ),
7170        CssProperty::TextJustify(p) => format!(
7171            "CssProperty::TextJustify({})",
7172            print_css_property_value(p, tabs, "LayoutTextJustify")
7173        ),
7174        CssProperty::TextColor(p) => format!(
7175            "CssProperty::TextColor({})",
7176            print_css_property_value(p, tabs, "StyleTextColor")
7177        ),
7178        CssProperty::FontSize(p) => format!(
7179            "CssProperty::FontSize({})",
7180            print_css_property_value(p, tabs, "StyleFontSize")
7181        ),
7182        CssProperty::FontFamily(p) => format!(
7183            "CssProperty::FontFamily({})",
7184            print_css_property_value(p, tabs, "StyleFontFamilyVec")
7185        ),
7186        CssProperty::TextAlign(p) => format!(
7187            "CssProperty::TextAlign({})",
7188            print_css_property_value(p, tabs, "StyleTextAlign")
7189        ),
7190        CssProperty::VerticalAlign(p) => format!(
7191            "CssProperty::VerticalAlign({})",
7192            print_css_property_value(p, tabs, "StyleVerticalAlign")
7193        ),
7194        CssProperty::LetterSpacing(p) => format!(
7195            "CssProperty::LetterSpacing({})",
7196            print_css_property_value(p, tabs, "StyleLetterSpacing")
7197        ),
7198        CssProperty::TextIndent(p) => format!(
7199            "CssProperty::TextIndent({})",
7200            print_css_property_value(p, tabs, "StyleTextIndent")
7201        ),
7202        CssProperty::InitialLetter(p) => format!(
7203            "CssProperty::InitialLetter({})",
7204            print_css_property_value(p, tabs, "StyleInitialLetter")
7205        ),
7206        CssProperty::LineClamp(p) => format!(
7207            "CssProperty::LineClamp({})",
7208            print_css_property_value(p, tabs, "StyleLineClamp")
7209        ),
7210        CssProperty::HangingPunctuation(p) => format!(
7211            "CssProperty::HangingPunctuation({})",
7212            print_css_property_value(p, tabs, "StyleHangingPunctuation")
7213        ),
7214        CssProperty::TextCombineUpright(p) => format!(
7215            "CssProperty::TextCombineUpright({})",
7216            print_css_property_value(p, tabs, "StyleTextCombineUpright")
7217        ),
7218        CssProperty::UnicodeBidi(p) => format!(
7219            "CssProperty::UnicodeBidi({})",
7220            print_css_property_value(p, tabs, "StyleUnicodeBidi")
7221        ),
7222        CssProperty::TextBoxTrim(p) => format!(
7223            "CssProperty::TextBoxTrim({})",
7224            print_css_property_value(p, tabs, "StyleTextBoxTrim")
7225        ),
7226        CssProperty::TextBoxEdge(p) => format!(
7227            "CssProperty::TextBoxEdge({})",
7228            print_css_property_value(p, tabs, "StyleTextBoxEdge")
7229        ),
7230        CssProperty::DominantBaseline(p) => format!(
7231            "CssProperty::DominantBaseline({})",
7232            print_css_property_value(p, tabs, "StyleDominantBaseline")
7233        ),
7234        CssProperty::AlignmentBaseline(p) => format!(
7235            "CssProperty::AlignmentBaseline({})",
7236            print_css_property_value(p, tabs, "StyleAlignmentBaseline")
7237        ),
7238        CssProperty::BaselineSource(p) => format!(
7239            "CssProperty::BaselineSource({})",
7240            print_css_property_value(p, tabs, "StyleBaselineSource")
7241        ),
7242        CssProperty::LineFitEdge(p) => format!(
7243            "CssProperty::LineFitEdge({})",
7244            print_css_property_value(p, tabs, "StyleLineFitEdge")
7245        ),
7246        CssProperty::InitialLetterAlign(p) => format!(
7247            "CssProperty::InitialLetterAlign({})",
7248            print_css_property_value(p, tabs, "StyleInitialLetterAlign")
7249        ),
7250        CssProperty::InitialLetterWrap(p) => format!(
7251            "CssProperty::InitialLetterWrap({})",
7252            print_css_property_value(p, tabs, "StyleInitialLetterWrap")
7253        ),
7254        CssProperty::ScrollbarGutter(p) => format!(
7255            "CssProperty::ScrollbarGutter({})",
7256            print_css_property_value(p, tabs, "StyleScrollbarGutter")
7257        ),
7258        CssProperty::OverflowClipMargin(p) => format!(
7259            "CssProperty::OverflowClipMargin({})",
7260            print_css_property_value(p, tabs, "StyleOverflowClipMargin")
7261        ),
7262        CssProperty::Clip(p) => format!(
7263            "CssProperty::Clip({})",
7264            print_css_property_value(p, tabs, "StyleClipRect")
7265        ),
7266        CssProperty::ExclusionMargin(p) => format!(
7267            "CssProperty::ExclusionMargin({})",
7268            print_css_property_value(p, tabs, "StyleExclusionMargin")
7269        ),
7270        CssProperty::HyphenationLanguage(p) => format!(
7271            "CssProperty::HyphenationLanguage({})",
7272            print_css_property_value(p, tabs, "StyleHyphenationLanguage")
7273        ),
7274        CssProperty::LineHeight(p) => format!(
7275            "CssProperty::LineHeight({})",
7276            print_css_property_value(p, tabs, "StyleLineHeight")
7277        ),
7278        CssProperty::WordSpacing(p) => format!(
7279            "CssProperty::WordSpacing({})",
7280            print_css_property_value(p, tabs, "StyleWordSpacing")
7281        ),
7282        CssProperty::TabSize(p) => format!(
7283            "CssProperty::TabSize({})",
7284            print_css_property_value(p, tabs, "StyleTabSize")
7285        ),
7286        CssProperty::Cursor(p) => format!(
7287            "CssProperty::Cursor({})",
7288            print_css_property_value(p, tabs, "StyleCursor")
7289        ),
7290        CssProperty::Display(p) => format!(
7291            "CssProperty::Display({})",
7292            print_css_property_value(p, tabs, "LayoutDisplay")
7293        ),
7294        CssProperty::Float(p) => format!(
7295            "CssProperty::Float({})",
7296            print_css_property_value(p, tabs, "LayoutFloat")
7297        ),
7298        CssProperty::BoxSizing(p) => format!(
7299            "CssProperty::BoxSizing({})",
7300            print_css_property_value(p, tabs, "LayoutBoxSizing")
7301        ),
7302        CssProperty::Width(p) => format!(
7303            "CssProperty::Width({})",
7304            print_css_property_value(p, tabs, "LayoutWidth")
7305        ),
7306        CssProperty::Height(p) => format!(
7307            "CssProperty::Height({})",
7308            print_css_property_value(p, tabs, "LayoutHeight")
7309        ),
7310        CssProperty::MinWidth(p) => format!(
7311            "CssProperty::MinWidth({})",
7312            print_css_property_value(p, tabs, "LayoutMinWidth")
7313        ),
7314        CssProperty::MinHeight(p) => format!(
7315            "CssProperty::MinHeight({})",
7316            print_css_property_value(p, tabs, "LayoutMinHeight")
7317        ),
7318        CssProperty::MaxWidth(p) => format!(
7319            "CssProperty::MaxWidth({})",
7320            print_css_property_value(p, tabs, "LayoutMaxWidth")
7321        ),
7322        CssProperty::MaxHeight(p) => format!(
7323            "CssProperty::MaxHeight({})",
7324            print_css_property_value(p, tabs, "LayoutMaxHeight")
7325        ),
7326        CssProperty::Position(p) => format!(
7327            "CssProperty::Position({})",
7328            print_css_property_value(p, tabs, "LayoutPosition")
7329        ),
7330        CssProperty::Top(p) => format!(
7331            "CssProperty::Top({})",
7332            print_css_property_value(p, tabs, "LayoutTop")
7333        ),
7334        CssProperty::Right(p) => format!(
7335            "CssProperty::Right({})",
7336            print_css_property_value(p, tabs, "LayoutRight")
7337        ),
7338        CssProperty::Left(p) => format!(
7339            "CssProperty::Left({})",
7340            print_css_property_value(p, tabs, "LayoutLeft")
7341        ),
7342        CssProperty::Bottom(p) => format!(
7343            "CssProperty::Bottom({})",
7344            print_css_property_value(p, tabs, "LayoutInsetBottom")
7345        ),
7346        CssProperty::ZIndex(p) => format!(
7347            "CssProperty::ZIndex({})",
7348            print_css_property_value(p, tabs, "LayoutZIndex")
7349        ),
7350        CssProperty::FlexWrap(p) => format!(
7351            "CssProperty::FlexWrap({})",
7352            print_css_property_value(p, tabs, "LayoutFlexWrap")
7353        ),
7354        CssProperty::FlexDirection(p) => format!(
7355            "CssProperty::FlexDirection({})",
7356            print_css_property_value(p, tabs, "LayoutFlexDirection")
7357        ),
7358        CssProperty::FlexGrow(p) => format!(
7359            "CssProperty::FlexGrow({})",
7360            print_css_property_value(p, tabs, "LayoutFlexGrow")
7361        ),
7362        CssProperty::FlexShrink(p) => format!(
7363            "CssProperty::FlexShrink({})",
7364            print_css_property_value(p, tabs, "LayoutFlexShrink")
7365        ),
7366        CssProperty::JustifyContent(p) => format!(
7367            "CssProperty::JustifyContent({})",
7368            print_css_property_value(p, tabs, "LayoutJustifyContent")
7369        ),
7370        CssProperty::AlignItems(p) => format!(
7371            "CssProperty::AlignItems({})",
7372            print_css_property_value(p, tabs, "LayoutAlignItems")
7373        ),
7374        CssProperty::AlignContent(p) => format!(
7375            "CssProperty::AlignContent({})",
7376            print_css_property_value(p, tabs, "LayoutAlignContent")
7377        ),
7378        CssProperty::BackgroundContent(p) => format!(
7379            "CssProperty::BackgroundContent({})",
7380            print_css_property_value(p, tabs, "StyleBackgroundContentVec")
7381        ),
7382        CssProperty::BackgroundPosition(p) => format!(
7383            "CssProperty::BackgroundPosition({})",
7384            print_css_property_value(p, tabs, "StyleBackgroundPositionVec")
7385        ),
7386        CssProperty::BackgroundSize(p) => format!(
7387            "CssProperty::BackgroundSize({})",
7388            print_css_property_value(p, tabs, "StyleBackgroundSizeVec")
7389        ),
7390        CssProperty::BackgroundRepeat(p) => format!(
7391            "CssProperty::BackgroundRepeat({})",
7392            print_css_property_value(p, tabs, "StyleBackgroundRepeatVec")
7393        ),
7394        CssProperty::OverflowX(p) => format!(
7395            "CssProperty::OverflowX({})",
7396            print_css_property_value(p, tabs, "LayoutOverflow")
7397        ),
7398        CssProperty::OverflowY(p) => format!(
7399            "CssProperty::OverflowY({})",
7400            print_css_property_value(p, tabs, "LayoutOverflow")
7401        ),
7402        CssProperty::OverflowBlock(p) => format!(
7403            "CssProperty::OverflowBlock({})",
7404            print_css_property_value(p, tabs, "LayoutOverflow")
7405        ),
7406        CssProperty::OverflowInline(p) => format!(
7407            "CssProperty::OverflowInline({})",
7408            print_css_property_value(p, tabs, "LayoutOverflow")
7409        ),
7410        CssProperty::PaddingTop(p) => format!(
7411            "CssProperty::PaddingTop({})",
7412            print_css_property_value(p, tabs, "LayoutPaddingTop")
7413        ),
7414        CssProperty::PaddingLeft(p) => format!(
7415            "CssProperty::PaddingLeft({})",
7416            print_css_property_value(p, tabs, "LayoutPaddingLeft")
7417        ),
7418        CssProperty::PaddingRight(p) => format!(
7419            "CssProperty::PaddingRight({})",
7420            print_css_property_value(p, tabs, "LayoutPaddingRight")
7421        ),
7422        CssProperty::PaddingBottom(p) => format!(
7423            "CssProperty::PaddingBottom({})",
7424            print_css_property_value(p, tabs, "LayoutPaddingBottom")
7425        ),
7426        CssProperty::PaddingInlineStart(p) => format!(
7427            "CssProperty::PaddingInlineStart({})",
7428            print_css_property_value(p, tabs, "LayoutPaddingInlineStart")
7429        ),
7430        CssProperty::PaddingInlineEnd(p) => format!(
7431            "CssProperty::PaddingInlineEnd({})",
7432            print_css_property_value(p, tabs, "LayoutPaddingInlineEnd")
7433        ),
7434        CssProperty::MarginTop(p) => format!(
7435            "CssProperty::MarginTop({})",
7436            print_css_property_value(p, tabs, "LayoutMarginTop")
7437        ),
7438        CssProperty::MarginLeft(p) => format!(
7439            "CssProperty::MarginLeft({})",
7440            print_css_property_value(p, tabs, "LayoutMarginLeft")
7441        ),
7442        CssProperty::MarginRight(p) => format!(
7443            "CssProperty::MarginRight({})",
7444            print_css_property_value(p, tabs, "LayoutMarginRight")
7445        ),
7446        CssProperty::MarginBottom(p) => format!(
7447            "CssProperty::MarginBottom({})",
7448            print_css_property_value(p, tabs, "LayoutMarginBottom")
7449        ),
7450        CssProperty::BorderTopLeftRadius(p) => format!(
7451            "CssProperty::BorderTopLeftRadius({})",
7452            print_css_property_value(p, tabs, "StyleBorderTopLeftRadius")
7453        ),
7454        CssProperty::BorderTopRightRadius(p) => format!(
7455            "CssProperty::BorderTopRightRadius({})",
7456            print_css_property_value(p, tabs, "StyleBorderTopRightRadius")
7457        ),
7458        CssProperty::BorderBottomLeftRadius(p) => format!(
7459            "CssProperty::BorderBottomLeftRadius({})",
7460            print_css_property_value(p, tabs, "StyleBorderBottomLeftRadius")
7461        ),
7462        CssProperty::BorderBottomRightRadius(p) => format!(
7463            "CssProperty::BorderBottomRightRadius({})",
7464            print_css_property_value(p, tabs, "StyleBorderBottomRightRadius")
7465        ),
7466        CssProperty::BorderTopColor(p) => format!(
7467            "CssProperty::BorderTopColor({})",
7468            print_css_property_value(p, tabs, "StyleBorderTopColor")
7469        ),
7470        CssProperty::BorderRightColor(p) => format!(
7471            "CssProperty::BorderRightColor({})",
7472            print_css_property_value(p, tabs, "StyleBorderRightColor")
7473        ),
7474        CssProperty::BorderLeftColor(p) => format!(
7475            "CssProperty::BorderLeftColor({})",
7476            print_css_property_value(p, tabs, "StyleBorderLeftColor")
7477        ),
7478        CssProperty::BorderBottomColor(p) => format!(
7479            "CssProperty::BorderBottomColor({})",
7480            print_css_property_value(p, tabs, "StyleBorderBottomColor")
7481        ),
7482        CssProperty::BorderTopStyle(p) => format!(
7483            "CssProperty::BorderTopStyle({})",
7484            print_css_property_value(p, tabs, "StyleBorderTopStyle")
7485        ),
7486        CssProperty::BorderRightStyle(p) => format!(
7487            "CssProperty::BorderRightStyle({})",
7488            print_css_property_value(p, tabs, "StyleBorderRightStyle")
7489        ),
7490        CssProperty::BorderLeftStyle(p) => format!(
7491            "CssProperty::BorderLeftStyle({})",
7492            print_css_property_value(p, tabs, "StyleBorderLeftStyle")
7493        ),
7494        CssProperty::BorderBottomStyle(p) => format!(
7495            "CssProperty::BorderBottomStyle({})",
7496            print_css_property_value(p, tabs, "StyleBorderBottomStyle")
7497        ),
7498        CssProperty::BorderTopWidth(p) => format!(
7499            "CssProperty::BorderTopWidth({})",
7500            print_css_property_value(p, tabs, "LayoutBorderTopWidth")
7501        ),
7502        CssProperty::BorderRightWidth(p) => format!(
7503            "CssProperty::BorderRightWidth({})",
7504            print_css_property_value(p, tabs, "LayoutBorderRightWidth")
7505        ),
7506        CssProperty::BorderLeftWidth(p) => format!(
7507            "CssProperty::BorderLeftWidth({})",
7508            print_css_property_value(p, tabs, "LayoutBorderLeftWidth")
7509        ),
7510        CssProperty::BorderBottomWidth(p) => format!(
7511            "CssProperty::BorderBottomWidth({})",
7512            print_css_property_value(p, tabs, "LayoutBorderBottomWidth")
7513        ),
7514        CssProperty::BoxShadowLeft(p) => format!(
7515            "CssProperty::BoxShadowLeft({})",
7516            print_css_property_value(p, tabs, "StyleBoxShadow")
7517        ),
7518        CssProperty::BoxShadowRight(p) => format!(
7519            "CssProperty::BoxShadowRight({})",
7520            print_css_property_value(p, tabs, "StyleBoxShadow")
7521        ),
7522        CssProperty::BoxShadowTop(p) => format!(
7523            "CssProperty::BoxShadowTop({})",
7524            print_css_property_value(p, tabs, "StyleBoxShadow")
7525        ),
7526        CssProperty::BoxShadowBottom(p) => format!(
7527            "CssProperty::BoxShadowBottom({})",
7528            print_css_property_value(p, tabs, "StyleBoxShadow")
7529        ),
7530        CssProperty::ScrollbarWidth(p) => format!(
7531            "CssProperty::ScrollbarWidth({})",
7532            print_css_property_value(p, tabs, "LayoutScrollbarWidth")
7533        ),
7534        CssProperty::ScrollbarColor(p) => format!(
7535            "CssProperty::ScrollbarColor({})",
7536            print_css_property_value(p, tabs, "StyleScrollbarColor")
7537        ),
7538        CssProperty::ScrollbarVisibility(p) => format!(
7539            "CssProperty::ScrollbarVisibility({})",
7540            print_css_property_value(p, tabs, "ScrollbarVisibilityMode")
7541        ),
7542        CssProperty::ScrollbarFadeDelay(p) => format!(
7543            "CssProperty::ScrollbarFadeDelay({})",
7544            print_css_property_value(p, tabs, "ScrollbarFadeDelay")
7545        ),
7546        CssProperty::ScrollbarFadeDuration(p) => format!(
7547            "CssProperty::ScrollbarFadeDuration({})",
7548            print_css_property_value(p, tabs, "ScrollbarFadeDuration")
7549        ),
7550        CssProperty::ScrollbarTrack(p) => format!(
7551            "CssProperty::ScrollbarTrack({})",
7552            print_css_property_value(p, tabs, "StyleBackgroundContent")
7553        ),
7554        CssProperty::ScrollbarThumb(p) => format!(
7555            "CssProperty::ScrollbarThumb({})",
7556            print_css_property_value(p, tabs, "StyleBackgroundContent")
7557        ),
7558        CssProperty::ScrollbarButton(p) => format!(
7559            "CssProperty::ScrollbarButton({})",
7560            print_css_property_value(p, tabs, "StyleBackgroundContent")
7561        ),
7562        CssProperty::ScrollbarCorner(p) => format!(
7563            "CssProperty::ScrollbarCorner({})",
7564            print_css_property_value(p, tabs, "StyleBackgroundContent")
7565        ),
7566        CssProperty::ScrollbarResizer(p) => format!(
7567            "CssProperty::ScrollbarResizer({})",
7568            print_css_property_value(p, tabs, "StyleBackgroundContent")
7569        ),
7570        CssProperty::Opacity(p) => format!(
7571            "CssProperty::Opacity({})",
7572            print_css_property_value(p, tabs, "StyleOpacity")
7573        ),
7574        CssProperty::Visibility(p) => format!(
7575            "CssProperty::Visibility({})",
7576            print_css_property_value(p, tabs, "StyleVisibility")
7577        ),
7578        CssProperty::Transform(p) => format!(
7579            "CssProperty::Transform({})",
7580            print_css_property_value(p, tabs, "StyleTransformVec")
7581        ),
7582        CssProperty::TransformOrigin(p) => format!(
7583            "CssProperty::TransformOrigin({})",
7584            print_css_property_value(p, tabs, "StyleTransformOrigin")
7585        ),
7586        CssProperty::PerspectiveOrigin(p) => format!(
7587            "CssProperty::PerspectiveOrigin({})",
7588            print_css_property_value(p, tabs, "StylePerspectiveOrigin")
7589        ),
7590        CssProperty::BackfaceVisibility(p) => format!(
7591            "CssProperty::BackfaceVisibility({})",
7592            print_css_property_value(p, tabs, "StyleBackfaceVisibility")
7593        ),
7594        CssProperty::MixBlendMode(p) => format!(
7595            "CssProperty::MixBlendMode({})",
7596            print_css_property_value(p, tabs, "StyleMixBlendMode")
7597        ),
7598        CssProperty::Filter(p) => format!(
7599            "CssProperty::Filter({})",
7600            print_css_property_value(p, tabs, "StyleFilterVec")
7601        ),
7602        CssProperty::BackdropFilter(p) => format!(
7603            "CssProperty::Filter({})",
7604            print_css_property_value(p, tabs, "StyleFilterVec")
7605        ),
7606        CssProperty::TextShadow(p) => format!(
7607            "CssProperty::TextShadow({})",
7608            print_css_property_value(p, tabs, "StyleBoxShadow")
7609        ),
7610        CssProperty::Hyphens(p) => format!(
7611            "CssProperty::Hyphens({})",
7612            print_css_property_value(p, tabs, "StyleHyphens")
7613        ),
7614        CssProperty::WordBreak(p) => format!(
7615            "CssProperty::WordBreak({})",
7616            print_css_property_value(p, tabs, "StyleWordBreak")
7617        ),
7618        CssProperty::OverflowWrap(p) => format!(
7619            "CssProperty::OverflowWrap({})",
7620            print_css_property_value(p, tabs, "StyleOverflowWrap")
7621        ),
7622        CssProperty::LineBreak(p) => format!(
7623            "CssProperty::LineBreak({})",
7624            print_css_property_value(p, tabs, "StyleLineBreak")
7625        ),
7626        CssProperty::TextOverflow(p) => format!(
7627            "CssProperty::TextOverflow({})",
7628            print_css_property_value(p, tabs, "StyleTextOverflow")
7629        ),
7630        CssProperty::ObjectFit(p) => format!(
7631            "CssProperty::ObjectFit({})",
7632            print_css_property_value(p, tabs, "StyleObjectFit")
7633        ),
7634        CssProperty::ObjectPosition(p) => format!(
7635            "CssProperty::ObjectPosition({})",
7636            print_css_property_value(p, tabs, "StyleObjectPosition")
7637        ),
7638        CssProperty::AspectRatio(p) => format!(
7639            "CssProperty::AspectRatio({})",
7640            print_css_property_value(p, tabs, "StyleAspectRatio")
7641        ),
7642        CssProperty::TextOrientation(p) => format!(
7643            "CssProperty::TextOrientation({})",
7644            print_css_property_value(p, tabs, "StyleTextOrientation")
7645        ),
7646        CssProperty::TextAlignLast(p) => format!(
7647            "CssProperty::TextAlignLast({})",
7648            print_css_property_value(p, tabs, "StyleTextAlignLast")
7649        ),
7650        CssProperty::TextTransform(p) => format!(
7651            "CssProperty::TextTransform({})",
7652            print_css_property_value(p, tabs, "StyleTextTransform")
7653        ),
7654        CssProperty::Direction(p) => format!(
7655            "CssProperty::Direction({})",
7656            print_css_property_value(p, tabs, "Direction")
7657        ),
7658        CssProperty::UserSelect(p) => format!(
7659            "CssProperty::UserSelect({})",
7660            print_css_property_value(p, tabs, "StyleUserSelect")
7661        ),
7662        CssProperty::TextDecoration(p) => format!(
7663            "CssProperty::TextDecoration({})",
7664            print_css_property_value(p, tabs, "StyleTextDecoration")
7665        ),
7666        CssProperty::WhiteSpace(p) => format!(
7667            "CssProperty::WhiteSpace({})",
7668            print_css_property_value(p, tabs, "WhiteSpace")
7669        ),
7670        CssProperty::FlexBasis(p) => format!(
7671            "CssProperty::FlexBasis({})",
7672            print_css_property_value(p, tabs, "LayoutFlexBasis")
7673        ),
7674        CssProperty::ColumnGap(p) => format!(
7675            "CssProperty::ColumnGap({})",
7676            print_css_property_value(p, tabs, "LayoutColumnGap")
7677        ),
7678        CssProperty::RowGap(p) => format!(
7679            "CssProperty::RowGap({})",
7680            print_css_property_value(p, tabs, "LayoutRowGap")
7681        ),
7682        CssProperty::GridTemplateColumns(p) => format!(
7683            "CssProperty::GridTemplateColumns({})",
7684            print_css_property_value(p, tabs, "LayoutGridTemplateColumns")
7685        ),
7686        CssProperty::GridTemplateRows(p) => format!(
7687            "CssProperty::GridTemplateRows({})",
7688            print_css_property_value(p, tabs, "LayoutGridTemplateRows")
7689        ),
7690        CssProperty::GridAutoFlow(p) => format!(
7691            "CssProperty::GridAutoFlow({})",
7692            print_css_property_value(p, tabs, "LayoutGridAutoFlow")
7693        ),
7694        CssProperty::JustifySelf(p) => format!(
7695            "CssProperty::JustifySelf({})",
7696            print_css_property_value(p, tabs, "LayoutJustifySelf")
7697        ),
7698        CssProperty::JustifyItems(p) => format!(
7699            "CssProperty::JustifyItems({})",
7700            print_css_property_value(p, tabs, "LayoutJustifyItems")
7701        ),
7702        CssProperty::Gap(p) => format!(
7703            "CssProperty::Gap({})",
7704            print_css_property_value(p, tabs, "LayoutGap")
7705        ),
7706        CssProperty::GridGap(p) => format!(
7707            "CssProperty::GridGap({})",
7708            print_css_property_value(p, tabs, "LayoutGap")
7709        ),
7710        CssProperty::AlignSelf(p) => format!(
7711            "CssProperty::AlignSelf({})",
7712            print_css_property_value(p, tabs, "LayoutAlignSelf")
7713        ),
7714        CssProperty::Font(p) => format!(
7715            "CssProperty::Font({})",
7716            print_css_property_value(p, tabs, "StyleFontFamilyVec")
7717        ),
7718        CssProperty::GridAutoRows(p) => format!(
7719            "CssProperty::GridAutoRows({})",
7720            print_css_property_value(p, tabs, "LayoutGridAutoRows")
7721        ),
7722        CssProperty::GridAutoColumns(p) => format!(
7723            "CssProperty::GridAutoColumns({})",
7724            print_css_property_value(p, tabs, "LayoutGridAutoColumns")
7725        ),
7726        CssProperty::GridRow(p) => format!(
7727            "CssProperty::GridRow({})",
7728            print_css_property_value(p, tabs, "LayoutGridRow")
7729        ),
7730        CssProperty::GridColumn(p) => format!(
7731            "CssProperty::GridColumn({})",
7732            print_css_property_value(p, tabs, "LayoutGridColumn")
7733        ),
7734        CssProperty::GridTemplateAreas(p) => format!(
7735            "CssProperty::GridTemplateAreas({})",
7736            print_css_property_value(p, tabs, "GridTemplateAreas")
7737        ),
7738        CssProperty::WritingMode(p) => format!(
7739            "CssProperty::WritingMode({})",
7740            print_css_property_value(p, tabs, "LayoutWritingMode")
7741        ),
7742        CssProperty::Clear(p) => format!(
7743            "CssProperty::Clear({})",
7744            print_css_property_value(p, tabs, "LayoutClear")
7745        ),
7746        CssProperty::BreakBefore(p) => format!(
7747            "CssProperty::BreakBefore({})",
7748            print_css_property_value(p, tabs, "PageBreak")
7749        ),
7750        CssProperty::BreakAfter(p) => format!(
7751            "CssProperty::BreakAfter({})",
7752            print_css_property_value(p, tabs, "PageBreak")
7753        ),
7754        CssProperty::BreakInside(p) => format!(
7755            "CssProperty::BreakInside({})",
7756            print_css_property_value(p, tabs, "BreakInside")
7757        ),
7758        CssProperty::Orphans(p) => format!(
7759            "CssProperty::Orphans({})",
7760            print_css_property_value(p, tabs, "Orphans")
7761        ),
7762        CssProperty::Widows(p) => format!(
7763            "CssProperty::Widows({})",
7764            print_css_property_value(p, tabs, "Widows")
7765        ),
7766        CssProperty::BoxDecorationBreak(p) => format!(
7767            "CssProperty::BoxDecorationBreak({})",
7768            print_css_property_value(p, tabs, "BoxDecorationBreak")
7769        ),
7770        CssProperty::ColumnCount(p) => format!(
7771            "CssProperty::ColumnCount({})",
7772            print_css_property_value(p, tabs, "ColumnCount")
7773        ),
7774        CssProperty::ColumnWidth(p) => format!(
7775            "CssProperty::ColumnWidth({})",
7776            print_css_property_value(p, tabs, "ColumnWidth")
7777        ),
7778        CssProperty::ColumnSpan(p) => format!(
7779            "CssProperty::ColumnSpan({})",
7780            print_css_property_value(p, tabs, "ColumnSpan")
7781        ),
7782        CssProperty::ColumnFill(p) => format!(
7783            "CssProperty::ColumnFill({})",
7784            print_css_property_value(p, tabs, "ColumnFill")
7785        ),
7786        CssProperty::ColumnRuleWidth(p) => format!(
7787            "CssProperty::ColumnRuleWidth({})",
7788            print_css_property_value(p, tabs, "ColumnRuleWidth")
7789        ),
7790        CssProperty::ColumnRuleStyle(p) => format!(
7791            "CssProperty::ColumnRuleStyle({})",
7792            print_css_property_value(p, tabs, "ColumnRuleStyle")
7793        ),
7794        CssProperty::ColumnRuleColor(p) => format!(
7795            "CssProperty::ColumnRuleColor({})",
7796            print_css_property_value(p, tabs, "ColumnRuleColor")
7797        ),
7798        CssProperty::FlowInto(p) => format!(
7799            "CssProperty::FlowInto({})",
7800            print_css_property_value(p, tabs, "FlowInto")
7801        ),
7802        CssProperty::FlowFrom(p) => format!(
7803            "CssProperty::FlowFrom({})",
7804            print_css_property_value(p, tabs, "FlowFrom")
7805        ),
7806        CssProperty::ShapeOutside(p) => format!(
7807            "CssProperty::ShapeOutside({})",
7808            print_css_property_value(p, tabs, "ShapeOutside")
7809        ),
7810        CssProperty::ShapeInside(p) => format!(
7811            "CssProperty::ShapeInside({})",
7812            print_css_property_value(p, tabs, "ShapeInside")
7813        ),
7814        CssProperty::ClipPath(p) => format!(
7815            "CssProperty::ClipPath({})",
7816            print_css_property_value(p, tabs, "ClipPath")
7817        ),
7818        CssProperty::ShapeMargin(p) => format!(
7819            "CssProperty::ShapeMargin({})",
7820            print_css_property_value(p, tabs, "ShapeMargin")
7821        ),
7822        CssProperty::ShapeImageThreshold(p) => format!(
7823            "CssProperty::ShapeImageThreshold({})",
7824            print_css_property_value(p, tabs, "ShapeImageThreshold")
7825        ),
7826        CssProperty::Content(p) => format!(
7827            "CssProperty::Content({})",
7828            print_css_property_value(p, tabs, "Content")
7829        ),
7830        CssProperty::CounterReset(p) => format!(
7831            "CssProperty::CounterReset({})",
7832            print_css_property_value(p, tabs, "CounterReset")
7833        ),
7834        CssProperty::CounterIncrement(p) => format!(
7835            "CssProperty::CounterIncrement({})",
7836            print_css_property_value(p, tabs, "CounterIncrement")
7837        ),
7838        CssProperty::ListStyleType(p) => format!(
7839            "CssProperty::ListStyleType({})",
7840            print_css_property_value(p, tabs, "StyleListStyleType")
7841        ),
7842        CssProperty::ListStylePosition(p) => format!(
7843            "CssProperty::ListStylePosition({})",
7844            print_css_property_value(p, tabs, "StyleListStylePosition")
7845        ),
7846        CssProperty::StringSet(p) => format!(
7847            "CssProperty::StringSet({})",
7848            print_css_property_value(p, tabs, "StringSet")
7849        ),
7850        CssProperty::TableLayout(p) => format!(
7851            "CssProperty::TableLayout({})",
7852            print_css_property_value(p, tabs, "LayoutTableLayout")
7853        ),
7854        CssProperty::BorderCollapse(p) => format!(
7855            "CssProperty::BorderCollapse({})",
7856            print_css_property_value(p, tabs, "StyleBorderCollapse")
7857        ),
7858        CssProperty::BorderSpacing(p) => format!(
7859            "CssProperty::BorderSpacing({})",
7860            print_css_property_value(p, tabs, "LayoutBorderSpacing")
7861        ),
7862        CssProperty::CaptionSide(p) => format!(
7863            "CssProperty::CaptionSide({})",
7864            print_css_property_value(p, tabs, "StyleCaptionSide")
7865        ),
7866        CssProperty::EmptyCells(p) => format!(
7867            "CssProperty::EmptyCells({})",
7868            print_css_property_value(p, tabs, "StyleEmptyCells")
7869        ),
7870        CssProperty::FontWeight(p) => format!(
7871            "CssProperty::FontWeight({})",
7872            print_css_property_value(p, tabs, "StyleFontWeight")
7873        ),
7874        CssProperty::FontStyle(p) => format!(
7875            "CssProperty::FontStyle({})",
7876            print_css_property_value(p, tabs, "StyleFontStyle")
7877        ),
7878    }
7879}
7880
7881fn print_css_property_value<T: FormatAsRustCode>(
7882    prop_val: &CssPropertyValue<T>,
7883    tabs: usize,
7884    property_value_type: &'static str,
7885) -> String {
7886    match prop_val {
7887        CssPropertyValue::Auto => format!("{property_value_type}Value::Auto"),
7888        CssPropertyValue::None => format!("{property_value_type}Value::None"),
7889        CssPropertyValue::Initial => format!("{property_value_type}Value::Initial"),
7890        CssPropertyValue::Inherit => format!("{property_value_type}Value::Inherit"),
7891        CssPropertyValue::Revert => format!("{property_value_type}Value::Revert"),
7892        CssPropertyValue::Unset => format!("{property_value_type}Value::Unset"),
7893        CssPropertyValue::Exact(t) => format!(
7894            "{}Value::Exact({})",
7895            property_value_type,
7896            t.format_as_rust_code(tabs)
7897        ),
7898    }
7899}
7900
7901#[cfg(test)]
7902#[allow(clippy::float_cmp)]
7903mod autotest_generated {
7904    use super::*;
7905    use crate::props::basic::animation::AnimationInterpolationFunction;
7906
7907    // ---- helpers -----------------------------------------------------------
7908
7909    fn resolver() -> InterpolateResolver {
7910        InterpolateResolver {
7911            interpolate_func: AnimationInterpolationFunction::Linear,
7912            parent_rect_width: 800.0,
7913            parent_rect_height: 600.0,
7914            current_rect_width: 400.0,
7915            current_rect_height: 300.0,
7916        }
7917    }
7918
7919    fn font_size(px: f32) -> CssProperty {
7920        CssProperty::font_size(StyleFontSize {
7921            inner: PixelValue::px(px),
7922        })
7923    }
7924
7925    fn font_size_px_of(prop: &CssProperty) -> f32 {
7926        match prop {
7927            CssProperty::FontSize(CssPropertyValue::Exact(fs)) => fs.inner.number.get(),
7928            other => panic!("expected an exact FontSize, got {other:?}"),
7929        }
7930    }
7931
7932    /// The five CSS table properties that `CssPropertyType::to_str()` names but
7933    /// `CSS_PROPERTY_KEY_MAP` never registers, so `from_str` can't find them.
7934    /// See `bug_table_properties_are_unreachable_from_stylesheet_text`.
7935    // Every property type now resolves through CSS_PROPERTY_KEY_MAP.
7936    const KEYS_MISSING_FROM_KEY_MAP: &[CssPropertyType] = &[];
7937
7938    // ---- CssKeyMap / get_css_key_map ---------------------------------------
7939
7940    #[test]
7941    fn key_map_is_populated_and_deterministic() {
7942        let a = get_css_key_map();
7943        let b = CssKeyMap::get();
7944        assert_eq!(a, b, "CssKeyMap::get() must equal get_css_key_map()");
7945        assert!(!a.non_shorthands.is_empty());
7946        assert!(!a.shorthands.is_empty());
7947        // Every registered key resolves back to the type it was registered under.
7948        for (k, v) in &a.non_shorthands {
7949            assert_eq!(CssPropertyType::from_str(k, &a), Some(*v), "key {k}");
7950        }
7951        for (k, v) in &a.shorthands {
7952            assert_eq!(
7953                CombinedCssPropertyType::from_str(k, &a),
7954                Some(*v),
7955                "shorthand {k}"
7956            );
7957        }
7958    }
7959
7960    // ---- from_str: malformed / boundary / unicode ---------------------------
7961
7962    #[test]
7963    fn from_str_empty_input_returns_none() {
7964        let map = get_css_key_map();
7965        assert_eq!(CssPropertyType::from_str("", &map), None);
7966        assert_eq!(CombinedCssPropertyType::from_str("", &map), None);
7967    }
7968
7969    #[test]
7970    fn from_str_whitespace_only_returns_none() {
7971        let map = get_css_key_map();
7972        for input in ["   ", "\t", "\n", "\r\n", " \t \n \r ", "\u{a0}"] {
7973            assert_eq!(CssPropertyType::from_str(input, &map), None, "{input:?}");
7974            assert_eq!(
7975                CombinedCssPropertyType::from_str(input, &map),
7976                None,
7977                "{input:?}"
7978            );
7979        }
7980    }
7981
7982    #[test]
7983    fn from_str_trims_surrounding_whitespace() {
7984        let map = get_css_key_map();
7985        assert_eq!(
7986            CssPropertyType::from_str("  \t width \n ", &map),
7987            Some(CssPropertyType::Width)
7988        );
7989        assert_eq!(
7990            CombinedCssPropertyType::from_str("\n border \t", &map),
7991            Some(CombinedCssPropertyType::Border)
7992        );
7993    }
7994
7995    #[test]
7996    fn from_str_garbage_returns_none() {
7997        let map = get_css_key_map();
7998        for input in [
7999            "asdfasdfasdf",
8000            ";",
8001            "{}",
8002            "widthh",
8003            "wid th",
8004            "width:",
8005            "width;garbage",
8006            "width!important",
8007            "\0",
8008            "\u{0}width\u{0}",
8009            "../../etc/passwd",
8010            "%s%s%s%n",
8011            "-",
8012            "--",
8013            "--custom-property",
8014        ] {
8015            assert_eq!(CssPropertyType::from_str(input, &map), None, "{input:?}");
8016            assert_eq!(
8017                CombinedCssPropertyType::from_str(input, &map),
8018                None,
8019                "{input:?}"
8020            );
8021        }
8022    }
8023
8024    #[test]
8025    fn from_str_is_case_sensitive() {
8026        // CSS keys are case-insensitive per spec, but these lookups are raw map
8027        // hits: normalisation is the caller's job (see parser2). Locked in so a
8028        // future change to the casing contract is a deliberate, visible one.
8029        let map = get_css_key_map();
8030        for input in ["WIDTH", "Width", "wIdTh"] {
8031            assert_eq!(CssPropertyType::from_str(input, &map), None, "{input:?}");
8032        }
8033        assert_eq!(
8034            CssPropertyType::from_str("width", &map),
8035            Some(CssPropertyType::Width)
8036        );
8037    }
8038
8039    #[test]
8040    fn from_str_boundary_number_strings_return_none() {
8041        let map = get_css_key_map();
8042        for input in [
8043            "0",
8044            "-0",
8045            "NaN",
8046            "nan",
8047            "inf",
8048            "-inf",
8049            "Infinity",
8050            "9223372036854775807",  // i64::MAX
8051            "-9223372036854775808", // i64::MIN
8052            "340282350000000000000000000000000000000", // ~f32::MAX
8053            "1e309",                // overflows f64
8054            "0.00000000000000000001",
8055        ] {
8056            assert_eq!(CssPropertyType::from_str(input, &map), None, "{input:?}");
8057            assert_eq!(
8058                CombinedCssPropertyType::from_str(input, &map),
8059                None,
8060                "{input:?}"
8061            );
8062        }
8063    }
8064
8065    #[test]
8066    fn from_str_unicode_does_not_panic() {
8067        let map = get_css_key_map();
8068        for input in [
8069            "\u{1F600}",                // emoji
8070            "wi\u{0301}dth",            // combining acute accent
8071            "\u{202E}width",            // RTL override
8072            "width",               // fullwidth latin
8073            "width\u{FEFF}",            // BOM suffix
8074            "𝓌𝒾𝒹𝓉𝒽",                    // mathematical script
8075            "ширина",                   // cyrillic
8076            "\u{0301}\u{0301}\u{0301}", // lone combining marks
8077        ] {
8078            assert_eq!(CssPropertyType::from_str(input, &map), None, "{input:?}");
8079            assert_eq!(
8080                CombinedCssPropertyType::from_str(input, &map),
8081                None,
8082                "{input:?}"
8083            );
8084        }
8085    }
8086
8087    #[test]
8088    fn from_str_extremely_long_input_does_not_panic_or_hang() {
8089        let map = get_css_key_map();
8090        let huge = "width".repeat(200_000); // 1_000_000 chars
8091        assert_eq!(huge.len(), 1_000_000);
8092        assert_eq!(CssPropertyType::from_str(&huge, &map), None);
8093        assert_eq!(CombinedCssPropertyType::from_str(&huge, &map), None);
8094
8095        // A valid key buried in a megabyte of padding is still not a valid key.
8096        let padded = format!("{}width{}", "x".repeat(500_000), "x".repeat(500_000));
8097        assert_eq!(CssPropertyType::from_str(&padded, &map), None);
8098    }
8099
8100    #[test]
8101    fn from_str_deeply_nested_brackets_do_not_stack_overflow() {
8102        let map = get_css_key_map();
8103        let nested = format!("{}{}", "(".repeat(10_000), ")".repeat(10_000));
8104        assert_eq!(CssPropertyType::from_str(&nested, &map), None);
8105        assert_eq!(CombinedCssPropertyType::from_str(&nested, &map), None);
8106    }
8107
8108    #[test]
8109    fn from_str_valid_minimal_positive_control() {
8110        let map = get_css_key_map();
8111        assert_eq!(
8112            CssPropertyType::from_str("width", &map),
8113            Some(CssPropertyType::Width)
8114        );
8115        assert_eq!(
8116            CssPropertyType::from_str("justify-content", &map),
8117            Some(CssPropertyType::JustifyContent)
8118        );
8119        assert_eq!(
8120            CombinedCssPropertyType::from_str("border", &map),
8121            Some(CombinedCssPropertyType::Border)
8122        );
8123    }
8124
8125    #[test]
8126    fn word_wrap_is_a_registered_alias_for_overflow_wrap() {
8127        let map = get_css_key_map();
8128        assert_eq!(
8129            CssPropertyType::from_str("word-wrap", &map),
8130            Some(CssPropertyType::OverflowWrap)
8131        );
8132        assert_eq!(
8133            CssPropertyType::from_str("overflow-wrap", &map),
8134            Some(CssPropertyType::OverflowWrap)
8135        );
8136        // The alias is not the canonical name.
8137        assert_eq!(CssPropertyType::OverflowWrap.to_str(), "overflow-wrap");
8138    }
8139
8140    #[test]
8141    fn keys_present_in_both_maps_are_shorthand_shadowed() {
8142        // These four strings are registered in *both* key maps. parser2 consults
8143        // the shorthand map first, so the CombinedCssPropertyType always wins and
8144        // the same-named CssPropertyType is never reached from stylesheet text.
8145        let map = get_css_key_map();
8146        for k in ["background", "font", "gap", "grid-gap"] {
8147            assert!(
8148                CssPropertyType::from_str(k, &map).is_some(),
8149                "{k} should be in the non-shorthand map"
8150            );
8151            assert!(
8152                CombinedCssPropertyType::from_str(k, &map).is_some(),
8153                "{k} should be in the shorthand map"
8154            );
8155        }
8156    }
8157
8158    // ---- to_str / Display / Debug round-trips -------------------------------
8159
8160    #[test]
8161    fn css_property_type_to_str_is_non_empty_and_unique() {
8162        let mut seen = BTreeMap::new();
8163        for t in CssPropertyType::iter() {
8164            let s = t.to_str();
8165            assert!(!s.is_empty(), "{t:?} has an empty to_str()");
8166            assert!(!s.contains(' '), "{t:?} to_str() contains whitespace: {s:?}");
8167            assert_eq!(s.trim(), s, "{t:?} to_str() is not trimmed: {s:?}");
8168            if let Some(prev) = seen.insert(s, t) {
8169                panic!("to_str() collision: {prev:?} and {t:?} both return {s:?}");
8170            }
8171        }
8172        assert_eq!(seen.len(), CssPropertyType::ALL.len());
8173    }
8174
8175    #[test]
8176    fn css_property_type_display_and_debug_agree_with_to_str() {
8177        for t in CssPropertyType::iter() {
8178            assert_eq!(format!("{t}"), t.to_str());
8179            assert_eq!(format!("{t:?}"), t.to_str());
8180        }
8181    }
8182
8183    #[test]
8184    fn css_property_type_iter_matches_all() {
8185        let collected: Vec<CssPropertyType> = CssPropertyType::iter().collect();
8186        assert_eq!(collected.as_slice(), CssPropertyType::ALL);
8187        // Iteration is repeatable (no interior state).
8188        let again: Vec<CssPropertyType> = CssPropertyType::iter().collect();
8189        assert_eq!(collected, again);
8190    }
8191
8192    #[test]
8193    fn css_property_type_to_str_round_trips_except_known_gap() {
8194        // parse(serialize(x)) == x for every property type that is actually
8195        // registered in the key map. The set that fails to round-trip is pinned
8196        // to the five table properties below; a sixth regression fails here.
8197        let map = get_css_key_map();
8198        let mut unreachable = Vec::new();
8199        for t in CssPropertyType::iter() {
8200            match CssPropertyType::from_str(t.to_str(), &map) {
8201                Some(back) => assert_eq!(back, t, "{t:?} round-tripped to the wrong type"),
8202                None => unreachable.push(t),
8203            }
8204        }
8205        assert_eq!(
8206            unreachable.as_slice(),
8207            KEYS_MISSING_FROM_KEY_MAP,
8208            "the set of property types missing from CSS_PROPERTY_KEY_MAP changed"
8209        );
8210    }
8211
8212    #[test]
8213    fn bug_table_properties_are_unreachable_from_stylesheet_text() {
8214        let map = get_css_key_map();
8215        for t in KEYS_MISSING_FROM_KEY_MAP {
8216            assert_eq!(
8217                CssPropertyType::from_str(t.to_str(), &map),
8218                Some(*t),
8219                "`{}` has a to_str() name and a working value parser, but no key-map \
8220                 entry, so parser2 rejects the declaration outright",
8221                t.to_str()
8222            );
8223        }
8224    }
8225
8226    #[test]
8227    #[cfg(feature = "parser")]
8228    fn table_property_value_parsers_work_even_though_the_keys_do_not_resolve() {
8229        // Proves the gap above is purely in CSS_PROPERTY_KEY_MAP: given the key
8230        // *type*, every one of these values parses fine. Only the string -> type
8231        // lookup is missing.
8232        for (t, value) in [
8233            (CssPropertyType::TableLayout, "fixed"),
8234            (CssPropertyType::BorderCollapse, "collapse"),
8235            (CssPropertyType::CaptionSide, "top"),
8236            (CssPropertyType::EmptyCells, "hide"),
8237        ] {
8238            let parsed = parse_css_property(t, value)
8239                .unwrap_or_else(|e| panic!("`{}: {value}` should parse: {e}", t.to_str()));
8240            assert_eq!(parsed.get_type(), t);
8241        }
8242    }
8243
8244    #[test]
8245    fn combined_css_property_type_round_trips_and_display_agrees() {
8246        let map = get_css_key_map();
8247        for t in map.shorthands.values() {
8248            let s = t.to_str(&map);
8249            assert!(!s.is_empty());
8250            assert_eq!(
8251                CombinedCssPropertyType::from_str(s, &map),
8252                Some(*t),
8253                "{t:?} did not round-trip"
8254            );
8255            // Display is derived from the static array, to_str from the map:
8256            // the two sources must not drift apart.
8257            assert_eq!(format!("{t}"), s, "Display disagrees with to_str for {t:?}");
8258        }
8259        assert_eq!(map.shorthands.len(), COMBINED_CSS_PROPERTIES_KEY_MAP.len());
8260    }
8261
8262    // ---- predicates: totality + known true/false -----------------------------
8263
8264    #[test]
8265    fn is_inheritable_matches_the_css_spec_for_known_properties() {
8266        for t in [
8267            CssPropertyType::TextColor,
8268            CssPropertyType::FontFamily,
8269            CssPropertyType::FontSize,
8270            CssPropertyType::LineHeight,
8271            CssPropertyType::Visibility,
8272            CssPropertyType::Cursor,
8273            CssPropertyType::WritingMode,
8274        ] {
8275            assert!(t.is_inheritable(), "{t:?} is inherited per CSS spec");
8276        }
8277        for t in [
8278            CssPropertyType::Width,
8279            CssPropertyType::Height,
8280            CssPropertyType::Display,
8281            CssPropertyType::Position,
8282            CssPropertyType::Opacity,
8283            CssPropertyType::Transform,
8284            CssPropertyType::BackgroundContent,
8285            CssPropertyType::UnicodeBidi, // explicitly non-inherited, see +spec:display-property
8286        ] {
8287            assert!(!t.is_inheritable(), "{t:?} is NOT inherited per CSS spec");
8288        }
8289    }
8290
8291    #[test]
8292    fn predicates_are_total_over_every_property_type() {
8293        // Every predicate must return a deterministic bool for all 180 variants
8294        // without panicking, and must be pure (same answer twice).
8295        for t in CssPropertyType::iter() {
8296            assert_eq!(t.is_inheritable(), t.is_inheritable());
8297            assert_eq!(t.has_compact_encoding(), t.has_compact_encoding());
8298            assert_eq!(t.can_trigger_relayout(), t.can_trigger_relayout());
8299            assert_eq!(t.is_gpu_only_property(), t.is_gpu_only_property());
8300            assert_eq!(t.get_category(), t.get_category());
8301            assert_eq!(t.relayout_scope(false), t.relayout_scope(false));
8302            assert_eq!(t.relayout_scope(true), t.relayout_scope(true));
8303        }
8304    }
8305
8306    #[test]
8307    fn is_gpu_only_property_is_exactly_opacity_and_transform() {
8308        let gpu: Vec<CssPropertyType> = CssPropertyType::iter()
8309            .filter(CssPropertyType::is_gpu_only_property)
8310            .collect();
8311        assert_eq!(
8312            gpu,
8313            vec![CssPropertyType::Opacity, CssPropertyType::Transform]
8314        );
8315    }
8316
8317    #[test]
8318    fn has_compact_encoding_known_true_false() {
8319        assert!(CssPropertyType::Display.has_compact_encoding());
8320        assert!(CssPropertyType::Width.has_compact_encoding());
8321        assert!(CssPropertyType::FlexGrow.has_compact_encoding());
8322        assert!(!CssPropertyType::Transform.has_compact_encoding());
8323        assert!(!CssPropertyType::Filter.has_compact_encoding());
8324        assert!(!CssPropertyType::Content.has_compact_encoding());
8325    }
8326
8327    #[test]
8328    fn can_trigger_relayout_known_true_false() {
8329        for t in [
8330            CssPropertyType::Width,
8331            CssPropertyType::Display,
8332            CssPropertyType::FontSize,
8333            CssPropertyType::MarginTop,
8334        ] {
8335            assert!(t.can_trigger_relayout(), "{t:?} affects geometry");
8336        }
8337        for t in [
8338            CssPropertyType::TextColor,
8339            CssPropertyType::Opacity,
8340            CssPropertyType::Transform,
8341            CssPropertyType::BackgroundContent,
8342        ] {
8343            assert!(!t.can_trigger_relayout(), "{t:?} is paint-only");
8344        }
8345    }
8346
8347    #[test]
8348    fn get_category_is_derived_consistently_from_the_predicates() {
8349        for t in CssPropertyType::iter() {
8350            let expected = if t.is_gpu_only_property() {
8351                CssPropertyCategory::GpuOnly
8352            } else {
8353                match (t.is_inheritable(), t.can_trigger_relayout()) {
8354                    (true, true) => CssPropertyCategory::InheritedLayout,
8355                    (true, false) => CssPropertyCategory::InheritedPaint,
8356                    (false, true) => CssPropertyCategory::Layout,
8357                    (false, false) => CssPropertyCategory::Paint,
8358                }
8359            };
8360            assert_eq!(t.get_category(), expected, "{t:?}");
8361        }
8362        assert_eq!(
8363            CssPropertyType::Opacity.get_category(),
8364            CssPropertyCategory::GpuOnly
8365        );
8366        assert_eq!(
8367            CssPropertyType::Width.get_category(),
8368            CssPropertyCategory::Layout
8369        );
8370        assert_eq!(
8371            CssPropertyType::FontSize.get_category(),
8372            CssPropertyCategory::InheritedLayout
8373        );
8374    }
8375
8376    // ---- relayout_scope ------------------------------------------------------
8377
8378    #[test]
8379    fn relayout_scope_never_contradicts_can_trigger_relayout() {
8380        // relayout_scope is documented as "a more granular replacement for
8381        // can_trigger_relayout()". The safe direction must hold: anything the
8382        // coarse predicate calls paint-only must also be scope None, or an
8383        // incremental-layout consumer would skip a relayout it actually needs.
8384        for t in CssPropertyType::iter() {
8385            if !t.can_trigger_relayout() {
8386                for ifc in [false, true] {
8387                    assert_eq!(
8388                        t.relayout_scope(ifc),
8389                        RelayoutScope::None,
8390                        "{t:?} is paint-only but claims a relayout scope (ifc={ifc})"
8391                    );
8392                }
8393            }
8394        }
8395    }
8396
8397    #[test]
8398    fn relayout_scope_paint_only_ignores_the_ifc_flag() {
8399        for t in [
8400            CssPropertyType::TextColor,
8401            CssPropertyType::Opacity,
8402            CssPropertyType::Transform,
8403            CssPropertyType::BackgroundContent,
8404            CssPropertyType::CaretColor,
8405            CssPropertyType::ObjectFit,
8406        ] {
8407            assert_eq!(t.relayout_scope(false), RelayoutScope::None, "{t:?}");
8408            assert_eq!(t.relayout_scope(true), RelayoutScope::None, "{t:?}");
8409        }
8410    }
8411
8412    #[test]
8413    fn relayout_scope_upgrades_text_properties_only_inside_an_ifc() {
8414        // Font/text changes reflow an inline formatting context but do not
8415        // resize a block container that has only block children.
8416        for t in [
8417            CssPropertyType::FontSize,
8418            CssPropertyType::FontFamily,
8419            CssPropertyType::LineHeight,
8420            CssPropertyType::LetterSpacing,
8421        ] {
8422            assert_eq!(t.relayout_scope(true), RelayoutScope::IfcOnly, "{t:?}");
8423            assert_ne!(t.relayout_scope(false), RelayoutScope::IfcOnly, "{t:?}");
8424        }
8425    }
8426
8427    // ---- CssProperty keyword constructors: totality over all 180 variants -----
8428
8429    #[test]
8430    fn keyword_constructors_preserve_the_property_type_for_every_variant() {
8431        // css_property_from_type! is a 180-arm hand-written macro: a single
8432        // copy-paste slip would silently build the wrong variant.
8433        for t in CssPropertyType::iter() {
8434            assert_eq!(CssProperty::none(t).get_type(), t, "none({t:?})");
8435            assert_eq!(CssProperty::auto(t).get_type(), t, "auto({t:?})");
8436            assert_eq!(CssProperty::initial(t).get_type(), t, "initial({t:?})");
8437            assert_eq!(CssProperty::inherit(t).get_type(), t, "inherit({t:?})");
8438        }
8439    }
8440
8441    #[test]
8442    fn key_agrees_with_get_type_for_every_variant() {
8443        for t in CssPropertyType::iter() {
8444            assert_eq!(CssProperty::none(t).key(), t.to_str(), "{t:?}");
8445        }
8446    }
8447
8448    #[test]
8449    fn value_and_format_css_are_well_formed_for_every_keyword_variant() {
8450        for t in CssPropertyType::iter() {
8451            for (ctor, keyword) in [
8452                (CssProperty::none as fn(CssPropertyType) -> CssProperty, "none"),
8453                (CssProperty::auto, "auto"),
8454                (CssProperty::initial, "initial"),
8455                (CssProperty::inherit, "inherit"),
8456            ] {
8457                let prop = ctor(t);
8458                assert_eq!(prop.value(), keyword, "{t:?} {keyword}");
8459                assert!(!prop.value().is_empty());
8460                assert_eq!(
8461                    prop.format_css(),
8462                    format!("{}: {keyword};", t.to_str()),
8463                    "{t:?} {keyword}"
8464                );
8465            }
8466        }
8467    }
8468
8469    #[test]
8470    fn format_css_does_not_panic_on_extreme_and_non_finite_numbers() {
8471        for px in [
8472            0.0,
8473            -0.0,
8474            1.0,
8475            -1.0,
8476            f32::MAX,
8477            f32::MIN,
8478            f32::MIN_POSITIVE,
8479            f32::EPSILON,
8480            f32::INFINITY,
8481            f32::NEG_INFINITY,
8482            f32::NAN,
8483        ] {
8484            let prop = font_size(px);
8485            let css = prop.format_css();
8486            assert!(!css.is_empty(), "empty css for font-size {px}");
8487            assert!(css.starts_with("font-size: "), "malformed: {css:?}");
8488            assert!(css.ends_with(';'), "malformed: {css:?}");
8489            assert_eq!(prop.get_type(), CssPropertyType::FontSize);
8490        }
8491    }
8492
8493    #[test]
8494    fn extreme_float_inputs_saturate_rather_than_wrap() {
8495        // FloatValue stores a fixed-point isize; `f32 as isize` saturates, so
8496        // huge magnitudes must clamp and NaN must land on a defined value.
8497        assert!(font_size_px_of(&font_size(f32::INFINITY)) > 0.0);
8498        assert!(font_size_px_of(&font_size(f32::NEG_INFINITY)) < 0.0);
8499        assert_eq!(font_size_px_of(&font_size(f32::NAN)), 0.0);
8500        assert_eq!(font_size_px_of(&font_size(0.0)), 0.0);
8501        assert_eq!(font_size_px_of(&font_size(16.0)), 16.0);
8502        assert_eq!(font_size_px_of(&font_size(-16.0)), -16.0);
8503    }
8504
8505    // ---- interpolate ---------------------------------------------------------
8506
8507    #[test]
8508    fn interpolate_at_and_beyond_the_endpoints() {
8509        let r = resolver();
8510        let a = font_size(10.0);
8511        let b = font_size(20.0);
8512
8513        assert_eq!(a.interpolate(&b, 0.0, &r), a, "t=0 must return self");
8514        assert_eq!(a.interpolate(&b, 1.0, &r), b, "t=1 must return other");
8515        assert_eq!(a.interpolate(&b, -0.0, &r), a);
8516        assert_eq!(a.interpolate(&b, -5.0, &r), a, "t<0 clamps to self");
8517        assert_eq!(a.interpolate(&b, 5.0, &r), b, "t>1 clamps to other");
8518        assert_eq!(a.interpolate(&b, f32::NEG_INFINITY, &r), a);
8519        assert_eq!(a.interpolate(&b, f32::INFINITY, &r), b);
8520        assert_eq!(a.interpolate(&b, f32::MIN, &r), a);
8521        assert_eq!(a.interpolate(&b, f32::MAX, &r), b);
8522    }
8523
8524    #[test]
8525    fn interpolate_midpoint_is_the_linear_average() {
8526        let r = resolver();
8527        let out = font_size(0.0).interpolate(&font_size(100.0), 0.5, &r);
8528        let px = font_size_px_of(&out);
8529        assert!(
8530            (px - 50.0).abs() < 1.0,
8531            "linear midpoint of 0px..100px should be ~50px, got {px}"
8532        );
8533    }
8534
8535    #[test]
8536    fn interpolate_nan_t_does_not_panic_and_keeps_the_property_type() {
8537        let r = resolver();
8538        let a = font_size(10.0);
8539        let b = font_size(20.0);
8540        // NaN fails both the `t <= 0.0` and `t >= 1.0` guards and survives
8541        // f32::clamp, so it reaches the per-property interpolators.
8542        let out = a.interpolate(&b, f32::NAN, &r);
8543        assert_eq!(out.get_type(), CssPropertyType::FontSize);
8544        assert!(!out.format_css().is_empty());
8545    }
8546
8547    #[test]
8548    fn interpolate_extreme_endpoints_do_not_panic() {
8549        let r = resolver();
8550        for (from, to) in [
8551            (f32::MAX, f32::MIN),
8552            (f32::MIN, f32::MAX),
8553            (f32::INFINITY, f32::NEG_INFINITY),
8554            (f32::NAN, 10.0),
8555            (10.0, f32::NAN),
8556            (0.0, 0.0),
8557        ] {
8558            for t in [0.25, 0.5, 0.75] {
8559                let out = font_size(from).interpolate(&font_size(to), t, &r);
8560                assert_eq!(out.get_type(), CssPropertyType::FontSize);
8561                assert!(!out.format_css().is_empty());
8562            }
8563        }
8564    }
8565
8566    #[test]
8567    fn interpolate_between_mismatched_types_falls_back_without_panic() {
8568        let r = resolver();
8569        let width = CssProperty::width(LayoutWidth::Px(PixelValue::px(10.0)));
8570        let height = CssProperty::height(LayoutHeight::Px(PixelValue::px(20.0)));
8571
8572        // Not animatable across types: snaps to the nearer endpoint.
8573        assert_eq!(width.interpolate(&height, 0.25, &r), width);
8574        assert_eq!(width.interpolate(&height, 0.75, &r), height);
8575        // NaN takes neither branch of `t > 0.5`, so it must fall back to self.
8576        assert_eq!(width.interpolate(&height, f32::NAN, &r), width);
8577    }
8578
8579    #[test]
8580    fn interpolate_keyword_operands_fall_back_to_defaults_without_panic() {
8581        let r = resolver();
8582        // `auto`/`inherit` carry no concrete value; interpolating them must not
8583        // unwrap a missing property.
8584        let auto = CssProperty::auto(CssPropertyType::FontSize);
8585        let inherit = CssProperty::inherit(CssPropertyType::FontSize);
8586        let exact = font_size(24.0);
8587
8588        for (a, b) in [
8589            (&auto, &exact),
8590            (&exact, &auto),
8591            (&inherit, &exact),
8592            (&auto, &inherit),
8593        ] {
8594            let out = a.interpolate(b, 0.5, &r);
8595            assert_eq!(out.get_type(), CssPropertyType::FontSize);
8596            assert!(!out.format_css().is_empty());
8597        }
8598    }
8599
8600    // ---- parse_css_property --------------------------------------------------
8601
8602    #[test]
8603    #[cfg(feature = "parser")]
8604    fn parse_css_property_keyword_shortcut_works_for_every_property_type() {
8605        // `initial` / `inherit` short-circuit before any key-specific parsing,
8606        // so they must succeed for all 180 types and keep the requested type.
8607        for t in CssPropertyType::iter() {
8608            for keyword in ["initial", "inherit"] {
8609                let parsed = parse_css_property(t, keyword)
8610                    .unwrap_or_else(|e| panic!("{}: {keyword} failed: {e}", t.to_str()));
8611                assert_eq!(parsed.get_type(), t, "{t:?} {keyword}");
8612                assert_eq!(parsed.value(), keyword);
8613            }
8614            // Surrounding whitespace is trimmed before the keyword match.
8615            let parsed = parse_css_property(t, "  \t initial \n ")
8616                .unwrap_or_else(|e| panic!("{}: padded initial failed: {e}", t.to_str()));
8617            assert_eq!(parsed, CssProperty::initial(t), "{t:?}");
8618        }
8619    }
8620
8621    #[test]
8622    #[cfg(feature = "parser")]
8623    fn parse_css_property_valid_minimal_positive_control() {
8624        let width = parse_css_property(CssPropertyType::Width, "100px").expect("100px is valid");
8625        assert_eq!(width.get_type(), CssPropertyType::Width);
8626        assert_eq!(width.value(), "100px");
8627        assert_eq!(width.format_css(), "width: 100px;");
8628
8629        let display =
8630            parse_css_property(CssPropertyType::Display, "flex").expect("flex is valid display");
8631        assert_eq!(display.get_type(), CssPropertyType::Display);
8632
8633        // text-overflow: full dispatch through parse_css_property -> typed CssProperty,
8634        // correct type mapping, and canonical serialization.
8635        let text_overflow = parse_css_property(CssPropertyType::TextOverflow, "ellipsis")
8636            .expect("ellipsis is valid text-overflow");
8637        assert_eq!(text_overflow.get_type(), CssPropertyType::TextOverflow);
8638        assert_eq!(
8639            text_overflow,
8640            CssProperty::TextOverflow(CssPropertyValue::Exact(StyleTextOverflow::Ellipsis))
8641        );
8642        assert_eq!(text_overflow.value(), "ellipsis");
8643        assert_eq!(text_overflow.format_css(), "text-overflow: ellipsis;");
8644        assert!(parse_css_property(CssPropertyType::TextOverflow, "bogus").is_err());
8645    }
8646
8647    #[test]
8648    #[cfg(feature = "parser")]
8649    fn parse_css_property_empty_and_whitespace_only_are_rejected() {
8650        for value in ["", " ", "\t", "\n", "   \t\n  "] {
8651            assert!(
8652                parse_css_property(CssPropertyType::Width, value).is_err(),
8653                "width: {value:?} should not parse"
8654            );
8655            assert!(
8656                parse_css_property(CssPropertyType::TextColor, value).is_err(),
8657                "color: {value:?} should not parse"
8658            );
8659        }
8660    }
8661
8662    #[test]
8663    #[cfg(feature = "parser")]
8664    fn parse_css_property_garbage_is_rejected_without_panicking() {
8665        for value in [
8666            "!!!",
8667            "not-a-value",
8668            "100pxx",
8669            "px100",
8670            "100 px",
8671            ";",
8672            "}",
8673            "100px;",
8674            "100px !important",
8675            "\0",
8676            "#gg0000",
8677            "rgb(",
8678            "rgb(1,2",
8679        ] {
8680            assert!(
8681                parse_css_property(CssPropertyType::Width, value).is_err()
8682                    || parse_css_property(CssPropertyType::TextColor, value).is_err(),
8683                "{value:?} parsed as both a width and a color"
8684            );
8685        }
8686        // Spot-check the ones that must be rejected by *both* parsers.
8687        for value in ["!!!", "not-a-value", "\0", ";"] {
8688            assert!(parse_css_property(CssPropertyType::Width, value).is_err());
8689            assert!(parse_css_property(CssPropertyType::TextColor, value).is_err());
8690        }
8691    }
8692
8693    #[test]
8694    #[cfg(feature = "parser")]
8695    fn parse_css_property_unicode_is_rejected_without_panicking() {
8696        for value in [
8697            "\u{1F600}",
8698            "100\u{0301}px",
8699            "\u{202E}100px",
8700            "100px",
8701            "100px\u{FEFF}",
8702            "红色",
8703        ] {
8704            // Must not panic; a multibyte slice must never be cut mid-codepoint.
8705            let _ = parse_css_property(CssPropertyType::Width, value).is_err();
8706            let _ = parse_css_property(CssPropertyType::TextColor, value).is_err();
8707            let _ = parse_css_property(CssPropertyType::FontFamily, value).is_ok();
8708        }
8709        assert!(parse_css_property(CssPropertyType::Width, "\u{1F600}").is_err());
8710    }
8711
8712    #[test]
8713    #[cfg(feature = "parser")]
8714    fn parse_css_property_boundary_numbers_do_not_panic() {
8715        for value in [
8716            "0",
8717            "0px",
8718            "-0px",
8719            "-1px",
8720            "2147483647px",
8721            "-2147483648px",
8722            "9223372036854775807px",
8723            "340282350000000000000000000000000000000px",
8724            "1e309px",
8725            "NaNpx",
8726            "infpx",
8727            "0.00000000000000000001px",
8728            "99999999999999999999999999999999999999999999px",
8729        ] {
8730            // The contract is "no panic, no overflow trap" — a saturating Ok or a
8731            // clean Err are both acceptable, a debug-overflow panic is not.
8732            let parsed = parse_css_property(CssPropertyType::Width, value);
8733            if let Ok(p) = parsed {
8734                assert_eq!(p.get_type(), CssPropertyType::Width, "{value:?}");
8735                assert!(!p.format_css().is_empty(), "{value:?}");
8736            }
8737        }
8738    }
8739
8740    #[test]
8741    #[cfg(feature = "parser")]
8742    fn parse_css_property_extremely_long_input_does_not_hang() {
8743        // Long *digit* runs stay at 100k: the float parser is the expensive part
8744        // and the point is to prove it terminates, not to benchmark it.
8745        let huge = "1".repeat(100_000);
8746        if let Ok(p) = parse_css_property(CssPropertyType::Width, &huge) {
8747            assert_eq!(p.get_type(), CssPropertyType::Width);
8748        }
8749        let huge_px = format!("{}px", "9".repeat(100_000));
8750        let _ = parse_css_property(CssPropertyType::Width, &huge_px);
8751
8752        // Pure garbage is rejected on the first byte, so a full megabyte is cheap.
8753        let huge_garbage = "z".repeat(1_000_000);
8754        assert!(parse_css_property(CssPropertyType::Width, &huge_garbage).is_err());
8755    }
8756
8757    #[test]
8758    #[cfg(feature = "parser")]
8759    fn parse_css_property_deeply_nested_calc_does_not_stack_overflow() {
8760        // parse_calc_expression is an iterative stack machine, not a recursive
8761        // descent parser, so deep nesting must stay on the heap.
8762        let depth = 10_000;
8763        let nested = format!("calc({}1px{})", "(".repeat(depth), ")".repeat(depth));
8764        let _ = parse_css_property(CssPropertyType::Width, &nested);
8765
8766        let unbalanced = format!("calc({})", "(".repeat(depth));
8767        let _ = parse_css_property(CssPropertyType::Width, &unbalanced);
8768    }
8769
8770    #[test]
8771    #[cfg(feature = "parser")]
8772    fn parse_css_property_leading_trailing_junk_is_handled_deterministically() {
8773        // Padding is trimmed...
8774        let padded = parse_css_property(CssPropertyType::Width, "  \t 100px \n ")
8775            .expect("surrounding whitespace should be trimmed");
8776        assert_eq!(padded.value(), "100px");
8777        assert_eq!(
8778            padded,
8779            parse_css_property(CssPropertyType::Width, "100px").unwrap()
8780        );
8781        // ...but embedded junk is not silently dropped.
8782        assert!(parse_css_property(CssPropertyType::Width, "100px;garbage").is_err());
8783        assert!(parse_css_property(CssPropertyType::Width, "garbage 100px").is_err());
8784    }
8785
8786    // ---- parse_combined_css_property ------------------------------------------
8787
8788    #[test]
8789    #[cfg(feature = "parser")]
8790    fn parse_combined_css_property_valid_minimal_positive_control() {
8791        let props = parse_combined_css_property(CombinedCssPropertyType::Margin, "10px")
8792            .expect("margin: 10px is valid");
8793        let types: Vec<CssPropertyType> = props.iter().map(CssProperty::get_type).collect();
8794        assert_eq!(
8795            types,
8796            vec![
8797                CssPropertyType::MarginTop,
8798                CssPropertyType::MarginBottom,
8799                CssPropertyType::MarginLeft,
8800                CssPropertyType::MarginRight,
8801            ]
8802        );
8803        for p in &props {
8804            assert_eq!(p.value(), "10px");
8805        }
8806    }
8807
8808    #[test]
8809    #[cfg(feature = "parser")]
8810    fn parse_combined_css_property_expands_every_shorthand_or_errors_cleanly() {
8811        // `initial` short-circuits ahead of every value parser, so all 27
8812        // shorthands must expand to a non-empty list of `initial` longhands.
8813        let map = get_css_key_map();
8814        for key in map.shorthands.values() {
8815            let props = parse_combined_css_property(*key, "initial")
8816                .unwrap_or_else(|e| panic!("{key:?}: initial failed: {e}"));
8817            assert!(
8818                !props.is_empty(),
8819                "{key:?} expanded to an empty property list"
8820            );
8821            for p in &props {
8822                assert_eq!(p.value(), "initial", "{key:?} -> {:?}", p.get_type());
8823                assert_eq!(*p, CssProperty::initial(p.get_type()), "{key:?}");
8824            }
8825        }
8826    }
8827
8828    #[test]
8829    #[cfg(feature = "parser")]
8830    fn parse_combined_css_property_empty_and_whitespace_are_rejected() {
8831        for value in ["", " ", "\t\n", "    "] {
8832            assert!(
8833                parse_combined_css_property(CombinedCssPropertyType::Margin, value).is_err(),
8834                "margin: {value:?} should not parse"
8835            );
8836            assert!(
8837                parse_combined_css_property(CombinedCssPropertyType::BorderRadius, value).is_err(),
8838                "border-radius: {value:?} should not parse"
8839            );
8840        }
8841    }
8842
8843    #[test]
8844    #[cfg(feature = "parser")]
8845    fn parse_combined_css_property_garbage_is_rejected_without_panicking() {
8846        for value in ["!!!", "not-a-value", "10pxx", ";", "\0", "10px 20px 30px 40px 50px"] {
8847            assert!(
8848                parse_combined_css_property(CombinedCssPropertyType::Margin, value).is_err(),
8849                "margin: {value:?} should not parse"
8850            );
8851        }
8852    }
8853
8854    #[test]
8855    #[cfg(feature = "parser")]
8856    fn parse_combined_css_property_unicode_and_long_input_do_not_panic() {
8857        for value in ["\u{1F600}", "1\u{0301}0px", "10px", "红色"] {
8858            let _ = parse_combined_css_property(CombinedCssPropertyType::Margin, value).is_err();
8859            let _ = parse_combined_css_property(CombinedCssPropertyType::Background, value).is_err();
8860        }
8861        // The padding/margin parser parses every value before it counts them, so
8862        // 20k values already exercises the TooManyValues path without a long run.
8863        let many = "10px ".repeat(20_000);
8864        assert!(
8865            parse_combined_css_property(CombinedCssPropertyType::Margin, &many).is_err(),
8866            "20_000 margin values should be TooManyValues, not a panic"
8867        );
8868        let huge_garbage = "z".repeat(1_000_000);
8869        assert!(
8870            parse_combined_css_property(CombinedCssPropertyType::Margin, &huge_garbage).is_err()
8871        );
8872    }
8873
8874    #[test]
8875    #[cfg(feature = "parser")]
8876    fn parse_combined_css_property_nested_parens_do_not_stack_overflow() {
8877        let nested = format!("{}10px{}", "(".repeat(1_000), ")".repeat(1_000));
8878        let _ = parse_combined_css_property(CombinedCssPropertyType::Margin, &nested);
8879        let _ = parse_combined_css_property(CombinedCssPropertyType::Border, &nested);
8880    }
8881
8882    // ---- CssParsingError round-trip -------------------------------------------
8883
8884    #[test]
8885    #[cfg(feature = "parser")]
8886    fn parsing_error_survives_the_owned_round_trip() {
8887        let err = parse_css_property(CssPropertyType::Width, "definitely-not-a-width")
8888            .expect_err("garbage width must fail");
8889
8890        let owned = err.to_contained();
8891        let shared = owned.to_shared();
8892
8893        // to_contained/to_shared must preserve the error, not flatten it to a
8894        // generic variant: the rendered message is the observable contract.
8895        assert_eq!(format!("{err}"), format!("{shared}"));
8896        assert!(!format!("{err}").is_empty());
8897        // ...and the round-trip is idempotent.
8898        let owned_again = shared.to_contained();
8899        assert_eq!(format!("{}", owned_again.to_shared()), format!("{err}"));
8900    }
8901
8902    #[test]
8903    #[cfg(feature = "parser")]
8904    fn parsing_errors_round_trip_for_a_spread_of_property_kinds() {
8905        for t in [
8906            CssPropertyType::Width,
8907            CssPropertyType::TextColor,
8908            CssPropertyType::FontSize,
8909            CssPropertyType::Opacity,
8910            CssPropertyType::Transform,
8911            CssPropertyType::BackgroundContent,
8912        ] {
8913            let Err(err) = parse_css_property(t, "\u{1F600}not-valid\u{1F600}") else {
8914                continue;
8915            };
8916            let owned = err.to_contained();
8917            let round_tripped = owned.to_shared();
8918            assert_eq!(
8919                format!("{err}"),
8920                format!("{round_tripped}"),
8921                "{} error lost information in to_contained()",
8922                t.to_str()
8923            );
8924        }
8925    }
8926}