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

# Styling

> Widgets are styled with Tailwind utility classes in ui.tsx. The design tokens and the dark variant come from the template's stylesheet, and no app-level CSS is bundled.

A widget styles itself with utility classes in its `ui.tsx`. There is no `styles.css` at any level of an app folder, and nothing imports one:

```tsx theme={null}
<span className="text-xs font-bold tracking-wide text-ink-muted dark:text-slate-400">
```

`text-ink-muted` comes from the distribution template's `src/index.css`, which is the Tailwind entry and the design system in one file:

```css src/index.css theme={null}
@import "tailwindcss";

/* The host hands the colour scheme to the view rather than to the browser, so
   `dark:` hangs off a class instead of `prefers-color-scheme`. */
@custom-variant dark (&:where(.dark, .dark *));

@theme {
  --font-sans: "Inter", system-ui, sans-serif;
  --color-ink: #0a1334;
  --color-ink-muted: #5a628a;
  --color-surface: #ffffff;
}
```

Every entry under `@theme` becomes a utility, so `--color-ink` gives you `text-ink` and `bg-ink`. Rebranding every app on the template is a matter of editing those four values in the template repo. The generator writes one import of that file into each `src/views/<widget>.tsx` entry, and since each view is its own bundle, Tailwind emits only the utilities that view's source uses.

## The dark class

A view is mounted alone in its own iframe, so there is no shared ancestor to hang the variant off. Each widget puts the class on its own root, driven by the theme the host reports:

```tsx theme={null}
import { useLayout } from "@waniwani/kit/web";

const { theme } = useLayout();
return <div className={theme === "dark" ? "dark" : ""}>…</div>;
```

## The stylesheet's origins

`src/index.css` pulls Inter from Google Fonts, and a host that enforces the widget CSP drops undeclared requests without erroring, so the font falls back and the widget looks subtly wrong. Codegen reads the origins off the stylesheet and the runtime merges them into every widget's `resourceDomains`, alongside whatever the widget declares itself. `fonts.googleapis.com` brings `fonts.gstatic.com` with it, since the second is only reachable by following the first.

## Why app-level CSS is refused

Tailwind v4 rejects `@apply` in any file that has not imported Tailwind itself:

```text theme={null}
Cannot apply unknown utility class `text-ink`. Are you using CSS modules or
similar and missing `@reference`?
```

Fixing that from an app folder means writing a `@reference` at a path into the generated tree, which does not exist in the author's own repo. One place for a class name beats two, so the build check names a stray `styles.css` rather than letting it sit there doing nothing:

```text theme={null}
  widgets/select-plan/styles.css
  └ app CSS is not bundled — nothing imports this file
    style with Tailwind utility classes in ui.tsx; the template's src/index.css
    carries the @theme tokens and the `dark` variant
```
