@scope (swatch-ui) {
  :where(:scope) {
    /* ── Layout ── */
    --swatch-gap:               var(--a-space-2);

    /* ── Sizes ──
       The "tile" is the coloured shape; the label is plain text rendered
       beside (or below, for shape="block") the tile. Tile dimensions are
       size-driven; line shapes use a fixed thickness regardless of size. */
    --swatch-tile-sm:           var(--a-space-2);          /* 8px ~ */
    --swatch-tile-md:           var(--a-space-2-5);        /* 10px ~ */
    --swatch-tile-lg:           40px;                       /* token-scale block */
    --swatch-line-thickness:    2px;
    --swatch-line-length:       calc(var(--swatch-tile-md) * 1.75);

    /* ── Colors ──
       Default colour falls back through the data palette so a bare
       <swatch-ui> still renders something visible; consumers usually set
       --swatch-color via [color] attr or inline style. */
    --swatch-color:             var(--a-data-0);
    --swatch-label-fg:          var(--a-fg-subtle);

    /* ── Shape ── */
    --swatch-radius-block:      var(--a-radius-sm);
    --swatch-radius-square:     var(--a-radius-sm);

    /* ── Block-shape extras (token-scale) ── */
    --swatch-block-shadow:      inset 0 0 0 1px color-mix(in oklab, currentColor 8%, transparent);

    /* ── Typography ── */
    --swatch-label-size:        var(--a-ui-size);
    --swatch-label-step-size:   10px;
    --swatch-label-step-mt:     4px;
    --swatch-detail-size:       var(--a-ui-xs);
    --swatch-detail-fg:         var(--a-fg-subtle);

    /* ── Badge ── */
    --swatch-badge-size:        var(--a-ui-xs);
    --swatch-badge-fg:          var(--a-chrome-fg);
    --swatch-badge-bg:          var(--a-chrome-bg);
    --swatch-badge-pad:         2px 4px;
    --swatch-badge-radius:      var(--a-radius-xs);

    /* ── Copy button ── */
    --swatch-copy-size:         var(--a-space-3);
    --swatch-copy-fg:           var(--a-fg-muted);
    --swatch-copy-fg-ok:        var(--a-success);
    --swatch-copy-fg-fail:      var(--a-warning);

    /* ── Selectable ring ── */
    --swatch-select-ring:       var(--a-accent);
    --swatch-select-ring-width: 2px;
  }

  :scope {
    /* Default: inline-flex row — tile + label side-by-side, vertically
       centered. shape="block" overrides to flex-column (label sits below
       the tile, mimicking the token-scale step layout). */
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    gap: var(--swatch-gap);
    min-width: 0;
    color: var(--swatch-label-fg);
    font-size: var(--swatch-label-size);
    line-height: 1.2;
    vertical-align: baseline;
  }

  /* The colored tile — sized by [size] + [shape] combinations below. */
  :scope > [data-tile] {
    box-sizing: border-box;
    display: block;
    flex-shrink: 0;
    background: var(--swatch-color);
    line-height: 0;
  }

  :scope > [data-label] {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  :scope > [data-label][hidden] { display: none; }

  /* ═══════ Shape: dot ═══════ */
  :scope[shape="dot"] > [data-tile] {
    width: var(--_size, var(--swatch-tile-md));
    height: var(--_size, var(--swatch-tile-md));
    border-radius: 50%;
  }

  /* ═══════ Shape: square ═══════ */
  :scope[shape="square"] > [data-tile] {
    width: var(--_size, var(--swatch-tile-md));
    height: var(--_size, var(--swatch-tile-md));
    border-radius: var(--swatch-radius-square);
  }

  /* ═══════ Shape: line (solid hairline) ═══════ */
  :scope[shape="line"] > [data-tile] {
    width: var(--swatch-line-length);
    height: var(--swatch-line-thickness);
    border-radius: var(--swatch-line-thickness);
  }

  /* ═══════ Shape: dashed (dashed hairline) ═══════ */
  :scope[shape="dashed"] > [data-tile] {
    width: var(--swatch-line-length);
    height: var(--swatch-line-thickness);
    background: transparent;
    border-top: var(--swatch-line-thickness) dashed var(--swatch-color);
  }

  /* ═══════ Shape: block (token-scale tile) ═══════
     Filled rectangle whose height grows with [size]; label sits BELOW
     the tile (flex-column) so we can use it as a token-step swatch
     without any extra wrapper. */
  :scope[shape="block"] {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }

  :scope[shape="block"] > [data-tile] {
    width: 100%;
    height: var(--_block-h, var(--swatch-tile-lg));
    border-radius: var(--swatch-radius-block);
    box-shadow: var(--swatch-block-shadow);
  }

  :scope[shape="block"] > [data-label] {
    text-align: center;
    font-family: var(--a-font-family-code);
    font-size: var(--swatch-label-step-size);
    font-variant-numeric: tabular-nums;
    color: var(--a-fg-muted);
    margin-block-start: var(--swatch-label-step-mt);
    white-space: nowrap;
  }

  /* ═══════ §253 (v0.5.12, FB-23 §1): label-position="overlay" ═══════
     Renders the label INSIDE the block tile via absolute positioning.
     Pair with [auto-contrast] for OKLab-L-driven legibility (existing
     `data-on-light` / `data-on-dark` classes stamp on the label per
     the OKLab-L probe; see auto-contrast rules below).

     The host becomes the positioning context (default flex-column flow
     for the tile + detail line remains); the label is pulled out of
     flow + absolutely positioned to overlap the tile's full bounds
     (`top: 0; height: var(--_block-h)`). Tile is the first flex child
     with the same height, so the absolute label aligns exactly to it.

     Only meaningful when `shape="block"` (other shapes are too small
     for in-tile labels). Unblocks Tokens Studio's C1.3 dogfood
     migration (label-inside-the-tile pattern; blocked 3 cycles on this
     design call). */
  :scope[shape="block"][label-position="overlay"] {
    position: relative;
  }
  :scope[shape="block"][label-position="overlay"] > [data-label] {
    position: absolute;
    top: 0;
    inset-inline: 0;
    height: var(--_block-h, var(--swatch-tile-lg));
    display: flex;
    align-items: center;
    justify-content: center;
    margin-block-start: 0;        /* override the below-tile margin */
    padding: var(--a-space-1) var(--a-space-2);
    pointer-events: none;          /* don't intercept clicks on the tile */
  }

  /* ═══════ Sizes ═══════
     Override the dot/square diameter (`--_size`) and the block-shape
     height (`--_block-h`) for each size preset. Line/dashed widths use
     --swatch-line-length so they stay consistent at all sizes. */
  :scope[size="sm"] {
    --_size: var(--swatch-tile-sm);
    --_block-h: calc(var(--swatch-tile-lg) * 0.6);
  }
  :scope[size="md"] {
    --_size: var(--swatch-tile-md);
    --_block-h: calc(var(--swatch-tile-lg) * 0.75);
  }
  :scope[size="lg"] {
    --_size: calc(var(--swatch-tile-md) * 1.4);
    --_block-h: var(--swatch-tile-lg);
  }

  /* ═══════ Detail line ═══════
     Second line below the label — typically the raw token value for a
     design-token swatch. For shape="block" sits under the label; for
     non-block shapes is inline (small, muted, after label). */
  :scope > [data-detail] {
    color: var(--swatch-detail-fg);
    font-size: var(--swatch-detail-size);
    font-family: var(--a-font-family-code);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
  }
  :scope > [data-detail][hidden] { display: none; }

  :scope[shape="block"] > [data-detail] {
    text-align: center;
    margin-block-start: 2px;
  }

  /* ═══════ Badge stack ═══════
     Symbol pips (△ / ✦ / ✓ / ✗) in the upper-right of the tile. v0.4.9 §92
     supports multiple simultaneous badges — the container is a flex row;
     each pip is a positioned child with semantic color. */
  :scope > [data-badge] {
    position: absolute;
    top: -4px;
    right: -4px;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    pointer-events: none;
  }
  :scope > [data-badge][hidden] { display: none; }

  :scope > [data-badge] > [data-badge-variant] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--a-space-4);
    height: var(--a-space-4);
    padding: var(--swatch-badge-pad);
    background: var(--swatch-badge-bg);
    color: var(--swatch-badge-fg);
    font-size: var(--swatch-badge-size);
    line-height: 1;
    border-radius: var(--swatch-badge-radius);
    box-shadow: 0 0 0 1px color-mix(in oklab, var(--a-border-subtle) 60%, transparent);
  }

  /* Make sure the badge has a positioning context — the tile holds it. */
  :scope { position: relative; }

  /* Badge variants — symbol color encodes semantic */
  :scope > [data-badge] > [data-badge-variant="out-of-gamut"] { color: var(--a-warning); }
  :scope > [data-badge] > [data-badge-variant="p3-only"]      { color: var(--a-info); }
  :scope > [data-badge] > [data-badge-variant="apca-pass"]    { color: var(--a-success); }
  :scope > [data-badge] > [data-badge-variant="apca-fail"]    { color: var(--a-danger); }

  /* ═══════ Auto-contrast label color ═══════
     When [auto-contrast] is set, JS computes the swatch's OKLab L and
     stamps [data-on-light] or [data-on-dark] on the label. The label then
     swaps fg color so it remains legible against the tile background.
     Only fires for shape="block" (label sits ON the tile); for other
     shapes the label is beside the tile and uses the normal chrome fg.

     §339 (FB-41): the auto-contrast rules previously set `position:
     relative` which collided at equal specificity (0,3,1) with the
     overlay rule's `position: absolute` (line 164). Source order made
     the later auto-contrast rule win, so `[label-position="overlay"]
     [auto-contrast]` resolved the label to `position: relative`,
     dropping it OUT of overlay and below the tile (host height doubled).
     Fix: drop `position: relative` from auto-contrast. `z-index: 1`
     only does work on a positioned element; the overlay rule already
     supplies `position: absolute` for the overlay case. For the
     non-overlay default (label below tile), the label is in normal
     flow and doesn't overlap anything, so z-index is irrelevant. */
  :scope[shape="block"][auto-contrast] > [data-label] {
    z-index: 1;
  }
  :scope[shape="block"][auto-contrast] > [data-label][data-on-dark] {
    color: var(--a-chrome-light, #fafafa);
  }
  :scope[shape="block"][auto-contrast] > [data-label][data-on-light] {
    color: var(--a-chrome-dark, #111);
  }
  /* Detail line follows the same auto-contrast choice. */
  :scope[shape="block"][auto-contrast] > [data-detail] {
    z-index: 1;
  }
  :scope[shape="block"][auto-contrast] > [data-label][data-on-dark] ~ [data-detail] {
    color: color-mix(in oklab, var(--a-chrome-light, #fafafa) 80%, transparent);
  }
  :scope[shape="block"][auto-contrast] > [data-label][data-on-light] ~ [data-detail] {
    color: color-mix(in oklab, var(--a-chrome-dark, #111) 70%, transparent);
  }

  /* ═══════ Copy button ═══════ */
  :scope > [data-copy] {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    padding: 2px 4px;
    margin-inline-start: var(--a-space-1);
    color: var(--swatch-copy-fg);
    font-size: var(--a-ui-sm);
    line-height: 1;
    cursor: pointer;
    border-radius: var(--a-radius-xs);
    transition: color var(--a-duration-fast) var(--a-easing-out), background var(--a-duration-fast) var(--a-easing-out);
  }
  :scope > [data-copy]:hover { color: var(--a-fg); background: var(--a-bg-muted); }
  :scope > [data-copy]:focus-visible {
    outline: var(--swatch-select-ring-width) solid var(--swatch-select-ring);
    outline-offset: 1px;
  }
  :scope > [data-copy][hidden] { display: none; }
  :scope > [data-copy][data-copy-state="ok"]   { color: var(--swatch-copy-fg-ok); }
  :scope > [data-copy][data-copy-state="fail"] { color: var(--swatch-copy-fg-fail); }

  /* ═══════ Selectable + selected states ═══════
     [selectable] makes the whole host focusable; ring on :focus-visible.
     [selected] always shows the ring. */
  :scope[selectable] {
    cursor: pointer;
    border-radius: var(--a-radius-sm);
    transition: box-shadow var(--a-duration-fast) var(--a-easing-out);
  }
  :scope[selectable]:focus { outline: none; }
  :scope[selectable]:focus-visible {
    box-shadow: 0 0 0 var(--swatch-select-ring-width) var(--swatch-select-ring);
  }
  :scope[selected] {
    box-shadow: 0 0 0 var(--swatch-select-ring-width) var(--swatch-select-ring);
  }
  :scope[selectable]:hover:not([selected]) {
    box-shadow: 0 0 0 1px color-mix(in oklab, var(--swatch-select-ring) 50%, transparent);
  }
}
