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

# Styling & Theming

> Update widget settings or write your own CSS to customize Remark's appearance

Remark ships two custom elements: `<remark-chat-widget>` for the **floating chat** and `<remark-qa-activator>` for the **embedded chat** (also known as the inline activator). Both share the same theme system and can be customized at two levels: through **widget settings** in the Remark dashboard, and through **custom CSS** targeting Shadow DOM parts and CSS custom properties. Widget settings handle the most common adjustments. Custom CSS picks up where widget settings leave off, giving you control over individual elements.

<CardGroup cols={2}>
  <Card title="Widget Settings" icon="sliders-horizontal" href="#widget-settings">
    Configure colors, typography, spacing, layout, and behavior from the dashboard.
  </Card>

  <Card title="CSS Custom Properties" icon="code" href="#css-custom-properties">
    Override sizing tokens and reference generated color tokens.
  </Card>

  <Card title="Shadow DOM Parts" icon="puzzle" href="#shadow-dom-parts">
    Target specific elements using the `::part()` pseudo-element.
  </Card>

  <Card title="Full Example" icon="file-code" href="#full-example">
    A complete example combining tokens and part selectors.
  </Card>
</CardGroup>

## Widget Settings

The Remark dashboard provides visual controls for theming, layout, and behavior across three pages — no CSS required.

### Appearance

The Appearance page (**Settings > Appearance**) is the primary way to theme both widgets. These settings apply to the floating chat and the embedded chat together.

| Setting              | Controls                                                                     |
| -------------------- | ---------------------------------------------------------------------------- |
| **Brand color**      | Primary color used to generate the full theme palette                        |
| **Color scheme**     | Light, dark, or auto (matches the user's system preference)                  |
| **Text color**       | Content and text color                                                       |
| **Background color** | Surface background color                                                     |
| **Button color**     | Color of the chat input send button and floating activator button background |
| **Border color**     | Border and divider color                                                     |
| **Online indicator** | Online/available status indicator color                                      |
| **Error color**      | Error and critical state color                                               |
| **Font family**      | Custom font stack (popular Google Fonts are loaded automatically)            |
| **Font size**        | Base font size in pixels (minimum 10 px) — all typography scales from this   |
| **Padding**          | Internal spacing (`sm`, `md`, `lg`, or a custom pixel value)                 |
| **Border roundness** | Corner radius (`sm`, `md`, `lg`, or a custom pixel value)                    |
| **Spacing scale**    | Unitless multiplier that scales all internal spacing                         |

Each palette color is optional. When a value isn't provided, the theme system generates an appropriate color from the brand color automatically, with both light and dark mode variants.

The Appearance page also includes a **Custom CSS** field for advanced overrides (see sections 2 and 3 below). Custom rules must target `remark-chat-widget` or `remark-qa-activator` in their selectors. The Custom CSS field supports `@media`, `@supports`, and other at-rules, so you can write responsive `::part()` overrides directly in the dashboard.

### Chat Settings

The Chat page (**Settings > Features > Chat**) controls the floating chat widget's layout and behavior.

| Setting                                      | Controls                                                               |
| -------------------------------------------- | ---------------------------------------------------------------------- |
| **Enable chat**                              | Show or hide the floating chat widget                                  |
| **Turn off chat when no experts are online** | Automatically hide the widget when no experts are available            |
| **Allow transfer to human**                  | Whether AI can hand off to a human expert (always or only when online) |
| **Activator style**                          | Button (floating action button) or text bar                            |
| **Position**                                 | Left, center (text bar only), or right                                 |
| **Enable activator animation**               | Show the icon animation on the button activator                        |

### Inline Activator Settings

The Inline Activator page (**Settings > Features > Inline Activator**) controls the embedded chat.

| Setting                | Controls                                                                                         |
| ---------------------- | ------------------------------------------------------------------------------------------------ |
| **Enable activator**   | Show or hide the embedded chat                                                                   |
| **Activator type**     | Expert (shows featured expert header) or text-only                                               |
| **Interaction mode**   | Inline (conversations stay within the embedded chat) or handoff (opens the floating chat widget) |
| **CSS selector**       | Which page element the embedded chat is inserted relative to                                     |
| **Activator position** | Insert before or after the selected element                                                      |

<Info>
  We recommend using widget settings over custom CSS when possible. Settings available in the dashboard have been tested to work cohesively and adapt to light and dark mode automatically.
</Info>

## CSS Custom Properties

The chat widget's theme system generates CSS custom properties that you can reference in custom CSS rules. These properties are grouped into sizing tokens (which can be overridden directly) and color tokens (which are generated from widget settings).

### Sizing and Typography

These properties are set on the widget's root element — `<remark-chat-widget>` or `<remark-qa-activator>`. Override them by targeting that element directly in your CSS, the same way you'd style any other HTML element. They correspond to dashboard settings but can also be overridden in custom CSS when finer control is needed.

| Variable                      | Default           | Controls                                                             | Dashboard Setting |
| ----------------------------- | ----------------- | -------------------------------------------------------------------- | ----------------- |
| `--hem`                       | `16px`            | Base font size unit — all typography scales as a ratio of this value | Font size         |
| `--remark-spacing-multiplier` | `1`               | Unitless multiplier for all spacing tokens                           | Spacing scale     |
| `--remark-radii-base`         | `0.5rem`          | Base border radius                                                   | Border roundness  |
| `--remark-fonts-sans`         | System font stack | Font family for all text                                             | Font family       |

`--hem` stands for "host em" — it serves the same role as [`rem`](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/font-size#rems) but is scoped to the widget's shadow DOM root rather than the page's `<html>` element. This means the widget's typography scales independently of the host page's font size. Font sizes are not exposed as individual variables; they are calculated as ratios of `--hem` (e.g., base text = `--hem`, small text = `calc(var(--hem) * 14 / 16)`). To scale all text proportionally, adjust the font size in the dashboard or override `--hem` in custom CSS.

<Tip>
  `--hem` is already responsive to the host page's root font size. If your site already adjusts `font-size` on `<html>` for different viewports, the widget may scale along with it automatically depending on your configuration.
</Tip>

### Distance from the Screen Edge

The floating chat and its activator sit a fixed distance from the viewport edge, controlled by two custom properties. Both default to `24px` and are independent of `--remark-spacing-multiplier`, which scales spacing *inside* the widget.

| Variable                           | Default | Controls                             |
| ---------------------------------- | ------- | ------------------------------------ |
| `--remark-spacing-bottom-distance` | `24px`  | Distance from the bottom edge        |
| `--remark-spacing-side-distance`   | `24px`  | Distance from the left or right edge |

Set them on the host element (or `::part(theme-root)`) to move the activator and the open chat panel together. To move only one, scope the override to its part — `::part(activator-parent)` for the activator, `::part(app-parent)` for the open chat panel:

```css theme={null}
/* Raise the activator and open chat to clear a sticky footer bar */
remark-chat-widget::part(theme-root) {
  --remark-spacing-bottom-distance: 96px;
}

/* Move only the activator, leaving the open chat where it is */
remark-chat-widget::part(activator-parent) {
  --remark-spacing-bottom-distance: 96px;
}
```

This applies to the floating chat only; the embedded chat follows normal page flow. On mobile, the open chat panel fills the screen and ignores the bottom distance, but the activator still respects it.

### Colors

Color tokens are generated from the brand color and palette overrides configured in the dashboard. They follow the naming pattern `--remark-colors-{name}` and have separate light and dark mode values.

These tokens are set on the `theme-root` part — an internal element within the shadow DOM. You can reference the tokens in `::part()` rules, but to change colors, use the dashboard palette settings rather than overriding variables directly.

#### Content

| Variable                            | Purpose                                         |
| ----------------------------------- | ----------------------------------------------- |
| `--remark-colors-content-default`   | Primary text                                    |
| `--remark-colors-content-secondary` | Secondary text                                  |
| `--remark-colors-content-muted`     | De-emphasized text                              |
| `--remark-colors-content-action`    | Brand-tinted text meeting contrast requirements |

#### Backgrounds

| Variable                               | Purpose                                             |
| -------------------------------------- | --------------------------------------------------- |
| `--remark-colors-background-default`   | Primary background                                  |
| `--remark-colors-background-hover`     | Background on hover                                 |
| `--remark-colors-background-secondary` | Secondary background (e.g., alternate message rows) |

#### Borders

| Variable                          | Purpose                    |
| --------------------------------- | -------------------------- |
| `--remark-colors-border-default`  | Default border             |
| `--remark-colors-border-subtle`   | Subtle or secondary border |
| `--remark-colors-border-active`   | Active or focused border   |
| `--remark-colors-border-emphasis` | Emphasized border          |

#### Brand

| Variable                        | Purpose                 |
| ------------------------------- | ----------------------- |
| `--remark-colors-brand-fill`    | Brand color fill        |
| `--remark-colors-brand-on-fill` | Text on brand fill      |
| `--remark-colors-brand-subdued` | Subdued brand tint      |
| `--remark-colors-brand-content` | Brand color for text    |
| `--remark-colors-brand-border`  | Brand color for borders |

#### Action

These correspond to the **Button color** override in the dashboard.

| Variable                         | Purpose                                                    |
| -------------------------------- | ---------------------------------------------------------- |
| `--remark-colors-action-fill`    | Interactive element fill (send button, floating activator) |
| `--remark-colors-action-on-fill` | Text on action fill                                        |
| `--remark-colors-action-hover`   | Interactive element fill on hover                          |

#### Status

| Variable                           | Purpose                    |
| ---------------------------------- | -------------------------- |
| `--remark-colors-online-fill`      | Online indicator           |
| `--remark-colors-online-on-fill`   | Text on online indicator   |
| `--remark-colors-critical-fill`    | Error or critical fill     |
| `--remark-colors-critical-on-fill` | Text on critical fill      |
| `--remark-colors-critical-content` | Critical color for text    |
| `--remark-colors-critical-border`  | Critical color for borders |

#### Elevated Surfaces

| Variable                           | Purpose                             |
| ---------------------------------- | ----------------------------------- |
| `--remark-colors-elevated-fill`    | Elevated surface (cards, dropdowns) |
| `--remark-colors-elevated-hover`   | Elevated surface on hover           |
| `--remark-colors-elevated-on-fill` | Text on elevated surfaces           |

#### Overlays and Inverse

| Variable                                | Purpose                  |
| --------------------------------------- | ------------------------ |
| `--remark-colors-overlay-fill`          | Semi-transparent overlay |
| `--remark-colors-overlay-emphasis-fill` | Strong overlay           |
| `--remark-colors-inverse-background`    | Inverted background      |
| `--remark-colors-inverse-content`       | Inverted text            |

## Shadow DOM Parts

Both `remark-chat-widget` and `remark-qa-activator` expose internal elements through the `part` attribute. You can target those elements from outside the shadow tree with the `::part()` pseudo-element.

Many parts carry **scene suffixes** so you can style the same structural element differently depending on context. The widget has three scenes: `landing` (before the conversation starts), `chat` (active conversation), and `paused` (conversation active on another device). For example, `widget-header` matches the header in any scene, while `widget-header-landing` targets only the landing screen header. Some elements also expose a `skeleton` token during loading states for styling placeholders.

### Floating Activators

These parts control the entry point to the floating chat — the button or text bar that visitors click to open the conversation. They are not present on the embedded chat (inline activator).

| Part                                 | Element                                                |
| ------------------------------------ | ------------------------------------------------------ |
| `activator-parent`                   | Activator root container                               |
| `activator-button`                   | Floating action button activator                       |
| `activator-button-icon`              | Icon inside button activator                           |
| `activator-message`                  | Floating message bubble                                |
| `activator-message-avatar`           | Message bubble avatar                                  |
| `activator-message-text`             | Message bubble text                                    |
| `activator-message-dismiss`          | Message dismiss button                                 |
| `floating-activator-prompts`         | Floating prompt group shown above the button activator |
| `activator-text-bar-button`          | Text bar button                                        |
| `activator-text-bar-badge`           | Unread badge                                           |
| `activator-text-bar-icon`            | Search icon                                            |
| `activator-text-bar-placeholder`     | Typewriter or placeholder text                         |
| `activator-text-bar-send-icon`       | Send icon button                                       |
| `back-to-bottom-button`              | Scroll-to-bottom button                                |
| `back-to-bottom-button-unread-badge` | Unread badge on scroll button                          |

### Shared Parts

The remaining parts are shared by both the floating chat and the embedded chat (inline activator).

#### Widget Shell

The outermost structural elements that wrap the widget's header, content area, and footer. Scene suffixes let you style each section differently on the landing screen, during an active conversation, or while paused.

| Part                     | Element                                                                 |
| ------------------------ | ----------------------------------------------------------------------- |
| `theme-root`             | Element that carries the generated color tokens (see [Colors](#colors)) |
| `parent-container`       | Outermost shadow DOM container                                          |
| `app-parent`             | Widget root (floating or embedded)                                      |
| `widget-header`          | Header slot                                                             |
| `widget-header-landing`  | Header on the landing scene                                             |
| `widget-header-chat`     | Header during an active conversation                                    |
| `widget-content`         | Main content slot                                                       |
| `widget-content-landing` | Content on the landing scene                                            |
| `widget-content-chat`    | Content during an active conversation                                   |
| `widget-content-paused`  | Content on the paused scene                                             |
| `widget-footer`          | Footer slot                                                             |
| `widget-footer-landing`  | Footer on the landing scene                                             |
| `widget-footer-chat`     | Footer during an active conversation                                    |

#### Chat Header

The header bar at the top of the chat, showing brand and expert info. Visible once the widget is open (floating) or always visible (embedded). The `header-content` container carries a scene suffix so you can style the header differently on the landing screen vs. during a conversation.

| Part                         | Element                                      |
| ---------------------------- | -------------------------------------------- |
| `header-content`             | Header content container                     |
| `header-content-landing`     | Header content on the landing scene          |
| `header-content-chat`        | Header content during an active conversation |
| `chat-header-avatar`         | Expert avatar                                |
| `chat-header-brand-name`     | Brand name heading                           |
| `chat-header-expert-trigger` | Clickable area that opens the expert profile |
| `chat-header-expert-name`    | Expert name heading                          |
| `chat-header-tagline`        | Expert tagline                               |

#### Header Menus

Dropdown menus accessible from the header — including options to mute, request a human, and adjust widget layout. The layout menu is only present in the floating chat. Menu button parts carry scene suffixes (e.g., `header-menu-close-button-chat`) so you can style them differently on the landing screen vs. during a conversation.

| Part                               | Element                                          |
| ---------------------------------- | ------------------------------------------------ |
| `header-menu`                      | Menu buttons container (scene-suffixed)          |
| `header-menu-button`               | Shared on every header action button             |
| `header-menu-more-button`          | More options icon button (scene-suffixed)        |
| `header-menu-close-button`         | Minimize or close button (scene-suffixed)        |
| `header-menu-open-chat-button`     | Open chat button, embedded mode (scene-suffixed) |
| `header-menu-layout-button`        | Layout menu trigger (scene-suffixed)             |
| `more-options-menu`                | More options menu content                        |
| `more-options-menu-mute`           | Mute or unmute item                              |
| `more-options-menu-speak-to-human` | Speak to human item                              |
| `layout-menu`                      | Layout menu content                              |
| `layout-menu-size`                 | Size radio group                                 |
| `layout-menu-size-default`         | Default size radio                               |
| `layout-menu-size-expanded`        | Expanded size radio                              |
| `layout-menu-align`                | Alignment radio group                            |
| `layout-menu-align-left`           | Left align radio                                 |
| `layout-menu-align-center`         | Center align radio                               |
| `layout-menu-align-right`          | Right align radio                                |
| `layout-menu-activator`            | Activator style group                            |
| `layout-menu-activator-text-bar`   | Text bar activator radio                         |
| `layout-menu-activator-button`     | Button activator radio                           |

#### Expert Intro

An introductory card shown before the conversation starts. Appears on the landing scene in both compact (embedded) and hero (floating) variants, depending on the activator type setting.

| Part                   | Element                                     |
| ---------------------- | ------------------------------------------- |
| `expert-intro`         | Intro container (compact and hero variants) |
| `expert-intro-avatar`  | Expert avatar                               |
| `expert-intro-name`    | Expert name heading                         |
| `expert-intro-tagline` | Expert tagline                              |

#### Paused Scene

Shown when the visitor has an active conversation on another device or tab. Displays the matched expert's avatar, a status message, suggested prompts, and a button to resume the conversation here.

| Part                       | Element                                     |
| -------------------------- | ------------------------------------------- |
| `intro`                    | Intro container (scene-suffixed)            |
| `intro-avatar`             | Expert avatar (scene-suffixed)              |
| `intro-message`            | Pause status message (scene-suffixed)       |
| `actions`                  | Actions container (scene-suffixed)          |
| `move-conversation-button` | Resume conversation button (scene-suffixed) |

#### Expert Profile Card

A summary card for the matched expert, displayed after a conversation starts. Includes a photo gallery and a button to open the full profile drawer.

| Part                                | Element                         |
| ----------------------------------- | ------------------------------- |
| `expert-profile-card`               | Card root                       |
| `expert-profile-card-title`         | Expert name                     |
| `expert-profile-card-caption`       | Bio or caption                  |
| `expert-profile-card-button`        | View Profile button             |
| `expert-profile-card-gallery`       | Gallery container               |
| `expert-profile-card-gallery-item`  | Individual gallery item wrapper |
| `expert-profile-card-gallery-image` | Gallery image                   |

#### Expert Profile Drawer

A slide-over panel with the expert's full profile, including bio and credentials. Opens when the visitor clicks "View Profile" on the expert profile card.

| Part                                | Element                |
| ----------------------------------- | ---------------------- |
| `expert-profile-drawer`             | Drawer content         |
| `expert-profile-drawer-back-button` | Back or close button   |
| `expert-profile-drawer-name`        | Expert name heading    |
| `expert-profile-drawer-bio`         | Bio markdown container |

#### Welcome Card

A greeting area shown when the chat first opens, before the visitor sends a message. Displays one or more welcome messages from the brand or expert.

| Part                          | Element                |
| ----------------------------- | ---------------------- |
| `welcome-card`                | Welcome area container |
| `welcome-card-message`        | Welcome message row    |
| `welcome-card-message-avatar` | Welcome message avatar |
| `welcome-card-message-text`   | Welcome message text   |

#### Messages

The conversation thread. Expert messages are grouped with an avatar; user messages appear on the opposite side. Each message bubble wraps markdown content.

| Part                     | Element                                                                           |
| ------------------------ | --------------------------------------------------------------------------------- |
| `message-group`          | Shared on expert and user message groups                                          |
| `expert-message-group`   | Expert message group (with avatar)                                                |
| `user-message-group`     | User message group container                                                      |
| `agent-message`          | Avatar-and-content frame shared by expert messages, prompts, and the welcome card |
| `agent-message-content`  | Content column inside the agent message frame                                     |
| `agent-message-text`     | Standalone agent text (prompts, confirmations, notices)                           |
| `message-bubble`         | Shared on every message bubble — user, NPS summary, PII request                   |
| `user-message-bubble`    | Individual user message bubble                                                    |
| `message-content`        | Message text or markdown wrapper                                                  |
| `message-link`           | Link inside markdown                                                              |
| `message-media`          | Image, video, or other media attached to a message                                |
| `gallery`                | Image gallery on a message with multiple images                                   |
| `gallery-grid`           | Gallery image grid                                                                |
| `gallery-item`           | Individual gallery image wrapper                                                  |
| `gallery-item-trigger`   | Button that opens a gallery image in the lightbox                                 |
| `gallery-item-overflow`  | "+N" overflow button on the last visible gallery image                            |
| `linked-product`         | Product badge above a user message linked to a product                            |
| `linked-product-image`   | Linked product thumbnail                                                          |
| `linked-product-name`    | Linked product name                                                               |
| `system-message`         | System message root                                                               |
| `system-message-content` | System message text                                                               |

#### Message Prose

Markdown rendered in a message carries `part="prose"` on its container, and every element inside it is stamped with `prose-<tag>` — `prose-p`, `prose-a`, `prose-h2`, `prose-li`, and so on — so any rendered element can be styled individually. Links carry `message-link` alongside `prose-a`.

Block spacing inside prose is driven by custom properties set on the container, overridable through `::part(prose)`. Prefer these over margin overrides on the per-element parts — a variable keeps the first/last-child edge resets intact and covers grouped elements in one declaration:

| Variable                                                        | Controls                                |
| --------------------------------------------------------------- | --------------------------------------- |
| `--prose-paragraph-spacing`                                     | Paragraph block margins                 |
| `--prose-list-spacing`                                          | List block margins                      |
| `--prose-list-gap`                                              | Gap between list items                  |
| `--prose-blockquote-spacing`                                    | Blockquote block margins                |
| `--prose-code-block-spacing`                                    | Code block margins                      |
| `--prose-heading-spacing-start` / `--prose-heading-spacing-end` | Space before and after headings         |
| `--prose-divider-spacing-start` / `--prose-divider-spacing-end` | Space before and after horizontal rules |
| `--prose-image-spacing`                                         | Image block margins                     |

```css theme={null}
/* Wider paragraph spacing in every message */
remark-chat-widget::part(prose) {
  --prose-paragraph-spacing: 1.8rem;
}

/* Brand-colored links */
remark-chat-widget::part(prose-a) {
  color: var(--remark-colors-brand-content);
}
```

#### Typing and Input

The text input area at the bottom of the chat, plus indicators shown while the expert or AI is composing a response.

| Part                              | Element                                            |
| --------------------------------- | -------------------------------------------------- |
| `typing-indicator`                | Typing indicator container                         |
| `expert-connecting-indicator`     | Expert connecting state                            |
| `carousel-avatar`                 | Individual avatar in the connecting-state carousel |
| `chat-input`                      | Input form                                         |
| `chat-input-root`                 | Input root container                               |
| `chat-input-field`                | Text input textarea                                |
| `chat-input-send-button`          | Send button                                        |
| `chat-input-file-input-container` | File attachment area                               |

#### Prompts

Suggested questions shown on the landing screen, during a paused conversation, or as conversation starters. Visitors click a prompt to send it as their first message. Individual prompt buttons carry scene suffixes (e.g., `prompt-button-landing`) so you can style prompts differently by context.

| Part                            | Element                                   |
| ------------------------------- | ----------------------------------------- |
| `prompt-button`                 | Individual prompt button (scene-suffixed) |
| `prompt-button-icon-container`  | Icon wrapper                              |
| `prompt-button-icon`            | Prompt icon                               |
| `prompt-button-text`            | Prompt label text                         |
| `prompt-button-hover-symbol`    | Hover accent symbol                       |
| `scene-prompts`                 | Prompts container (scene-suffixed)        |
| `conversation-starters-prompts` | Conversation starter prompts container    |

#### Product Recommendations

Product cards shown inline when an expert or AI recommends items. Each card links to the product page and displays a thumbnail carousel, name, and price. The add-to-cart button adds the product directly, or opens a variant picker sheet when the product has options; a post-add toast offers checkout.

| Part                                         | Element                                                |
| -------------------------------------------- | ------------------------------------------------------ |
| `product-recommendations`                    | Carousel container wrapping the recommendation cards   |
| `product-recommendations-nav-button`         | Carousel navigation arrow                              |
| `product-recommendation`                     | Product card root                                      |
| `product-recommendation-thumbnail`           | Image carousel container                               |
| `product-recommendation-image`               | Product thumbnail image                                |
| `product-recommendation-add-to-cart`         | Add-to-cart button on the card                         |
| `product-recommendation-details`             | Name and price container                               |
| `product-recommendation-name`                | Product name link                                      |
| `product-recommendation-price`               | Product price                                          |
| `product-recommendation-cart-toast`          | Toast shown after adding a recommended product to cart |
| `product-recommendation-cart-toast-checkout` | Checkout button inside the cart toast                  |
| `product-variant-sheet-link`                 | "View Product" link in the variant picker sheet        |

#### Presented Showcases

Scene-style imagery the agent generates from products in the catalog and presents inline in the conversation. A summary header introduces the showcase; hotspots on the rendered image let visitors hover for product details and add items directly to cart.

| Part                                    | Element                                                             |
| --------------------------------------- | ------------------------------------------------------------------- |
| `showcase`                              | Showcase frame root                                                 |
| `showcase-image`                        | The rendered showcase image                                         |
| `showcase-summary`                      | Summary header above the image                                      |
| `showcase-summary-title`                | Showcase title text                                                 |
| `showcase-summary-items`                | Featured product list inside the summary                            |
| `showcase-edge-gradients`               | Edge-fade overlay on the showcase image                             |
| `showcase-styled-badge`                 | "AI styled" badge shown when the showcase uses a brand style anchor |
| `showcase-unavailable`                  | Frame state shown when a showcase is no longer available            |
| `showcase-hotspot`                      | Hotspot button placed over a featured product                       |
| `showcase-hotspot-dot`                  | Idle dot indicator on a hotspot                                     |
| `showcase-hotspot-cart`                 | Cart icon shown on hotspots with an actionable variant              |
| `showcase-hotspot-add-to-cart`          | Hotspot in its add-to-cart state                                    |
| `showcase-hotspot-busy`                 | Busy indicator while adding to cart                                 |
| `showcase-hotspot-hover-card`           | Hover card root                                                     |
| `showcase-hotspot-hover-card-thumbnail` | Hover card image container                                          |
| `showcase-hotspot-hover-card-image`     | Hover card product image                                            |
| `showcase-hotspot-hover-card-details`   | Hover card name and price container                                 |
| `showcase-hotspot-hover-card-name`      | Hover card product name                                             |
| `showcase-hotspot-hover-card-price`     | Hover card product price                                            |

#### Content Previews

Rich previews for URLs shared in the conversation. Open Graph previews display an image, title, and optional price. YouTube links render an embedded video player.

| Part                              | Element                                 |
| --------------------------------- | --------------------------------------- |
| `content-preview`                 | Shared root for OG and YouTube previews |
| `content-preview-media-container` | Media wrapper                           |
| `og-preview`                      | OG preview root                         |
| `og-preview-image`                | OG image                                |
| `og-preview-title`                | OG title                                |
| `og-preview-price`                | OG price                                |
| `youtube-preview`                 | YouTube preview root                    |
| `youtube-preview-video`           | YouTube iframe                          |
| `youtube-preview-title`           | YouTube title                           |

#### Inline Cards

Interactive cards the agent renders inline in the conversation, such as discount codes and return-portal links. Every card shares the generic `card` part and a common anatomy, so you can style all cards at once, a specific kind by its own part, or a specific element by its anatomy part.

| Part                 | Element                           |
| -------------------- | --------------------------------- |
| `card`               | Shared on every inline event card |
| `discount-card`      | Discount-code card                |
| `return-card`        | Return-portal link card           |
| `card-header`        | Card header row                   |
| `card-media`         | Card media area                   |
| `card-heading-group` | Heading and subheading wrapper    |
| `card-heading`       | Card heading                      |
| `card-subheading`    | Card subheading                   |
| `card-badge`         | Badge (e.g., the discount code)   |
| `card-actions`       | Action button row                 |
| `card-legal`         | Fine-print text                   |

#### Assistant Indicator

A small tag shown alongside messages to indicate whether the response came from an AI assistant or a human expert.

| Part                        | Element              |
| --------------------------- | -------------------- |
| `assistant-indicator`       | AI or Human tag root |
| `assistant-indicator-label` | Tag label text       |

#### Footer

The bar at the bottom of the chat, containing terms of service text and Remark branding.

| Part                     | Element               |
| ------------------------ | --------------------- |
| `chat-footer`            | Footer container      |
| `inline-terms`           | Terms of service text |
| `powered-by`             | Powered by container  |
| `powered-by-remark-text` | Powered by text       |
| `powered-by-remark-logo` | Remark logo           |

<Warning>
  Avoid hiding the chat footer, terms text, or terms of service controls with custom CSS. These elements may contain legal disclosures or consent prompts that visitors need to see before using chat.
</Warning>

#### Data Collection

Forms and prompts for collecting visitor information (email, name, phone) and feedback. These appear at specific points during the conversation flow. The NPS survey itself opens in a bottom sheet built from the widget's standard dialog elements; its rating request and summary appear in the message stream.

| Part                              | Element                               |
| --------------------------------- | ------------------------------------- |
| `terms-of-service`                | Terms of service consent container    |
| `terms-of-service-consent-button` | TOS consent button                    |
| `terms-of-service-text`           | TOS text content                      |
| `pii-request-form`                | PII collection form                   |
| `pii-request-message-bubble`      | PII request message                   |
| `pii-request-submit-error`        | Error shown when PII submission fails |
| `nps-summary-message-bubble`      | NPS summary message                   |

#### Skeleton and Loading

Placeholder elements shown while the widget loads. Skeleton elements use a `-skeleton` suffix (e.g., `chat-header-avatar-skeleton`) and also carry the `skeleton` token, so you can target a specific placeholder or style all loading states at once.

| Part                               | Element                                                   |
| ---------------------------------- | --------------------------------------------------------- |
| `skeleton`                         | Applied alongside `-skeleton` parts during loading states |
| `chat-header-skeleton`             | Header skeleton container                                 |
| `chat-header-avatar-skeleton`      | Avatar placeholder                                        |
| `chat-header-expert-name-skeleton` | Expert name placeholder                                   |
| `chat-header-tagline-skeleton`     | Tagline placeholder                                       |
| `loading-dots`                     | Animated loading dots                                     |

### Targeting Parts in Your CSS

Use `::part()` on the host custom element. Replace the element name with whichever widget you are styling — `remark-chat-widget` for the floating chat or `remark-qa-activator` for the embedded chat (inline activator):

```css theme={null}
/* Floating chat: add a bottom border to the header during a conversation */
remark-chat-widget::part(header-content-chat) {
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--remark-colors-border-subtle);
}

/* Embedded chat: hide the profile card gallery */
remark-qa-activator::part(expert-profile-card-gallery) {
  display: none;
}

/* Floating chat: hide prompt bubbles above the button activator */
remark-chat-widget::part(floating-activator-prompts) {
  display: none;
}
```

A common use case for the embedded chat is adding spacing above or below the widget to separate it from surrounding page content:

```css theme={null}
/* Add vertical spacing around the embedded chat */
remark-qa-activator {
  margin-block: 2rem;
}
```

You can use nested media queries to apply different styles at different viewport sizes:

```css theme={null}
remark-qa-activator {
  @media (min-width: 50rem) {
    --hem: 18px;
  }
}
```

In this example, the embedded chat uses the default base font size (16 px) on smaller screens and bumps it up on larger viewports.

<Info>
  Some parts are only present in specific UI states. For example, `more-options-menu` and `layout-menu` are only rendered while those dropdowns are open, and `skeleton` parts are only present while the widget is loading.
</Info>

## Full Example

This example shows custom CSS that adjusts sizing tokens and styles individual parts. Colors and font family would typically be set through the dashboard rather than in CSS.

```css theme={null}
/* Override sizing tokens on both widgets */
remark-chat-widget,
remark-qa-activator {
  --hem: 18px;
  --remark-spacing-multiplier: 1.25;
  --remark-radii-base: 0.75rem;
}

/* Style individual parts (floating chat) */
remark-chat-widget::part(header-content-chat) {
  padding: 1rem 1.25rem;
}

remark-chat-widget::part(chat-header-tagline) {
  color: var(--remark-colors-content-muted);
}

/* Style individual parts (embedded chat) */
remark-qa-activator::part(product-recommendation) {
  border: 1px solid var(--remark-colors-border-subtle);
}
```

## Best Practices

* **Use widget settings first.** The dashboard handles colors, typography, spacing, and border radius with built-in dark mode support. Reach for custom CSS only when you need to style a specific element differently.
* **Reference token variables in `::part()` rules.** When writing custom CSS, use the `--remark-colors-*` tokens rather than hardcoded color values so your overrides adapt to light and dark mode.
* **Style semantic parts, not layout wrappers.** Prefer parts like `header-content` or `product-recommendation` over incidental containers.
* **Use scene suffixes for targeted styling.** Parts like `widget-header`, `header-menu-close-button`, and `prompt-button` match all scenes. Append a scene name (e.g., `widget-header-landing`, `header-menu-close-button-chat`) to scope styles to a specific context.
* **Account for stateful parts.** Menu, loading, and prompt parts may only render in specific states. Test your overrides in those states.
* **Check responsive layouts.** Header menus, product cards, activators, and input affordances can shift across screen sizes.

## Beyond CSS

For designs that go further than settings and custom CSS can reach — a fully custom activator built into your product grid, redesigned widget surfaces, or a bespoke theme — Remark supports brand-specific widget extensions built and maintained by our team. If you have a design in mind, contact your Remark representative to discuss what's possible.
