/* Radio — `.l-radio` on a native `<input type="radio">`.

   Mirrors the checkbox primitive (same `--l-form-control-*` tokens, same
   states) but reads as a single-choice control: the box is round and the
   selected state paints a centered dot instead of a checkmark. Native radios
   in the same `name` group already enforce single selection and roving focus,
   so there is no JS — this is a CSS-only `appearance: none` skin.

   The dot is drawn with a `background-image` SVG on the input itself —
   `::before`/`::after` do not paint on replaced elements like `<input>`.
   `background-image` can't read the host's `currentColor`, so the glyph color
   is baked white. This stays legible because the accent
   (`--l-form-control-activated-color`) is a stable color that does not invert
   between light and dark. Override `--dot` to swap the icon.

   `l-form-field` auto-styles a bare radio via a zero-specificity `:where()`
   selector, so inside a field no class is needed (`unstyled` opts out). */

@layer components {
  .l-radio,
  :where(l-form-field:not([unstyled])) > input[type='radio'] {
    /* Public knobs */
    --size: var(--l-form-control-toggle-size);
    --accent: var(--l-form-control-activated-color);
    --dot: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><circle cx="12" cy="12" r="6"/></svg>');
    /* Hover-halo tint — neutral when unselected, accent when selected (set
       below); mirrors the switch so the toggle family shares one hover language. */
    --_halo: var(--l-form-control-border-color-hover);

    box-sizing: border-box;
    flex: 0 0 auto;
    inline-size: var(--size);
    block-size: var(--size);
    margin: 0;
    padding: 0;
    appearance: none;
    border: var(--l-form-control-border-width) solid var(--l-form-control-border-color);
    border-radius: 50%;
    background-color: var(--l-form-control-background-color);
    background-repeat: no-repeat;
    background-position: center;
    background-size: 100%;
    vertical-align: middle;
    cursor: pointer;
    transition-property: background-color, border-color, box-shadow;
    transition-duration: 150ms;

    &:checked {
      --_halo: var(--accent);
      border-color: var(--accent);
      background-color: var(--accent);
      background-image: var(--dot);
    }

    @media (hover: hover) {
      &:hover:not(:disabled) {
        border-color: var(--l-form-control-border-color-hover);
        box-shadow: 0 0 0 calc(var(--size) * var(--l-form-control-toggle-halo-ratio))
          color-mix(in oklab, var(--_halo), transparent 84%);
      }
    }

    &:focus-visible {
      outline: 2px solid var(--l-focus-ring);
      outline-offset: 2px;
    }

    /* Invalid: only after interaction (`:user-invalid`), or forced via
       `aria-invalid` (set by `l-form-field` / server-side validation).
       Overriding `--accent` makes a checked invalid radio fill with the error
       color too (not just the border). */
    &:user-invalid,
    &[aria-invalid='true'] {
      --accent: var(--l-form-control-border-color-invalid);
      border-color: var(--l-form-control-border-color-invalid);
    }

    &:disabled {
      cursor: not-allowed;
      opacity: 0.4;
    }

    /* High contrast: the selected fill is forced to Canvas, hiding the accent
       and leaving the baked-white dot invisible — pin the selected box to a
       system color so the dot stays legible. */
    @media (forced-colors: active) {
      &:checked {
        border-color: Highlight;
        background-color: Highlight;
      }
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .l-radio,
    :where(l-form-field:not([unstyled])) > input[type='radio'] {
      transition-duration: 0ms;
    }
  }
}
