Strata tokens

Source of truth: packages/ui/src/css/theme.css (raw values, :root + .dark) and packages/ui/src/css/tailwind.css (token → Tailwind utility wiring, radius ramp, type scale, base document styles). Edit those files; every consumer picks the change up automatically. The workbench (apps/strata) renders the live palette in both themes.

Palette model

  • Semantic tokens only. Components consume --background, --foreground, --card, --muted, --accent, --border, --ring, --sidebar-*, --chart-1..5, etc. via the Tailwind utilities (bg-background, text-muted-foreground, border-border). Never raw palette utilities.
  • Dark mode is class-based .dark, overrides live in the same theme.css. To tweak a dark-mode color, edit the .dark block — one edit propagates to web-v2, marketing, and the docs sites. The dark surface model is two-level stacking: base level (background/card/popover) over a deeper backdrop (secondary is the darkest plane); secondary must always sit darker than background in dark mode.
  • Neutral grays carry a +2 blue channel (cool/slate tinge) in both themes. Keep that when adding grays.
  • --ink is the fixed brand near-black (rgb(0 0 2), same in both themes) for chrome like the nav island and footer.

Brand palette

Four fixed pastels, identical in light and dark, exposed as text-/bg-brand-{purple,blue,green,peach}:

  • --brand-purple rgb(198 172 226) — also aliased as --brand (text-brand/bg-brand), the primary accent. A subtree may override --brand locally (section accent bands) and every --brand-backed utility and color-mix() follows.
  • --brand-blue / --brand-green / --brand-peach — the carousel accents.
  • --brand-green-success rgb(73 200 95) — saturated functional green for money/positive signals only.

JS mirror: components that need literal values (inline styles, SVG attributes) read apps/marketing/src/lib/palette.ts. If you change a --brand-* value in theme.css, update the mirror in the same commit.

Radius

Everything derives from the single --radius token (0.625rem) via the ramp --radius-sm--radius-4xl in tailwind.css. Never write a bare var(--radius-*) that isn’t in the ramp, and never invent an arbitrary radius value. Squircle corners (corner-shape: squircle) are authored ~2x the visual target and MUST ship a half-value fallback behind an @supports gate — never inline-style a squircle radius.

Type scale

The Layers scale is denser than Tailwind’s defaults — shared components are authored against it and render ~2px oversized without it:

UtilitySize
text-xxs10px
text-xs11px
text-sm12px
text-base14px (body default)
text-lg16px
text-xl20px

The one 16px input exception is marketing-only: the marketing hero composer uses literal text-[16px] because mobile Safari auto-zooms any focused input under 16px and prospective signups must not hit that; the hero context also warrants the display break. In-app inputs stay on the scale.

Fonts: --font-sans = Inter Variable (via @fontsource-variable/inter); --font-mono = Berkeley Mono (self-hosted per app); --font-heading = the sans. Base document styles (14px body, antialiasing, the theme-aware thin scrollbars) come from tailwind.css’s @layer base — don’t re-declare them per app.

Misc tokens

--noise-url (hosted noise SVG), --logo-color (the logo lime, rgb(181 255 107)), --success-background, --dot-grid (the dot-grid backdrop fill; deliberately fainter in dark mode).

Rules

  • Grep packages/ui/src/css/theme.css before writing any var(--x) — if the token doesn’t exist there (or in the consumer’s own app layer), don’t use it.
  • Never redefine a Strata token in an app stylesheet. App-specific tokens (e.g. marketing’s --container-marketing) live in the app’s own @theme inline block under a distinct name.
  • Never invent arbitrary CSS values (heights, offsets, spacing) — ask for the correct value if a design doesn’t specify one.

Raw markdown for agents: /docs/tokens.md