# bitvid Design System Primitives
bitvid's visual language is now powered by Tailwind utilities backed by our design tokens. This document lists the primitives available via `css/tailwind.source.css`, how they behave across states, and when to mix them with Tailwind utilities.
## Theme System
The default experience renders the production dark palette. Pages and embeds can opt into alternates by setting the `data-theme` attribute on the `` (or any ancestor that wraps the component). `data-theme="light"` promotes the light tokens defined in `css/tokens.css`, swapping surface, panel, border, muted, and overlay colors while keeping semantic accents consistent. Omit the attribute or set it back to `default` to inherit the dark baseline. Reserve additional theme keys (for example, `data-theme="contrast"`) for upcoming accessibility palettes—the same hook will activate them once their tokens land.
### Per-page overrides
Add `` to force a page into light mode. The attribute can also target specific islands—wrap your component tree in a container with `data-theme="light"` when you need to render light cards inside a dark shell.
### Embedding in third-party surfaces
Components consume design tokens via CSS custom properties, so they pick up the active theme from the closest ancestor. When embedding widgets into a host site, include the `css/tokens.css` bundle and set `data-theme` on the wrapper to control contrast. If the host already defines its own theme, namespace our tokens (e.g., nest them inside a dedicated `.bitvid-embed[data-theme="light"]`) to avoid collisions while still letting overlay, border, and panel tokens cascade.
## Focus Handling
All interactive primitives mix in the shared `.focus-ring` helper. It removes default outlines and applies a branded ring using `focus-visible` only. When building bespoke components, add `.focus-ring` to your root interactive element or replicate its rules:
```html
```
The helper includes:
- `focus-visible:ring-2` with `ring-info` and `ring-opacity-70`
- `focus-visible:ring-offset-2` with an offset on `bg-surface`
- `focus-visible:transition-shadow` using the tokenized `duration-fast` easing curve
Never hide focus styles without providing an accessible alternative.
## Component Primitives
### Buttons
| Class | Description |
| --- | --- |
| `.btn` | Primary action button (`bg-primary`, white text). Hover lifts to `bg-info-strong`, focus pushes to `bg-info-pressed`, disabled reduces opacity. |
| `.btn-ghost` | Framed secondary action. Transparent by default with subtle border, fills with `bg-panel-hover` on hover/focus. |
Both buttons:
- Use `.focus-ring` internally
- Include pointer-blocking and opacity changes on `:disabled`
- Are uppercase with wide tracking to match our existing CTA styling
Mix in Tailwind utilities for icon spacing (`gap-3`), sizing (`px-lg`, `py-sm`), or layout (`w-full`). Avoid overriding colors unless introducing a new semantic variant.
#### Variants & Toggle States
- Apply `data-variant="critical"` to `.btn-ghost` when rendering destructive affordances (for example, "Remove variant" pills inside repeater rows). The primitive swaps the border and text colors to the critical palette and deepens the fill on hover/focus.
- Toggle groups can rely on `[aria-pressed="true"]` or `data-state="active"` without extra utilities. When a `.btn-ghost` reports an active state it automatically promotes to the filled primary style.
```html
```
### Badges
`.badge` renders an inline pill (`bg-panel`, uppercase text). Opt into semantic variants with `data-variant="info"`, `data-variant="critical"`, or `data-variant="neutral"`. Layer on utilities for icon alignment or truncation.
### Cards
`.card` is the base surface for grid items and panels:
- Rounded corners (`rounded-lg`) and `bg-card`
- Token shadows on hover
- Focus states reuse `.focus-ring`
- Accepts `data-state="private" | "critical" | "disabled"` for special treatments
Combine with padding utilities per layout. Interactive cards should maintain `cursor-pointer` manually (see legacy shim example below) until templates adopt dedicated controller classes.
> **2025-10-11 update:** The legacy `.video-card*` shim selectors were removed. Video grids should now render plain `.card` elements and opt into semantic variants via `data-state`, `data-alert`, and `data-motion` attributes. Runtime code no longer maps the deprecated classes, so older selectors will not receive token updates.
### Form Inputs
`.form-control` is the base primitive for text entry surfaces. It handles layout (`block`, `w-full`), rounded corners, subtle borders, muted placeholders, and the shared focus ring. Hovering deepens the border, focus highlights with `border-info-strong`, `:invalid` raises a critical border, and `:disabled` mutes the field while blocking pointer events.
Specialisations reuse `.form-control`:
- `.input` – Standard single-line text input.
- `.textarea` – Multi-line input with a minimum height (`min-h-[8rem]`) and `resize-y` enabled.
- `.select` – Native `