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

# Advanced Styling

> Styling, themes, CSS variables, and parts reference for the Bonsai Search web component

<Callout color="#0A5B3B" icon="info">
  **Where styling lives as of SDK v3.2+.** Colors, borders, layout, and shadows are driven by **CSS custom properties** — not by HTML attributes. These variables can be set two ways:

  1. **From the Settings API** (preferred) — theming is configured per-tenant in the Bonsai dashboard and injected into the component's shadow DOM automatically at load time.
  2. **From your page's CSS** — set any variable **on the `<bonsai-search>` element itself** to customize per-embed. Page CSS wins over the Settings API because Settings-API variables are injected at `:host` low specificity.

  <Callout color="#0A5B3B" icon="circle-alert">
    **Target the element, not an ancestor.** The SDK declares its defaults on `:host` — a direct declaration on the component — so a value that merely *inherits* down from `:root` or a wrapper `<div>` loses to it. `bonsai-search { --bonsai-text-color: … }` works; `:root { --bonsai-text-color: … }` does not.
  </Callout>

  <Callout color="#B45309" icon="triangle-alert">
    **`theme="dark"` overrides both of the above.** The dark palette is declared on an element inside the component's shadow root, so it beats page CSS, inline `style=""`, and the Settings API alike — 21 colour and shadow variables are silently discarded. Read [Dark theme](#dark-theme) before styling a dark embed.
  </Callout>

  Legacy HTML attributes like `brand-color`, `text-color`, `input-bg`, `card-bg`, etc. are no longer supported — use the variables on this page instead.
</Callout>

## Outer Container

If you want to customize the layout and positioning, wrap the component in a container and add custom CSS.

<Accordion title="Example:" defaultOpen>
  ```html theme={null}
  <style>
    .bonsai-search-outer-container {
      width: 100%;
      max-width: 42rem;
      margin: 4rem auto;
      min-height: 350px;
    }

    bonsai-search {
      --bonsai-brand-color: #0A5B3B;
      --bonsai-text-color: #303030;
      --bonsai-muted-color: #9CA3AF;
    }
  </style>

  <div class="bonsai-search-outer-container">
    <bonsai-search
      api-key="API-KEY"
      theme="light"
    ></bonsai-search>
  </div>
  ```
</Accordion>

## CSS Variables

The web component uses a closed shadow root, but CSS custom properties still pass through. You can set any `--bonsai-*` variables directly on the `<bonsai-search>` element if you prefer CSS-only customization.

<Accordion title="Example:" defaultOpen>
  ```html theme={null}
  <bonsai-search
    style="
      --bonsai-font-body: 'Space Grotesk', sans-serif;
      --bonsai-font-heading: 'Space Grotesk', sans-serif;
      --bonsai-font-mono: 'IBM Plex Mono', monospace;
      --bonsai-search-max-width: 100%;
      --bonsai-brand-color: #0a5b3b;
      --bonsai-text-color: #111111;
      --bonsai-muted-color: #6b7280;
      --bonsai-input-bg: #ffffff;
      --bonsai-input-text-color: #111111;
      --bonsai-suggestions-text-color: #111111;
      --bonsai-results-text-color: #111111;
      --bonsai-card-text-color: #111111;
    "
    api-key="API-KEY"
    theme="light"
  ></bonsai-search>
  ```
</Accordion>

### Reference Table

<Callout color="#0A5B3B" icon="circle-alert">
  Defaults shown are for the light theme. The dark theme automatically overrides color and shadow variables.
</Callout>

| Variable | Default | Purpose |
| - | - | - |
| `--bonsai-brand-color` | `#0a5b3b` | Accent color for focus, buttons, and highlights |
| `--bonsai-text-color` | `#303030` | Primary text |
| `--bonsai-suggestions-text-color` | `#303030` | Suggestions text |
| `--bonsai-input-text-color` | `#303030` | Input text + icon |
| `--bonsai-results-text-color` | `#303030` | Summary + section headers |
| `--bonsai-card-text-color` | `#303030` | Result card text |
| `--bonsai-muted-color` | `#9ca3af` | Secondary text |
| `--bonsai-input-bg` | `#f5f5f5` | Input + dropdown background |
| `--bonsai-card-bg` | `transparent` | Result card background |
| `--bonsai-canvas-color` | `#fafafa` | Page/canvas background **Declared but not consumed by the SDK — setting it currently has no effect.** |
| `--bonsai-surface-color` | `#ffffff` | Surface background |
| `--bonsai-border-color` | `rgba(0, 0, 0, 0.06)` | Default border |
| `--bonsai-border-color-hover` | `rgba(0, 0, 0, 0.12)` | Hover border |
| `--bonsai-hover-bg` | `rgba(0, 0, 0, 0.04)` | Hover background |
| `--bonsai-suggestions-hover-bg` | `rgba(0, 0, 0, 0.04)` | Suggestions hover |
| `--bonsai-error-bg` | `rgba(220, 53, 69, 0.1)` | Error background |
| `--bonsai-error-color` | `#c82333` | Error text |
| `--bonsai-space-1` | `0.25rem` | Spacing token |
| `--bonsai-space-2` | `0.5rem` | Spacing token |
| `--bonsai-space-3` | `0.75rem` | Spacing token |
| `--bonsai-space-4` | `1rem` | Spacing token |
| `--bonsai-space-5` | `1.25rem` | Spacing token |
| `--bonsai-space-6` | `1.5rem` | Spacing token |
| `--bonsai-font-heading` | `system-ui, -apple-system, sans-serif` | Heading font |
| `--bonsai-font-body` | `system-ui, -apple-system, sans-serif` | Body font |
| `--bonsai-font-mono` | `ui-monospace, monospace` | Mono font |
| `--bonsai-font-size-xs` | `0.75rem` | Text size |
| `--bonsai-font-size-sm` | `0.875rem` | Text size |
| `--bonsai-font-size-base` | `1rem` | Text size |
| `--bonsai-font-size-lg` | `1.125rem` | Text size |
| `--bonsai-font-size-xl` | `1.25rem` | Text size |
| `--bonsai-radius-none` | `0` | Radius token **Declared but not consumed by the SDK — setting it currently has no effect.** |
| `--bonsai-radius-sm` | `0.25rem` | Radius token **Declared but not consumed by the SDK — setting it currently has no effect.** |
| `--bonsai-radius-md` | `0.375rem` | Radius token |
| `--bonsai-radius-lg` | `0.5rem` | Radius token |
| `--bonsai-radius-xl` | `0.75rem` | Radius token **Declared but not consumed by the SDK — setting it currently has no effect.** |
| `--bonsai-radius-full` | `9999px` | Full radius |
| `--bonsai-duration-fast` | `150ms` | Animation timing |
| `--bonsai-duration-base` | `200ms` | Animation timing |
| `--bonsai-duration-slow` | `300ms` | Animation timing |
| `--bonsai-easing` | `cubic-bezier(0, 0, 0.2, 1)` | Animation easing |
| `--bonsai-shadow-sm` | `0 1px 2px 0 rgb(0 0 0 / 0.05)` | Shadow token **Declared but not consumed by the SDK — setting it currently has no effect.** |
| `--bonsai-shadow-md` | `0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)` | Shadow token **Declared but not consumed by the SDK — setting it currently has no effect.** |
| `--bonsai-shadow-lg` | `0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)` | Shadow token |
| `--bonsai-search-min-height` | `3.5rem` | Search bar height **Declared but not consumed by the SDK — setting it currently has no effect.** |
| `--bonsai-search-max-width` | `42rem` | Max container width |
| `--bonsai-icon-size` | `1.25rem` | Icon size **Declared but not consumed by the SDK — setting it currently has no effect.** |
| `--bonsai-icon-size-sm` | `1rem` | Small icon size |
| `--bonsai-results-columns` | `3` | Results grid columns |
| `--bonsai-image-object-fit` | `cover` | Image sizing mode |

#### Color

<ResponseField name="--bonsai-brand-color" default="#0a5b3b">
  Accent color used for focus states, buttons, and highlights throughout the component.
</ResponseField>

<ResponseField name="--bonsai-text-color" default="#303030">
  Primary text color for main content.
</ResponseField>

<ResponseField name="--bonsai-input-text-color" default="#303030">
  Text color for input field and search icon.
</ResponseField>

<ResponseField name="--bonsai-suggestions-text-color" default="#303030">
  Text color for suggestion items.
</ResponseField>

<ResponseField name="--bonsai-results-text-color" default="#303030">
  Text color for AI summary and section headers.
</ResponseField>

<ResponseField name="--bonsai-card-text-color" default="#303030">
  Text color for result card content.
</ResponseField>

<ResponseField name="--bonsai-muted-color" default="#9ca3af">
  Secondary text color for less prominent content.
</ResponseField>

<ResponseField name="--bonsai-input-bg" default="#f5f5f5">
  Background color for input field and dropdown areas.
</ResponseField>

<ResponseField name="--bonsai-card-bg" default="transparent">
  Background color for result cards. Defaults to `transparent`, so cards sit directly on your page background unless you set a surface.
</ResponseField>

<ResponseField name="--bonsai-canvas-color" default="#fafafa">
  Background color for the main canvas area. **Declared but not consumed by the SDK — setting it currently has no effect.**
</ResponseField>

<ResponseField name="--bonsai-surface-color" default="#ffffff">
  Background color for elevated surfaces.
</ResponseField>

<ResponseField name="--bonsai-border-color" default="rgba(0, 0, 0, 0.06)">
  Default border color.
</ResponseField>

<ResponseField name="--bonsai-border-color-hover" default="rgba(0, 0, 0, 0.12)">
  Border color on hover state.
</ResponseField>

<ResponseField name="--bonsai-hover-bg" default="rgba(0, 0, 0, 0.04)">
  Background color for hover states.
</ResponseField>

<ResponseField name="--bonsai-suggestions-hover-bg" default="rgba(0, 0, 0, 0.04)">
  Background color when hovering over suggestion items.
</ResponseField>

<ResponseField name="--bonsai-error-bg" default="rgba(220, 53, 69, 0.1)">
  Background color for error states.
</ResponseField>

<ResponseField name="--bonsai-error-color" default="#c82333">
  Text color for error messages.
</ResponseField>

#### Spacing

<ResponseField name="--bonsai-space-1" default="0.25rem">
  Smallest spacing unit (4px).
</ResponseField>

<ResponseField name="--bonsai-space-2" default="0.5rem">
  Extra small spacing unit (8px).
</ResponseField>

<ResponseField name="--bonsai-space-3" default="0.75rem">
  Small spacing unit (12px).
</ResponseField>

<ResponseField name="--bonsai-space-4" default="1rem">
  Base spacing unit (16px).
</ResponseField>

<ResponseField name="--bonsai-space-5" default="1.25rem">
  Medium spacing unit (20px).
</ResponseField>

<ResponseField name="--bonsai-space-6" default="1.5rem">
  Large spacing unit (24px).
</ResponseField>

#### Typography

<ResponseField name="--bonsai-font-heading" default="system-ui, -apple-system, sans-serif">
  Font family for headings and section titles.
</ResponseField>

<ResponseField name="--bonsai-font-body" default="system-ui, -apple-system, sans-serif">
  Font family for body text.
</ResponseField>

<ResponseField name="--bonsai-font-mono" default="ui-monospace, monospace">
  Font family for monospace text.
</ResponseField>

<ResponseField name="--bonsai-font-size-xs" default="0.75rem">
  Extra small font size (12px).
</ResponseField>

<ResponseField name="--bonsai-font-size-sm" default="0.875rem">
  Small font size (14px).
</ResponseField>

<ResponseField name="--bonsai-font-size-base" default="1rem">
  Base font size (16px).
</ResponseField>

<ResponseField name="--bonsai-font-size-lg" default="1.125rem">
  Large font size (18px).
</ResponseField>

<ResponseField name="--bonsai-font-size-xl" default="1.25rem">
  Extra large font size (20px).
</ResponseField>

#### Border Radius

<ResponseField name="--bonsai-radius-none" default="0">
  No border radius. **Declared but not consumed by the SDK — setting it currently has no effect.**
</ResponseField>

<ResponseField name="--bonsai-radius-sm" default="0.25rem">
  Small border radius (4px). **Declared but not consumed by the SDK — setting it currently has no effect.**
</ResponseField>

<ResponseField name="--bonsai-radius-md" default="0.375rem">
  Medium border radius (6px).
</ResponseField>

<ResponseField name="--bonsai-radius-lg" default="0.5rem">
  Large border radius (8px).
</ResponseField>

<ResponseField name="--bonsai-radius-xl" default="0.75rem">
  Extra large border radius (12px). **Declared but not consumed by the SDK — setting it currently has no effect.**
</ResponseField>

<ResponseField name="--bonsai-radius-full" default="9999px">
  Full border radius for pill-shaped elements.
</ResponseField>

#### Animation

<ResponseField name="--bonsai-duration-fast" default="150ms">
  Fast animation duration for quick transitions.
</ResponseField>

<ResponseField name="--bonsai-duration-base" default="200ms">
  Base animation duration for standard transitions.
</ResponseField>

<ResponseField name="--bonsai-duration-slow" default="300ms">
  Slow animation duration for emphasized transitions.
</ResponseField>

<ResponseField name="--bonsai-easing" type="timing-function" default="cubic-bezier(0, 0, 0.2, 1)">
  Easing function for smooth animations.
</ResponseField>

#### Shadow

<ResponseField name="--bonsai-shadow-sm" type="shadow" default="0 1px 2px 0 rgb(0 0 0 / 0.05)">
  Small shadow for subtle elevation. **Declared but not consumed by the SDK — setting it currently has no effect.**
</ResponseField>

<ResponseField name="--bonsai-shadow-md" type="shadow" default="0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)">
  Medium shadow for moderate elevation. **Declared but not consumed by the SDK — setting it currently has no effect.**
</ResponseField>

<ResponseField name="--bonsai-shadow-lg" type="shadow" default="0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)">
  Large shadow for prominent elevation.
</ResponseField>

#### Layout

<ResponseField name="--bonsai-search-min-height" default="3.5rem">
  Minimum height for the search bar (56px). **Declared but not consumed by the SDK — setting it currently has no effect.**
</ResponseField>

<ResponseField name="--bonsai-search-max-width" default="42rem">
  Maximum width for the search container (672px).
</ResponseField>

<ResponseField name="--bonsai-icon-size" default="1.25rem">
  Standard icon size (20px). **Declared but not consumed by the SDK — setting it currently has no effect.**
</ResponseField>

<ResponseField name="--bonsai-icon-size-sm" default="1rem">
  Small icon size (16px).
</ResponseField>

<ResponseField name="--bonsai-results-columns" default="3">
  Number of columns in the results grid layout.
</ResponseField>

<ResponseField name="--bonsai-image-object-fit" default="cover">
  CSS object-fit value for product images. Options: `cover` or `contain`.
</ResponseField>

## Dark theme

<Callout color="#B45309" icon="triangle-alert">
  **`theme="dark"` cannot be re-coloured.** Its palette is declared on an element inside the component's shadow root, so page CSS, inline `style=""`, `!important`, and Settings-API colours are all outranked. The 21 variables below are discarded whenever `theme` resolves to `dark` — including `theme="auto"` on a visitor whose system prefers dark.
</Callout>

### The 21 variables `theme="dark"` takes over

| Variable | Dark value |
| - | - |
| `--bonsai-text-color` | `#e5e7eb` |
| `--bonsai-results-text-color` | `#e5e7eb` |
| `--bonsai-card-text-color` | `#e5e7eb` |
| `--bonsai-suggestions-text-color` | `#303030` |
| `--bonsai-input-text-color` | `#303030` |
| `--bonsai-muted-color` | `#a1a1aa` |
| `--bonsai-input-bg` | `#ffffff` |
| `--bonsai-card-bg` | `transparent` |
| `--bonsai-canvas-color` | `#0f1115` **Declared but not consumed by the SDK — setting it currently has no effect.** |
| `--bonsai-surface-color` | `#181a20` |
| `--bonsai-border-color` | `rgba(255, 255, 255, 0.08)` |
| `--bonsai-border-color-hover` | `rgba(255, 255, 255, 0.14)` |
| `--bonsai-hover-bg` | `rgba(255, 255, 255, 0.06)` |
| `--bonsai-suggestions-hover-bg` | `rgba(0, 0, 0, 0.04)` |
| `--bonsai-error-bg` | `rgba(248, 113, 113, 0.15)` |
| `--bonsai-error-color` | `#fca5a5` |
| `--bonsai-skeleton-base` | `rgba(255, 255, 255, 0.04)` |
| `--bonsai-skeleton-highlight` | `rgba(255, 255, 255, 0.08)` |
| `--bonsai-shadow-sm` | `0 1px 2px 0 rgb(0 0 0 / 0.5)` **Declared but not consumed by the SDK — setting it currently has no effect.** |
| `--bonsai-shadow-md` | `0 4px 6px -1px rgb(0 0 0 / 0.55), 0 2px 4px -2px rgb(0 0 0 / 0.5)` **Declared but not consumed by the SDK — setting it currently has no effect.** |
| `--bonsai-shadow-lg` | `0 10px 15px -3px rgb(0 0 0 / 0.6), 0 4px 6px -4px rgb(0 0 0 / 0.55)` |

Everything else — `--bonsai-brand-color`, the fonts, spacing, radii, `--bonsai-search-max-width`, `--bonsai-image-object-fit`, `--bonsai-content-padding`, `--bonsai-card-radius`, `--bonsai-image-radius` — is untouched by the theme and can be set normally.

### How to build a dark embed you control

**Set `theme="light"` and supply the dark palette yourself.** On the light theme nothing inside the shadow root re-declares these variables, so every value on the element takes effect.

The block below is the built-in dark palette, copied out so you can edit it. A component with `theme="light"` and this CSS looks the same as `theme="dark"` — the difference is that these lines now work.

Start from this block, which reproduces the built-in dark palette exactly, and change the values you want:

```html theme={null}
<style>
  bonsai-search {
    --bonsai-text-color: #e5e7eb;
    --bonsai-results-text-color: #e5e7eb;
    --bonsai-card-text-color: #e5e7eb;
    --bonsai-suggestions-text-color: #303030;
    --bonsai-input-text-color: #303030;
    --bonsai-muted-color: #a1a1aa;
    --bonsai-input-bg: #ffffff;
    --bonsai-card-bg: transparent;
    --bonsai-canvas-color: #0f1115;
    --bonsai-surface-color: #181a20;
    --bonsai-border-color: rgba(255, 255, 255, 0.08);
    --bonsai-border-color-hover: rgba(255, 255, 255, 0.14);
    --bonsai-hover-bg: rgba(255, 255, 255, 0.06);
    --bonsai-suggestions-hover-bg: rgba(0, 0, 0, 0.04);
    --bonsai-error-bg: rgba(248, 113, 113, 0.15);
    --bonsai-error-color: #fca5a5;
    --bonsai-skeleton-base: rgba(255, 255, 255, 0.04);
    --bonsai-skeleton-highlight: rgba(255, 255, 255, 0.08);
    --bonsai-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.5);
    --bonsai-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.55), 0 2px 4px -2px rgb(0 0 0 / 0.5);
    --bonsai-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.6), 0 4px 6px -4px rgb(0 0 0 / 0.55);
  }
</style>

<bonsai-search api-key="API-KEY" theme="light"></bonsai-search>
```

<Callout color="#0A5B3B" icon="circle-alert">
  Copy the **whole** block, not only the lines you want to change. `theme="light"` puts the component on the light palette, so any variable you leave out falls back to a light default — an invisible `rgba(0, 0, 0, 0.06)` border on a black page, for example.
</Callout>

### Following the system preference

`theme="auto"` is subject to the same restriction, so drive it from your own media query instead:

```css theme={null}
bonsai-search {
  --bonsai-text-color: #303030;
  --bonsai-card-text-color: #303030;
  /* ...the rest of your light palette... */
}

@media (prefers-color-scheme: dark) {
  bonsai-search {
    --bonsai-text-color: #e5e7eb;
    --bonsai-card-text-color: #e5e7eb;
    /* ...the rest of the dark block above... */
  }
}
```

### If you must keep `theme="dark"`

Use [Shadow Parts](#shadow-parts). `::part()` rules are written from your page against elements the component exposes, and they set properties directly rather than through an inherited variable, so they are not affected:

```css theme={null}
bonsai-search::part(result-card) {
  background: #f4f3f1;
}

bonsai-search::part(result-title),
bonsai-search::part(result-caption),
bonsai-search::part(result-price) {
  color: #111111;
}
```

<Callout color="#0A5B3B" icon="circle-alert">
  Recolour the caption and price alongside the title. They inherit `--bonsai-card-text-color`, which under `theme="dark"` stays light — on a light card the caption renders near-invisible at its 0.7 opacity.
</Callout>

## Shadow Parts

The web component uses a closed shadow root, but it exposes stable `part` hooks for external styling. This lets you style specific inner elements with `::part(...)` from outside the component.

`::part(...)` is supported in modern evergreen browsers. For older browsers, prefer CSS variables or wrapper styling.

**Example (full part customization):**

```html theme={null}
<style>
  bonsai-search::part(search-wrapper) {
    padding: 1.5rem;
    border: 1px solid #262626;
    border-radius: 18px;
    background: linear-gradient(180deg, #0b0b0b 0%, #0f0f0f 100%);
  }

  bonsai-search::part(search-bar) {
    border-radius: 14px;
    border: 1px solid #303030;
    background: #111111;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  }

  bonsai-search::part(search-icon) {
    color: #c9a77a;
  }

  bonsai-search::part(search-input) {
    color: #f7f3ee;
    letter-spacing: 0.01em;
  }

  bonsai-search::part(search-actions) {
    gap: 0.25rem;
  }

  bonsai-search::part(submit-button) {
    background: #c9a77a;
    color: #111111;
    border-radius: 10px;
  }

  bonsai-search::part(loading-state) {
    background: #161616;
    border-radius: 10px;
  }

  bonsai-search::part(loading-text) {
    color: #c9a77a;
  }

  bonsai-search::part(loading-text-inner) {
    font-weight: 600;
  }

  bonsai-search::part(spinner) {
    color: #c9a77a;
  }

  bonsai-search::part(suggestions) {
    background: #101010;
    border: 1px solid #2a2a2a;
  }

  bonsai-search::part(suggestion-item) {
    border-radius: 10px;
  }

  bonsai-search::part(suggestion-text) {
    color: #f3f4f6;
  }

  bonsai-search::part(suggestion-icon) {
    color: #c9a77a;
  }

  bonsai-search::part(powered-by) {
    color: #9ca3af;
  }

  bonsai-search::part(results) {
    padding: 1rem 0 0 0;
  }

  bonsai-search::part(results-section) {
    border-top: 1px dashed #2a2a2a;
    padding-top: 1.25rem;
  }

  bonsai-search::part(results-header) {
    color: #c9a77a;
  }

  bonsai-search::part(results-grid) {
    gap: 1.25rem;
  }

  bonsai-search::part(summary) {
    padding: 1rem 1.25rem;
    border-radius: 14px;
    background: #0f0f0f;
    border: 1px solid #262626;
  }

  bonsai-search::part(summary-text) {
    color: #e5e7eb;
  }

  bonsai-search::part(also-like) {
    margin-top: 1rem;
  }

  bonsai-search::part(also-like-header) {
    color: #c9a77a;
    letter-spacing: 0.06em;
  }

  bonsai-search::part(result-card) {
    background: #111111;
    border: 1px solid #262626;
    border-radius: 16px;
    overflow: hidden;
  }

  bonsai-search::part(result-image-wrapper) {
    background: #0b0b0b;
  }

  bonsai-search::part(result-image) {
    filter: saturate(0.95);
  }

  bonsai-search::part(result-content) {
    padding: 0.75rem 0.9rem;
  }

  bonsai-search::part(result-title) {
    color: #f9fafb;
  }

  bonsai-search::part(result-price-container) {
    gap: 0.35rem;
  }

  bonsai-search::part(result-price) {
    color: #c9a77a;
  }

  bonsai-search::part(result-compare-at) {
    color: #6b7280;
  }

  bonsai-search::part(result-caption) {
    color: #d1d5db;
  }

  bonsai-search::part(loading-thumbs) {
    border: 1px dashed #2a2a2a;
    border-radius: 12px;
  }

  bonsai-search::part(spinner) {
    color: #c9a77a;
  }

  bonsai-search::part(loading-text) {
    color: #e5e7eb;
  }

  bonsai-search::part(empty-state) {
    color: #9ca3af;
    background: #0f0f0f;
    border-radius: 12px;
    padding: 1rem;
  }

  bonsai-search::part(error) {
    background: #2a0f12;
    border: 1px solid #7f1d1d;
    color: #fecaca;
    padding: 0.75rem 1rem;
    border-radius: 10px;
  }
</style>
```

### Reference Table

| Group | Part | Description |
| - | - | - |
| Search | `search-wrapper` | Outer wrapper |
| Search | `search-bar` | Input container |
| Search | `search-icon` | Left icon |
| Search | `search-input` | Input field |
| Search | `search-actions` | Action button container |
| Search | `submit-button` | Submit action |
| Search | `loading-state` | Loading pill |
| Search | `loading-text` | Loading text |
| Search | `loading-text-inner` | Emphasized loading text |
| Search | `spinner` | Loading spinner |
| Suggestions | `suggestions` | Suggestions container |
| Suggestions | `suggestion-item` | Suggestion row |
| Suggestions | `suggestion-text` | Suggestion text |
| Suggestions | `suggestion-icon` | Suggestion leading icon |
| Suggestions | `suggestion-image` | Suggestion thumbnail |
| Suggestions | `suggestion-match` | Matched substring in a suggestion |
| Footer | `powered-by` | Powered by footer |
| Footer | `powered-by-link` | Powered by link |
| Footer | `powered-by-dot` | Powered by separator |
| Results | `results` | Results container |
| Results | `results-section` | Results section |
| Results | `results-header` | Results header |
| Results | `results-grid` | Results grid |
| Results | `summary` | AI summary container |
| Results | `summary-text` | AI summary text |
| Cards | `result-card` | Result card |
| Cards | `result-image-wrapper` | Result image wrapper |
| Cards | `result-image` | Result image |
| Cards | `result-image-alternate` | Secondary image shown on hover |
| Cards | `result-content` | Result content |
| Cards | `result-title` | Result title |
| Cards | `result-price-container` | Price wrapper |
| Cards | `result-price` | Price |
| Cards | `result-compare-at` | Compare-at price |
| Cards | `result-caption` | Description |
| States | `empty-state` | Empty state |
| States | `error` | Error state |
| Layout | `outer-container` | Component outer container |
| Layout | `inner-container` | Component inner container |
| Layout | `content` | Content region |
| Results | `also-like` | "You may also like" section |
| Results | `also-like-header` | "You may also like" header |
| Sort | `sort` | Sort control wrapper |
| Sort | `sort-select` | Sort `<select>` |
| Filters | `filter-panel` | Filter panel |
| Filters | `filter-panel-inner` | Filter panel inner wrapper |
| Filters | `filter-header` | Filter panel header |
| Filters | `filter-title` | Filter panel title |
| Filters | `filter-group` | One filter dimension |
| Filters | `filter-group-title` | Filter dimension title |
| Filters | `filter-options` | Options list |
| Filters | `filter-option` | One option |
| Filters | `filter-range` | Range control |
| Filters | `filter-apply` | Apply button |
| Filters | `filter-clear` | Clear button |
| Refine | `refine` | Refinement block |
| Refine | `refine-question` | Refinement question |
| Refine | `refine-options` | Refinement options |
| Refine | `refine-option` | One refinement option |
| Refine | `refine-step` | Refinement step |
| Loading | `loading-thumbs` | Skeleton thumbnail grid |
| Loading | `loading-thumb` | One skeleton thumbnail |
| Search | `clear-button` | Clear-query button |
| Search | `close-button` | Close button |

## Customization Tips

### Theme Defaults vs. Overrides

`theme="light"` (the default) sets a palette of light defaults for surfaces, borders, shadows, and text. Any `--bonsai-*` custom property you set on the host overrides those defaults, because they are declared at `:host` inside the shadow root and your page sits outside it.

`theme="dark"` behaves differently, and the difference is not cosmetic: its palette is declared on an element **inside** the shadow root, which your page cannot reach by selector. Under `theme="dark"` the 21 variables listed in [Dark theme](#dark-theme) ignore anything you set. See that section for the supported way to build a dark embed.

`theme="auto"` resolves to `light` or `dark` from the visitor's `prefers-color-scheme`, so on a dark-preference machine it has exactly the dark behaviour above. Treat `auto` as dark for styling purposes.

### Where styling values come from

Precedence, highest to lowest:

1. **The active `theme`'s dark palette** — only when `theme` resolves to `dark`, and only for the 21 variables it declares. Nothing below can override these.
2. **Your page CSS** — any `--bonsai-*` variable set on the `<bonsai-search>` element itself. Not an ancestor and not `:root`: the SDK declares its defaults on `:host`, and a direct declaration always beats an inherited one.
3. **Settings API** — values configured per-tenant from the Bonsai dashboard; the component injects a low-specificity `:host { ... }` block of CSS variables into its shadow DOM at load time. Because this is a `:host` block, it is also outranked by the dark palette.
4. **Built-in light defaults.**

Set defaults once in the Settings API to theme all embeds for a tenant; only write page CSS when you need to override a specific embed. If the embed is dark, read [Dark theme](#dark-theme) first — neither route reaches those 21 variables.

### Wrapper Styling

The example includes a wrapper `<div>` with custom CSS to control the component's width and positioning. You can modify these styles to match your site's layout:

```css theme={null}
.bonsai-search-outer-container {
  width: 100%;
  max-width: 42rem; /* Adjust maximum width */
  margin: 4rem auto; /* Adjust vertical and horizontal spacing */
  min-height: 350px; /* Ensure minimum height for layout stability */
}
```

### Color Scheme

Choose colors that match your brand identity. The component uses your specified colors throughout the interface:

* **`--bonsai-brand-color`**: Used for primary actions and highlights
* **`--bonsai-text-color`**: Used for main content text
* **`--bonsai-muted-color`**: Used for secondary information
* **Background colors**: Control the overall appearance
  * `--bonsai-input-bg` affects the input *and* the dropdown background
  * `--bonsai-card-bg` affects result cards
  * `--bonsai-surface-color` affects elevated surfaces such as the image placeholder
  * `--bonsai-canvas-color` is **not read by the SDK** — the component draws no page background of its own. Set the background on your own container or `<body>` instead

### Suggestions Best Practices

Create suggestions that:

* Address common customer questions
* Highlight popular products or features
* Use natural, conversational language
* Are specific to your product catalog


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.