Skip to main content
The SDK ships a single stylesheet — import it once at your app root:
import "@calm-xyz/react/styles.css";
Every visual token is a CSS variable scoped under .calm-root. Override on any ancestor (or globally) to retheme — copy the full default block below and edit what you want:
.calm-root {
  --calm-popover: 0 0% 100%;
  --calm-popover-foreground: 240 10% 3.9%;
  --calm-primary: 217 100% 65%;
  --calm-primary-foreground: 0 0% 100%;
  --calm-secondary: 190 27% 82% / 0.35;
  --calm-secondary-foreground: 240 5.9% 10%;
  --calm-muted: 160 13% 86%;
  --calm-muted-foreground: 240 3.8% 46.1%;
  --calm-destructive: 0 84.2% 60.2%;
  --calm-destructive-foreground: 0 0% 100%;
  --calm-success: 142 71% 38%;
  --calm-success-foreground: 0 0% 100%;
  --calm-border: 160 13% 85%;
  --calm-input: 160 13% 85%;
  --calm-ring: 217 100% 65%;
  --calm-overlay: 215 19% 35% / 0.24;
  --calm-radius: 8px;
  --calm-font-sans:
    "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui,
    sans-serif;
  --calm-shadow-edge: inset 0 0 0 1px hsl(var(--calm-border));
  --calm-shadow-modal:
    0 0 0 1px hsl(0 0% 0% / 0.04),
    0 8px 30px hsl(0 0% 0% / 0.10);
}
Colors are HSL space-separated triples (Tailwind v4 convention) — 217 100% 65%, not #4B90FF. The SDK wraps them with hsl(...) at use-time so opacity modifiers work (hsl(var(--calm-primary) / 0.5)).

Color tokens

The SDK ships light-only — see Dark mode for how to override tokens inside a dark-themed ancestor.
VariableDefaultWhat it paints
--calm-popover0 0% 100%Modal surface
--calm-popover-foreground240 10% 3.9%Body text on popover
--calm-primary217 100% 65%Primary CTA, accents (Calm blue)
--calm-primary-foreground0 0% 100%Text on primary
--calm-secondary190 27% 82% / 0.35Secondary buttons, list rows
--calm-secondary-foreground240 5.9% 10%Text on secondary
--calm-muted160 13% 86%Muted surfaces, disabled chips
--calm-muted-foreground240 3.8% 46.1%Helper text, captions
--calm-destructive0 84.2% 60.2%Error states, destructive actions
--calm-destructive-foreground0 0% 100%Text on destructive
--calm-success142 71% 38%Settled-state indicators, check badges
--calm-success-foreground0 0% 100%Text on success
--calm-border160 13% 85%Default border color
--calm-input160 13% 85%Input borders
--calm-ring217 100% 65%Focus ring color
--calm-overlay215 19% 35% / 0.24Modal backdrop

Layout

VariableDefaultWhat it controls
--calm-radius8pxBase corner radius (buttons, cards). Other steps slide with it: xs = base − 12px, sm = base − 8px, md = base − 4px, lg = base, xl = base + 4px.

Typography

VariableDefaultWhat it controls
--calm-font-sans"Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serifThe whole modal’s font stack. Partner pages load Geist (or any font in the stack) themselves.

Shadows

VariableDefaultWhat it paints
--calm-shadow-edgeinset 0 0 0 1px hsl(var(--calm-border))1px inset edge on cards (replaces a CSS border)
--calm-shadow-modal0 0 0 1px hsl(0 0% 0% / 0.04), 0 8px 30px hsl(0 0% 0% / 0.10)Modal drop shadow

Dark mode

The SDK ships light-only. Override tokens inside any dark-themed ancestor — via a data-theme="dark" selector, a media query, or a provider you already control:
[data-theme="dark"] .calm-root {
  --calm-popover: 240 10% 3.9%;
  --calm-popover-foreground: 0 0% 100%;
  --calm-border: 240 3.7% 15.9%;
  --calm-muted: 240 3.7% 15.9%;
  /* ...etc */
}

Scoping

The SDK uses Tailwind v4 with a calm: prefix, scoped under .calm-root. That means:
  • Every internal utility class ships as calm:bg-primary (not bg-primary) — no collision with your app’s Tailwind utilities.
  • Tailwind’s preflight is skipped — the SDK’s reset is scoped under .calm-root via :where() so it never touches the host page’s typography or box-sizing.
  • Custom Tailwind tokens (--text-xs: 13px, tighter --spacing: 0.2rem) apply only inside .calm-root.
You don’t need to apply .calm-root yourself — the modal’s portal container adds it.