<div class="ts-card" style="max-width:360px;">

    <div class="ts-card__header">
        <div>

            <h3 class="ts-card__title">Card title</h3>
        </div>

    </div>

    <p class="ts-card__body">A short description of the card content.</p>

</div>
<div class="ts-card{{#if single}} ts-card--tint{{/if}}{{#if selected}} is-selected{{/if}}"
     style="{{#if maxWidth}}max-width:{{maxWidth}};{{/if}}">
  {{#if image}}
  <div class="ts-card__figure">
    <img src="{{image}}" alt="{{imageAlt}}">
  </div>
  {{/if}}

  {{#if title}}
  <div class="ts-card__header">
    <div>
      {{#if eyebrow}}<div class="ts-eyebrow">{{eyebrow}}</div>{{/if}}
      <h3 class="ts-card__title">{{title}}</h3>
    </div>
    {{#if meta}}<div class="ts-card__meta">{{meta}}</div>{{/if}}
  </div>
  {{/if}}

  {{#if body}}<p class="ts-card__body">{{body}}</p>{{/if}}

  {{#if hint}}<p class="ts-hint">{{hint}}</p>{{/if}}

  {{#if empty}}
  <div class="ts-card__empty">
    <p class="ts-card__empty-title">{{empty.title}}</p>
    <p class="ts-card__empty-body">{{empty.body}}</p>
    <a href="#" class="button button--primary">{{empty.action}}</a>
  </div>
  {{/if}}

  {{#if action}}
  <div class="ts-card__actions">
    <a href="#" class="button button--primary">{{action}}</a>
    {{#if secondaryAction}}<a href="#" class="button">{{secondaryAction}}</a>{{/if}}
  </div>
  {{/if}}
</div>
{
  "title": "Card title",
  "body": "A short description of the card content.",
  "eyebrow": null,
  "meta": null,
  "hint": null,
  "image": null,
  "action": null,
  "secondaryAction": null,
  "empty": null,
  "single": false,
  "selected": false,
  "maxWidth": "360px"
}

The house container. Every panel on a page is one of these, so its anatomy is fixed:

Anatomy, in order: optional eyebrow, title, optional right-aligned meta slot, body, optional italic hint, then actions. Nothing else goes in the header row.

The meta slot is for a value belonging to the card as a whole rather than to a control inside it: a character count, a “last updated” time, a total. Right-aligned, muted, never a button.

Shape: white surface, 12px radius, quiet border, soft shadow. There is one card radius. Panels at 8px or 5px are drift and should be migrated.

Padding and gaps: cards use the space-5 step internally (24px) and sit space-5 apart. Do not hand-pick a value per page; that is how padding ended up ranging from 0 to 30px across the estate.

Headings: the card title is an h3 so the page keeps a real heading structure. Sibling cards on a page must share one header treatment. A card with a title beside a card without one reads as two different systems.

Empty states belong inside the card, not instead of it. An empty card still explains what would be here and offers the action that fills it. A bare sentence such as “No posts scheduled for this date.” is a dead end and is not acceptable.

Selection: selected cards take .is-selected, which draws the brand border. Every selectable thing on a page (mode cards, day cells, platform tabs) uses this same treatment, so selection means one visual thing.