/* Shared checkbox appearance — the visual skin behind `.l-checkbox`.

   Colocated with its `checkbox-appearance.styles.ts` wrapper so Shadow-DOM
   elements that render their own native checkbox (e.g. `<l-tree-item>` in
   `selection="multiple"`) can pull in the exact same look via `static styles`.
   The global light-DOM `checkbox.css` primitive `@import`s this file too, so
   both surfaces stay in sync. The global `.l-checkbox` class cannot pierce a
   shadow boundary, but the `--l-form-control-*` tokens this rule relies on DO
   inherit across shadow roots.

   Shadow consumers must emit the class via `cls('checkbox')`, never a static
   `class="l-checkbox"` literal. This file ships to dist as a real CSS file and
   is imported `?inline`, so the CONSUMER's Vite runs postcss-plugin-prefix over
   it and rewrites this selector to `.<cssPrefix>-checkbox`. The vite-plugin's
   `transform` hook only rewrites `_cssPrefix` in registry.js — it never touches
   template literals in element JS — so a hardcoded class attribute would stop
   matching the rewritten selector and the checkbox would render unstyled.

   The checkmark / indeterminate dash are 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 `--checkmark` to swap the icon. */

@layer components {
  .l-checkbox,
  :where(l-form-field:not([unstyled])) > input[type='checkbox']:not([role='switch']) {
    /* Public knobs */
    --size: var(--l-form-control-toggle-size);
    --accent: var(--l-form-control-activated-color);
    --checkmark: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>');
    --_dash: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round"><line x1="5" y1="12" x2="19" y2="12"/></svg>');

    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: calc(var(--size) * 0.2);
    background-color: var(--l-form-control-background-color);
    background-repeat: no-repeat;
    background-position: center;
    background-size: 75%;
    vertical-align: middle;
    cursor: pointer;
    transition-property: background-color, border-color;
    transition-duration: 150ms;

    &:checked,
    &:indeterminate {
      border-color: var(--accent);
      background-color: var(--accent);
    }

    &:checked {
      background-image: var(--checkmark);
    }

    &:indeterminate {
      background-image: var(--_dash);
    }

    @media (hover: hover) {
      &:hover:not(:disabled) {
        border-color: var(--l-form-control-border-color-hover);
      }
    }

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

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

      &:disabled {
        border-color: GrayText;
      }

      &:disabled:is(:checked, :indeterminate) {
        background-color: GrayText;
      }
    }

    /* 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 box 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;
    }

    /* Unchecked: the same three tokens as `input`/`select`/`textarea`, so a
       checkbox and an input in the same disabled form grey out identically.
       There is no mark here — only a box — so nothing can be washed out. */
    &:disabled:not(:checked, :indeterminate) {
      border-color: var(--l-form-control-disabled-border);
      background-color: var(--l-form-control-disabled-background);
    }

    /* Checked: faded rather than greyed. A solid neutral fill keeps the glyph
       crisp but reads as a styled, still-live control; the fade reads as
       "inactive" at a glance, which is the message that matters more here.
       The cost is measured and accepted: the checkmark drops to 1.85:1 against
       its own box, and the residual accent tint (1.81:1 against the page) is
       what carries "this one is checked". WCAG 1.4.11 exempts inactive
       components, so this is a deliberate trade, not a shortfall.

       It assumes the accent is dark enough for the baked-white glyph — the same
       assumption `--l-form-control-activated-color` already documents, and which
       the enabled state depends on just as much (a pale accent scores 1.31:1
       there, before anything is disabled). */
    &:disabled:is(:checked, :indeterminate) {
      opacity: 0.4;
    }

    /* Forced colors replaces author colors with the user's palette, so a fade
       would only dim a system color — the box is already GrayText up in the
       forced-colors block above. Placed here, after the fade, because it needs
       to win at equal specificity. */
    @media (forced-colors: active) {
      &:disabled:is(:checked, :indeterminate) {
        opacity: 1;
      }
    }
  }

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