BrandTheme values and packaged variants.
Theme fields
Theme a widget
Theme a subtree
Precedence
Four layers decide what a component actually renders, each able to override the one before it:- The SDK’s
@themedefaults — the platform baseline for every token. - The variant’s token block —
[data-fanfare-variant="…"], where each packaged variant sets its own colours, fonts and component tokens. - Your theme — the fields a
BrandThemesets, emitted as CSS custom properties on the widget’s.fanfare-themedelement. - Your own CSS — rules you write against
.fanfare-themedor anything inside it.
primary under the retro variant gives you your primary and retro’s everything else. It is also why the Fanfare admin saves only the fields a merchant actually changed — an untouched field is stored as no value at all, so it falls through to the variant.
One cascade detail is worth knowing before writing CSS against a themed widget. Layers 1 and 2 are ordinary stylesheet rules, so your own stylesheet can override them given enough specificity or a later load order — that is how overriding a token such as --ff-widget-max-width on .fanfare-themed works. Layer 3 is different in kind: theme fields are emitted as inline custom properties, and inline declarations outrank stylesheet rules however specific. To change a field your theme already sets, change the theme rather than the CSS, or mark your rule !important.
Variants
Variants change presentation, not state or behavior.