/* -- Number Input component ------------------------------------- */

@layer components {
  .number-input {
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--input);
    border-radius: var(--radius-md);
    background: var(--background);
    box-shadow: var(--shadow-xs);
    overflow: hidden;
    /* explicit border-box: the size ladder below sets an explicit container
       height and must land on it exactly (a div is content-box by default;
       inputs get border-box from the UA). The unsized default keeps its
       auto height (children drive it), so this changes nothing today. */
    box-sizing: border-box;
    /* explicit default box height (the size ladder below does the rest): an
       auto-height box let the UA-padding children overshoot to 44px. The
       unsized default IS the ladder's md step - field standard, see .input */
    height: 2.25rem;

    & input {
      border: none;
      outline: none;
      background: transparent;
      height: 100%;
      /* 4rem basis, but GROWS when the container is widened (w-full demos,
         grid cells): a fixed width left dead space after the + button.
         width pins the intrinsic size too - Chrome otherwise derives a
         number input's width from the digit count of max (no max: ~170px,
         max="100": 34px), so the field width followed a validation attr. */
      flex: 1 1 4rem;
      width: 4rem;
      min-width: 0;
      text-align: center;
      font-size: 0.875rem;
      font-family: var(--font-sans);
      color: var(--foreground);
      -moz-appearance: textfield;

      &::-webkit-inner-spin-button,
      &::-webkit-outer-spin-button {
        -webkit-appearance: none;
        margin: 0;
      }
    }

    & button {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 2rem;
      /* height:100% so the button can't overshoot the container's border-box
         height (the ladder below already sets children to 100%) */
      height: 100%;
      border: none;
      background: transparent;
      color: var(--muted-foreground);
      cursor: pointer;
      font-size: 1rem;
      font-family: var(--font-sans);
      transition: background 150ms, color 150ms;
      flex-shrink: 0;

      &:hover {
        background: var(--accent);
        color: var(--accent-foreground);
      }

      &:first-child {
        border-right: 1px solid var(--input);
      }

      &:last-child {
        border-left: 1px solid var(--input);
      }
    }

    /* -- Unit affix: <label class="number-input-unit" for="…"> -----
       A unit (°C, %, kg, €, h) sits before or after the input. It is a
       second <label> for the input: clicking it focuses the field and the
       unit joins the accessible name ("Temperature °C"). The value aligns
       TOWARD the unit so number + unit read as one ("19.0 °C", "€ 24.90"). */
    & .number-input-unit {
      display: flex;
      align-items: center;
      align-self: stretch;
      flex-shrink: 0;
      padding-inline: 0.25rem;
      color: var(--muted-foreground);
      font-size: 0.875rem;
      font-family: var(--font-sans);
      white-space: nowrap;
      cursor: text;

      /* edge of the box (no stepper on that side): field padding */
      &:first-child { padding-inline-start: 0.75rem; }
      &:last-child { padding-inline-end: 0.75rem; }
    }

    /* NOT user-select: none - the unit is part of the value when text is
       selected, copied or exported ("72,5 kg", not a bare "72,5") */

    &:has(input:not([type="hidden"]) + .number-input-unit) input { text-align: end; }
    &:has(.number-input-unit + input:not([type="hidden"])) input { text-align: start; }

    /* currency fields carry grouped amounts ("1.234.567,89") */
    &[data-currency] input { width: 8rem; }

    /* stepper-less field (currency, measurements): the input reaches the box
       edge - give it the regular field padding there */
    & input:first-child { padding-inline-start: 0.75rem; }
    & input:last-child { padding-inline-end: 0.75rem; }

    &:focus-within {
      border-color: var(--ring);
      box-shadow: 0 0 0 2px oklch(from var(--ring) l c h / 0.2);
    }

    /* -- Sizes -------------------------------------------------
       Container height + input/button/font scale together, matching the
       input/button ladders (md = 2.25rem; the unsized default stays at the
       historical 2.5rem, exactly like .input does). Children switch to
       height:100% so they can't fight the container. */
    &[data-size="xs"] {
      height: 1.75rem;
      & input { height: 100%; width: 3rem; font-size: 0.75rem; }
      & button { height: 100%; width: 1.5rem; font-size: 0.875rem; }
      & .number-input-unit { font-size: 0.75rem; }
    }
    &[data-size="sm"] {
      height: 2rem;
      & input { height: 100%; width: 3.5rem; font-size: 0.8125rem; }
      & button { height: 100%; width: 1.75rem; font-size: 0.9375rem; }
      & .number-input-unit { font-size: 0.8125rem; }
    }
    &[data-size="md"] {
      height: 2.25rem;
      & input { height: 100%; font-size: 0.875rem; }
      & button { height: 100%; }
    }
    &[data-size="lg"] {
      height: 2.75rem;
      & input { height: 100%; width: 4.5rem; font-size: 1rem; }
      & button { height: 100%; width: 2.25rem; font-size: 1.125rem; }
      & .number-input-unit { font-size: 1rem; }
    }
    &[data-size="xl"] {
      height: 3.25rem;
      & input { height: 100%; width: 5rem; font-size: 1.125rem; }
      & button { height: 100%; width: 2.5rem; font-size: 1.25rem; }
      & .number-input-unit { font-size: 1.125rem; }
    }
  }
}

/* Accessibility: suppress motion for users who request it (REQUIRED for all
   components - AGENTS.md "Accessibility CSS"). Near-zero duration instead of
   `none` keeps transitionend/animationend (and discrete display flips)
   firing so JS state machines that await them keep working. */
@media (prefers-reduced-motion: reduce) {
  @layer components {
    .number-input,
    .number-input *,
    .number-input::before,
    .number-input::after,
    .number-input *::before,
    .number-input *::after,
    .number-input::backdrop {
      transition-duration: 0.01ms !important;
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
    }
  }
}
