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

# Custom CSS

> Style the checkout with stable CSS variables and hooks that pass the checkout styling policy.

Use the custom CSS field in the checkout editor to adjust the sale page and the result pages beyond what the editor fields cover. This page documents the **style contract v1**: the variables and hooks that stay stable across checkout updates, and the rules every stylesheet must follow.

## How your CSS is applied

Your CSS applies only inside the checkout. `:root`, `html` and `body` target the checkout itself, and every other selector matches only elements inside it.

Set the variables in `:root` and style blocks through the `data-checkout-part` hooks:

```css theme={null}
:root {
  --checkout-surface: #111827;
  --checkout-text: #f9fafb;
  --checkout-text-muted: #9ca3af;
  --checkout-border: #374151;
  --checkout-background: #030712;
  --checkout-radius: 10px;
}

[data-checkout-part="order-summary"] {
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}

[data-checkout-part="pay-button"] {
  letter-spacing: 0.04em;
}
```

In a dark theme like this one, also darken the page background, with `--checkout-background` or the editor's Background color field, or it stays light. Both apply on the sale page and the result pages, and the variable wins over the field. Part of the text sits on the page background and part on `--checkout-surface`, so pick a text colour that contrasts with both. The card fields follow these colours only in the infoproduct theme; in the shop and stepped themes they keep their own light look.

## Variables you can set

Set these in `:root`. The default is what the theme's fields render while the variable is unset. Other elements that read the variable keep their own tone until you set it: in the infoproduct theme, for example, fields use `#d4d4d8` and cards use `#e5e5e5`. Setting the variable makes them match.

| Variable | What it changes | Default (shop · stepped · infoproduct) |
| - | - | - |
| `--checkout-surface` | Background of the fields, the payment method list, the order summary, the form cards, the testimonials and gift cards without their own editor colours, including the country dropdown, and of the cards on the result pages (Pix, card, boleto, confirmation and upsell). Those pages' QR code and payment code blocks stay white, for scanning. The chosen method's panel and the mobile order summary in the shop theme use `--checkout-surface-muted`. In the infoproduct theme the card fields take this colour when their text stays legible on it (see the `field` hook); in the shop and stepped themes they keep their own light look. The page background comes from `--checkout-background` or the Background colour field, and the header's from the Header colour field. On desktop in the shop theme, the order summary sits in a column painted with the page background, slightly darker when it comes from the editor field. | `#fff` in every theme |
| `--checkout-surface-muted` | Secondary background: the chosen payment method's panel (and, in the infoproduct theme, the area around the card fields, when their labels stay legible on it), the shipping and free-shipping notices, the apply-coupon button when the editor sets no colour for it, the order summary on mobile in the shop theme, hover backgrounds in lists, and the result pages' secondary blocks. When unset, `--checkout-surface` applies; when both are unset, each theme's own tone. | `#fafafa` · `#f5f6f7` · `#f7f7f7` |
| `--checkout-text` | Main text: what the buyer types in the fields, static labels, section titles, names and amounts in the order summary and payment methods, and the payment method icons (the boleto one included). In the stepped theme summary only the total uses the main text; the other lines use the secondary one. It also covers the testimonials and the result pages' text, outside the blocks that keep their own colours (QR code, payment code and waiting notices, the upsell timer badge and status panels). The editor's tertiary colour, when set, wins on the decline and apply buttons and needs contrast against the background the CSS sets. On the infoproduct order bump's add strip, this variable wins over the editor's button text colour. Part of it sits on the page background (`--checkout-background` or the Background colour field) and part on the surfaces (`--checkout-surface` and `--checkout-surface-muted`), so it needs contrast against all of them. | `oklch(21% 0.034 264.665)` in every theme |
| `--checkout-text-muted` | Secondary text: labels and icons inside the fields, notices, descriptions and struck-through prices in the order summary, and the footer of the shop and infoproduct themes. Like the main text, it sits on the page background and on both surfaces. The stepped theme footer uses its own colours set in the editor. | `oklch(55.1% 0.027 264.364)` in every theme |
| `--checkout-border` | Borders and dividers of the fields, the payment method list, the order summary and the form cards, including the country dropdown and the result pages' cards. On hover and focus, a field keeps its own colours. In the stepped and infoproduct themes, the chosen payment method keeps its own border. | `#d9d9d9` · `#d9d9d9` · `#d4d4d8` |
| `--checkout-background` | Page background, on the sale and result pages. When set, it wins over the editor's Background colour field; when unset, the field applies; with the field empty, each page uses its own tone (white or a very light grey). On desktop in the shop theme, the order summary column takes the same colour, without the slightly darker shade it gets from the editor field. | `#ffffff` in every theme |
| `--checkout-radius` | Rounded corners of the fields, payment methods, shipping, coupon and pay button. These keep their own corners: the fields, shipping and coupon in the infoproduct theme, and the payment methods in the stepped and infoproduct themes. On the pay button, the radius set in the editor wins over this variable. | `5px` in every theme |

## Variables you can read

These carry values from the editor fields. Use them inside `var(...)` in your rules, and change them in the editor.

| Variable | What it changes | Editor field | Default (shop · stepped · infoproduct) |
| - | - | - | - |
| `--checkout-primary` | Primary colour from the editor: field focus, highlights, and the pay button when the editor sets no button colour. In the country dropdown and dialogs, use it with a fallback: `var(--checkout-primary, #0066cc)`. | Primary color | `#0066cc` · `#16a34a` · `#0066cc` |
| `--checkout-primary-foreground` | Text colour on top of the primary colour, derived from it: white, or black when white lacks contrast. | Primary color | `#ffffff` · `#000000` · `#ffffff` |
| `--checkout-font` | Font family chosen in the editor. With no font chosen, the variable is unset and the page uses Inter, so always use it with a fallback: `var(--checkout-font, sans-serif)`. | Typography | `Inter` in every theme |

```css theme={null}
[data-checkout-part="order-summary"] {
  border-top: 3px solid var(--checkout-primary, #0066cc);
  font-family: var(--checkout-font, sans-serif);
}
```

## Hooks

Each hook is an attribute on an existing block of the sale page. Target it with the attribute selector.

| Hook | Block | Themes | Guarded |
| - | - | - | - |
| `[data-checkout-part="header"]` | Top bar holding the logo. Only shown when there is a logo. In the stepped theme it also shows on the result pages, outside the contract. | shop, stepped | No |
| `[data-checkout-part="logo"]` | Logo image in the header. In the stepped theme it also shows on the result pages, outside the contract. | shop, stepped | No |
| `[data-checkout-part="form"]` | Form: buyer details, payment and pay button. | shop, stepped, infoproduct | Yes |
| `[data-checkout-part="field"]` | Each text or select field in the form. Buyer and address fields are guarded; the coupon field is not. Card fields live in an iframe with no hook. In the infoproduct theme they take `--checkout-surface`, `--checkout-surface-muted`, `--checkout-text`, `--checkout-text-muted` and `--checkout-border` as set on `:root`, within three limits: transparent or semi-transparent colours are ignored; a background applies only if the text on it has a contrast of at least 3, otherwise the pair falls back to the theme's colours; and if the CSS is switched off for hiding something, the card returns to the theme's colours. In the shop and stepped themes they keep their own light look. | shop, stepped, infoproduct | Yes |
| `[data-checkout-part="payment-methods"]` | Payment method list. | shop, stepped, infoproduct | Yes |
| `[data-checkout-part="pay-button"]` | Pay button. In the stepped theme, it sits in the payment step, below the chosen method. | shop, stepped, infoproduct | Yes |
| `[data-checkout-part="order-summary"]` | Order summary. It may appear more than once on the page, in desktop and mobile versions. In the shop theme it also shows on the confirmation page, outside the contract. | shop, stepped, infoproduct | Yes |
| `[data-checkout-part="product"]` | Each product listed in the order summary. In the infoproduct theme, also at the top of the purchase card. In the shop theme, also on the confirmation page, outside the contract. | shop, stepped, infoproduct | No |
| `[data-checkout-part="footer"]` | Footer. In the stepped theme, only shown when the editor has content for it, and it also shows on the result pages, outside the contract. | shop, stepped, infoproduct | No |

<Warning>
  Guarded blocks hold what the buyer must see: fields, prices and the pay button. If your CSS hides or covers their content, the checkout switches your whole stylesheet off.
</Warning>

## Result pages

The colour variables also apply on the pages the buyer sees after paying: Pix, card, boleto, subscription, the confirmation of each theme, the upsell and the post-checkout summary.

* **Page background:** the same as on the sale page. `--checkout-background` wins when set; otherwise the editor's Background color field applies, and with the field empty each page keeps its own tone, white or a very light grey.
* **Blocks with their own colours:** these stay as they are, whatever your CSS sets:
  * the Pix QR code card, the code boxes and the copy buttons;
  * the boleto block, including its QR code in Peru;
  * the "waiting for confirmation" notices inside those blocks;
  * the upsell timer badge;
  * the map pin bubble;
  * the status panels.
* **Tertiary colour:** when the editor sets it, it wins on the decline and apply buttons, so it needs contrast against the background your CSS sets.
* **Hooks:** they are only guaranteed on the sale page. Where one also shows on a result page, it is outside the contract there.

## What stays in the editor fields

Set these in the editor, not in CSS. The one exception is the page background:

* primary colour
* page background: the editor's Background color field, which also applies on the result pages and which your CSS overrides when it sets `--checkout-background`
* header colour
* pay button colour and corner radius
* font
* logo, banner and images, since `url()` is not allowed in CSS

## Styling rules

Every stylesheet must follow these rules. When something breaks one, the editor does not save and lists each problem with its line and column.

* **Size:** up to 50,000 characters. The editor counts bytes, so accented characters take more than one. Once scoped to the checkout, the stylesheet is also capped at 150,000 characters.
* **At-rules:** only `@media`, `@supports`, `@container` and `@keyframes`. Any other at-rule, such as `@import`, `@font-face`, `@namespace`, `@layer`, `@page` or `@property`, is rejected.
* **No `url()`**, in any property.
* **Functions:** only these are allowed. Any other, such as `image-set()`, `image()` or `attr()`, is rejected.
  * colours: `rgb()`, `rgba()`, `hsl()`, `hsla()`, `hwb()`, `lab()`, `lch()`, `oklab()`, `oklch()`, `color()`, `color-mix()`, `light-dark()`
  * variables and environment: `var()`, `env()`
  * math: `calc()`, `-webkit-calc()`, `min()`, `max()`, `clamp()`, `round()`, `mod()`, `rem()`, `abs()`, `sign()`
  * gradients: `linear-gradient()`, `radial-gradient()`, `conic-gradient()`, their `repeating-` versions, and the `-webkit-` prefixed forms of all of them
  * transforms: `matrix()`, `matrix3d()`, `perspective()`, `rotate()`, `rotate3d()`, `rotateX()`, `rotateY()`, `rotateZ()`, `scale()`, `scale3d()`, `scaleX()`, `scaleY()`, `scaleZ()`, `skew()`, `skewX()`, `skewY()`, `translate()`, `translate3d()`, `translateX()`, `translateY()`, `translateZ()`
  * filters: `blur()`, `brightness()`, `contrast()`, `grayscale()`, `hue-rotate()`, `invert()`, `opacity()`, `saturate()`, `sepia()`
  * shapes: `inset()`, `circle()`, `ellipse()`, `polygon()`, `rect()`, `xywh()`
  * timing, grid and counters: `cubic-bezier()`, `steps()`, `minmax()`, `repeat()`, `fit-content()`, `counter()`, `counters()`
* **Selectors:** no `:visited`, no attribute selector on `value`, no selector that starts with a combinator, such as `> a`, and no `~` or `+` after `:root`, `html` or `body`.
* **No nesting:** no `&`, and no rules or at-rules inside another rule.
* **Properties:** `behavior`, `-moz-binding` and `-webkit-box-reflect` are rejected.
* **Reach and enlargement:** nothing may paint far outside its element or enlarge it much. In the properties below, lengths go in `px` or `rem` (a `rem` counts as 16px), or `0`, and scale factors as numbers. `em`, `%` lengths, viewport units, `calc()`, `min()`, `max()`, `clamp()` and `var()` are rejected there, whether as part of the value, as the colour or as the whole value.
  * `box-shadow`, `text-shadow`, `outline`, `outline-width`, `outline-offset`, the `border-image` outset, `text-decoration`, `text-decoration-thickness`, `text-underline-offset`, `-webkit-text-stroke` and their prefixed forms: each length up to 64px. To use a variable for the colour, set it in its own property, such as `outline-color: var(--checkout-primary)`.
  * `filter`: the `blur()` radii add up to at most 64px, and `drop-shadow()` is rejected. Colour filters such as `brightness()` or `grayscale()` have no limit and accept `var()`.
  * `transform`, `scale` and `zoom`: each declaration enlarges at most 1.1×, counting `scale()`, `matrix()` and `skew()`. `translate()` and `rotate()` have no limit and accept `var()` and `calc()`. `perspective()`, `matrix3d()` and any `perspective` other than `none` are rejected.
* **Guarded blocks:** nothing that hides or covers the content of a guarded hook. The editor does not check this rule when saving: the checkout does, by switching your stylesheet off, as the warning under the hooks says.

## Test before saving

<Steps>
  <Step title="Paste your CSS">
    Paste the stylesheet into the custom CSS field of the checkout editor.
  </Step>

  <Step title="Fix what the editor points out">
    Each problem shows its line and column. Save only works once the list is empty.
  </Step>

  <Step title="Check the preview">
    The editor preview applies the same CSS the published checkout serves. Check the blocks you changed on desktop and mobile.
  </Step>

  <Step title="Save">
    Save the configuration to publish the stylesheet.
  </Step>
</Steps>

<Note>
  If the preview applies your CSS and goes back to the default a moment later, the checkout switched your stylesheet off because a field, a price or the pay button became invisible or lost contrast. The typical case is light text on a page background that is still light: set `--checkout-background` or darken the Background color field.
</Note>

## Use with an AI

To reproduce the look of another checkout, copy the prompt below into the AI you use. Replace everything in brackets with the reference checkout and your current editor values, and attach screenshots of the reference. The answer has two parts: the values go into the editor fields and the CSS into the custom CSS field. Then test it in the preview as above.

````markdown theme={null}
You are a CSS expert. I want my checkout to reproduce the visual style of a reference checkout. My checkout only accepts changes in two places: the editor fields and a custom CSS block that follows the rules below.

## Reference checkout
Link: [paste the reference checkout link here]
Screenshots: [attach screenshots of the reference checkout, on desktop and mobile]
Attach the screenshots even when sending the link: not every AI can open links.

## My checkout today
Model: [Shop, Stepped or Infoproduct]
Editor fields, with their current values:
- Background color: [value]
- Primary color: [value]
- Header background color: [value]
- Typography: [value]
- Button rounding: [value in px]
Fonts available in the editor: Inter, Roboto, Open Sans, Montserrat, Poppins, Lato, Nunito, Source Sans 3, Raleway, Work Sans, Rubik.

## What the CSS can use
Variables the CSS can change, at the shop theme's default values (in the infoproduct theme the default border is #d4d4d8):
```css
:root {
  --checkout-surface: #fff;
  /* --checkout-surface-muted: #fafafa; when unset, it follows --checkout-surface */
  --checkout-text: oklch(21% 0.034 264.665);
  --checkout-text-muted: oklch(55.1% 0.027 264.364);
  --checkout-border: #d9d9d9;
  /* --checkout-background: #ffffff; only if the CSS changes the page background; it wins over the Background color field */
  --checkout-radius: 5px;
}
```
- `--checkout-surface`: background of the fields, the payment method list, the order summary, the form cards, the testimonials and the cards on the result pages, whose QR code and payment code blocks stay white. In the Infoproduct model the card fields take it when it is opaque and their text has a contrast of at least 3 on it; otherwise the card keeps the theme's colours. In Shop and Stepped they keep their own light look. The header background comes from the editor.
- `--checkout-surface-muted` (optional, only for a different tone in panels and notices): secondary background: the chosen payment method's panel (and, in the Infoproduct model, the area around the card fields, when it is opaque and their labels have a contrast of at least 3 on it), the shipping notices, the mobile order summary in the Shop model, hover backgrounds and the result pages' secondary blocks.
- `--checkout-text`: main text and the payment method icons, on the sale page and the result pages. It sits on the page background and on both surfaces, so it needs contrast against all of them.
- `--checkout-text-muted`: secondary text: labels, notices, descriptions and struck-through prices.
- `--checkout-border`: borders and dividers of the fields, the payment method list, the order summary, the form cards and the result pages' cards.
- `--checkout-background` (optional, only if the CSS changes the page background): page background. When set, it wins over the Background color field, on the sale page and the result pages.
- `--checkout-radius`: rounded corners of the fields, payment methods, shipping, coupon and pay button.

For a dark theme, darken the background in the Background color or in `--checkout-background`, and keep both consistent: if you set the variable, return the same color in the Background color field.

Read-only variables. Their value comes from the editor fields, and the CSS only uses them in `var()`:
- `var(--checkout-primary, #0066cc)`: the primary color.
- `var(--checkout-primary-foreground, #ffffff)`: text color on top of the primary color.
- `var(--checkout-font, sans-serif)`: the font chosen in the editor.

Stable hooks, to use as selectors:
- `[data-checkout-part="header"]`: top bar with the logo (shop and stepped themes).
- `[data-checkout-part="logo"]`: logo image (shop and stepped themes).
- `[data-checkout-part="form"]` (guarded): buyer details, payment and pay button.
- `[data-checkout-part="field"]` (guarded): each text or select field.
- `[data-checkout-part="payment-methods"]` (guarded): payment method list.
- `[data-checkout-part="pay-button"]` (guarded): pay button.
- `[data-checkout-part="order-summary"]` (guarded): order summary.
- `[data-checkout-part="product"]`: each product in the order summary.
- `[data-checkout-part="footer"]`: footer.

## CSS rules
- Set the variables on `:root`.
- Use only the variables and hooks above. The checkout's utility classes still work, but they may change at any time: prefer the hooks.
- No `@import`, `url()`, `image-set()` or external fonts. Of the at-rules, only `@media`, `@supports`, `@container` and `@keyframes`.
- Functions: only colors (such as `rgb()`, `hsl()`, `oklch()`, `color-mix()`), `var()`, `env()`, math (such as `calc()`, `min()`, `max()`, `clamp()`), gradients, transforms, filters, shapes, `cubic-bezier()`, `steps()`, `repeat()`, `minmax()`, `fit-content()` and counters. `attr()` and `image()` are rejected.
- Shadows, outlines, text decoration and stroke, the `border-image` outset and `blur()` take lengths only in `px` or `rem`, up to 64px (the `blur()` radii add up), with no `em`, `%`, `calc()` or `var()` in those values: put the color in its own property, like `outline-color`. `drop-shadow()` is rejected. `transform`, `scale` and `zoom` enlarge at most 1.1×, with scale factors as numbers; `translate()` and `rotate()` are free. No `perspective`, `perspective()`, `matrix3d()` or `-webkit-box-reflect`.
- No nested CSS, no `:visited`, no selector on the `value` attribute, no selector that starts with a combinator, and no `~` or `+` after `:root`, `html` or `body`.
- Nothing that hides or covers fields, prices, consent or the pay button: if that happens, the checkout switches off the whole CSS.
- Light text in the variables needs a dark background, in `--checkout-background` or in the Background color: part of the text sits on the page background, and on desktop in the Shop model the order summary column uses that background. Making blocks transparent does not darken the background.
- Up to 50,000 bytes.
- Logo, banner and images come from the editor fields, because `url()` is blocked.

## Answer
Return two parts:
1. The values for the editor fields: Background color, Primary color, Header background color, Typography, Button rounding. Colors go as 6-digit hex (#RRGGBB), the font must be one of the available ones and the button rounding is a whole number from 0 to 50, in px.
2. A single CSS block that uses only the variables and hooks above. In `:root`, include only the variables whose value changes.
````

## Utility classes

Selectors written against the checkout's utility classes, such as `.bg-white`, still work, but they are not part of the contract and can change in any checkout update. Prefer the hooks and variables on this page.

<Note>
  This page documents style contract **v1**. A change to the variables or hooks bumps the contract version.
</Note>
