# XWUICardX

The composable card. Where `XWUICard` renders one fixed arrangement (cover on top, then header, body, footer), `XWUICardX` makes the arrangement itself configurable through four orthogonal knobs and one shared placement grid.

| Prop | Values | Default | What it decides |
|---|---|---|---|
| `layout` | `stack` `row` `overlay` `plain` | `stack` | How media and content compose |
| `mediaPosition` | `start` `end` | `start` | Which logical side the media takes |
| `mediaRatio` | `0..1` or CSS length | `0.5` | How much of the card the media gets |
| `shape` | `auto` `wide` `square` `tall` | `auto` | The card's own footprint |
| `mediaAspect` | any ratio string | `16/9` (`1/1` in `row`) | The media box's aspect |
| `mediaActionsPlacement` / `contentActionsPlacement` | 9 cells | `top-start` / `bottom-start` | Where each action cluster sits |
| `mediaActionsAxis` / `contentActionsAxis` | `h` `v` | `h` | Cluster flow direction |
| `mediaActionsDistribute` / `contentActionsDistribute` | `packed` `spread` | `packed` | Whether buttons pack or spread |
| `scrim` | `none` `bottom` `top` `full` | `bottom` on `overlay`, else `none` | Gradient wash for overlay legibility |
| `hoverEffect` | `lift` `zoom` `glow` `zoom-glow` `none` | `lift` | How `hoverable` reacts (hover **and** focus) |
| `headerOrder` | `title-subtitle` `subtitle-title` | `title-subtitle` | Whether the dateline sits above the headline |
| `revealContent` | `always` `hover` | `always` | Fade the caption in only for the pointed-at card |
| `preset` | `summary` `hero` `tile` `rail` `stat` `banner` `capsule` `marquee` `news` | none | A named bundle of the above |

`data.overline` renders a category eyebrow as a band at the very top of the card, above the media.

## Presets

| Preset | Shape | Use |
|---|---|---|
| `summary` | row, 0.28 square thumb | og `summary`, compact link preview |
| `hero` | stack, 16/9 on top | og `summary_large_image` |
| `tile` | overlay, portrait, scrim | Netflix/Pinterest content tile |
| `rail` | row, 0.2 thumb, small | dense list row |
| `stat` | plain, large padding | KPI card, no media |
| `banner` | overlay, wide, full scrim | wide content-over-media |
| `capsule` | stack, 2/3 art, no chrome, `zoom-glow` | portrait cover art (game/app/poster) |
| `marquee` | stack, 21/9 art, no chrome, `glow` | featured banner beside a rail |
| `news` | stack, 16/9, small padding, `zoom`, dateline first | article/event card |

`capsule` and `marquee` are cover-art shapes: hand them only `media` and the card emits **no content region at all**, so a wall of tiles is exactly its artwork with no dead padding underneath.

## Why the props are shaped this way

**`layout` is the first prop, not `shape`.** A wide card whose media sits on top and a wide card whose media sits beside the content are both "wide" at the same ratio with the same ordering. Only a composition axis separates them, which is the same conclusion Fluent 2 reached with `orientation`.

**0 and 1 are layouts, not ratios.** At zero there is no media element; at one the content is not sized by any proportion, it is positioned over the media with a scrim. Leaving them on a numeric scale means `0.999` and `1.0` produce structurally different DOM. They are named modes here, and `mediaRatio` is a real proportion across its whole range.

**`mediaPosition` reorders the DOM.** Not CSS `order`, not `row-reverse`. A visual-only reorder desynchronises the accessibility tree from the rendered order (WCAG 1.3.2 Meaningful Sequence, 2.4.3 Focus Order). Because the values are logical rather than left/right, RTL mirrors for free.

**One placement vocabulary, two mechanisms.** Both clusters take the same nine cells. Media actions float over the image, resolved by grid self-alignment on a full-box overlay layer, so there are no physical insets or `translate` hacks to un-mirror under RTL. Content actions share a box with text, so their placement resolves into *flow*: the block half picks the slot (`top-*` above the title, `center-*` right after the body, `bottom-*` pinned to the end) and the inline half picks the justification. A content action can therefore never land on top of the paragraph next to it.

**`distribute` is separate from placement.** Where the cluster sits and whether its buttons pack together or spread apart are independent questions; one enum cannot answer both.

**Overlay gets a scrim by default.** White text on an unknown photograph is legible about half the time. The safe option is the default.

**The hit area is a sibling, not a wrapper.** A clickable card that also carries action buttons cannot wrap itself in an anchor without nesting interactive elements: invalid HTML for `<a>`, and a keyboard trap either way. `clickable` (or `href`) emits a covering element *underneath* the actions, the same shape as MUI's `CardActionArea`.

**No media means no media track.** A card configured `layout: 'row'` but handed no image collapses to `plain` rather than reserving an empty half.

## Notes and limits

- `mediaRatio` is inert for a `stack` whose `shape` is `auto`: a percentage of an indefinite block size means nothing, so the media box is sized by `mediaAspect` instead. The headless view reports this by returning a null media size rather than emitting a track that silently does nothing.
- `shape` other than `auto` pins an aspect-ratio, so overflowing content is clamped rather than growing the card. That is the cost of uniform tiles.
- `morphBreakpoint` is an enum, not a free CSS length, because a container query condition cannot read a custom property. Every accepted value has a real rule in the stylesheet.
- `conf_comp.preset` (arrangement) and `data.preset` (sample content) are independent and compose.

## Basic Usage

A stacked card: media on top, title, body, and a footer action row.

```example
file: examples/BasicUsage.ts
html: examples/BasicUsage.html
title: Basic Usage
description: Stacked card with media, title, body and footer actions.
```

## Row Layout

Media beside the content, with the ratio and the side both under control.

```example
file: examples/RowLayout.ts
html: examples/RowLayout.html
title: Row Layout
description: Side-by-side media and content, media on the inline-end side.
```

## Overlay Tile

Content over full-bleed media with a scrim, plus a media action cluster.

```example
file: examples/OverlayTile.ts
html: examples/OverlayTile.html
title: Overlay Tile
description: Portrait tile with content over media and corner actions.
```

## Sets of cards

State that spans more than one card - which is active, which is selected, where
an arrow key goes, one tab stop instead of N - belongs to
[XWUICardXGroup](../XWUICardXGroup/XWUICardXGroup.md), not here. A card owns its
own hover; it cannot know it is the third of six.

## Bazaar

A vehicle-listing card: inset photo column with a floating action cluster, contact row at the end of the content column.

```example
file: examples/Bazaar.ts
html: examples/Bazaar.html
title: Bazaar
description: Marketplace listing card built from four layout props.
```

## Action Placement

Both clusters placed from the same nine-cell vocabulary.

```example
file: examples/ActionPlacement.ts
html: examples/ActionPlacement.html
title: Action Placement
description: Media actions floating top-end, content actions spread along the footer.
```

```api
```
