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

# Widget Agent Skill

> Use this agent skill to set up the widget integration for your website with the correct widget type and slugs.

<Note>
  Use this agent skill to set up the widget integration for your website.
</Note>

```yaml theme={null}
---
name: anny-widget-integration
description: >
  How to embed anny booking widgets and the AI chat assistant on a website. Use when integrating
  anny widgets into a site, landing page, or web app. Covers script setup, widget types, seamless
  layout embedding (panels in cards, no extra padding, overflow hidden, border radius),
  full-page vs panel vs button vs AI chat widgets, fullscreen with nav-height for single-scroll
  pages, height behavior, design tokens, login/cart placement in the top-right nav,
  and asking for the correct resource/service/organization/plan/package slug before generating code.
---
```

# anny Widget Integration

## Quick Facts

* Widgets are **web components** (custom HTML elements).
* One `<script>` tag loads all widgets. Load it once per page.
* Widgets communicate via the iframe they contain — **no extra wrapper div or padding is needed**. Place the element directly where you want the content.
* Panels auto-resize to their content. Page widgets and maps support `fullscreen` or a fixed `height`.
* **Prefer `fullscreen="true"` + `nav-height` for full-page booking** so the page itself never scrolls — only the widget scrolls internally. This avoids the awkward double scrollbar (page scroll *and* widget scroll).
* **Put `a-login-button` and `a-cart-modal-button` in the top-right of the main navigation.** The cart should show icon + count indicator only (`show-icon="true"`, no label).
* `a-agent-chat` embeds the **anny AI chat assistant** — a launcher in the corner, an in-flow button, or an inline frame. It can drive the whole booking flow conversationally.
* UTMs and click IDs from the current page URL are forwarded automatically.
* Start in admin when possible. Admin-generated snippets are the safest source for widget type, slug wiring, and supported options.

## Ask First

Before generating integration code, make sure these inputs are known:

1. Which widget type is needed: page, panel, button, utility, or AI chat?
2. Which entity is being embedded: `resource`, `service`, `organization`, `plan`, or `package`?
3. What is the exact slug for that entity? (For `a-agent-chat`, the `organization` slug and an `assistant-id`.)
4. Is booking the main page content, part of an existing layout, or behind a CTA?
5. Are login and cart needed in the main nav (top-right)?

If the widget depends on an entity slug and the slug is missing, **ask the user for it before writing the final snippet**.

Use these prompts:

* "What is the exact resource slug?"
* "What is the exact service slug?"
* "What is the exact organization slug?"
* "What is the exact plan slug?"
* "What is the exact package slug?"

Do not guess slugs.

### When details are missing, ask for the admin snippet

If a required value isn't obvious — an `assistant-id` for `a-agent-chat`, an `idp-uuid` for SSO, or any slug — **ask the user to paste the widget code copied from the anny admin area** rather than guessing. Admin generates a ready-made snippet with the element, the correct slugs/ids, and supported options already wired.

Prompt:

* "Open this widget in the anny admin area, copy the generated embed code, and paste it here — I'll adapt it to your site."

Then keep the admin-provided slugs/ids verbatim and only adjust layout, theming, and placement around them.

## Integration Workflow

1. Ask for the missing slug if the widget is entity-based.
2. Choose the right widget type: page, panel, button, utility, or AI chat.
3. Load the widget script once.
4. Add the required entity slug attribute for that widget.
5. Place the widget directly into the page layout. For full-page booking, prefer `fullscreen="true"` + `nav-height` so only the widget scrolls.
6. If embedding inside a card, style the wrapper, not the widget.
7. Add `a-login-button` and `a-cart-modal-button` once in the top-right of the main nav when needed (cart = icon + count only).
8. Add design tokens as HTML attributes if brand customization is needed.
9. Add event listeners only if external tracking hooks such as GA4 are needed.

## Fast Decision Guide

| Need                                                          | Choose                                           |
| ------------------------------------------------------------- | ------------------------------------------------ |
| Booking is the main content of the page                       | page widget (`fullscreen="true"` + `nav-height`) |
| Existing marketing/editorial page needs embedded booking flow | panel widget                                     |
| Booking should open after a click                             | button widget                                    |
| Shared auth or cart control in nav                            | utility widget (top-right)                       |
| Conversational / assisted booking, support-style helper       | AI chat (`a-agent-chat`)                         |

Prefer admin-generated snippets when the user already has the widget configured in anny admin. Use manual HTML when building the integration directly in code or when custom layout control is needed.

## Preferred Defaults For New Websites

When building a new website from scratch, prefer these defaults unless the user asks for a different pattern:

1. Use page content plus a booking panel in the layout.
2. **For a dedicated booking page, use a fullscreen page widget with `nav-height` set to your header height.** This gives a single scroll *inside* the widget and none on the page — no double scrollbar.
3. **Put `a-login-button` and `a-cart-modal-button` in the top-right of the main navigation.** Render the cart as icon + count only (`show-icon="true"`, no `label`).
4. Use `a-subscription-button` for plans instead of embedding the plan page inline.
5. Use a fullscreen calendar page when calendar browsing is a primary use case.
6. Add `a-agent-chat` as a bottom-right launcher when the site benefits from assisted/conversational booking or a support helper.

| Scenario                                    | Preferred pattern                                                                          |
| ------------------------------------------- | ------------------------------------------------------------------------------------------ |
| Dedicated booking page                      | page widget with `fullscreen="true"` + `nav-height="64px"` (single in-widget scroll)       |
| Landing page or marketing page with booking | content + `a-resource-booking-panel` or `a-service-booking-panel`                          |
| Auth + cart in site chrome                  | `a-login-button` + `a-cart-modal-button`, top-right of the main nav (cart = icon + count)  |
| Plan / subscription sales                   | `a-subscription-button`                                                                    |
| Calendar-first experience                   | `a-resource-calendar` or `a-organization-calendar` with `fullscreen="true"` + `nav-height` |
| Assisted / conversational booking           | `a-agent-chat` launcher (`placement="bottom-right"`)                                       |

Do not default every new site to a full embedded page widget *inside* a content layout. Either give booking its own fullscreen page (with `nav-height`), or embed a panel in the existing layout — pick based on whether booking is the whole page.

## Script

```html theme={null}
<script src="https://cdn.anny.co/widget/annyComponents.umd.latest.min.js"></script>
```

Place once in `<head>` or before `</body>`. Do not load more than once per page.

## Widget Types

| Type              | Elements                                                                                                                                                                                                       | Use when                                                                                  |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| **Page widget**   | `a-organization-page`, `a-resource-page`, `a-service-page`, `a-resource-calendar`, `a-resource-map`, `a-organization-map`, `a-organization-calendar`, `a-subscription-page`, `a-package-page`, `a-my-bookings` | Booking is the main content of the page or section                                        |
| **Panel widget**  | `a-resource-booking-panel`, `a-service-booking-panel`                                                                                                                                                          | You already have a page layout and want the booking flow embedded inside it               |
| **Button widget** | `a-resource-button`, `a-service-button`, `a-organization-button`, `a-subscription-button`, `a-package-button`, `a-modal-button`                                                                                | Booking opens on user click in a modal                                                    |
| **Utility**       | `a-login-button`, `a-cart-modal-button`                                                                                                                                                                        | Shared auth/cart controls — place top-right in the main nav                               |
| **AI chat**       | `a-agent-chat`                                                                                                                                                                                                 | Conversational / assisted booking and support — launcher, in-flow button, or inline frame |

## Minimal Page Skeleton

```html theme={null}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Booking</title>
<script src="https://cdn.anny.co/widget/annyComponents.umd.latest.min.js"></script>
</head>
<body>
<!-- Main nav: brand on the left, links in the middle, auth + cart top-right -->
<header style="display: flex; align-items: center; gap: 16px; padding: 0 24px; height: 64px;">
<a href="/">Logo</a>
<nav style="flex: 1;"><!-- navigation links --></nav>
<a-login-button base-url="https://anny.co"></a-login-button>
<a-cart-modal-button base-url="https://anny.co" modal-layout="drawer" show-icon="true"></a-cart-modal-button>
</header>

<main>
<a-resource-booking-panel
base-url="https://anny.co"
resource="my-resource"
></a-resource-booking-panel>
</main>
</body>
</html>
```

For a **dedicated booking page** where booking is the whole page, swap the panel in `<main>` for a fullscreen page widget so only the widget scrolls:

```html theme={null}
<main>
<a-resource-page
base-url="https://anny.co"
resource="my-resource"
fullscreen="true"
nav-height="64px"
></a-resource-page>
</main>
```

## Seamless Embedding Patterns

### Panel inside a card

Panels resize dynamically. Put them directly inside a card — no extra wrapper or padding needed. Apply `overflow: hidden` and `border-radius` to the card, not the widget element.

```html theme={null}
<div style="border-radius: 16px; overflow: hidden; box-shadow: 0 4px 24px rgba(0,0,0,.1);">
<a-resource-booking-panel
base-url="https://anny.co"
resource="my-resource"
></a-resource-booking-panel>
</div>
```

Do **not** add padding inside the card around the widget — the widget handles its own internal spacing.

### Full-page widget with a single internal scroll (preferred for booking pages)

```html theme={null}
<section style="height: 100vh;">
<a-organization-page
base-url="https://anny.co"
organization="my-org"
fullscreen="true"
nav-height="64px"
></a-organization-page>
</section>
```

* `fullscreen="true"` → `height: 100vh`
* `nav-height` subtracts your sticky header: `calc(100vh - 64px)`. Match it to the real header height so the widget sits flush below the nav and fills the rest of the viewport exactly.
* The result: the **page does not scroll — only the widget scrolls internally**. This is the preferred pattern for any full-page booking, calendar, or map experience. It avoids the double-scrollbar problem where both the page and the widget scroll independently.
* If you give the widget a fixed `height` attribute, auto-resize is disabled — do not combine `height` with `fullscreen`.

Use this especially for booking-first and calendar-first pages where the widget should dominate the layout.

### Widget beside editorial content

```html theme={null}
<div style="display: grid; grid-template-columns: 1fr 420px; gap: 32px; align-items: start;">
<div>
<h1>Book your space</h1>
<p>…description…</p>
</div>
<a-resource-booking-panel
base-url="https://anny.co"
resource="my-resource"
></a-resource-booking-panel>
</div>
```

Panels expand vertically as the user navigates the booking flow. Use `align-items: start` so they don't stretch.

This is the preferred default for new marketing sites and content-driven pages.

### Button widget with a custom trigger

All button widgets accept a slotted element that replaces the built-in button.

```html theme={null}
<a-resource-button base-url="https://anny.co" resource="my-resource">
<button class="hero-cta">Book now</button>
</a-resource-button>
```

When a slot is provided, `label`, `button-background`, `button-text`, and `button-width` are ignored. Click and keyboard handling are still managed by the widget wrapper.

### Login and cart in the top-right of the main nav

Put `a-login-button` and `a-cart-modal-button` together in the **top-right of the main navigation** — the spot users instinctively look for account and cart. Render the cart as an **icon with a count indicator only** (no text label), like any e-commerce header.

```html theme={null}
<header style="display: flex; align-items: center; gap: 16px; padding: 0 24px; height: 64px;">
<a href="/">Logo</a>
<nav style="flex: 1;">…links…</nav>
<!-- pushed to the far right by the flex:1 nav above -->
<a-login-button base-url="https://anny.co"></a-login-button>
<a-cart-modal-button
base-url="https://anny.co"
modal-layout="drawer"
show-icon="true"
></a-cart-modal-button>
</header>
```

* These are utility widgets — put them in a stable position users can always find. They sync auth state and cart across all widgets on the page automatically.
* The cart button shows its own item-count indicator; keep it icon-only (omit `label`) so it reads as a standard cart icon.
* `drawer` is a good `modal-layout` for the cart so it slides in from the right, matching its top-right anchor.

For new sites, this top-right placement should be the default.

### Plan CTA button

For plans and subscriptions, prefer a button that opens checkout instead of embedding the full plan page into a mixed-content page.

```html theme={null}
<a-subscription-button
base-url="https://anny.co"
plan="my-plan"
label="Choose plan"
modal-layout="drawer"
></a-subscription-button>
```

Use `a-subscription-page` only when the whole page is dedicated to the plan checkout experience.

## AI Chat Assistant (`a-agent-chat`)

`a-agent-chat` embeds the anny **AI chat assistant**. The visitor can ask questions and the assistant can guide them through the booking flow conversationally; when it needs to show the booking UI it opens it in a modal over the host page. Login (when required) and the user's access token are handled first-party on the anny chat page — the widget only renders the launcher/panel chrome and forwards configuration.

It needs the `organization` slug and an `assistant-id` (created in anny admin). Ask for both before generating the snippet.

### Placement

Set `placement` to choose how the chat appears:

| `placement`              | Result                                                               | Use when                                                 |
| ------------------------ | -------------------------------------------------------------------- | -------------------------------------------------------- |
| `bottom-right` (default) | Fixed launcher button in the viewport corner; opens a floating panel | Site-wide support / assisted booking helper              |
| `relative` / `none`      | Launcher rendered in normal document flow (e.g. inside a section)    | A "chat with us" button placed in your own layout        |
| `inline`                 | No launcher — the chat frame is embedded directly                    | Chat *is* the page section; give the parent a fixed size |

### Floating launcher (most common)

```html theme={null}
<a-agent-chat
base-url="https://anny.co"
organization="my-org"
assistant-id="my-assistant"
placement="bottom-right"
greeting-message="Need a hand? Chat with us!"
></a-agent-chat>
```

The launcher is fixed bottom-right and the panel goes fullscreen on mobile. Place it once per page, near `</body>`.

### Inline frame

When the chat is itself a page section, use `placement="inline"` and give the **parent element** a fixed width/height — the frame fills it.

```html theme={null}
<div style="width: 400px; height: 560px;">
<a-agent-chat
base-url="https://anny.co"
organization="my-org"
assistant-id="my-assistant"
placement="inline"
></a-agent-chat>
</div>
```

### Chat attributes

| Attribute          | Purpose                                                                                                                            |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| `organization`     | **Required.** Organization slug whose chat to embed                                                                                |
| `assistant-id`     | Assistant identifier (from anny admin)                                                                                             |
| `placement`        | `bottom-right` (default), `relative` / `none`, or `inline`                                                                         |
| `start-message`    | Message the conversation is pre-seeded with                                                                                        |
| `greeting-message` | Teaser bubble shown next to the launcher before it's opened                                                                        |
| `launcher-label`   | Accessible label for the launcher button                                                                                           |
| `launcher-color`   | Launcher button background (defaults to `primary-color`, else the branded gradient)                                                |
| `consent`          | `accepted` (pre-opted-in, no banner) or `hidden` (no banner, no persistent visitor id); omit to show the chat's own consent banner |
| `supports-login`   | Require login before the chat is usable (gate handled first-party)                                                                 |

It also accepts the shared design tokens (`primary-color`, `primary-background`, `text-primary-color`, `text-secondary-color`, `button-text`, `logo-url`, `locale`, …) which are forwarded to the chat surface.

## Height Behavior

| Widget type           | Default behavior               | Override                                                             |
| --------------------- | ------------------------------ | -------------------------------------------------------------------- |
| Panel                 | Auto-resizes to content        | Cannot be overridden — `height` and `fullscreen` are ignored         |
| Page / map / calendar | Auto-resizes unless overridden | `height="700px"` (fixed) or `fullscreen="true"` (viewport fill)      |
| Button widget         | No height — opens modal        | Modal size controlled by `modal-layout`, `modal-size`, `modal-width` |

## Required Attributes

Every widget needs:

* `base-url` — the anny base URL, e.g. `https://anny.co`
* The entity slug for the widget type (`resource`, `organization`, `service`, `plan`, or `package`)

Utility widgets are the exception:

* `a-login-button` only needs `base-url` unless SSO options are required
* `a-cart-modal-button` only needs `base-url`

```html theme={null}
<a-resource-booking-panel
base-url="https://anny.co"
resource="my-resource-slug"
></a-resource-booking-panel>
```

### Entity slug mapping

| Widget                                                                                                      | Required entity attribute            |
| ----------------------------------------------------------------------------------------------------------- | ------------------------------------ |
| `a-resource-page`, `a-resource-map`, `a-resource-calendar`, `a-resource-booking-panel`, `a-resource-button` | `resource`                           |
| `a-service-page`, `a-service-booking-panel`, `a-service-button`                                             | `service`                            |
| `a-organization-page`, `a-organization-map`, `a-organization-calendar`, `a-organization-button`             | `organization`                       |
| `a-subscription-page`, `a-subscription-button`                                                              | `plan`                               |
| `a-package-page`, `a-package-button`                                                                        | `package`                            |
| `a-modal-button`                                                                                            | usually `resource` or `organization` |

### Common functional attributes

| Attribute          | Meaning                                               |
| ------------------ | ----------------------------------------------------- |
| `locale`           | force widget language                                 |
| `should-login`     | require login before booking                          |
| `idp-uuid`         | SSO identity provider                                 |
| `height`           | fixed iframe height for page widgets                  |
| `fullscreen`       | full viewport height for page widgets                 |
| `nav-height`       | subtract sticky header height from fullscreen widgets |
| `default-list`     | initial tab for organization widgets                  |
| `view`             | initial organization view                             |
| `calendar-view`    | day/week/month/list view where supported              |
| `default-category` | preselect category on `a-organization-page`           |

### Date parameters

Many widgets support `start` and some also support `end`.

* ISO format: `2025-06-15`
* Relative values for `start`: `today`, `tomorrow`, `this_week`, `next_week`, `this_month`, `next_month`
* `end` should be an ISO date string
* Relative values are **not** supported by `a-resource-calendar` or `a-organization-calendar`

```html theme={null}
<a-resource-booking-panel
base-url="https://anny.co"
resource="my-resource"
start="tomorrow"
></a-resource-booking-panel>
```

## Design Token Pass-Through

Pass brand colors and styling directly as HTML attributes. No CSS override needed.

```html theme={null}
<a-organization-page
base-url="https://anny.co"
organization="my-org"
primary-color="#0f766e"
primary-background="#f8fafc"
panel-background="#ffffff"
small-border-radius="8px"
panel-shadow="0 8px 32px rgba(0,0,0,.08)"
text-primary-color="#111827"
></a-organization-page>
```

### Color tokens

| Token                   | Purpose                                                       | Fallback                             |
| ----------------------- | ------------------------------------------------------------- | ------------------------------------ |
| `primary-color`         | Main accent color                                             | —                                    |
| `primary-color-rgb`     | RGB triplet for transparent accent usage, e.g. `15, 118, 110` | Auto-calculated from `primary-color` |
| `primary-color-hover`   | Hover state of main accent                                    | —                                    |
| `primary-color-overlay` | Accent overlay surface                                        | —                                    |
| `secondary-color`       | Secondary accent                                              | —                                    |
| `primary-stroke-color`  | Stroke / outline accent; also sets table borders              | —                                    |

### Text tokens

| Token                  | Purpose              |
| ---------------------- | -------------------- |
| `text-primary-color`   | Main text color      |
| `text-secondary-color` | Secondary text color |
| `text-tertiary-color`  | Muted text color     |

### Background tokens

| Token                            | Purpose                                                                                | Fallback                                                        |
| -------------------------------- | -------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| `primary-background`             | Page/outer background                                                                  | —                                                               |
| `primary-background-rgb`         | RGB triplet for layered page background                                                | Auto-calculated from `primary-background`                       |
| `panel-background`               | Panel surface. Also sets `primary-background` if `primary-background` is not provided. | —                                                               |
| `panel-background-rgb`           | RGB triplet for panel surface                                                          | Auto-calculated from `panel-background` or `primary-background` |
| `panel-background-light`         | Lighter panel variant                                                                  | —                                                               |
| `panel-background-overlay`       | Overlay background                                                                     | —                                                               |
| `panel-background-overlay-dense` | Dense overlay background                                                               | —                                                               |
| `panel-background-dark`          | Dark panel surface                                                                     | —                                                               |
| `input-background`               | Input field background                                                                 | —                                                               |

### Border and radius tokens

| Token                  | Purpose                     | Notes                                                                             |
| ---------------------- | --------------------------- | --------------------------------------------------------------------------------- |
| `small-border-radius`  | Base radius unit            | All larger radii are calculated from this: `1.5×`, `2×`, `2.5×`, `3×`, `4×`, `5×` |
| `panel-border-radius`  | Explicit large panel radius | Overrides the scale-up from `small-border-radius`                                 |
| `detail-border-radius` | Explicit detail card radius | Overrides the scale-up from `small-border-radius`                                 |
| `light-border-color`   | Light border color          | —                                                                                 |
| `table-border-color`   | Table and grid border color | —                                                                                 |
| `panel-border-style`   | Border style token          | —                                                                                 |

### Shadow tokens

| Token           | Purpose                                 |
| --------------- | --------------------------------------- |
| `panel-shadow`  | Panel shadow; also sets dropdown shadow |
| `detail-shadow` | Detail card shadow                      |

### Button styling tokens

These affect the outer CTA button for button widgets, cart button, and login button.

| Token               | Purpose                         | Fallback                           |
| ------------------- | ------------------------------- | ---------------------------------- |
| `button-background` | Trigger fill color              | Falls back to `input-background`   |
| `button-text`       | Trigger text and icon color     | Falls back to `text-primary-color` |
| `button-width`      | Trigger width                   | —                                  |
| `button-height`     | Trigger height                  | —                                  |
| `show-icon`         | Show or hide icon on login/cart | —                                  |

### Utility tokens

| Token      | Purpose                                                                                               |
| ---------- | ----------------------------------------------------------------------------------------------------- |
| `logo-url` | Custom logo shown in the pulsing loading animation only. Does not affect logos inside the booking UI. |

### RGB tokens — auto-calculation

`primary-color-rgb`, `panel-background-rgb`, and `primary-background-rgb` are automatically calculated from their hex counterparts when not explicitly provided. You only need to pass them if you want to supply a custom RGB triplet (e.g. for a non-hex color source).

Design rules:

* Prefer configuring design in admin first. HTML token overrides are for one-off page-specific changes.
* Keep contrast high between primary actions, text, and backgrounds.
* `small-border-radius` is the simplest way to control all corner radii at once. Use `panel-border-radius` and `detail-border-radius` only to override specific levels.
* Do not combine very strong shadows, very round corners, and low-contrast text simultaneously.

## Modal Layout Options

Button widgets open content in a modal. Control the layout with `modal-layout`:

| Value        | Description                                                               |
| ------------ | ------------------------------------------------------------------------- |
| `dialog`     | Centered dialog. Size with `modal-size` (`sm`/`md`/`lg`) or `modal-width` |
| `drawer`     | Side panel from the right — good for checkout flows                       |
| `fullscreen` | Full viewport — best for mobile                                           |

```html theme={null}
<a-resource-button
base-url="https://anny.co"
resource="my-resource"
modal-layout="drawer"
></a-resource-button>
```

### Modal behavior attributes

| Attribute           | Purpose                                             |
| ------------------- | --------------------------------------------------- |
| `modal-layout`      | `dialog`, `drawer`, or `fullscreen`                 |
| `modal-size`        | `sm`, `md`, or `lg` for dialog layout               |
| `modal-width`       | custom width such as `80vw`; overrides `modal-size` |
| `modal-title`       | modal header title                                  |
| `close-on-backdrop` | allow close on outside click                        |
| `show-close-button` | show close button                                   |
| `aria-label`        | accessible label for modal                          |

## Tracking Events

Booking widgets can emit DOM custom events you can subscribe to on the widget element.

Supported event names:

* `view-page`
* `add-to-cart`
* `start-checkout`
* `complete-checkout`

Common payload fields:

* `event_name`
* `value`
* `gross_value`
* `tax`
* `currency`
* `transaction_id`
* `items`

```html theme={null}
<a-resource-page
id="booking-widget"
base-url="https://anny.co"
resource="my-resource"
></a-resource-page>

<script>
const widget = document.getElementById('booking-widget')

widget.addEventListener('complete-checkout', (event) => {
const data = event.detail
console.log('Checkout complete', data.transaction_id, data.gross_value)
})
</script>
```

`a-login-button` and `a-cart-modal-button` are utility widgets and are not booking event emitters.

## Common Mistakes to Avoid

| Mistake                                                                                | Fix                                                                                                                             |
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Adding padding around a panel inside a card                                            | Apply `border-radius` + `overflow: hidden` to the card wrapper; put the widget element directly inside                          |
| Wrapping the widget in a flex/grid container with `align-items: stretch`               | Use `align-items: start` so the panel can grow freely                                                                           |
| Loading the script multiple times                                                      | One `<script>` tag per page is enough                                                                                           |
| Setting `height` or `fullscreen` on a panel widget                                     | These are ignored on panels — panels always auto-resize                                                                         |
| Placing `a-login-button` / `a-cart-modal-button` per entity instead of once in the nav | These are page-level shared controls — one set, top-right of the main nav                                                       |
| A full-page widget that makes the page scroll *and* the widget scroll                  | Use `fullscreen="true"` + `nav-height` so only the widget scrolls; don't wrap a fullscreen widget in a tall scrolling container |
| Giving the cart button a text label in the header                                      | Keep it icon + count only (`show-icon="true"`, no `label`) like a standard cart                                                 |
| Setting `height`/`fullscreen` on `a-agent-chat` inline mode                            | Size the **parent element** instead — the inline chat frame fills its container                                                 |
| Styling the widget element itself with CSS borders/radius                              | Style the wrapper element instead; the widget manages its own internal layout                                                   |

## Attribution Forwarding

UTM params and click IDs (`gclid`, `fbclid`, `ttclid`, `li_fat_id`) from the page URL are automatically forwarded into the widget iframe. No extra setup needed for conversion tracking.
