mosaic-headless 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +94 -0
  3. package/README.md +133 -0
  4. package/README.zh-CN.md +87 -0
  5. package/README.zh-TW.md +87 -0
  6. package/SKILL.md +353 -0
  7. package/assets/templates/platforms/claude-ai.json +34 -0
  8. package/assets/templates/platforms/claude-code.json +28 -0
  9. package/assets/templates/platforms/codex-cli.json +33 -0
  10. package/assets/templates/platforms/continue.json +31 -0
  11. package/assets/templates/platforms/copilot.json +46 -0
  12. package/assets/templates/platforms/cursor.json +36 -0
  13. package/assets/templates/platforms/gemini-cli.json +33 -0
  14. package/assets/templates/platforms/windsurf.json +34 -0
  15. package/bin/check-release.mjs +143 -0
  16. package/bin/install.mjs +452 -0
  17. package/bin/sync-version.mjs +63 -0
  18. package/data/animatable-properties.csv +23 -0
  19. package/data/condition-comparators.csv +13 -0
  20. package/data/condition-subjects.csv +60 -0
  21. package/data/db-columns.csv +207 -0
  22. package/data/default-children.csv +11 -0
  23. package/data/dynamic-variables.csv +75 -0
  24. package/data/element-classes.csv +152 -0
  25. package/data/evaluator-functions.csv +20 -0
  26. package/data/interaction-types.csv +13 -0
  27. package/data/node-properties.csv +182 -0
  28. package/data/node-property-verification.csv +182 -0
  29. package/data/node-types.csv +123 -0
  30. package/data/node-verification.csv +123 -0
  31. package/data/placement-rules.csv +123 -0
  32. package/data/pluggables.csv +208 -0
  33. package/data/property-verification.csv +171 -0
  34. package/data/rest-routes.csv +115 -0
  35. package/data/rwd-verification.csv +570 -0
  36. package/data/style-properties.csv +99 -0
  37. package/data/style-states.csv +54 -0
  38. package/data/style-value-shapes.csv +23 -0
  39. package/data/style-verification.csv +99 -0
  40. package/package.json +59 -0
  41. package/references/data-model.md +95 -0
  42. package/references/design-system.md +118 -0
  43. package/references/dynamic-content.md +113 -0
  44. package/references/failure-modes.md +182 -0
  45. package/references/interactions.md +126 -0
  46. package/references/placement.md +117 -0
  47. package/references/responsive.md +174 -0
  48. package/references/styling.md +172 -0
  49. package/references/templates-and-conditions.md +122 -0
  50. package/references/vs-elementor-gutenberg.md +73 -0
  51. package/references/write-protocol.md +79 -0
  52. package/sites/_moksa.py +1165 -0
  53. package/sites/moksa.json +8685 -0
  54. package/tools/bootstrap_probe_theme.php +68 -0
  55. package/tools/build_all.py +55 -0
  56. package/tools/build_page.py +352 -0
  57. package/tools/build_report.py +221 -0
  58. package/tools/build_site.py +174 -0
  59. package/tools/capture_live.py +130 -0
  60. package/tools/check_placement_predicts.py +72 -0
  61. package/tools/copy_styles.py +204 -0
  62. package/tools/extract_default_children.py +94 -0
  63. package/tools/extract_dynamic_variables.py +104 -0
  64. package/tools/extract_interactions.py +98 -0
  65. package/tools/extract_node_types.py +165 -0
  66. package/tools/extract_placement.py +135 -0
  67. package/tools/extract_pluggables.py +90 -0
  68. package/tools/extract_style_properties.py +163 -0
  69. package/tools/mint_session.php +52 -0
  70. package/tools/probe.py +144 -0
  71. package/tools/sweep_node_properties.py +271 -0
  72. package/tools/sweep_node_types.py +318 -0
  73. package/tools/sweep_properties.py +215 -0
  74. package/tools/sweep_style_properties.py +254 -0
  75. package/tools/theme_export.php +91 -0
  76. package/tools/theme_import.php +113 -0
  77. package/tools/verify_rwd.py +278 -0
@@ -0,0 +1,99 @@
1
+ property,group,factory,value_class,accepted_values,tokenable
2
+ display,,CSSPropertyFactory,,,
3
+ alignItems,,CSSPropertyFactory,,normal|start|center|end|stretch|flex-start|flex-end|self-start|self-end|baseline|first baseline|last baseline,
4
+ justifyItems,,CSSPropertyFactory,,normal|start|center|end|stretch|flex-start|flex-end|self-start|self-end|baseline|first baseline|last baseline,
5
+ alignContent,,CSSPropertyFactory,,normal|start|center|end|stretch|space-between|space-around|space-evenly|flex-start|flex-end|baseline,
6
+ justifyContent,,CSSPropertyFactory,,normal|start|center|end|stretch|space-between|space-around|space-evenly|flex-start|flex-end|left|right,
7
+ flexDirection,,CSSPropertyFactory,,row|row-reverse|column|column-reverse,
8
+ flexWrap,,CSSPropertyFactory,,nowrap|wrap|wrap-reverse,
9
+ columnGap,,CSSCollectionVariablePropertyFactory,,,yes
10
+ rowGap,,CSSCollectionVariablePropertyFactory,,,yes
11
+ gridAutoFlow,,CSSPropertyFactory,,row|row dense|column|column dense,
12
+ gridAutoColumns,,CSSCollectionVariablePropertyFactory,,,yes
13
+ gridAutoRows,,CSSCollectionVariablePropertyFactory,,,yes
14
+ gridTemplateColumns,,CSSGridTemplateStylePropertyFactory,,,
15
+ gridTemplateRows,,CSSGridTemplateStylePropertyFactory,,,
16
+ gridTemplateAreas,,CSSGridAreaPropertyFactory,,,
17
+ gridRowStart,gridChildPosition,CSSGrouppedPropertyFactory,,,
18
+ gridColumnStart,gridChildPosition,CSSGrouppedPropertyFactory,,,
19
+ gridRowEnd,gridChildPosition,CSSGrouppedPropertyFactory,,,
20
+ gridColumnEnd,gridChildPosition,CSSGrouppedPropertyFactory,,,
21
+ flexSizing,,CSSFlexSizingPropertyFactory,,,
22
+ flexBasis,,CSSPropertyFactory,,,
23
+ alignSelf,,CSSPropertyFactory,,auto|start|center|end|stretch|normal|flex-start|flex-end|self-start|self-end|baseline|first baseline|last baseline,
24
+ justifySelf,,CSSPropertyFactory,,auto|start|center|end|stretch|normal|flex-start|flex-end|self-start|self-end|baseline|first baseline|last baseline,
25
+ order,,CSSPropertyFactory,,,
26
+ listStylePosition,,CSSPropertyFactory,,inside|outside,
27
+ listStyleType,,CSSListStyleTypeStylePropertyFactory,,disc|circle|square|decimal|georgian|trad-chinese-informal|kannada|none,
28
+ fontFamily,,CSSFontFamilyPropertyFactory,,,
29
+ textDecorationLine,,CSSPropertyFactory,,none|underline|overline|line-through,
30
+ fontStyle,,CSSPropertyFactory,,normal|italic,
31
+ color,,CSSColorPropertyFactory,,,yes
32
+ fontSize,,CSSCollectionVariablePropertyFactory,,,yes
33
+ lineHeight,,CSSCollectionVariablePropertyFactory,,,yes
34
+ fontWeight,,CSSPropertyFactory,,100|200|300|400|500|600|700|800|900,
35
+ textAlign,,CSSPropertyFactory,,start|center|end|justify|left|right,
36
+ letterSpacing,,CSSCollectionVariablePropertyFactory,,,yes
37
+ wordSpacing,,CSSCollectionVariablePropertyFactory,,,yes
38
+ whiteSpace,,CSSPropertyFactory,,normal|pre-wrap|nowrap|pre,
39
+ textTransform,,CSSPropertyFactory,,none|lowercase|uppercase|capitalize,
40
+ textShadow,,CSSTextShadowStylePropertyFactory,,,
41
+ width,,CSSCollectionVariablePropertyFactory,,,yes
42
+ minWidth,,CSSCollectionVariablePropertyFactory,,,yes
43
+ maxWidth,,CSSCollectionVariablePropertyFactory,,,yes
44
+ height,,CSSCollectionVariablePropertyFactory,,,yes
45
+ minHeight,,CSSCollectionVariablePropertyFactory,,,yes
46
+ maxHeight,,CSSCollectionVariablePropertyFactory,,,yes
47
+ position,,CSSPropertyFactory,,static|relative|absolute|fixed|sticky,
48
+ zIndex,,CSSPropertyFactory,,,
49
+ top,,CSSCollectionVariablePropertyFactory,,,yes
50
+ right,,CSSCollectionVariablePropertyFactory,,,yes
51
+ bottom,,CSSCollectionVariablePropertyFactory,,,yes
52
+ left,,CSSCollectionVariablePropertyFactory,,,yes
53
+ marginTop,,CSSCollectionVariablePropertyFactory,,,yes
54
+ marginRight,,CSSCollectionVariablePropertyFactory,,,yes
55
+ marginBottom,,CSSCollectionVariablePropertyFactory,,,yes
56
+ marginLeft,,CSSCollectionVariablePropertyFactory,,,yes
57
+ paddingTop,,CSSCollectionVariablePropertyFactory,,,yes
58
+ paddingRight,,CSSCollectionVariablePropertyFactory,,,yes
59
+ paddingBottom,,CSSCollectionVariablePropertyFactory,,,yes
60
+ paddingLeft,,CSSCollectionVariablePropertyFactory,,,yes
61
+ borderRadius,,CSSBorderRadiusPropertyFactory,,,
62
+ borderTopWidth,borderStyle,CSSGrouppedPropertyFactory,CSSCollectionVariableProperty,,yes
63
+ borderTopStyle,borderStyle,CSSGrouppedPropertyFactory,,,
64
+ borderTopColor,borderStyle,CSSGrouppedPropertyFactory,CSSColorProperty,,
65
+ borderRightWidth,borderStyle,CSSGrouppedPropertyFactory,CSSCollectionVariableProperty,,yes
66
+ borderRightStyle,borderStyle,CSSGrouppedPropertyFactory,,,
67
+ borderRightColor,borderStyle,CSSGrouppedPropertyFactory,CSSColorProperty,,
68
+ borderBottomWidth,borderStyle,CSSGrouppedPropertyFactory,CSSCollectionVariableProperty,,yes
69
+ borderBottomStyle,borderStyle,CSSGrouppedPropertyFactory,,,
70
+ borderBottomColor,borderStyle,CSSGrouppedPropertyFactory,CSSColorProperty,,
71
+ borderLeftWidth,borderStyle,CSSGrouppedPropertyFactory,CSSCollectionVariableProperty,,yes
72
+ borderLeftStyle,borderStyle,CSSGrouppedPropertyFactory,,,
73
+ borderLeftColor,borderStyle,CSSGrouppedPropertyFactory,CSSColorProperty,,
74
+ outlineWidth,outlineStyle,CSSGrouppedPropertyFactory,CSSCollectionVariableProperty,,yes
75
+ outlineStyle,outlineStyle,CSSGrouppedPropertyFactory,,,
76
+ outlineColor,outlineStyle,CSSGrouppedPropertyFactory,CSSColorProperty,,
77
+ outlineOffset,outlineStyle,CSSGrouppedPropertyFactory,CSSCollectionVariableProperty,,yes
78
+ boxShadow,,CSSBoxShadowStylePropertyFactory,,,
79
+ opacity,,CSSPropertyFactory,,,
80
+ visibility,,CSSPropertyFactory,,visible|hidden,
81
+ overflow,,CSSPropertyFactory,,visible|hidden|clip|scroll|auto,
82
+ filter,,CSSFilterStylePropertyFactory,,,
83
+ backdropFilter,,CSSBackdropFilterPropertyFactory,,,
84
+ transform,,CSSTransformPropertyFactory,,,
85
+ translate,,CSSTranslateStylePropertyFactory,,,
86
+ rotate,,CSSRotateStylePropertyFactory,,,
87
+ transformOrigin,,CSSTransformOriginStylePropertyFactory,,,
88
+ transformStyle,,CSSPropertyFactory,,flat|preserve-3d,
89
+ transition,,CSSTransitionPropertyFactory,,,
90
+ mask,,CSSMaskStylePropertyFactory,,,
91
+ perspectiveOrigin,,CSSPerspectiveOriginStylePropertyFactory,,,
92
+ objectFitStyle,,CSSObjectFitStylePropertyFactory,,,
93
+ mixBlendMode,,CSSPropertyFactory,,normal|multiply|screen|overlay|darken|lighten|color-dodge|color-burn|hard-light|soft-light|difference|exclusion|hue|saturation|color|luminosity,
94
+ boxSizing,,CSSPropertyFactory,,border-box|content-box,
95
+ aspectRatio,,CSSPropertyFactory,,,
96
+ backgroundColor,,CSSColorPropertyFactory,,,yes
97
+ backgroundStyle,,CSSBackgroundStylePropertyFactory,,,
98
+ cursor,,CSSPropertyFactory,,auto|default|none|context-menu|help|pointer|progress|wait|cell|crosshair|text|vertical-text|alias|copy|move|no-drop|not-allowed|grab|grabbing|e-resize|n-resize|ne-resize|nw-resize|s-resize|se-resize|sw-resize|w-resize|ew-resize|ns-resize|nesw-resize|nwse-resize|col-resize|row-resize|all-scroll|zoom-in|zoom-out|inherit|initial|revert|revert-layer|unset,
99
+ customStyles,,CSSCustomStylePropertyFactory,,,
@@ -0,0 +1,54 @@
1
+ state,selector_template,order,scope,declared_in
2
+ &,&,0,global,Mosaic/Builder/Style/StatesMeta.php
3
+ focus,&:FOCUS,750,global,Mosaic/Builder/Style/StatesMeta.php
4
+ focus-visible,&:FOCUS-VISIBLE,760,global,Mosaic/Builder/Style/StatesMeta.php
5
+ hover,&:HOVER,100,global,Mosaic/Builder/Style/StatesMeta.php
6
+ hover-on-link,":where(a[href]:not([disabled]),button:not([disabled])):HOVER &",200,global,Mosaic/Builder/Style/StatesMeta.php
7
+ hover-on-tab,:where(.M_EL_Tab:not(.M_EL_Tab--active)):HOVER &,200,global,Mosaic/NodeTypes/Pro/Tabs/TabsMenu/Tab/TabElementTypeFactory.php
8
+ hover-tab,&:where(.M_EL_Tab:not(.M_EL_Tab--active)):HOVER,100,global,Mosaic/NodeTypes/Pro/Tabs/TabsMenu/Tab/TabElementTypeFactory.php
9
+ hover-when-link,"&:where([tabindex]:not([tabindex=""-1""]),a[href]:not([disabled]),button:not([disabled])):HOVER",100,global,Mosaic/Builder/Style/StatesMeta.php
10
+ ____loop_pagination_number--active,&.M_EL_LoopPaginationNumber--active,500,node-type,Mosaic/NodeTypes/Loop/LoopPagination/Numbers/Number/LoopPaginationNumberElementTypeFactory.php
11
+ ____loop_pagination_number_ellipsis,&.M_EL_LoopPaginationNumber_ellipsis,0,node-type,Mosaic/NodeTypes/Loop/LoopPagination/Numbers/Number/LoopPaginationNumberElementTypeFactory.php
12
+ ___arrow_hidden,&:where(.M_EL_SliderArrow--hidden),800,node-type,Mosaic/NodeTypes/Pro/Slider/SliderArrow/SliderArrowElementTypeFactoryAbstract.php
13
+ ___checkbox-input--checked,&:checked,500,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/Checkbox/CheckboxInput/CheckboxInputElementTypeFactory.php
14
+ ___checkbox-input--checkmark,&:checked::before,500,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/Checkbox/CheckboxInput/CheckboxInputElementTypeFactory.php
15
+ ___choice--checked,&:has(:where(input):checked),500,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/Choice/ChoiceElementTypeFactory.php
16
+ ___choice--checked-within,.M_EL_Choice:where(:has(input:checked)) &,500,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/Choice/ChoiceElementTypeFactory.php
17
+ ___choice--focus-visible,&:has(:where(input):focus-visible),760,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/Choice/ChoiceElementTypeFactory.php
18
+ ___choice-field--invalid,&:has(:user-invalid),700,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/ChoiceField/ChoiceFieldElementTypeFactory.php
19
+ ___choice-field--invalid-within,.M_EL_ChoiceField:where(:has(:user-invalid)) &,700,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/ChoiceField/ChoiceFieldElementTypeFactory.php
20
+ ___dropdown--opening,.M_EL_Dropdown:where(.dropdown--opening) &,600,node-type,Mosaic/NodeTypes/Menu/Dropdown/DropdownElementTypeFactoryAbstract.php
21
+ ___dropdown-toggle--current,&.M_EL_DropdownToggle--current,500,node-type,Mosaic/NodeTypes/Menu/Dropdown/DropdownToggle/DropdownToggleElementTypeFactory.php
22
+ ___dropdown-toggle--current-within,".M_EL_Dropdown:where(:has(.M_EL_MenuLink--current,.M_EL_DropdownToggle--current)) > &",500,node-type,Mosaic/NodeTypes/Menu/Dropdown/DropdownToggle/DropdownToggleElementTypeFactory.php
23
+ ___field--focus-visible,"&:has(:where(input, textarea, select):focus-visible)",760,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/Field/FieldElementTypeFactory.php
24
+ ___field--invalid,&:has(:user-invalid),700,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/Field/FieldElementTypeFactory.php
25
+ ___field--invalid-focus-visible,&:has(:user-invalid:focus-visible),770,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/Field/FieldElementTypeFactory.php
26
+ ___field--invalid-within,.M_EL_Field:where(:has(:user-invalid)) &,700,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/Field/FieldElementTypeFactory.php
27
+ ___field-set--invalid,&:has(:user-invalid),700,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/FieldSet/FieldSetElementTypeFactory.php
28
+ ___fileupload-input--selector-button,&::file-selector-button,0,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/FileUpload/FileUploadElementTypeFactory.php
29
+ ___fileupload-input--selector-button-hover,&::file-selector-button:hover,100,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/FileUpload/FileUploadElementTypeFactory.php
30
+ ___form--error,"&[data-form-state=""error""]",700,node-type,Mosaic/NodeTypes/Pro/Form/FormWrapperElementTypeFactory.php
31
+ ___form--invalid-within,.M_EL_FormWrapper:where(:has(:user-invalid)) &,700,node-type,Mosaic/NodeTypes/Pro/Form/FormWrapperElementTypeFactory.php
32
+ ___input--placeholder,&.M_EL_InputText::placeholder,0,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/InputText/InputTextElementTypeFactory.php
33
+ ___loop_element_no_result,&.M_EL_Loop--no-result,600,node-type,Mosaic/NodeTypes/Loop/LoopElementTypeFactory.php
34
+ ___loop_pagination_button--disabled,&.M_EL_LoopPaginationButton--disabled,800,node-type,Mosaic/NodeTypes/Loop/LoopPagination/Button/ButtonNext/LoopPaginationButtonNextElementTypeFactory.php
35
+ ___menu-link--current,&.M_EL_MenuLink--current,500,node-type,Mosaic/NodeTypes/Menu/MenuLink/MenuLinkElementTypeFactory.php
36
+ ___navbar--dropdown-mode,"&:where(.M_EL_Navbar.dropdown-mode,.M_EL_Navbar.dropdown-mode &)",600,node-type,Mosaic/NodeTypes/Navbar/NavbarElementTypeFactory.php
37
+ ___navbar--opened,.dropdown-mode:where(.M_EL_Navbar.dropdown--opened) &,600,node-type,Mosaic/NodeTypes/Navbar/NavbarElementTypeFactory.php
38
+ ___navbar--opening,.dropdown-mode:where(.M_EL_Navbar.dropdown--opening) &,600,node-type,Mosaic/NodeTypes/Navbar/NavbarElementTypeFactory.php
39
+ ___nested_dropdown_mode,"&:where(.dropdown-mode .M_EL_Navigation .M_EL_Dropdown &, .M_EL_Dropdown .M_EL_Dropdown &):not(x)",600,node-type,Mosaic/NodeTypes/Menu/Dropdown/DropdownElementTypeFactoryAbstract.php
40
+ ___radio-input--checked,&:checked,500,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/Radio/RadioInput/RadioInputElementTypeFactory.php
41
+ ___radio-input--checkmark,&:checked::before,500,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/Radio/RadioInput/RadioInputElementTypeFactory.php
42
+ ___select-input-option,"&.M_EL_Select:where(:has(option:not(:disabled):checked)), &.M_EL_Select :where(option)",500,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/Select/SelectElementTypeFactory.php
43
+ ___select-input-option--disabled,"&.M_EL_Select:where(:has(option:disabled:checked)), &.M_EL_Select :where(option:disabled)",800,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/Select/SelectElementTypeFactory.php
44
+ ___slide--active,.M_EL_SliderSlide--active > &,500,node-type,Mosaic/NodeTypes/Pro/Slider/SliderSlides/SliderSlide/SliderSlideElementTypeFactory.php
45
+ ___slider_navigation_bullet--active,&.M_EL_SliderNavigationBullet--active,500,node-type,Mosaic/NodeTypes/Pro/Slider/SliderNavigation/SliderNavigationBullet/SliderNavigationBulletElementTypeFactory.php
46
+ ___slider_navigation_bullet--hover,&:not(.M_EL_SliderNavigationBullet--active):HOVER,100,node-type,Mosaic/NodeTypes/Pro/Slider/SliderNavigation/SliderNavigationBullet/SliderNavigationBulletElementTypeFactory.php
47
+ ___step--active,&.M_EL_Step--active,500,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/MultiSteps/Steps/Step/StepElementTypeFactory.php
48
+ ___step--active___descendants,.M_EL_Step--active &,500,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/MultiSteps/Steps/Step/StepElementTypeFactory.php
49
+ ___step--completed,&.M_EL_Step--completed,500,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/MultiSteps/Steps/Step/StepElementTypeFactory.php
50
+ ___step--completed___descendants,.M_EL_Step--completed &,500,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/MultiSteps/Steps/Step/StepElementTypeFactory.php
51
+ ___submit-button--busy,"&[aria-busy=""true""]",800,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/SubmitButton/SubmitButtonElementTypeFactory.php
52
+ ___tab--active,&.M_EL_Tab--active,500,node-type,Mosaic/NodeTypes/Pro/Tabs/TabsMenu/Tab/TabElementTypeFactory.php
53
+ ___tab--active___descendants,.M_EL_Tab--active &,500,node-type,Mosaic/NodeTypes/Pro/Tabs/TabsMenu/Tab/TabElementTypeFactory.php
54
+ ___textarea-input--placeholder,&.M_EL_TextArea::placeholder,0,node-type,Mosaic/NodeTypes/Pro/Form/Form/MElements/TextArea/TextAreaElementTypeFactory.php
@@ -0,0 +1,23 @@
1
+ property,kind,shape,compiles_to,status
2
+ borderRadius,object,"{""type"":""all"",""allOptions"":{""borderRadiusValue"":""18px""}}",border-radius:18px,OK
3
+ borderStyle,object,"{""borderTopWidth"":""5px"",""borderTopStyle"":""solid"",""borderTopColor"":""rgb(..)"", ...12 keys}",border-top-width:5px; ...,OK
4
+ outlineStyle,object,"{""outlineWidth"":""3px"",""outlineStyle"":""dotted"",""outlineColor"":""rgb(..)"",""outlineOffset"":""4px""}",outline-width:3px;outline-style:dotted;...,OK
5
+ boxShadow,array,"[{""x"":""8px"",""y"":""8px"",""blur"":""0px"",""spread"":""0px"",""color"":""rgb(..)"",""type"":""outside"",""uuid"":""<uuid>""}]",box-shadow:rgb(..) 8px 8px 0px 0px,"OK - type is ""outside""/""inside"", NOT outset/inset"
6
+ textShadow,array,"[{""x"":""0px"",""y"":""2px"",""blur"":""8px"",""color"":""rgb(..)"",""uuid"":""<uuid>""}]",text-shadow:rgb(..) 0px 2px 8px,OK
7
+ transition,array,"[{""transitionProperty"":""all"",""transitionDuration"":""350ms"",""transitionDelay"":""0ms"",""transitionTimingFunction"":""ease"",""uuid"":""<uuid>""}]",transition-property:all;transition-duration:350ms;...,OK - easing maps to var(--mosaic-easing-<name>)
8
+ transform,array,"[{""type"":""translateY"",""translateYOptions"":{""value"":""-8px""},""uuid"":""<uuid>""}]",transform:translateY(-8px),"OK - types: translateX/Y/Z, rotateX/Y/Z, skewX/Y, scale, scaleX/Y/Z"
9
+ transform (scale),array,"[{""type"":""scale"",""scaleOptions"":{""value"":""1.05""},""uuid"":""<uuid>""}]",transform:scale(1.05),"OK - key is value, not x/y"
10
+ translate,object,"{""x"":""0px"",""y"":""-6px"",""z"":""0px""}",--mosaic-translate-*; translate:0px -6px 0px,OK
11
+ rotate,object,"{""x"":""0deg"",""y"":""0deg"",""z"":""4deg""}",--mosaic-rotate-*; rotate:0 0 1 4deg,OK
12
+ transformOrigin,object,"{""x"":""0%"",""y"":""0%"",""z"":""0px""}",transform-origin:0% 0% 0px,OK
13
+ perspectiveOrigin,object,"{""x"":""50%"",""y"":""50%""}",perspective-origin:50% 50%,OK
14
+ filter,array,"[{""type"":""blur"",""blurOptions"":{""value"":""5px""},""uuid"":""<uuid>""}]",filter:blur(5px),OK - also brightness/contrast/... each with <type>Options
15
+ backdropFilter,array,"[{""type"":""blur"",""blurOptions"":{""value"":""14px""},""uuid"":""<uuid>""}]",backdrop-filter:blur(14px) + -webkit- prefix,OK
16
+ gridTemplateColumns,array,"[{""type"":""default"",""defaultOptions"":{""size"":""1fr""},""uuid"":""<uuid>""}, ...one per column]",grid-template-columns:1fr 1fr 2fr,OK
17
+ gridTemplateColumns (autofit),array,"[{""type"":""default"",""defaultOptions"":{""size"":""240px"",""autofit"":""1""},""uuid"":""<uuid>""}]","grid-template-columns:repeat(auto-fit, 240px)",OK - autofit is rejected with an fr size
18
+ gridChildPosition,object,"{""gridRowStart"":""1"",""gridColumnStart"":""1"",""gridRowEnd"":""2"",""gridColumnEnd"":""3""}",grid-row-start:1;grid-column-start:1;...,OK
19
+ flexSizing,object,"{""type"":""grow"",""growOptions"":{}}",flex-grow:1;flex-shrink:0,OK
20
+ objectFitStyle,object,"{""objectFit"":""cover"",""objectPositionX"":""50%"",""objectPositionY"":""50%""}",object-fit:cover;object-position:50%,OK
21
+ mask,array,"[{""type"":""gradient"",""gradientOptions"":{""subType"":""linear"",""linearOptions"":{""angle"":""180deg""},""dots"":[...]},""uuid"":""<uuid>""}]",mask-image:linear-gradient(...),"PARTIAL - compiles, but only the last dot survives"
22
+ backgroundStyle,array,"[{""type"":""overlay"",""overlayOptions"":{""color"":""rgba(..)""},""uuid"":""<uuid>""}]","(accepted, emits background-image:none)",UNRESOLVED - use customStyles
23
+ customStyles,string,"""outline: 2px dashed rgb(7,8,9);""",emitted verbatim into the rule,OK - the escape hatch; bypasses the collection-variable layer
@@ -0,0 +1,99 @@
1
+ property,group,css_property,sent,compiled,status
2
+ display,,display,,,SKIPPED
3
+ alignItems,,align-items,"""baseline""",baseline,COMPILED
4
+ justifyItems,,justify-items,"""baseline""",baseline,COMPILED
5
+ alignContent,,align-content,"""baseline""",baseline,COMPILED
6
+ justifyContent,,justify-content,"""right""",right,COMPILED
7
+ flexDirection,,flex-direction,"""column-reverse""",column-reverse,COMPILED
8
+ flexWrap,,flex-wrap,"""wrap-reverse""",wrap-reverse,COMPILED
9
+ columnGap,,column-gap,"""37px""",37px,COMPILED
10
+ rowGap,,row-gap,"""37px""",37px,COMPILED
11
+ gridAutoFlow,,grid-auto-flow,"""column""",column,COMPILED
12
+ gridAutoColumns,,grid-auto-columns,,,SKIPPED
13
+ gridAutoRows,,grid-auto-rows,,,SKIPPED
14
+ gridTemplateColumns,,grid-template-columns,"[{""type"": ""default"", ""defaultOptions"": {""size"": ""37px""}}]",none,COMPILED
15
+ gridTemplateRows,,grid-template-rows,"[{""type"": ""default"", ""defaultOptions"": {""size"": ""37px""}}]",none,COMPILED
16
+ gridTemplateAreas,,grid-template-areas,,,SKIPPED
17
+ gridRowStart,gridChildPosition,grid-row-start,"""7""",,ABSENT
18
+ gridColumnStart,gridChildPosition,grid-column-start,"""7""",,ABSENT
19
+ gridRowEnd,gridChildPosition,grid-row-end,"""7""",,ABSENT
20
+ gridColumnEnd,gridChildPosition,grid-column-end,"""7""",,ABSENT
21
+ flexSizing,,flex-sizing,,,SKIPPED
22
+ flexBasis,,flex-basis,"""37px""",37px,COMPILED
23
+ alignSelf,,align-self,"""baseline""",baseline,COMPILED
24
+ justifySelf,,justify-self,"""baseline""",baseline,COMPILED
25
+ order,,order,"""7""",7,COMPILED
26
+ listStylePosition,,list-style-position,"""outside""",outside,COMPILED
27
+ listStyleType,,list-style-type,"""none""",none,COMPILED
28
+ fontFamily,,font-family,,,SKIPPED
29
+ textDecorationLine,,text-decoration-line,"""line-through""",line-through,COMPILED
30
+ fontStyle,,font-style,"""italic""",italic,COMPILED
31
+ color,,color,"""rgb(9, 99, 199)""","rgb(9, 99, 199)",COMPILED
32
+ fontSize,,font-size,"""37px""",37px,COMPILED
33
+ lineHeight,,line-height,"""7""",7,COMPILED
34
+ fontWeight,,font-weight,"""900""",900,COMPILED
35
+ textAlign,,text-align,"""right""",right,COMPILED
36
+ letterSpacing,,letter-spacing,"""37px""",37px,COMPILED
37
+ wordSpacing,,word-spacing,"""37px""",37px,COMPILED
38
+ whiteSpace,,white-space,"""pre""",pre,COMPILED
39
+ textTransform,,text-transform,"""capitalize""",capitalize,COMPILED
40
+ textShadow,,text-shadow,,,SKIPPED
41
+ width,,width,"""37px""",37px,COMPILED
42
+ minWidth,,min-width,"""37px""",37px,COMPILED
43
+ maxWidth,,max-width,"""37px""",37px,COMPILED
44
+ height,,height,"""37px""",37px,COMPILED
45
+ minHeight,,min-height,"""37px""",37px,COMPILED
46
+ maxHeight,,max-height,"""37px""",37px,COMPILED
47
+ position,,position,"""sticky""",sticky,COMPILED
48
+ zIndex,,z-index,"""7""",7,COMPILED
49
+ top,,top,"""37px""",37px,COMPILED
50
+ right,,right,"""37px""",37px,COMPILED
51
+ bottom,,bottom,"""37px""",37px,COMPILED
52
+ left,,left,"""37px""",37px,COMPILED
53
+ marginTop,,margin-top,"""37px""",37px,COMPILED
54
+ marginRight,,margin-right,"""37px""",37px,COMPILED
55
+ marginBottom,,margin-bottom,"""37px""",37px,COMPILED
56
+ marginLeft,,margin-left,"""37px""",37px,COMPILED
57
+ paddingTop,,padding-top,"""37px""",37px,COMPILED
58
+ paddingRight,,padding-right,"""37px""",37px,COMPILED
59
+ paddingBottom,,padding-bottom,"""37px""",37px,COMPILED
60
+ paddingLeft,,padding-left,"""37px""",37px,COMPILED
61
+ borderRadius,,border-radius,"{""type"": ""all"", ""allOptions"": {""borderRadiusValue"": ""37px""}}",37px,COMPILED
62
+ borderTopWidth,borderStyle,border-top-width,"""37px""",,ABSENT
63
+ borderTopStyle,borderStyle,border-top-style,"""37px""",,ABSENT
64
+ borderTopColor,borderStyle,border-top-color,"""rgb(9, 99, 199)""",,NO_ELEMENT
65
+ borderRightWidth,borderStyle,border-right-width,"""37px""",,ABSENT
66
+ borderRightStyle,borderStyle,border-right-style,"""37px""",,ABSENT
67
+ borderRightColor,borderStyle,border-right-color,"""rgb(9, 99, 199)""",,ABSENT
68
+ borderBottomWidth,borderStyle,border-bottom-width,"""37px""",,ABSENT
69
+ borderBottomStyle,borderStyle,border-bottom-style,"""37px""",,ABSENT
70
+ borderBottomColor,borderStyle,border-bottom-color,"""rgb(9, 99, 199)""",,ABSENT
71
+ borderLeftWidth,borderStyle,border-left-width,"""37px""",,ABSENT
72
+ borderLeftStyle,borderStyle,border-left-style,"""37px""",,ABSENT
73
+ borderLeftColor,borderStyle,border-left-color,"""rgb(9, 99, 199)""",,ABSENT
74
+ outlineWidth,outlineStyle,outline-width,"""37px""",,ABSENT
75
+ outlineStyle,outlineStyle,outline-style,,,SKIPPED
76
+ outlineColor,outlineStyle,outline-color,"""rgb(9, 99, 199)""",,ABSENT
77
+ outlineOffset,outlineStyle,outline-offset,"""37px""",,ABSENT
78
+ boxShadow,,box-shadow,,,SKIPPED
79
+ opacity,,opacity,"""0.37""",0.37,COMPILED
80
+ visibility,,visibility,"""hidden""",hidden,COMPILED
81
+ overflow,,overflow,"""auto""",auto,COMPILED
82
+ filter,,filter,,,SKIPPED
83
+ backdropFilter,,backdrop-filter,,,SKIPPED
84
+ transform,,transform,,,SKIPPED
85
+ translate,,translate,,,SKIPPED
86
+ rotate,,rotate,,,SKIPPED
87
+ transformOrigin,,transform-origin,,,SKIPPED
88
+ transformStyle,,transform-style,"""preserve-3d""",preserve-3d,COMPILED
89
+ transition,,transition,,,SKIPPED
90
+ mask,,mask,,,SKIPPED
91
+ perspectiveOrigin,,perspective-origin,,,SKIPPED
92
+ objectFitStyle,,object-fit,"{""objectFit"": ""cover"", ""objectPositionX"": ""37%"", ""objectPositionY"": ""37%""}",cover,COMPILED
93
+ mixBlendMode,,mix-blend-mode,"""luminosity""",luminosity,COMPILED
94
+ boxSizing,,box-sizing,"""content-box""",content-box,COMPILED
95
+ aspectRatio,,aspect-ratio,,,SKIPPED
96
+ backgroundColor,,background-color,"""rgb(9, 99, 199)""","rgb(9, 99, 199)",COMPILED
97
+ backgroundStyle,,background-image,,,SKIPPED
98
+ cursor,,cursor,"""unset""",unset,COMPILED
99
+ customStyles,,,,,SKIPPED
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "mosaic-headless",
3
+ "version": "1.2.0",
4
+ "description": "AI-agent skill: build Mosaic Pro (Nextend) WordPress sites by writing the underlying data model directly - 23 custom tables, no visual editor, no DOM. Every node type, style property and node property swept against a live install and asserted on the delivered HTML and compiled CSS. Installs into Claude Code, Cursor, Codex CLI, Gemini CLI, Copilot, Continue, Windsurf and Claude.ai.",
5
+ "keywords": [
6
+ "wordpress",
7
+ "mosaic",
8
+ "mosaic-pro",
9
+ "nextend",
10
+ "page-builder",
11
+ "claude-code",
12
+ "agent-skill",
13
+ "ai-agent",
14
+ "headless",
15
+ "woocommerce",
16
+ "wp-cli"
17
+ ],
18
+ "homepage": "https://github.com/Moksa1123/mosaic-headless#readme",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/Moksa1123/mosaic-headless.git"
22
+ },
23
+ "bugs": {
24
+ "url": "https://github.com/Moksa1123/mosaic-headless/issues"
25
+ },
26
+ "license": "MIT",
27
+ "author": "moksa (https://moksaweb.com)",
28
+ "type": "module",
29
+ "bin": {
30
+ "mosaic-headless": "bin/install.mjs"
31
+ },
32
+ "files": [
33
+ "bin/",
34
+ "assets/",
35
+ "data/*.csv",
36
+ "references/",
37
+ "sites/_moksa.py",
38
+ "sites/moksa.json",
39
+ "tools/*.py",
40
+ "tools/*.php",
41
+ "SKILL.md",
42
+ "README.md",
43
+ "README.zh-TW.md",
44
+ "README.zh-CN.md",
45
+ "README.ja.md",
46
+ "LICENSE"
47
+ ],
48
+ "engines": {
49
+ "node": ">=18"
50
+ },
51
+ "scripts": {
52
+ "install-skill": "node bin/install.mjs",
53
+ "check": "node bin/check-release.mjs",
54
+ "preversion": "npm run check",
55
+ "version": "node bin/sync-version.mjs && git add SKILL.md assets/templates/platforms",
56
+ "postversion": "git push && git push --tags",
57
+ "prepublishOnly": "npm run check"
58
+ }
59
+ }
@@ -0,0 +1,95 @@
1
+ # The Mosaic data model
2
+
3
+ ## Where a page lives
4
+
5
+ Nowhere you would guess from Elementor or Gutenberg. Mosaic stores **nothing** of a
6
+ page's structure in `wp_posts` or `wp_postmeta`. It owns **23 of its own tables**,
7
+ all prefixed `wp_mosaic_`, and the WordPress post is only one of several things a
8
+ Mosaic *template* can be assigned to.
9
+
10
+ Measured on a real install (`data/db-columns.csv`, 23 tables / 206 columns):
11
+
12
+ | table | holds |
13
+ |---|---|
14
+ | `mosaic_themes` | the top-level container. Everything else is scoped to a `themeID`. |
15
+ | `mosaic_masters` | master layouts (the outermost shell a template renders into) |
16
+ | `mosaic_templates` | a template + its `conditions` blob and `path`/`assign` mode |
17
+ | `mosaic_template_assigns` | which template serves which `type`/`typeIdentifier` |
18
+ | `mosaic_nodes` | **the element tree** — one row per element, on every document |
19
+ | `mosaic_components`, `mosaic_component_documents`, `mosaic_component_categories` | reusable components and their category tree |
20
+ | `mosaic_styleguides` | style guide documents |
21
+ | `mosaic_element_classes`, `mosaic_sub_classes` | the built-in class system (151 classes, see `data/element-classes.csv`) |
22
+ | `mosaic_utility_classes`, `mosaic_utility_sub_classes` | user-defined utility classes |
23
+ | `mosaic_collections`, `mosaic_collection_modes`, `mosaic_collection_skins`, `mosaic_collection_groups`, `mosaic_collection_variables` | the design-token system (a collection has modes and skins; variables resolve per mode) |
24
+ | `mosaic_breakpoints` | responsive breakpoints, per theme — not global |
25
+ | `mosaic_settings` | theme-scoped settings |
26
+ | `mosaic_submissions`, `mosaic_submission_actions` | form submissions (Pro) |
27
+ | `mosaic_locks` | editing locks; the only table created at plugin activation |
28
+
29
+ `mosaic_locks` appearing alone is the signature of a **half-installed** Mosaic: the
30
+ plugin's network-level install ran, but the site-level install (which creates the
31
+ other 22 tables) has not. It is triggered by an admin loading
32
+ `/wp-admin/admin.php?page=mosaic`, not by activation.
33
+
34
+ ## The node row
35
+
36
+ `mosaic_nodes` is the whole element tree, flattened:
37
+
38
+ ```
39
+ themeID varchar(36) scope
40
+ documentType varchar(36) which kind of document this node belongs to
41
+ documentID varchar(36) which document
42
+ ID varchar(36) node uuid
43
+ parentType varchar(36) parent's kind
44
+ parentID varchar(36) parent node uuid -> the tree lives here
45
+ ordering varchar(400) fractional-index string, NOT an integer
46
+ status varchar(36) 'publish' etc.
47
+ type varchar(128) the node type slug -> data/node-types.csv
48
+ data longtext the node's own properties, JSON
49
+ revision varchar(36) optimistic-lock token
50
+ version varchar(128)
51
+ ```
52
+
53
+ Two things bite here:
54
+
55
+ **`ordering` is a string, not a number.** It is a fractional index (`a0`, `a1`,
56
+ `a0V`…), so siblings sort lexicographically and a node can be inserted between two
57
+ others without renumbering. Sorting it numerically produces a scrambled page.
58
+
59
+ **The tree is by `parentID`, not by nesting.** There is no nested JSON blob to edit
60
+ like `_elementor_data`. Reparenting is a single-column update; moving a subtree
61
+ does not touch the subtree's rows.
62
+
63
+ ## Node types and properties
64
+
65
+ 122 node types are registered (`data/node-types.csv`), **48 of them Pro-only** —
66
+ the split is structural, not a flag: Pro types live under `Mosaic/NodeTypes/Pro/`
67
+ and cover the whole form system, slider, tabs and code element. If a type's
68
+ `edition` column says `pro`, a Free install has no factory for it and the node
69
+ falls back to the `__unknown` type rather than erroring.
70
+
71
+ Each type declares its own data properties (`data/node-properties.csv`, 181
72
+ properties across 49 classes). Properties are declared by `createDataSimple` (175),
73
+ `createDataArray` (3) and `createDataGroup` (3), each with a validator chain. **174
74
+ of 181 properties set `supportsInherit: true`** — inheritance is the norm in this
75
+ model, not the exception, which is why a property being absent from a node's `data`
76
+ is meaningful rather than merely missing.
77
+
78
+ The validator chain in the `validators` column is what actually gates a write.
79
+ `ValidatorAcceptedValues` means an enum (the accepted list is in the source file
80
+ named by the `file` column); `ValidateAllowUndefined` means the property may be
81
+ omitted; `ValidatorDynamicCodeObject` means the property accepts a dynamic-code
82
+ object instead of a literal — that is Mosaic's dynamic-tag equivalent.
83
+
84
+ ## Styling
85
+
86
+ Mosaic does not attach CSS to a node the way Elementor attaches controls to a
87
+ widget. Styling goes through the **element class** system: 151 built-in classes
88
+ (`data/element-classes.csv`), each with its own CSS selectors, arranged in a parent
89
+ tree, some marked `metaIsGroup` (organisational) and some `metaIsEditable`. A node
90
+ points at a default element class (`default_element_class` in `node-types.csv`) and
91
+ takes variations from there.
92
+
93
+ That is why the same visual change can be made in two very different places, and
94
+ why writing a style onto a node directly is usually the wrong move: the class is
95
+ the unit of reuse, and the collection/variable tables are the token layer beneath it.
@@ -0,0 +1,118 @@
1
+ # The design-system layer: element classes and collection variables
2
+
3
+ Everything in `references/styling.md` is about styling **one node**. That is the lowest
4
+ layer and the wrong place to build a site. Mosaic has two layers above it, and both
5
+ were measured on a live install.
6
+
7
+ ## Element classes: style every element of a kind, once
8
+
9
+ The 151 rows in `data/element-classes.csv` are `elementClassMeta` records — Mosaic's
10
+ built-in taxonomy of what an element *is* (Heading 2, Button, Section, Div, Body …),
11
+ each carrying the CSS selectors that identify it.
12
+
13
+ You do not create element classes. You **commit a style for one that already exists**,
14
+ using its meta ID as the record ID:
15
+
16
+ ```json
17
+ POST …/masterDocumentInstance/<masterID>/commit
18
+ {
19
+ "elementClass": [{
20
+ "newRevisionRecord": {
21
+ "ID": "d1642e3d-12cc-0379-ac2a-33f5292aa0dd", // the Heading 2 meta ID
22
+ "parentType": "", "parentID": "", "ordering": "a0",
23
+ "status": "publish", "revision": "", "version": "",
24
+ "data": {"states": {"&": {"_": {"color": "rgb(3,33,133)", "fontSize": "47px"}}}}
25
+ },
26
+ "originalRevisionRecord": null
27
+ }]
28
+ }
29
+ ```
30
+
31
+ The `data.states` structure is **identical to a node's `style.states`** — same states,
32
+ same breakpoints, same property names and value shapes.
33
+
34
+ What comes out is a global rule built from that meta's own selectors:
35
+
36
+ ```css
37
+ h2,.M_EL_Text__Heading2{color:rgb(3, 33, 133);font-size:47px;letter-spacing:-1px}
38
+ ```
39
+
40
+ One row restyles every `h2` on the site. This is the theme layer, and it is where
41
+ typography, spacing rhythm and component defaults belong.
42
+
43
+ Two things learned the hard way:
44
+
45
+ - **Only element-class metas are valid IDs.** Committing an `elementClass` with a
46
+ fresh UUID is accepted with HTTP 200 and then silently dropped — the response's
47
+ `syncResponseEnvelopes` simply does not mention it. Check the response for a
48
+ `create elementClass` entry; its absence is the only signal.
49
+ - Look up the meta ID in `data/element-classes.csv` by `name`. Several rows share a
50
+ name (`Button` appears four times) because sub-components have their own metas — the
51
+ `selectors` and `parent` columns tell them apart.
52
+
53
+ ## Collection variables: the design tokens
54
+
55
+ A collection variable compiles to a real CSS custom property on `:root`, and any
56
+ token-referencable style property can point at it.
57
+
58
+ The theme's healed default gives you one collection, one mode and one skin. A variable
59
+ hangs off the collection, and its value is stored per **skin → mode**:
60
+
61
+ ```json
62
+ {
63
+ "ID": "<variable uuid>",
64
+ "parentType": "collection", "parentID": "<collectionID>",
65
+ "ordering": "a0", "status": "publish", "revision": "", "version": "",
66
+ "data": {
67
+ "name": "Brand",
68
+ "type": "color",
69
+ "customProperty": "--brand",
70
+ "skinsData": { "<skinID>": { "<modeID>": { "value": "rgb(9,99,199)" } } }
71
+ }
72
+ }
73
+ ```
74
+
75
+ Reference it from any of the 34 token-referencable properties in
76
+ `data/style-properties.csv` with a one-key object:
77
+
78
+ ```json
79
+ "backgroundColor": {"var": "<variable uuid>"}
80
+ ```
81
+
82
+ Measured output:
83
+
84
+ ```css
85
+ :root{--brand: rgb(9, 99, 199)}
86
+ .M_EL3{padding-top:31px;background-color:var(--brand)}
87
+ ```
88
+
89
+ Details that cost time to find:
90
+
91
+ - **`skinsData[skinID]` is keyed by mode ID directly.** There is no `modesData`
92
+ wrapper — `CollectionVariableSkinDataDataSub::getSubData($modeID)` goes straight to
93
+ the mode, whose only property is `value`.
94
+ - **`customProperty` is emitted verbatim**, so it must include the leading `--`.
95
+ Writing `"brand"` produces `background-color:var(brand)` and a `:root{brand: …}`
96
+ declaration, neither of which is valid CSS.
97
+ - **A wrong `skinsData` shape does not fail.** The variable is created, `:root` gets
98
+ the declaration, and the value is the sub-factory's default (`#FFF` for colours).
99
+ If your token renders white, the value never arrived.
100
+ - Variable types are `color`, `imageGradient`, `lengthPercentage`,
101
+ `numberLengthPercentage`, `boxShadow`, `textShadow`, `fontFamily`
102
+ (`CollectionTypesConst::COLLECTION_VARIABLE_TYPES`).
103
+ - Deleting probe variables needs an explicit `status: "delete"` commit on the
104
+ `collectionVariable` manager — clearing nodes does not remove them, and orphans
105
+ accumulate as duplicate `:root` declarations.
106
+
107
+ ## How to actually build a theme
108
+
109
+ 1. Define collection variables for the palette, the type scale and the spacing scale.
110
+ 2. Commit element-class styles for the structural metas — Body, Text and its heading
111
+ children, Button, Section — referencing those variables rather than literals.
112
+ 3. Only then write per-node `style` for the things that genuinely differ.
113
+
114
+ The nine probe pages built while verifying this skill deliberately do **not** do
115
+ this (they are gitignored - they were scaffolding, not a deliverable) — they set
116
+ everything
117
+ per node, because their job was to exercise the style compiler across eight visual
118
+ languages, not to model a maintainable theme. A real site inverts that ratio.