@scope (badge-ui) {
  :where(:scope) {
    /* ── Tokens ── */
    --badge-bg-default:        var(--a-bg-muted);
    --badge-fg-default:        var(--a-fg);
    --badge-radius-default:    var(--a-radius-md);
    --badge-px-default:        var(--a-space-2);
    --badge-py-default:        2px;
    --badge-gap-default:       var(--a-space-1);
    --badge-font-size-default: var(--a-ui-sm);
    text-align: start;  /* §text-align-reset — blocks inheritance from centered ancestors */
}

  :scope {
    /* ── Base ── */
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--badge-gap, var(--badge-gap-default));
    width: fit-content;
    padding: var(--badge-py, var(--badge-py-default)) var(--badge-px, var(--badge-px-default));
    background: var(--badge-bg, var(--badge-bg-default));
    color: var(--badge-fg, var(--badge-fg-default));
    font: inherit;
    font-size: var(--badge-font-size, var(--badge-font-size-default));
    font-weight: 500;
    line-height: 1;
    border-radius: var(--badge-radius, var(--badge-radius-default));
    white-space: nowrap;
    vertical-align: middle;
  }

  /* `[text]` attribute selector gates the ::after so consumers using
     slotted content (`<badge-ui>3</badge-ui>`) don't get an empty
     pseudo-element flex item — which would otherwise inherit the
     host's `gap` and add a phantom `--badge-gap`-wide trailing space
     after the slotted content. Mirrors `button.css` / `tag.css`. */
  :scope[text]::after {
    content: attr(text);
  }

  /* Leading icon stamped by JS (when [icon] is set). Inherits the badge's
     foreground color so legend chips read as a single color-coded unit
     (e.g. accent variant → accent-colored dot + accent-colored label). */
  :scope > icon-ui {
    --a-icon-size: 0.75em;
    color: currentColor;
    flex-shrink: 0;
  }

  /* ── Variants ──
     Badge fg pairs with the muted (tinted) bg — use --a-{family}-text, which
     flips with scheme (shade in light, tint in dark) for proper contrast.
     --a-{family}-text-strong is for solid fills (--a-{family}-bg) and would
     collapse contrast on muted: warning fails in dark, danger fails in light.
     Accent keeps the saturated-text-on-tint look (intentional brand emphasis). */
  :scope[variant="accent"] {
    --badge-bg-default: var(--a-accent-muted);
    --badge-fg-default: var(--a-accent-text);
  }

  :scope[variant="info"] {
    --badge-bg-default: var(--a-info-muted);
    --badge-fg-default: var(--a-info-text);
  }

  :scope[variant="success"] {
    --badge-bg-default: var(--a-success-muted);
    --badge-fg-default: var(--a-success-text);
  }

  :scope[variant="warning"] {
    --badge-bg-default: var(--a-warning-muted);
    --badge-fg-default: var(--a-warning-text);
  }

  :scope[variant="danger"] {
    --badge-bg-default: var(--a-danger-muted);
    --badge-fg-default: var(--a-danger-text);
  }

  /* `primary` is the accent-filled variant — solid bg + on-accent text,
     used for "PRO"-style emphasis chips that should read as a brand
     stamp rather than tinted-on-canvas. Uses the L3 primary-* surface
     matrix so it tracks the same accent-strong source as button-ui's
     primary variant. */
  :scope[variant="primary"] {
    --badge-bg-default: var(--a-primary-bg);
    --badge-fg-default: var(--a-primary-fg);
  }

  /* `muted` and `neutral` are semantic aliases of the base — same tokens
     as the default variant, declared explicitly so the yaml enum and the
     CSS contract agree. Use cases: passive metadata chips (counts, IDs,
     "Not set" states) where the badge should read as quiet chrome. */
  :scope[variant="muted"],
  :scope[variant="neutral"] {
    --badge-bg-default: var(--a-bg-muted);
    --badge-fg-default: var(--a-fg);
  }

  /* Size handled by universal [size] attribute system. */
}
