> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stackra.figentra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 0320 — Stackra brand: the glass material and the showcase stage

> Accepted · 2026-10-24

> [!NOTE]
>
> Amends the stackra brand kit's surface rule, which said "No glass (shadows allowed), no gradients"
> and "no top-line highlight". The rule's record is
> `packages/design-system/tokens/assets/data/stackra/brand.json` (`decided.surfaces`). Amends
> [0302](https://docs.stackra.figentra.com/adr/0302-stackra-design-system-tokens-ui-and-the-playground.md) only where it describes the
> playground's look.

## Context

The stackra brand kit (approved 2026-09-29) settled every surface as an opaque layer: the page ground, then section
sheets, then recessed stages, with emphasis by an inverted card. It recorded "no glass, no gradients, no top-line
highlight". On 2026-10-24 the owner asked for a premium, glass showcase for the design system playground, with Stackra
branding throughout, and decided to change the brand record to allow it. This ADR records the change and draws its
limits, so the material does not drift into product screens or into the component library.

## Decision

1. **A glass material joins the brand.** It is a translucent fill of a surface role, a backdrop blur and a hairline
   edge, with a light top edge allowed. It is built from the theme's roles only, with no colour of its own. Glass is
   for **showcase and marketing surfaces**: the playground, the docs landing, marketing pages and the static host.
   Product UI (console, mobile, panel resources) and the `@stackra/ui` components keep the opaque layers. A future ADR
   decides whether glass reaches them.
2. **Glass never sits under a component's reference samples.** The components' soft and translucent variants are tuned
   against the theme's `background`, so a page that documents a component (its variants, sizes and states) places them
   on a solid sheet of that colour; glass frames that sheet and never sits behind it. Composed scenes that show the
   system at work (the playground index's showcase, its gallery panels) may sit on glass cards, as a product's would;
   axe checks them in every material mode, so their contrast holds.
3. **Gradients are allowed only as soft ambient tints, never as fills of a control or of text.** Each tint is a flat
   colour shaped by a mask. A contrast checker (axe) then measures text against every tint at full strength at once.
   That is a stricter background than any point of the page shows, so the check gives a result instead of reporting
   "incomplete". The tints stay light enough that muted text passes AA in that worst case.
4. **The fallbacks are part of the material, and its contrast is measured.**
   * The glass turns solid (its surface role, no blur) under `prefers-reduced-transparency`, under
     `prefers-contrast: more`, and where `backdrop-filter` is unsupported.
   * Where `color-mix()` is unsupported it is a static, opaque material: the surface, no filter, the border role as
     its edge. A static declaration written before a computed one cannot do this, because a declaration that holds
     `var()` always parses, so the fallback is an `@supports` block after the colour blocks.
   * It keeps a visible edge in forced colours.
   * Under reduced motion it does not animate.
   * The page root (`html` and `body`) stays opaque, so the material always blurs a painted page.
   * **Reading text holds 4.5:1 over the worst backdrops.** On the `regular` and `thick` levels, the theme's
     `foreground` holds 4.5:1 over pure black and over pure white, in every mode and colour scheme, with liquid's
     sheen at full strength. `stackra-theme.constant.test.ts` computes it through 8-bit sRGB, as a browser
     composites. The `thin` level carries no reading text.
   * **Muted text holds 4.5:1 too, on the `thick` level only** (owner decision 2026-10-25, STA-486).
     * On `regular` it cannot: over pure black on the light scheme it reaches 3.70:1 in glass and 2.36:1 in liquid.
       So muted text never sits on `thin` or `regular`.
     * Where the `thick` level's own fill cannot hold it either (liquid, 3.15:1), the mode's `thickFloor` makes that
       level solid. The other levels keep the mode's look.
     * The same test computes it, and axe still checks muted text where it sits, in every mode, scheme and direction.
5. **The marks are unchanged.**
   * The beam-S wordmark stays static, in its artwork colour (steel-deep on light, steel on dark).
   * It may be drawn large and echoed as a hairline outline on a showcase stage.
   * It is never glass, never a gradient, and never animated.
   * Steel still fills no UI role, and the amber bar stays inside the "by figentra\_" signature.
6. **Patterns and illustration.**
   * The brand's grid, graph and dots patterns may sit under glass, in hairline roles, and never carry meaning.
   * The brand icons (square caps, mitred joins, 24px grid) may wear a glass tile on a showcase stage.
7. **The material is a theme token with three levels and four modes** (added 2026-10-24, STA-424).
   * **Levels** (`MaterialLevel`) are thicknesses:
     * `thin` is for small chrome without reading text (tiles, chips over art).
     * `regular` (`.material`) is for bars, cards and panels whose text is all `foreground`.
     * `thick` is for surfaces that hold muted text or long reading text (sheets, palettes, cards with a
       description).
     * A theme gives each level a fill share of `surface` per colour mode, a px blur and a saturation factor, plus
       the edge and rim-light shares (`Theme.materials`, validated by `defineTheme`).
   * **Modes** (`MaterialMode`) are degrees, set once on `<html data-material>`. Every level scales by the mode's
     factors (`MATERIAL_MODES`), so one switch moves the whole page:
     * `solid` is opaque. It is the product default, and also what reduced transparency, more contrast and a missing
       `backdrop-filter` force.
     * `frosted` gives a dense fill and a heavy blur.
     * `glass` is the theme as written, and the showcase default.
     * `liquid` gives a thinner fill and a lifted backdrop (more saturation, a little brightness) with a sheen
       along the top inside edge. Its `thick` level is solid, so muted text keeps 4.5:1 (decision 4).
   * **Where each default comes from.** `glass` is the stylesheet's `:root` default, so a page with no
     `data-material` (a static showcase page, the docs landing) gets the theme as written. `DesignSystemProvider`
     sets `solid` unless it is given another mode (`material`), so product UI is opaque without asking, and a
     showcase asks for glass. Solid also comes from the fallbacks of decision 4.
   * **The sheen is the rim light spread down.** Its white is the mode's `sheen` times the colour scheme's rim-light
     share (`materials.highlight`): about 22% on the stackra light scheme and under 3% on its dark one, where more
     white would wash out light text.
   * **Liquid draws no refraction.** A displacement filter costs a filter pass per frame, works in Chromium only,
     and warps text behind it. The lens is suggested by the lifted backdrop, the rim light and the sheen, all drawn
     with backdrop filters and inset shadows. There are no pseudo-elements and no gradient images, so contrast
     checkers can still measure text on the material.
     * Rejected: an SVG displacement filter through `backdrop-filter: url()`, a WebGL or canvas lens, and
       pre-rendered refraction images.
     * Revisit when WebKit bug 245510, Mozilla bug 1961378 or CSS Working Group issue 12316 is resolved.
   * **Rendering.** `renderWebCss` writes the material:
     * the shares, fills and filters go in the colour blocks, so a subtree with its own `data-theme` computes them
       again;
     * the mode factors go on `[data-material]`;
     * the fallbacks come after the modes;
     * the classes go in the one components layer.
   * **Native** uses the platform's own material: Liquid Glass on iOS 26 and later, solid everywhere else (older iOS
     and Android). It reads `Theme.materials` and `MATERIAL_MODES` only to choose between the two; the web's CSS
     material is not drawn on native.

## Consequences

* `brand.json` `decided.surfaces` now cites this ADR. The kit's own `--check` (outside this repository) still asserts
  the old rule and must be updated when the kit is next regenerated.
* The playground (`apps/playground`, STA-422) is the first surface. It uses the `.material*` classes, offers the four
  modes in its display switcher (`?material=`) and keeps only its ambient field in `src/styles/app.css`.
* `@stackra/tokens` carries the material (decision 7). A theme without `materials` no longer validates, and every
  product theme adds the block.
* The Theme Studio (STA-423, `/theme-studio`) derives a theme from a few controls and previews it, with its contrast
  checked against AA. It exports from the one theme through `@stackra/tokens`:

  * the web CSS (`renderWebCss`, HeroUI v3) and native CSS (`renderNativeCss`, Uniwind);
  * the full JSON (`stackra.theme/1`: the theme, with HeroUI's own custom properties and Stackra's additions);
  * a changes-only JSON (`stackra.theme-diff/1`);
  * W3C DTCG tokens.

  It imports either JSON, checked by `parseThemeJson`.

## Enforcement

* `stackra-theme.constant.test.ts`: the worst-case contrast of decision 4.
* `render-web-css.function.test.ts`: the levels, modes, sheen and fallbacks are written, the fallbacks after the
  blocks they override; `web.css` is its file snapshot.
* The playground's end-to-end suite: axe on the index in every mode, scheme and direction over an opaque root; the
  glass solid under more contrast and under reduced transparency (emulated through the DevTools protocol); an edge in
  forced colours.
* `apps/playground/src/styles/__tests__/app.test.ts`: the playground never loads HeroUI Pro's glass theme.
* Planned: a design-brand review rule that refuses `backdrop-filter`, or a gradient fill, outside the surfaces of
  decision 1. Until then, review applies it.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.