.vendo/theme.json. The theme has this exact shape:
<VendoRoot theme={...}> at build time
(sync regenerates it on each build), so a fresh install renders on brand without
passing theme by hand.
Pass partial runtime overrides through VendoProvider.theme. Shipped chrome
derives its colors, typography, radius, density, and motion from these tokens.
It does not hardcode a Vendo brand.
Generation receives the same theme. Optional .vendo/design-rules.md adds
generation-time design rules without changing runtime tokens.
Emitted CSS variables
VendoRoot emits stable CSS custom properties derived from density and
motion. Chrome and the prewired primitives read
them directly, and you can consume the same variables from your own styles.
The --vendo-density-* and --vendo-motion-* names below are stable — new
variables may be added under these prefixes, but the ones listed here will
not be renamed.
Density
density: "compact" tightens control sizes, padding, and gaps; density: "comfortable" relaxes them. Every compact value is less than or equal to
its comfortable counterpart.
Color scheme
VendoRoot derives color-scheme from the WCAG relative luminance of
colors.background and exposes it as --vendo-color-scheme. Backgrounds
below the flip point (L < 0.179) resolve to dark; everything else, including
unparseable values, resolves to light.
Chrome uses this variable to activate
light-dark() branches, so a dark-brand
host automatically gets the dark chrome treatment without any extra
configuration. Set colors.background in .vendo/theme.json (or through a
VendoProvider.theme override) and the scheme follows.
.vendo/theme.json
--vendo-color-scheme from your own styles if you want custom
surfaces to track the same flip:
Motion
motion: "reduced" collapses --vendo-motion-duration to 0ms so chrome
respects user reduced-motion preferences. The easing curve stays constant.
Reference the variables from your own CSS to keep custom surfaces in sync
with the current theme:
Mobile takeover
Shipped overlay, page, and palette chrome switch to a full-viewport takeover at viewports 767px wide and narrower. The takeover covers the host layout instead of docking inside a squeezed column and portals todocument.body
so transformed host ancestors cannot confine it. It honors iOS safe-area
insets on all four edges. On touch devices (pointer: coarse), the composer
and palette search render at 16px to prevent iOS auto-zoom, and icon buttons
and the overlay close control expand to a 44px touch target. Desktop chrome
is unchanged.
The takeover surface stamps a stable --fl-kb-inset CSS variable derived
from visualViewport so the composer lifts above the on-screen keyboard.
Read it from your own styles if you render a custom surface inside a
takeover:
--fl-kb-inset is 0px when no keyboard is open and outside of takeover mode.