/*
  Badge: [data-badge] on data, span, a or button, value picks the color.
  Gotcha: every direct child span of a badge is visually hidden, because that is
  how screen reader context is written. Wrap icons or styled text in an inner
  element other than a span (for example <i> or <b>), or nest them deeper.
*/

:root,
:host,
[data-theme] {
  /* Soft by default: a 14% tint of the color, text in a darker (light scheme) or lighter
     (dark scheme) shade of it. data-badge="contrast" stays solid, for counters. */
  --pico-badge-background-color: color-mix(in oklab, var(--pico-primary) 14%, transparent);
  --pico-badge-color: light-dark(
    color-mix(in oklab, var(--pico-primary), #000 35%),
    color-mix(in oklab, var(--pico-primary), #fff 35%)
  );
  --pico-badge-success-background-color: oklch(0.6 0.12 165 / 0.14);
  --pico-badge-success-color: light-dark(oklch(0.39 0.078 165), oklch(0.74 0.078 165));
  --pico-badge-warning-background-color: oklch(0.72 0.15 75 / 0.16);
  --pico-badge-warning-color: light-dark(oklch(0.45 0.097 75), oklch(0.82 0.097 75));
  --pico-badge-danger-background-color: oklch(0.58 0.18 25 / 0.14);
  --pico-badge-danger-color: light-dark(oklch(0.42 0.13 25), oklch(0.75 0.117 25));
}

[data-badge] {
  display: inline-flex;
  box-sizing: border-box;
  align-items: center;
  justify-content: center;
  min-inline-size: 1.75em;
  block-size: 1.75em;
  margin-block: 0;
  margin-inline-start: 0.4em;
  padding-block: 0;
  padding-inline: 0.6em;
  border: 0;
  border-radius: 100vmax;
  background-color: var(--pico-badge-background-color);
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--pico-badge-color) 25%, transparent);
  color: var(--pico-badge-color);
  font-size: 0.8em;
  font-style: normal;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  line-height: 1;
  text-align: center;
  text-decoration: none;
  vertical-align: middle;
  white-space: nowrap;

  &[hidden] {
    display: none;
  }

  /* Trim the line box to the cap height so digits sit on the optical center */
  @supports (text-box: trim-both cap alphabetic) {
    text-box: trim-both cap alphabetic;
  }

  /* No text: a solid dot in the text shade */
  &:empty {
    min-inline-size: 0;
    inline-size: 0.65em;
    block-size: 0.65em;
    margin-inline-end: 0.4em;
    padding: 0;
  }

  &:empty:not([data-badge="contrast"]) {
    background-color: var(--pico-badge-color);
  }

  &[data-badge="secondary"] {
    --pico-badge-background-color: var(--pico-secondary-background);
    --pico-badge-color: var(--pico-secondary-inverse);
  }

  &[data-badge="contrast"] {
    --pico-badge-background-color: var(--pico-contrast-background);
    --pico-badge-color: var(--pico-contrast-inverse);
    box-shadow: none;
  }

  &[data-badge="success"] {
    --pico-badge-background-color: var(--pico-badge-success-background-color);
    --pico-badge-color: var(--pico-badge-success-color);
  }

  &[data-badge="warning"] {
    --pico-badge-background-color: var(--pico-badge-warning-background-color);
    --pico-badge-color: var(--pico-badge-warning-color);
  }

  &[data-badge="danger"] {
    --pico-badge-background-color: var(--pico-badge-danger-background-color);
    --pico-badge-color: var(--pico-badge-danger-color);
  }

  /* Screen reader context, for example "unread messages: " before the count */
  & > span {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    border: 0;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/*
  On a solid button a tint would disappear, so the default badge inverts with
  the tokens of that button variant. Status badges turn solid in their text
  shade and gain a ring in the button text color so the pill still reads as a
  shape. An outline button has no fill, so its badges apply normally.
*/
:is(button, [role="button"], input[type="submit"], input[type="button"]) > [data-badge] {
  /* vertical-align: middle centers on the x-height, a button label reads on its cap height */
  vertical-align: 0.1em;
}

:is(button, [role="button"], input[type="submit"], input[type="button"]):not(.outline) {
  --pico-badge-ring-color: var(--pico-primary-inverse);

  &.secondary {
    --pico-badge-ring-color: var(--pico-secondary-inverse);
  }

  &.contrast {
    --pico-badge-ring-color: var(--pico-contrast-inverse);
  }

  & > [data-badge]:not([data-badge="success"], [data-badge="warning"], [data-badge="danger"]) {
    --pico-badge-background-color: var(--pico-badge-ring-color);
    --pico-badge-color: var(--pico-primary-background);
  }

  &.secondary
    > [data-badge]:not([data-badge="success"], [data-badge="warning"], [data-badge="danger"]) {
    --pico-badge-color: var(--pico-secondary-background);
  }

  &.contrast
    > [data-badge]:not([data-badge="success"], [data-badge="warning"], [data-badge="danger"]) {
    --pico-badge-color: var(--pico-contrast-background);
  }

  /* Status counters on a fill: one saturated step in both schemes, with a ring in the
     button text color so they do not blend into the button */
  & > [data-badge]:is([data-badge="success"], [data-badge="warning"], [data-badge="danger"]) {
    background-color: var(--_badge-solid);
    box-shadow: 0 0 0 0.125rem var(--pico-badge-ring-color);
    color: var(--_badge-solid-color, oklch(1 0 0));
  }

  & > [data-badge="success"] {
    --_badge-solid: oklch(0.5 0.11 165);
  }

  & > [data-badge="warning"] {
    --_badge-solid: oklch(0.8 0.15 75);
    --_badge-solid-color: oklch(0.2 0.02 75);
  }

  & > [data-badge="danger"] {
    --_badge-solid: oklch(0.54 0.19 25);
  }
}

/* A status dot at the start of a list item replaces the bullet */
li:has(> [data-badge]:empty:first-child) {
  list-style: none;

  & > [data-badge]:first-child {
    margin-inline-start: 0;
  }
}

/* The link underline belongs to the link, not to the pill */
a[data-badge] {
  &:hover,
  &:focus-visible {
    text-decoration: none;
  }
}

@media (forced-colors: active) {
  [data-badge] {
    border: 1px solid;
  }
}
