# Styling & Theming

## Overview

The assistant renders in a shadow root, so its internal classes are not reachable
from an app stylesheet. Customization is exposed through three deliberate,
stable surfaces:

1. **Design-system tokens** — the widget reads standard tokens (`--neutral-layer-*`,
   `--accent-fill-rest`, `--design-unit`, `--control-corner-radius`, `--body-font`,
   the `--type-ramp-*` ramp, …). These inherit through the shadow boundary, so
   theming the host design system themes the assistant with no widget-specific work.
2. **`--ai-*` custom properties** — a small set of assistant-specific variables,
   each with a built-in fallback, for the parts of the UI that have no natural
   design-system token.
3. **CSS Shadow Parts (`::part()`)** — named hooks on internal elements for
   arbitrary restyling from an app stylesheet.

Prefer tokens where one exists (they inherit and can be set inline); reach for
`::part()` when you need to change something a token doesn't cover.

---

## `--ai-*` custom properties

| Property | Default | Applies to |
| --- | --- | --- |
| `--ai-conversation-max-width` | `1500px` | Max width of the centred conversation column **and** the composer (kept in sync) |
| `--ai-message-shadow` | `0 2px 8px rgb(0 0 0 / 15%)` | Assistant message bubble shadow |
| `--ai-thinking-color` | `#7c3aed` | Thinking/reasoning bubble and its avatar ring |
| `--ai-function-color` | `#86efac` | Tool-call bubble text and border |

Set them on the host element (or any ancestor — they inherit):

```css
foundation-ai-assistant {
  --ai-thinking-color: #2563eb;
  --ai-message-shadow: none;
}
```

---

## Shadow parts

Parts on the conversation area (the outer frame exposes many more — e.g.
`chat-header`, `input-row`, `input`, `send-button`):

| Part | Element |
| --- | --- |
| `chat-wrapper` | Outer frame (header + messages + composer) |
| `messages` | Scroll container (full width; owns the scrollbar) |
| `messages-content` | Width-capped, centred column that holds every message |
| `message` | Every message bubble |
| `message-<type>` | A bubble of one kind: `message-user`, `message-ai`, `message-ai-thinking`, `message-ai-function`, `message-interaction` |
| `message-interaction-<presentation>` | An interaction bubble in one presentation: `message-interaction-label`, `message-interaction-bare`, `message-interaction-bubble` |
| `thinking` | The loading-indicator row |

Target them from an app stylesheet with `::part()`:

```css
/* Constrain every bubble to a width range */
foundation-ai-assistant::part(message) {
  min-width: 200px;
  max-width: 640px;
}

/* Restyle just one kind of bubble */
foundation-ai-assistant::part(message-user) {
  border-radius: 18px;
}

/* Only interaction widgets, and only when framed as a bubble */
foundation-ai-assistant::part(message-interaction-bubble) {
  min-width: 320px;
}

/* Change the padding inside bubbles */
foundation-ai-assistant::part(message) {
  padding: 12px 16px;
}
```

### The conversation column (`messages-content`)

Messages sit in a column capped at `1000px` and centred inside the full-width
scroll container, so the scrollbar stays at the panel edge while the text keeps
a readable width. Adjust or remove the cap via the part:

```css
/* Widen (or narrow) the column */
foundation-ai-assistant::part(messages-content) { max-width: 1400px; }

/* Remove the cap — messages fill the full width */
foundation-ai-assistant::part(messages-content) { max-width: none; }

/* Neutralise the wrapper entirely (as if the div weren't there) */
foundation-ai-assistant::part(messages-content) { display: contents; }
```

---

## Responsive sizing

A `min-width` only ever affects *short* messages — long ones are already wider —
so it can push a bubble past a narrow container. The assistant can be rendered at
any width (docked panel, popout, inline), so size overrides against the *element's*
width, not the viewport.

`@media` queries the viewport, which does not track the assistant's width, so it is
the wrong tool. Use a **container query** instead. `::part()` rules can be wrapped
in `@container` from the host stylesheet; the reliable pattern is to make your own
wrapper a container:

```css
.ai-slot {
  container-type: inline-size;
}

/* A comfortable minimum on wide layouts… */
foundation-ai-assistant::part(message) {
  min-width: 220px;
}

/* …dropped when the assistant itself is narrow, so bubbles never overflow. */
@container (max-width: 420px) {
  foundation-ai-assistant::part(message) {
    min-width: 0;
  }
}
```

