> For the complete documentation index, see [llms.txt](https://docs.allout.game/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.allout.game/ui/uidoc-game-ui-kit.md).

# UIDoc Game UI Kit

***

The Game UI kit is the art team's hand-drawn UI set (`$AO/ui/kit/Game UI/**`): modals, buttons, tabs, progress bars, banners, portholes, item slots, checkboxes, and toggles. The engine ships a matching stylesheet so any UIDoc asset can adopt the kit look without copying CSS.

**Apply the kit as a final styling pass.** Build the screen first — layout, bindings, events, viewport behavior — verify it works, then skin it. Kit styling is paint and padding; it must never be the tool used to fix layout.

## Enabling the kit

Add one line to the asset's `index.css`:

```css
@import "game-ui-kit";
```

At bake time the engine splices `res/ui/kit/kit.css` in place of the import, so put the import first and your own rules below it — your rules win cascade ties. The import composes with Tailwind utilities. Editing the engine stylesheet re-bakes importing assets on the next build; UIDoc still does not hot reload in a running game.

## The one pattern to know

UIDoc has no bitmap CSS backgrounds, so kit art enters through ordinary `img` elements. Every kit container is a positioned element whose first child is a `.kit-bg` image; the div owns shape and layout, the image just paints, nine-slicing via asset settings that ship with the kit:

```html
<div class="kit-modal">
  <img class="kit-bg kit-bg--shadow" src="$AO/ui/kit/Game UI/Modals/Basic Modals/modal_simple_grey1.png">
  <!-- content -->
</div>
```

`.kit-bg` is `object-fit: fill` for nine-sliced art (modals, buttons, tabs, bars, banners). Fixed-aspect art (checkboxes, toggles, portholes, slot icons) uses `.kit-bg--contain` and the container's own width/height.

Use `.kit-bg--shadow` on the actual backing `img` when the art should cast a shadow. It uses an alpha-aware `drop-shadow(...)`, so transparent corners and the painted result of nine-slicing define the silhouette. A `box-shadow` follows the container's rectangular border box instead, while putting `drop-shadow(...)` on the container would also include its text and other descendants.

Put visible button/tab copy in a foreground label element after the art. Raw text owned by the container can paint below its child image:

```html
<button class="kit-btn kit-btn--green">
  <img class="kit-bg" src="$AO/ui/kit/Game UI/Buttons/basic_buttons/button_large_green1.png">
  <span class="kit-btn-label">PLAY</span>
</button>
```

The kit optically lowers direct button labels by 5px to match the art. For a compound foreground such as an icon plus a price, wrap the whole foreground in `.kit-btn-content` so the icon and copy move together:

```html
<button class="kit-btn kit-btn--green">
  <img class="kit-bg" src="$AO/ui/kit/Game UI/Buttons/shiny_buttons/button_large_green1.png">
  <span class="kit-btn-content price">
    <img src="coin.png">
    <span class="kit-btn-label">300</span>
  </span>
</button>
```

## Class reference

| Class                                                                               | Use                                                                                       |
| ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `.kit-bg`, `.kit-bg--contain`, `.kit-bg--shadow`                                    | Art backing image, fixed-aspect fit, and alpha-aware image shadow                         |
| `.kit-fg`                                                                           | Generic foreground layer above `.kit-bg`                                                  |
| `.kit-modal`                                                                        | Positioned flex-column panel with kit padding                                             |
| `.kit-modal-header`                                                                 | Centered title safe area with 72px reserved on both sides                                 |
| `.kit-modal-title`                                                                  | Centered title row; combine with `.kit-text-header`                                       |
| `.kit-title-banner`                                                                 | `pointy_banner_*` backing behind a modal title, fully inside the modal                    |
| `.kit-header-band`                                                                  | `modal_header_*` band across the modal's painted top edge                                 |
| `.kit-dim`                                                                          | Full-screen dim behind a modal                                                            |
| `.kit-btn`, `.kit-btn-label`, `.kit-btn-content`, `.kit-btn--<colour>`              | Button art plus an optically lowered foreground label/group with a colour-matched outline |
| `.kit-tab-row`, `.kit-tab`, `.kit-tab-label`, `.kit-tab--active`                    | Pill-tab navigation row with foreground labels                                            |
| `.kit-progress`, `.kit-progress-fill`, `.kit-progress--N`, `.kit-progress--compact` | Track plus bound fill; family modifier aligns the fill and compact selects the 30px scale |
| `.kit-card`, `.kit-list-row`                                                        | Structural containers for art-backed cards and rows                                       |
| `.kit-close`                                                                        | Foreground close control absolutely rooted at the modal's top-right                       |
| `.kit-slot`, `.kit-slot-icon`, `.kit-slot-qty`                                      | Inventory/shop square with icon and count                                                 |
| `.kit-porthole`                                                                     | Circular frame; stack `*_back.png` under `*_ring.png`                                     |
| `.kit-checkbox`, `.kit-toggle`                                                      | Fixed-aspect state controls                                                               |
| `.kit-text-header/body/body-dark/info`                                              | The art doc's four approved text styles                                                   |

Text sizes follow the art doc (65/55/45/40) at the standard logical viewport; override in the asset when a screen needs a different scale.

## Assembly rules

These come from the art team's Game UI documentation and established practice; the classes encode most of them, the markup patterns cover the rest.

* **Titles**: white, Heavy, black outline, drop shadow (`.kit-text-header`), set either straight on the modal, on a `.kit-title-banner` (dark banner backing, fully inside the modal — avoid the brown "yellow" pointy banner), or on a `.kit-header-band` when the colour pairing works: a saturated band on a light modal (red on white) reads well; muted-on-muted (gold on grey) does not. When unsure, plain title text is always safe.
* **Closable modal headers**: keep `.kit-close` as a direct child of `.kit-modal`, where it remains absolutely rooted at the top-right. Put the title or title banner inside `.kit-modal-header`; its symmetric 72px side reserves keep the title visually centered and clear of the close control. Budget modal width as the desired title/banner width plus both 72px reserves plus the panel's left and right padding. This deliberately makes closable modals a little wider than tightly fitted body content.
* **Art shadows**: `box-shadow` follows a rectangular border box. For irregular or nine-sliced kit art, put `.kit-bg--shadow` on the actual backing `img` so the shadow follows its painted alpha. Do not put the filter on `.kit-modal`, because that would include the modal's text and child art in the shadow silhouette.
* **Buttons**: text is white with a **colour outline** complementing the button art — never black. Put a plain label directly in `.kit-btn-label` so it paints above the art and receives the kit's 5px optical baseline offset. For icon-plus-text content, put both inside a direct `.kit-btn-content` child so the pair receives that offset together. Use `shiny_buttons` for purchases and special interactions, `basic_buttons` for everything else, and give text generous padding. The grey button is the disabled look.
* **Body text**: subtle 20%-opacity outline (`.kit-text-body`) on colour modals; plain dark text (`.kit-text-body-dark`) on white/grey modals.
* **Tabs**: a pill row *inside* the modal body, not attached to the top edge. Put copy in `.kit-tab-label`. Active tab uses a colour art variant (e.g. `tabs_blue`) with a matching text outline; inactive tabs use `tabs_black`. Use `tab_med.png` or `tab_large.png` for dynamic labels. The `tab_small.png` source files are inconsistent and some contain baked labels, so they are intentionally not nine-sliced.
* **Progress bars**: each `progress_bar_N` folder pairs a `backing.png` with a purpose-built `fill_*.png`, but the interior offsets differ by family and are often asymmetric because of the lower rim/drop shadow. Track art goes in `.kit-bg`; the matching family fill goes in `.kit-progress-fill`, which uses `object-fit: fill`; add the matching `.kit-progress--N` modifier to the container and bind `data-style-image-fill-amount`. Do not substitute a tinted icon or decorative transparent image: tint preserves source alpha, and `cover` can crop square art into gaps or diagonal wedges on a thin track. Preview the bar at `0`, `0.25`, `0.5`, and `1`; current diagnostics do not detect unsuitable texture alpha. The default component is 40px thick; add `.kit-progress--compact` for the proportionally scaled 30px form. For a custom thickness, set equal `font-size` and `height` values on the container so its em-based family insets scale with it. Kit tracks use `flex-shrink: 0`; choose the thickness explicitly instead of relying on a flex parent to compress the track, which can make the track and its fill resolve at different sizes.
* **Item slots**: colour squares (`inv_square_<colour>1.png`) for filled slots; `inv_square_empty2.png` is the designed EMPTY state.
* **Modal family art shares one scale** (37px corners, 6px outline in source pixels — the shipped slice insets already account for this). Pieces meant to composite, like a header band over a modal, align because they are drawn at the same scale; do not hand-edit individual slice values.

## Example: settings modal

Stripe modals (`modal_stripe_*`) carry a darker footer band — seat the action row on it by keeping it the last flow child.

```html
<div class="kit-modal settings">
  <img class="kit-bg kit-bg--shadow" src="$AO/ui/kit/Game UI/Modals/Basic Modals/modal_stripe_blue1.png">
  <div class="kit-modal-header">
    <div class="kit-modal-title kit-text-header">SETTINGS</div>
  </div>
  <button class="kit-close" data-on-click="event:settings:close">
    <img src="$AO/ui/kit/Icons/misc_icons_2/exit_button_small.png">
  </button>
  <div class="rows">
    <div class="row">
      <span class="kit-text-body">Music</span>
      <button class="kit-toggle" data-on-click="event:toggle:music">
        <img class="kit-bg kit-bg--contain" data-if="music.on" src="$AO/ui/kit/Game UI/Additional Elements/Sliders + Toggles/switch_long_on.png">
        <img class="kit-bg kit-bg--contain" data-if="music.off" src="$AO/ui/kit/Game UI/Additional Elements/Sliders + Toggles/switch_long_off.png">
      </button>
    </div>
    <div class="row">
      <span class="kit-text-body">Season pass</span>
      <div class="kit-progress kit-progress--1 pass-progress">
        <img class="kit-bg" src="$AO/ui/kit/Game UI/Additional Elements/Progress Bars/progress_bar_1/backing.png">
        <img class="kit-progress-fill" src="$AO/ui/kit/Game UI/Additional Elements/Progress Bars/progress_bar_1/fill_yellow.png"
             data-style-image-fill-amount="pass.progress">
      </div>
    </div>
  </div>
  <div class="actions">
    <button class="kit-btn kit-btn--yellow" data-on-click="event:settings:save">
      <img class="kit-bg" src="$AO/ui/kit/Game UI/Buttons/basic_buttons/button_large_yellow1.png">
      <span class="kit-btn-label">SAVE</span>
    </button>
    <button class="kit-btn kit-btn--red" data-on-click="event:settings:reset">
      <img class="kit-bg" src="$AO/ui/kit/Game UI/Buttons/basic_buttons/button_large_red1.png">
      <span class="kit-btn-label">RESET</span>
    </button>
  </div>
</div>
```

```css
@import "game-ui-kit";

.settings { width: 620px; }
.settings .rows { display: flex; flex-direction: column; gap: 18px; margin-bottom: 26px; }
.settings .row { display: flex; align-items: center; justify-content: space-between; gap: 20px; }
.settings .pass-progress { width: 260px; }
.settings .actions { display: flex; gap: 16px; justify-content: center; }
```

```csl
UI.uidoc_bind_bool("music.on", player.music_enabled);
UI.uidoc_bind_bool("music.off", !player.music_enabled);
UI.uidoc_bind_float("pass.progress", clamp(player.pass_progress, 0.0, 1.0));
```

## Example: confirm dialog (battle request)

A saturated header band on a light modal, dark body text, and a yellow/red accept/decline pair.

```html
<div class="kit-modal battle">
  <img class="kit-bg kit-bg--shadow" src="$AO/ui/kit/Game UI/Modals/Basic Modals/modal_simple_white1.png">
  <div class="kit-header-band">
    <img class="kit-bg" src="$AO/ui/kit/Game UI/Modals/Basic Modals/modal_header_red1.png">
    <div class="kit-modal-header">
      <span class="kit-text-header band-title">BATTLE REQUEST</span>
    </div>
  </div>
  <button class="kit-close" data-on-click="event:battle:close">
    <img src="$AO/ui/kit/Icons/misc_icons_2/exit_button_small.png">
  </button>
  <div class="kit-porthole challenger">
    <img class="kit-bg kit-bg--contain" src="$AO/ui/kit/Game UI/Additional Elements/Circle Portholes/blue_back.png">
    <img class="kit-bg kit-bg--contain" src="$AO/ui/kit/Game UI/Additional Elements/Circle Portholes/gold_ring.png">
  </div>
  <span class="kit-text-body-dark message">{{challenger.name}} challenges you to a battle!</span>
  <div class="actions">
    <button class="kit-btn kit-btn--yellow" data-on-click="event:battle:accept">
      <img class="kit-bg" src="$AO/ui/kit/Game UI/Buttons/basic_buttons/button_large_yellow1.png">
      <span class="kit-btn-label">ACCEPT</span>
    </button>
    <button class="kit-btn kit-btn--red" data-on-click="event:battle:decline">
      <img class="kit-bg" src="$AO/ui/kit/Game UI/Buttons/basic_buttons/button_large_red1.png">
      <span class="kit-btn-label">DECLINE</span>
    </button>
  </div>
</div>
```

```css
@import "game-ui-kit";

.battle { width: 680px; align-items: center; }
.battle .band-title { font-size: 55px; }
.battle .challenger { margin-bottom: 10px; }
.battle .message { text-align: center; margin-bottom: 24px; }
.battle .actions { display: flex; gap: 16px; }
```

## Example: daily reward

A banner-backed title on a grey modal, reward slots, a streak bar, and a shiny claim button.

```html
<div class="kit-modal reward">
  <img class="kit-bg kit-bg--shadow" src="$AO/ui/kit/Game UI/Modals/Basic Modals/modal_simple_grey1.png">
  <div class="kit-modal-header">
    <div class="kit-title-banner">
      <img class="kit-bg" src="$AO/ui/kit/Game UI/Additional Elements/Horizontal Banners/pointy_banner_blue.png">
      <span class="kit-text-header banner-title">DAILY REWARD</span>
    </div>
  </div>
  <button class="kit-close" data-on-click="event:reward:close">
    <img src="$AO/ui/kit/Icons/misc_icons_2/exit_button_small.png">
  </button>
  <span class="kit-text-body-dark streak">Day {{streak.day}} — keep it going!</span>
  <div class="slots">
    <div class="kit-slot" data-for="reward in rewards" data-for-key="reward.id">
      <img class="kit-bg kit-bg--contain" src="{{reward.back}}">
      <img class="kit-slot-icon" src="{{reward.icon}}">
      <span class="kit-slot-qty">{{reward.count}}</span>
    </div>
  </div>
  <div class="kit-progress kit-progress--1 streak-bar">
    <img class="kit-bg" src="$AO/ui/kit/Game UI/Additional Elements/Progress Bars/progress_bar_1/backing.png">
    <img class="kit-progress-fill" src="$AO/ui/kit/Game UI/Additional Elements/Progress Bars/progress_bar_1/fill_yellow.png"
         data-style-image-fill-amount="streak.progress">
  </div>
  <button class="kit-btn kit-btn--yellow claim" data-on-click="event:reward:claim">
    <img class="kit-bg" src="$AO/ui/kit/Game UI/Buttons/shiny_buttons/button_large_yellow1.png">
    <span class="kit-btn-label">CLAIM</span>
  </button>
</div>
```

```css
@import "game-ui-kit";

.reward { width: 600px; align-items: center; }
.reward .banner-title { font-size: 50px; }
.reward .streak { margin-bottom: 16px; }
.reward .slots { display: flex; gap: 12px; margin-bottom: 18px; }
.reward .streak-bar { width: 320px; margin-bottom: 22px; }
```

Filled slots bind `reward.back` to `$AO/ui/kit/Game UI/Item Backs/inventory_squares_1/inv_square_blue1.png` (or another colour); empty slots use `inv_square_empty2.png` with no icon.

## Art coverage

Nine-slice insets ship in `res/ui/kit/Game UI/.asset_settings` for: Basic Modals (simple, stripe, headers), basic and shiny buttons, medium/large modal tab pills and trapezoids, horizontal progress-bar backings/fills (excluding segment sprites and fixed-aspect bar 12), horizontal pointy banners, and horizontal interior panels. Fixed-aspect pieces — including inventory squares, checkboxes, sliders and toggles, portholes, helper masks, and highlights — need no slices. Other families (cards, speech bubbles, fancy banners, ranking backings) exist in the kit but have no tuned insets yet — measure before slicing them, and keep composited pieces at one shared scale.
