Developer preview. Vela, Facet, and Quire are pre-release and in active development — syntax, APIs, and availability may change, and they are not yet generally available.
SStretch Dev Docs
Facet

Theming and Brand Setup

Configure Facet theme, brand, and density axes without changing authored utilities.

Facet theming is resolver-driven. A theme is not a separate stylesheet fork; it is a coordinate in the resolver mode space.

The checked-in source resolver uses three axes:

  • theme: light, dark
  • brand: acme, globex, verdant
  • density: comfortable, compact

That creates 12 resolved permutations. The compiler emits the all-default coordinate at :root, then emits diffs under selectors such as .dark, [data-brand="globex"], and [data-density="compact"].

Resolver shape

{
  "modifiers": {
    "theme": {
      "values": ["light", "dark"],
      "default": "light",
      "selector": { "light": ":root", "dark": ".dark" }
    },
    "brand": {
      "values": ["acme", "globex", "verdant"],
      "default": "acme",
      "selector": { "acme": ":root", "globex": "[data-brand=\"globex\"]", "verdant": "[data-brand=\"verdant\"]" }
    },
    "density": {
      "values": ["comfortable", "compact"],
      "default": "comfortable",
      "selector": { "comfortable": ":root", "compact": "[data-density=\"compact\"]" }
    }
  }
}

Brand files

Brand sets keep semantic token names stable while changing brand values. The default acme brand defines an OKLCH seed, derives adjacent stops, and maps component semantics to those stops.

{
  "color": {
    "$type": "color",
    "brand": {
      "500": { "$value": { "colorSpace": "oklch", "components": [0.555, 0.205, 268], "hex": "#5865f2" } },
      "600": {
        "$value": { "colorSpace": "oklch", "components": [0.5, 0.2, 268] },
        "$extensions": { "com.facet": { "derive": { "fn": "oklch.darken", "from": "{color.brand.500}", "by": 0.06 } } }
      },
      "400": {
        "$value": { "colorSpace": "oklch", "components": [0.62, 0.18, 268] },
        "$extensions": { "com.facet": { "derive": { "fn": "oklch.lighten", "from": "{color.brand.500}", "by": 0.07 } } }
      }
    },
    "action":       { "$value": "{color.brand.500}" },
    "action-hover": { "$value": "{color.brand.600}" },
    "accent":       { "$value": "{color.brand.400}" }
  }
}

The globex brand uses the same semantic names. Its on-action maps to dark text because the source notes that white fails contrast on its orange action color.

{
  "action":       { "$value": "{color.brand.500}" },
  "action-hover": { "$value": "{color.brand.600}" },
  "accent":       { "$value": "{color.brand.400}" },
  "on-action": {
    "$value": "{color.text.strong}",
    "$extensions": { "com.facet": { "a11y": [
      { "pairsWith": "{color.action}", "minContrast": 4.5, "metric": "WCAG21" }
    ] } }
  }
}

Runtime switching

Authored utilities do not change between brands:

<button class="bg-action fg-on-action radius-control px-inset-lg py-inset-md hover:bg-action-hover focus-visible:ring @md:px-inset-lg">
  Primary action
</button>

Switch modes by changing the selectors declared in the resolver:

document.documentElement.classList.toggle("dark");
document.documentElement.dataset.brand = "globex";
document.documentElement.dataset.density = "compact";

Generated brand helper

The source includes a pre-release generation command for a brand set:

facet theme tokens/app.resolver.json --brief "calm natural growth" --name verdant --write

verdant.facet.json is present in the sources and is marked as AI-generated and contrast-correct. Treat this as a helper around the same token graph model, not a replacement for reviewing brand tokens.