# Theming

Match your site with the form's tokens, CSS variables and parts.

The form draws inside its own shadow root, so your site's CSS never changes it by accident. You style it on purpose in three ways: pick a preset and colors on the form's **Style** tab, set its CSS variables from your own stylesheet, and style its named parts. On Max you can also add custom CSS inside the form.

## Presets

Choose one on the form's **Style** tab:

| Preset | Look |
|---|---|
| **Light** | The default. White card, dark text. |
| **Dark** | Dark card, light text. |
| **Auto** | Light or dark with the visitor's system setting (`prefers-color-scheme`). |
| **Paper** | A warm off white card. |
| **Match my site** | Takes your page's font and text color, on a clear background with a neutral grey accent and no shadow. |

**Auto** follows the visitor's system setting, not a dark mode switch on your site. To follow your own switch, set the tokens yourself under the selector your switch uses (below).

## Tokens

The form's look comes from eleven CSS custom properties. Custom properties cross the shadow boundary, so you can set them on the element from your own CSS:

```css styles.css
onestar-feedback {
  --os-font: inherit;
  --os-bg: #ffffff;
  --os-surface: #f4f4f2;
  --os-text: #17181c;
  --os-muted: #62656d;
  --os-border: #e2e2dc;
  --os-accent: #c98a1e;
  --os-accent-text: #17181c;
  --os-radius: 12px;
  --os-gap: 12px;
  --os-shadow: 0 8px 24px rgb(0 0 0 / 0.12);
}
```

| Token | Used for | Light default |
|---|---|---|
| `--os-font` | Every piece of text | The system font |
| `--os-bg` | The card's background | `#ffffff` |
| `--os-surface` | Options, inputs and messages | `#f4f4f2` |
| `--os-text` | Questions and answers | `#17181c` |
| `--os-muted` | Help text, labels and the notice | `#62656d` |
| `--os-border` | Borders and empty stars | `#e2e2dc` |
| `--os-accent` | Selected options, filled stars, the main button, focus rings, the floating tab | `#c98a1e` |
| `--os-accent-text` | Text on the accent | `#17181c` |
| `--os-radius` | Corner radius of the card (controls use a share of it) | `12px` |
| `--os-gap` | Space between parts of the card | `12px` |
| `--os-shadow` | The card's shadow (inline forms draw none) | `0 8px 24px rgb(0 0 0 / 0.12)` |

The layers apply in this order, later winning: the preset, then the colors and sizes saved on the **Style** tab, then anything your CSS sets on the element. So the **Style** tab sets the form's look everywhere it runs, and your CSS adjusts it for one site.

To follow your own dark mode switch:

```css styles.css
[data-theme="dark"] onestar-feedback {
  --os-bg: #151a24;
  --os-surface: #1e2533;
  --os-text: #e8ecf3;
  --os-muted: #9aa3b5;
  --os-border: #2c3446;
  --os-accent: #e0a43f;
  --os-accent-text: #151a24;
}
```

A font set in `--os-font` must already be on your page: a font your page loads with `@font-face` works inside the form too. When you change `--os-accent`, check that `--os-accent-text` still reads on it; the **Style** tab shows the contrast of each pair.

### Values the Style tab accepts

Your own CSS can set any value. Tokens saved on the form are checked, since they apply wherever the form runs:

- Colors as hex, `rgb()`, `rgba()`, `hsl()` or `hsla()`, or `transparent`, `currentColor` or `inherit`.
- `--os-radius` and `--os-gap` in whole pixels, such as `8px`.
- Fonts as a list of family names, with no URLs.

## Sizes are in pixels

Every size inside the form is in px: 14px text, 16px questions. Your page's root font size and `rem` units never change the form, so it looks the same on every site. The card is up to 520px wide inline, 640px in `page` mode, 360px in a popover or slide-in and 440px in a modal, and never wider than the screen.

## Parts

Named parts can be styled from outside with `::part()`:

| Part | Element |
|---|---|
| `card` | The card around the form |
| `title` | The form's title in the card head, and the thank you heading |
| `form-title` | The form's title in the card head only |
| `prompt` | Each question |
| `option` | Each option button, star, face, list choice and ranking item |
| `option-selected` | The selected option (it also carries `option`) |
| `input` | Text inputs, text areas, the slider and the contact fields |
| `button` | The main button: Next, Send, and Send in a conversation |
| `button-secondary` | Back, Skip, Retry, Reload, Read, Close and the ranking's move buttons |
| `footer` | The line holding the badge |
| `badge` | The "Feedback by OneStar" link |
| `trigger` | The popover's floating tab |

```css styles.css
onestar-feedback::part(button) {
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
onestar-feedback::part(trigger) {
  bottom: 24px;
}
```

`::part()` styles only the part itself, not what is inside it, and the form's own CSS still decides layout. Prefer tokens for colors and spacing, and parts for the odd finishing touch.

## Custom CSS (Max)

On Max, the **Style** tab has a **Custom CSS** box. Its rules are added inside the form's shadow root after the tokens, so they can reach anything in the form:

- It runs only where the form is embedded on your own sites. The form's own page on OneStar and the page for apps use the preset and tokens only.
- It cannot import files, load URLs (`url()`, `@import`, `@font-face`) or use backslash escapes, and it is up to 10,000 characters.
- Class names inside the form are not a stable interface and may change. Write against parts and tokens where you can.

## The badge

Forms show a small "Feedback by OneStar" link under the card. On Max you can turn it off in the form's **Settings**. To restyle it instead, use the `badge` and `footer` parts.

## Floating tab

The popover's floating tab uses `--os-font`, `--os-accent`, `--os-accent-text` and `--os-shadow`, and its text is the `label` attribute. Style it with `::part(trigger)`, or skip it and open the popover from your own button with `trigger-for` ([Modes and triggers](https://onestar.sh/docs/feedback/modes-and-triggers.md)).
