> For the complete documentation index, see [llms.txt](https://docs.tern.eco/v1/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tern.eco/v1/storefront-integration/storefront-integration/storefront-styling-guide.md).

# Storefront styling guide

## Purpose

This guide explains how to restyle the **Returns Centre** — the trade-in widget Tern renders on your storefront — so it matches the rest of your site. It applies whether Tern embeds the widget for you or you mount `<tern-trade-in>` yourself using one of the integration guides in this section.

The Returns Centre picks up your shop's fonts and colours automatically, but you can go further. There are two ways to change how it looks, and both live in the Tern admin under **Copy Customisation**:

1. **Theme settings** — colours, fonts and corner rounding that restyle the whole widget consistently. No CSS knowledge needed. Start here.
2. **Custom CSS** — your own style rules, for fine-grained control over individual parts of the widget.

Everything on this page is **supported**: it will keep working from release to release. We add new options over time, but we don't rename or remove anything listed here without telling you first.

## Terminology

A few terms this guide uses precisely:

* **The widget** — the Returns Centre UI, rendered inside the `<tern-trade-in>` element on your page. Its root element is `#trn-app`.
* **Theme variable** — a CSS custom property (also called a CSS variable) with a `--trn-` prefix. These are the widget's design tokens: named values for colours, fonts and corner rounding that the whole UI reads from.
* **Styling hook** — a stable class name with a `.trn-` prefix (for example `.trn-button`). These follow a BEM-flavoured naming scheme (`block__element--modifier`) and are the supported targets for custom CSS.
* **Utility class** — a short, generated class such as `mt-6` or `flex`. These are build output, not a stable API — see [What not to target](#what-not-to-target).

## How your styles reach the widget

The widget renders inside a **shadow root** attached to the `<tern-trade-in>` element. Shadow DOM is the browser's style-encapsulation mechanism: styles outside it don't leak in, and the widget's styles don't leak out onto your page.

Two practical consequences:

1. **Rules in your site's own stylesheets will not restyle the widget's internals.** The supported route is the **Custom CSS** field in Copy Customisation — Tern delivers that CSS inside the widget for you.
2. **The widget can never break your page's styling**, however heavily you customise it.

Your custom CSS is applied **after** the widget's own styles and always takes precedence — you never need `!important` to override us (existing `!important` rules keep working fine).

> **For CSS experts:** the widget's own styles live in named cascade layers, while your custom CSS is injected unlayered after them. Per the cascade, unlayered author styles beat layered ones regardless of specificity — that's why a plain `#trn-app .trn-button { … }` rule always wins.

## 1. Theme settings (colours, fonts, corners)

These are applied as theme variables on the widget. Most merchants set them through the theme fields in the admin; if you prefer, you can also set them yourself at the top of your custom CSS:

```css
#trn-app {
  --trn-brand: #0f4c81;
  --trn-radius-md: 12px;
}
```

**Colour format:** colours are plain hex codes, used exactly like any other CSS colour — no `rgb()` wrapper needed:

```css
/* ✓ works */ --trn-error: #c6454a;
```

### Brand

Your accent colour — used for buttons and the widget's other key accents.

| Variable         | What it changes                               |
| ---------------- | --------------------------------------------- |
| `--trn-brand`    | Buttons and key accents — your "brand" colour |
| `--trn-on-brand` | Text on those buttons                         |

### Page

Your base palette — the widget's background, card colour and main text colour.

| Variable           | What it changes                                                   |
| ------------------ | ----------------------------------------------------------------- |
| `--trn-background` | The widget's background                                           |
| `--trn-surface`    | Card and panel backgrounds (defaults to the background colour)    |
| `--trn-foreground` | Your ink colour — main text, and what your greys are derived from |

### Status

Colours for error and success messages, and for the status badges on the trade-in history pages.

| Variable        | What it changes                                   |
| --------------- | ------------------------------------------------- |
| `--trn-error`   | Error states                                      |
| `--trn-success` | Success states                                    |
| `--trn-warning` | Status badge colour for waiting states (amber)    |
| `--trn-info`    | Status badge colour for in-progress states (blue) |

### Corners

Corner rounding, in three sizes.

| Variable            | What it changes                                                                                                                       |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `--trn-radius-sm`   | Corner rounding on small elements — inputs, tags (default 4px)                                                                        |
| `--trn-radius-md`   | Corner rounding on cards and dialogs (default 8px)                                                                                    |
| `--trn-radius-full` | The "pill" radius used by buttons (default 9999px; lower it for squarer buttons, or use `--trn-button-radius` to change buttons only) |

### Derived colours

A further seven variables are computed automatically from your foreground and background colours, so cards, borders and secondary text always stay in proportion to the rest of your theme — you don't need to pick them by hand, and they keep up automatically if you change your page or brand colours later. Set one yourself only if you want to break that link and fix its value instead; like any other variable on this page, it can be overridden in your custom CSS.

| Variable                | What it changes                                                                 |
| ----------------------- | ------------------------------------------------------------------------------- |
| `--trn-surface-muted`   | Subtle tint on a card — callouts, empty states, hover fills, image placeholders |
| `--trn-surface-strong`  | A stronger tint on a card — heavier fills and higher-contrast callouts          |
| `--trn-text-muted`      | Secondary text                                                                  |
| `--trn-text-subtle`     | The least prominent text — captions, helper copy                                |
| `--trn-border`          | Standard borders and dividers                                                   |
| `--trn-border-subtle`   | Faint borders and dividers, close to the background colour                      |
| `--trn-button-bg-hover` | Button background on hover                                                      |

### Component-level theming

A second layer of variables restyles one part of the widget without touching the base palette — useful when, say, you want squarer buttons but everything else unchanged. Each defaults to the base colour/corner setting above, so you only need to set the ones you want to differ:

| Variable              | What it changes                                                          | Defaults to                |
| --------------------- | ------------------------------------------------------------------------ | -------------------------- |
| `--trn-button-bg`     | Button background specifically (independent of the general brand colour) | `--trn-brand`              |
| `--trn-button-text`   | Button text colour specifically                                          | `--trn-on-brand`           |
| `--trn-button-radius` | Button corner rounding                                                   | `--trn-radius-full` (pill) |
| `--trn-card-radius`   | Product/start-card corner rounding                                       | `--trn-radius-md`          |
| `--trn-card-shadow`   | Drop shadow on cards, e.g. `0 2px 8px rgba(0, 0, 0, 0.08)`               | none                       |
| `--trn-input-border`  | Form field border colour                                                 | `--trn-border`             |

```css
/* Square buttons, everything else untouched */
#trn-app {
  --trn-button-radius: 4px;
}
```

### Fonts and casing

| Variable                       | What it changes                                                                                                                                                                        |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--trn-font-body`              | Font for all text, e.g. `'Inter', sans-serif`. (`--font-main` is the legacy name for the same knob and is still honoured — the body font it holds flows through to `--trn-font-body`.) |
| `--trn-font-heading`           | Headings only (defaults to `--trn-font-body`)                                                                                                                                          |
| `--trn-heading-text-transform` | Set to `uppercase` to render headings in all caps; default `none`                                                                                                                      |
| `--trn-button-text-transform`  | Set to `uppercase` to render button labels in all caps; default `none`                                                                                                                 |

### Renamed variables

Some variables on this page previously went by different names. If your custom CSS **sets** one of the old names, it still works — the value flows through to its replacement automatically — but use the new names in anything you write from now on:

| Old name                        | New name                |
| ------------------------------- | ----------------------- |
| `--trn-button-background-color` | `--trn-brand`           |
| `--trn-button-text-color`       | `--trn-on-brand`        |
| `--trn-gray-1`                  | `--trn-button-bg-hover` |
| `--trn-gray-2`                  | `--trn-text-muted`      |
| `--trn-gray-3`                  | `--trn-text-subtle`     |
| `--trn-gray-4`                  | `--trn-border`          |
| `--trn-gray-5`                  | `--trn-surface-strong`  |
| `--trn-gray-6`                  | `--trn-border-subtle`   |
| `--trn-gray-light`              | `--trn-surface-muted`   |
| `--trn-border-inner`            | `--trn-radius-sm`       |
| `--trn-border-outer`            | `--trn-radius-md`       |
| `--trn-border-full`             | `--trn-radius-full`     |

One difference worth knowing: the old grey scale was a set of fixed colours, while the new derived colours are computed live from your foreground and background — so they now stay in step when you change your base palette, instead of needing to be re-picked.

## 2. Custom CSS

Two habits make your CSS reliable:

* **Start every rule with `#trn-app`** so it can only affect the widget, never the rest of your page.
* **Target the supported styling hooks below** — they are stable across releases.

### Recipes

```css
/* Restyle the main button */
#trn-app .trn-button {
  background: #0f4c81;
  border-radius: 6px;
}

/* The secondary (outlined) button */
#trn-app .trn-button.trn-button--outlined {
  border-width: 2px;
}

/* Product cards */
#trn-app .trn-product-card {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

/* Headings inside the widget */
#trn-app .h2 {
  letter-spacing: 0.02em;
}

/* Reuse your theme colours anywhere — no wrapping needed */
#trn-app .trn-alert {
  border-color: var(--trn-error);
}

/* Modal dialogs */
#trn-app .trn-modal__card {
  border-radius: 10px;
}
```

### Replacing the start-page card artwork

The cards on the start page ("trade in from your order history" / "registered products") ship with built-in illustrations. You can swap in your own artwork with custom CSS alone — no upload to Tern needed, just an image hosted at a public URL. If you're on Shopify, **Content → Files** in your Shopify admin gives you a CDN URL in two clicks.

Any image format the browser can load works: **SVG, PNG, WebP, JPEG or GIF**. SVG or a transparent PNG will look best against the card background.

```css
/* 1. Hide the built-in illustration (its 80×80px box stays as the frame) */
#trn-app .trn-start-card__icon path { display: none; }

/* 2. Show your own image inside that frame */
#trn-app .trn-start-card__icon {
  background: url(https://cdn.shopify.com/s/files/.../my-artwork.svg) center / contain no-repeat;
}
```

To size the frame differently, set `width` and `height` on `.trn-start-card__icon` in the same rule.

**A different image per card** — the register / product-catalogue card carries a `.trn-start-card--register` modifier:

```css
#trn-app .trn-start-card__icon path { display: none; }

/* order-history card */
#trn-app .trn-start-card .trn-start-card__icon {
  background: url(.../history.svg) center / contain no-repeat;
}

/* registered-products card (keep this rule after the one above) */
#trn-app .trn-start-card--register .trn-start-card__icon {
  background: url(.../register.svg) center / contain no-repeat;
}
```

**A different image per section** — if you have both trade-ins and repairs enabled, the two start pages share the same cards. To vary the artwork by section, scope the rule with the card-row hooks `.trn-start-cards--trade-in` and `.trn-start-cards--repairs`:

```css
#trn-app .trn-start-cards--repairs .trn-start-card__icon {
  background: url(.../repairs.svg) center / contain no-repeat;
}
```

**Matching the theme colour** — the built-in illustrations are drawn in your foreground colour. If you want your artwork tinted the same way, use it as a `mask` instead of a background: the image's own colours are ignored and its shape is filled with the current text colour (`currentColor`). This variant needs an image with transparency (SVG or transparent PNG/WebP — a JPEG won't work as a mask):

```css
#trn-app .trn-start-card__icon path { display: none; }

#trn-app .trn-start-card__icon {
  background-color: currentColor;
  mask: url(.../my-artwork.svg) center / contain no-repeat;
}
```

One thing to keep in mind: the image stays on your server, so if it's ever deleted or moved the cards will show an empty space until the URL is fixed.

### Supported styling hooks (stable)

**Naming pattern:** hook names follow one grammar, so once you know it you can predict a name before you look it up. A block starts with the `trn-` prefix, e.g. `.trn-product-card`; a part inside it is the block name plus `__element`, e.g. `.trn-product-card__image`; a variant or state is the block name plus `--modifier`, e.g. `.trn-button--outlined` or `.trn-option--selected`. States are always modifiers, never bare classes — look for `--selected` / `--open` / `--active`, not `.selected` / `.open` / `.active`.

**Finding the right hook:** you don't have to work from this page alone. In the Tern admin, the **CSS tab** of the Copy Customisation screen has a built-in hook viewer — hover over any part of the preview and it highlights that element and the containers around it, listing the hooks on each, so you can see exactly what to target before you write the rule.

The hooks are grouped in the order your customers meet them — the path through the widget first, then the pieces that appear on every page. Each area separates **layout wrappers** — structural containers you'd target for spacing, width or positioning — from **components** — the visible pieces you'd restyle. Every hook has its own entry; simple ones list their parts inline, and anything richer gets a small table breaking its parts down by kind: **Element** — a `__` part inside it, **Variant** — a `--` kind it comes in, **State** — a `--` condition it can enter.

#### The widget at a glance

```
#trn-app                          widget root — start every rule here
└─ .trn-app-wrapper               main layout
   ├─ .trn-navbar                 top navigation
   ├─ (the current page)
   │   ├─ start page:             .trn-start-cards › .trn-start-card
   │   ├─ item picker:            .trn-pick-your-items › .trn-card-grid › .trn-product-card
   │   ├─ checkout steps:         .trn-wizard › .trn-checkout (one step modifier each)
   │   │                             ├─ .trn-cart-items / .trn-checkout-summary
   │   │                             └─ .trn-summary-sidebar
   │   ├─ outcome pages:          .trn-checkout--outcome › .trn-outcome
   │   └─ history & details:      .trn-history-header, .trn-accordion, .trn-details-card
   └─ .trn-footer                 footer

overlays:          .trn-modal — dialog chrome; the questions flow (.trn-questions) opens in one
outside #trn-app:  .trn-refund-modal — the refund widget's popup chrome (see below)
```

The nesting here is indicative — it shows which hooks you'll find within which regions, not the exact markup (extra wrappers between them can change; see [What not to target](#what-not-to-target)). The class names themselves are the stable contract.

#### Start page

**Layout wrappers**

**`.trn-start-cards`** — the row holding the start-page cards

* **Variants:** `.trn-start-cards--trade-in` / `.trn-start-cards--repairs` — which section's start page the row is on

**Components**

**`.trn-start-card`** — one start-page card

* **Elements:** `.trn-start-card__icon` — the card's illustration
* **Variants:** `.trn-start-card--register` — the registered-products card

#### Picking items

**Layout wrappers**

**`.trn-pick-your-items`** — the item-picker page

| Kind    | Hook                            | What it is                 |
| ------- | ------------------------------- | -------------------------- |
| Variant | `.trn-pick-your-items--orders`  | The order-history view     |
| Variant | `.trn-pick-your-items--catalog` | The product-catalogue view |
| Variant | `.trn-pick-your-items--repairs` | The repairs view           |

**`.trn-card-grid`** — the grid a set of cards is laid out in (order history, registered products, repairs)

**`.trn-catalog`** — the register-a-product / product-catalogue browser

**Components**

**`.trn-product-card`** — a product card

| Kind    | Hook                                  | What it is                                        |
| ------- | ------------------------------------- | ------------------------------------------------- |
| Element | `.trn-product-card__image`            | The product image                                 |
| Element | `.trn-product-card__info`             | The card's text area                              |
| Element | `.trn-product-card__title`            | The product title                                 |
| Element | `.trn-product-card__price`            | The price area                                    |
| Element | `.trn-product-card__variant`          | The variant/option title                          |
| Element | `.trn-product-card__date`             | The purchase date                                 |
| Element | `.trn-product-card__check`            | The selected checkmark badge                      |
| Element | `.trn-product-card__unavailable-note` | The "not eligible" note                           |
| Variant | `.trn-product-card--placeholder`      | A loading skeleton card                           |
| Variant | `.trn-product-card--prompt`           | The register-a-product / browse-more prompt cards |
| State   | `.trn-product-card--selected`         | While the card is selected                        |
| State   | `.trn-product-card--unavailable`      | When the item isn't eligible                      |

**`.trn-carousel`** — the featured-products carousel

| Kind    | Hook                       | What it is                  |
| ------- | -------------------------- | --------------------------- |
| Element | `.trn-carousel__title`     | Its heading                 |
| Element | `.trn-carousel__nav`       | The prev/next arrow buttons |
| Variant | `.trn-carousel__nav--prev` | The previous arrow          |
| Variant | `.trn-carousel__nav--next` | The next arrow              |

**`.trn-thumb`** — the square product/item thumbnail, wherever one appears (cards, cart rows, the summary sidebar)

**`.trn-category-card`** — the category browse cards

**`.trn-breadcrumbs`** — the catalogue breadcrumb trail

* **Elements:** `.trn-breadcrumbs__item` — each crumb

**`.trn-search`** — the product search bar

* **Elements:** `.trn-search__suggestions` — the dropdown panel; `.trn-search__suggestion` — each row in it

**`.trn-actions-bar`** — the selection counter / next-step bar under the item-picker grids

* **Elements:** `.trn-actions-bar__info` — its text

#### Condition questions

**Layout wrappers**

**`.trn-option-group`** — a group of answer options

* **Elements:** `.trn-option-group__header` — its heading

**Components**

**`.trn-questions`** — the condition-questions dialog (trade-ins and repairs)

| Kind    | Hook                                    | What it is                           |
| ------- | --------------------------------------- | ------------------------------------ |
| Element | `.trn-questions__progress`              | The step progress bar                |
| Element | `.trn-questions__progress-step`         | One step in the bar                  |
| Variant | `.trn-questions--compact`               | A tighter presentation of the dialog |
| State   | `.trn-questions__progress-step--active` | The current step                     |

**`.trn-question`** — one question

**`.trn-option`** — an individual answer pill or variant swatch

* **Elements:** `.trn-option__check` — the checkmark badge
* **States:** `.trn-option--selected`

**`.trn-item-summary`** — the "your item" recap panel shown alongside the questions

#### Checkout steps

**Layout wrappers**

**`.trn-checkout`** — the two-column shell every checkout step and the outcome pages sit in

| Kind    | Hook                          | What it is               |
| ------- | ----------------------------- | ------------------------ |
| Variant | `.trn-checkout--cart`         | The cart step            |
| Variant | `.trn-checkout--address`      | The contact-details step |
| Variant | `.trn-checkout--shipping`     | The shipping step        |
| Variant | `.trn-checkout--confirmation` | The confirmation step    |
| Variant | `.trn-checkout--outcome`      | The outcome pages        |

> `.trn-shipping`, previously listed on the checkout shell, has been removed — it duplicated `.trn-checkout` on every step. Use `.trn-checkout--shipping` to reach the shipping step only.

**`.trn-cart-items`**, **`.trn-checkout-summary`**, **`.trn-summary-sidebar`** — the three checkout regions inside the shell

**`.trn-summary-list`** — the itemised list inside the order summary and the reward-choice cards

**`.trn-carrier-options`** — the shipping-options list

**Components**

**`.trn-checkout-item`** — a cart/confirmation line-item row

| Kind    | Hook                          | What it is               |
| ------- | ----------------------------- | ------------------------ |
| Element | `.trn-checkout-item__name`    | The item name            |
| Element | `.trn-checkout-item__variant` | The variant/option title |
| Element | `.trn-checkout-item__price`   | The price                |
| Element | `.trn-checkout-item__actions` | The row's actions area   |

**`.trn-summary-total`** — the total row beneath the summary list

**`.trn-reward-choice`** — the cash-or-product reward picker

* **Elements:** `.trn-reward-choice__option` — each choice
* **States:** `.trn-reward-choice__option--selected` — the chosen one

**`.trn-carrier-option`** — one row in the shipping-options list

* **States:** `.trn-carrier-option--selected` — the chosen row

**`.trn-cart-badge`** — the wizard's cart button

* **Elements:** `.trn-cart-badge__count` — the item-count bubble

**`.trn-panel`** — the bordered panel each block of wizard content sits in (cart, contact details, shipping, confirmation); also used by collapsible sections

#### Outcome pages

**`.trn-outcome`** — the block wrapping the "thank you" / "requested" / "rejected" outcome pages (inside the `.trn-checkout--outcome` shell)

| Kind    | Hook                      | What it is                                     |
| ------- | ------------------------- | ---------------------------------------------- |
| Element | `.trn-outcome__title`     | The icon + heading row                         |
| Element | `.trn-outcome__reference` | The trade-in reference row, on all three pages |
| Element | `.trn-outcome__steps`     | The numbered next-steps list                   |
| Element | `.trn-outcome__labels`    | The shipping-label downloads                   |
| Element | `.trn-outcome__contact`   | The "contact us" text on the rejected page     |

#### History & trade-in details

**Layout wrappers**

**`.trn-products-list`** — the item list inside a history accordion entry

**Components**

**`.trn-history-header`** — the page header on the History and trade-in details pages

**`.trn-accordion`** — collapsible sections; each history entry is one

| Kind    | Hook                      | What it is               |
| ------- | ------------------------- | ------------------------ |
| Element | `.trn-accordion__header`  | The clickable header row |
| Element | `.trn-accordion__content` | The collapsible body     |
| State   | `.trn-accordion--open`    | While expanded           |

**`.trn-item-row`** — an item row inside a history accordion entry or a details card

**`.trn-badge`** — the status badge on history/details pages

| Kind    | Hook                  | What it is           |
| ------- | --------------------- | -------------------- |
| Variant | `.trn-badge--success` | Success statuses     |
| Variant | `.trn-badge--error`   | Error statuses       |
| Variant | `.trn-badge--warning` | Waiting statuses     |
| Variant | `.trn-badge--info`    | In-progress statuses |

**`.trn-details-card`** — the info cards on the confirmation, details and summary pages; one purpose variant per card

| Kind    | Hook                          | What it is                |
| ------- | ----------------------------- | ------------------------- |
| Element | `.trn-details-card__header`   | Its title row             |
| Variant | `.trn-details-card--shipping` | The shipping card         |
| Variant | `.trn-details-card--items`    | The items card            |
| Variant | `.trn-details-card--tracking` | The tracking card         |
| Variant | `.trn-details-card--credit`   | The credit/reward card    |
| Variant | `.trn-details-card--exchange` | The exchange card         |
| Variant | `.trn-details-card--service`  | The service-cost card     |
| Variant | `.trn-details-card--summary`  | The summary card          |
| Variant | `.trn-details-card--customer` | The customer-details card |

**`.trn-tracking`** — the return-tracking timeline

| Kind    | Hook                         | What it is              |
| ------- | ---------------------------- | ----------------------- |
| Element | `.trn-tracking__event`       | One timeline entry      |
| Element | `.trn-tracking__status`      | The entry's status      |
| Element | `.trn-tracking__date`        | The entry's date        |
| Element | `.trn-tracking__description` | The entry's description |

**`.trn-tracking-number`** — the tracking-number row above the timeline

The remaining hooks aren't tied to one page — they appear throughout the widget.

#### Buttons & forms

**`.trn-button`** — buttons

| Kind    | Hook                    | What it is                     |
| ------- | ----------------------- | ------------------------------ |
| Element | `.trn-button__spinner`  | The in-button loading spinner  |
| Variant | `.trn-button--outlined` | The secondary (outlined) style |
| Variant | `.trn-button--sm`       | Small                          |
| Variant | `.trn-button--bold`     | Bold label                     |

**`.trn-input-group`** — form fields

**`.trn-checkbox`** — checkboxes

**`.trn-validation`**, **`.trn-validation-error`** — form validation messages

#### Money display

**`.trn-reward-value`** — what you get for an item, however it's expressed: a formatted money amount, or a text description for a non-monetary reward (e.g. "20% off")

* **Elements:** `.trn-reward-value__terms` — the terms-and-conditions asterisk

**`.trn-amount`** — any formatted currency figure, wherever it appears (history credit totals, sidebar totals, item prices)

These two overlap by design: a monetary reward carries both classes at once (`.trn-reward-value.trn-amount`) — one selector styles all money, the other styles all rewards.

#### Dialogs

**`.trn-modal`** — dialogs

| Kind    | Hook                               | What it is                                           |
| ------- | ---------------------------------- | ---------------------------------------------------- |
| Element | `.trn-modal__backdrop`             | The backdrop                                         |
| Element | `.trn-modal__card`                 | The dialog box                                       |
| Element | `.trn-modal__title`                | The title                                            |
| Element | `.trn-modal__content`              | The content area                                     |
| Element | `.trn-modal__footer`               | The footer                                           |
| Element | `.trn-modal__close`                | The close button                                     |
| Variant | `.trn-modal--fixed`                | A dialog fixed to the viewport                       |
| Variant | `.trn-modal--absolute`             | A dialog positioned within the page                  |
| Variant | `.trn-modal__card--fit-content`    | A dialog sized to its content                        |
| Variant | `.trn-modal__content--fit-content` | A dialog sized to its content                        |
| Variant | `.trn-modal--refund-questions`     | The questions dialog opened inside the refund widget |

Use the variants when you want a rule to apply to only one kind of dialog.

#### Chrome & feedback

**Frame**

**`.trn-navbar`** — the widget's top navigation

* **Elements:** `.trn-navbar__inner` — its inner wrapper; `.trn-navbar__item` — each link

**`.trn-footer`** — the widget's footer

**`.trn-wizard`** — the chrome around each wizard step (title, progress bar, back link)

| Kind    | Hook                        | What it is                      |
| ------- | --------------------------- | ------------------------------- |
| Element | `.trn-wizard__title`        | The step title                  |
| Element | `.trn-wizard__progress`     | The progress-bar track          |
| Element | `.trn-wizard__progress-bar` | The filled portion of the track |

**`.trn-back-btn`** — the wizard's Back link

**Feedback**

**`.trn-alert`** — notification banners

| Kind    | Hook                   | What it is             |
| ------- | ---------------------- | ---------------------- |
| Element | `.trn-alert__icon`     | The severity icon      |
| Element | `.trn-alert__content`  | The message body       |
| Variant | `.trn-alert--info`     | Info severity          |
| Variant | `.trn-alert--success`  | Success severity       |
| Variant | `.trn-alert--warning`  | Warning severity       |
| Variant | `.trn-alert--error`    | Error severity         |
| Variant | `.trn-alert--fixed`    | Pinned to the viewport |
| State   | `.trn-alert--disabled` | While disabled         |

**`.trn-info-box`** — inline info callouts

**`.trn-loading`** — the loading state

* **Elements:** `.trn-loading__spinner`, `.trn-loading__text`

**`.trn-pagination-wrapper`** — pagination controls

* **States:** the current page and disabled arrows are targetable as plain `.active` / `.disabled` classes within it

#### Refund widget dialog

**`.trn-refund-modal`** — the refund widget's popup (the "trade in" dialog embedded on a product page); the class sits on the backdrop

| Kind    | Hook                         | What it is                  |
| ------- | ---------------------------- | --------------------------- |
| Element | `.trn-refund-modal__content` | The dialog box              |
| Element | `.trn-refund-modal__close`   | The close button            |
| Element | `.trn-refund-modal__body`    | The scrollable content area |

This dialog's chrome renders *outside* `#trn-app`, so rules for it can't start with `#trn-app` — start them with `.trn-refund-modal` instead. Everything *inside* the body is the normal Returns Centre widget, so any rule targeting something in there starts with `#trn-app` as usual.

#### Text styles

`.h1`, `.h2`, `.h3`, `.h4`, `.subtitle`, `.caption`, `.button-text`, `.strong`.

### What not to target

Alongside the styling hooks above you'll see lots of short, generated utility classes in the widget's HTML — things like `mt-6`, `w-12`, `flex`, `uppercase`. If you use Tailwind CSS yourself you'll recognise these; they are output of our build tooling, **not** a stable API. They can appear, disappear or move to different elements in any release, without notice.

The FilePond file-upload widget's `filepond--*` classes are third-party DOM and are not covered by this contract either.

```css
/* ✗ fragile — can break on any widget update */
#trn-app .mt-6.mb-8 { text-align: center; }

/* ✓ stable — supported hook + plain element */
#trn-app .trn-start-card h2 { text-align: center; }
```

Also avoid relying on the exact wrapper structure *between* supported elements (extra `div`s, element types) — it can change as we improve the widget.

**Missing a hook?** If there's something you want to restyle and no supported hook reaches it, tell us at <support@tern.eco> — adding a stable class for you is quick and safe, and much better than either of us relying on generated names. Check the [component-level theming](#component-level-theming) table too: a lot of what used to need a hook is now a one-line variable instead.

## 3. Tips

* The widget's sizing is pixel-based on purpose — it does not use `rem` units, so it will not be affected by your theme's root `font-size`. We recommend px units in your custom CSS for the same predictability.
* The Copy Customisation screen previews your CSS exactly the way the live storefront applies it — check there before publishing.
* Keep a copy of your custom CSS in your own records; it's the quickest way to review what you've changed if you redesign later.
