Theming and styling

The agent paints in your palette on the first frame. Theme tokens, URL parameters, and the CSS contract for anything beyond them.

Appearance is configured in the admin portal with a live preview: brand colour, fonts, corner radius, light and dark, and the colour of every element in the chat. This page covers the parts a web team may want to know about.

Precedence

Three layers, highest first:

  1. URL parameters on an embed, for a host page that needs a specific palette on a specific page.
  2. The assistant's theme in the admin portal.
  3. NeevAI defaults.

The embed applies the resolved theme before the first paint, so the chat never flashes the wrong colours.

Theme parameters on the embed URL

| Parameter | Maps to | |---|---| | theme | dark or light base palette | | bg | page background | | fg | primary text | | card | surfaces: cards, popovers, the navigation panel | | border | hairlines | | accent | brand accent, used for the primary button and focus ring | | accentFg | readable text on the accent | | userBubble and userBubbleFg | the visitor's message bubble | | radius | corner radius, for example 12px | | font | a font stack from a safelist of generic families and common faces |

Validation is strict and silent. Colours must be #rgb, #rrggbb, rgb(r, g, b) or oklch(L C H). Radius must be a number with px, rem or em. Fonts must resolve entirely from the safelist. Anything else is dropped and the default applies. Values never reach the page as raw strings.

Example:

&theme=dark&bg=%23101114&card=%2316181C&border=%23272A30
&accent=%23CCFF00&accentFg=%23131608

Light and dark at runtime

If your site has its own theme toggle, the host page can carry the chat with it:

NeevaiChat.setTheme('dark') // 'light' | 'dark' | 'system'

The choice persists in the visitor's browser. When you drive the theme this way, turn off the appearance row in the assistant's navigation panel so the two controls do not fight.

Custom CSS

For anything the theme tokens do not cover, the assistant accepts custom CSS in the admin portal, up to ten thousand characters. It is sanitised and injected inside the chat. Because the chat runs in an iframe, this is the only way to style it; your page's stylesheets never reach it.

Two things are stable and safe to target. Everything else in the chat's markup may change without notice.

Anchor attributes

| Anchor | Element | |---|---| | [data-neevai-chat] | chat root; scope every rule under it | | [data-neevai-header] | header row | | [data-neevai-welcome] | welcome state, with -title, -greeting and -prompts variants | | [data-neevai-prompt] | suggested-prompt chips | | [data-neevai-message="user"] and [data-neevai-message="ai"] | message bubbles | | [data-neevai-sources] and [data-neevai-source] | the sources footer and each source row | | [data-neevai-card] | an interactive card in the thread, with data-neevai-card-kind and data-neevai-card-state | | [data-neevai-pre-chat] | the pre-chat lead form | | [data-neevai-input] and [data-neevai-send] | composer and send button | | [data-neevai-disclaimer] and [data-neevai-powered-by] | the disclaimer row and the "Powered by" line |

CSS custom properties

The theme engine sets the palette on the chat's root as OKLCH triples, consumed as oklch(var(--x)): --primary, --secondary, --brand-accent, --background, --card, --foreground, --muted-foreground, --border, --ring, and their sidebar equivalents. A custom value must be a bare triple such as 0.62 0.21 245, never a hex string.