/*
NumberInput

A text input in the control chrome with decrement and increment buttons,
drawn as one control: the group carries the border, radius and focus ring,
the input inside it is borderless. Buttons are fixed squares (sides) or a
fixed column of two halves (end), so pressing, disabling at a bound or
scrubbing never changes the box.

  .number-input                  root (data-disabled, data-readonly, data-scrubbing, data-invalid)
  .number-input-scrub            optional label that scrubs the value on drag
  .number-input-group            the bordered control
  .number-input-input            the text input (role=spinbutton)
  .number-input-button           decrement / increment (data-direction)
  .number-input.is-sm | is-lg    size
  .number-input-group[data-buttons="sides" | "end" | "none"]
  .number-input-cursor           the scrub cursor while the pointer is locked
*/

@layer components {

.number-input {
  --number-input-height: var(--control-height);
  --number-input-font:   var(--text-ui);
  --number-input-pad:    var(--control-padding-x);

  display:        flex;
  flex-direction: column;
  gap:            var(--space-1);
  min-width:      0;
}

.number-input.is-sm {
  --number-input-height: var(--control-height-sm);
  --number-input-font:   var(--text-ui-sm);
  --number-input-pad:    var(--control-padding-x-sm);
}

.number-input.is-lg {
  --number-input-height: var(--control-height-lg);
  --number-input-font:   var(--text-ui-lg);
  --number-input-pad:    var(--control-padding-x-lg);
}

.number-input-scrub {
  align-self:     flex-start;
  color:          var(--ink);
  font-family:    var(--font-ui);
  font-size:      var(--text-label);
  font-weight:    var(--weight-ui);
  letter-spacing: var(--tracking-ui);
  cursor:         ew-resize;
  touch-action:   none;
  user-select:    none;
}

.number-input-scrub[data-direction="vertical"] {
  cursor: ns-resize;
}

.number-input:is([data-disabled], :has(.number-input-input:disabled)) .number-input-scrub,
.number-input[data-readonly] .number-input-scrub {
  cursor: default;
}

.number-input-group {
  display:        flex;
  align-items:    stretch;
  width:          100%;
  min-width:      0;
  height:         var(--number-input-height);
  overflow:       hidden;
  border:         var(--control-border-width) solid var(--control-border);
  border-radius:  var(--radius-control);
  background:     var(--control-bg);
  box-shadow:     var(--control-shadow);
  transition:     border-color var(--duration-fast) var(--ease-out),
                  box-shadow var(--duration-fast) var(--ease-out);
}

.number-input-group:hover {
  border-color: var(--rule-strong);
}

.number-input-group:focus-within {
  border-color: var(--focus);
  box-shadow:   var(--focus-ring);
}

.number-input[data-invalid] .number-input-group {
  border-color: var(--danger);
}

.number-input[data-invalid] .number-input-group:focus-within {
  box-shadow: var(--focus-ring-danger);
}

.number-input-input {
  flex:                 1 1 auto;
  width:                100%;
  min-width:            0;
  height:               100%;
  margin:               0;
  padding:              0 var(--number-input-pad);
  border:               0;
  border-radius:        0;
  background:           transparent;
  box-shadow:           none;
  color:                var(--ink);
  font-family:          var(--font-ui);
  font-size:            var(--number-input-font);
  font-weight:          var(--weight-body);
  letter-spacing:       var(--tracking-ui);
  font-variant-numeric: tabular-nums;
  text-align:           start;
}

.number-input-group[data-buttons="sides"] .number-input-input {
  text-align: center;
}

.number-input-input:focus,
.number-input-input:focus-visible {
  outline:    none;
  box-shadow: none;
}

.number-input-input::placeholder {
  color:   var(--ink-dim);
  opacity: 1;
}

.number-input-button {
  display:         inline-flex;
  flex:            none;
  align-items:     center;
  justify-content: center;
  width:           var(--number-input-height);
  height:          100%;
  margin:          0;
  padding:         0;
  border:          0;
  border-radius:   0;
  background:      transparent;
  color:           var(--ink-soft);
  cursor:          pointer;
  touch-action:    manipulation;
  user-select:     none;
  transition:      background-color var(--duration-fast) var(--ease-out),
                   color var(--duration-fast) var(--ease-out);
}

.number-input-button .icon {
  width:  var(--icon-size);
  height: var(--icon-size);
  transition: transform var(--duration-fast) var(--ease-out);
}

.number-input-button:hover:not(:disabled) {
  background: var(--item-highlight);
  color:      var(--item-highlight-ink);
}

.number-input-button:active:not(:disabled) .icon {
  transform: scale(0.85);
}

.number-input-button:focus-visible {
  outline:    none;
  background: var(--item-highlight);
  box-shadow: inset 0 0 0 var(--focus-ring-width) var(--focus);
}

.number-input-button:disabled {
  cursor:  not-allowed;
  opacity: var(--opacity-disabled);
}

.number-input-group[data-buttons="sides"] .number-input-button[data-direction="down"] {
  border-inline-end: var(--control-border-width) solid var(--control-border);
}

.number-input-group[data-buttons="sides"] .number-input-button[data-direction="up"] {
  border-inline-start: var(--control-border-width) solid var(--control-border);
}

/* End: a column of two half-height buttons after the input. */
.number-input-steppers {
  display:            flex;
  flex:               none;
  flex-direction:     column;
  width:              calc(var(--number-input-height) * 0.75);
  border-inline-start: var(--control-border-width) solid var(--control-border);
}

.number-input-steppers .number-input-button {
  width:  100%;
  height: 50%;
}

.number-input-steppers .number-input-button .icon {
  width:  var(--icon-size-sm);
  height: var(--icon-size-sm);
}

.number-input-steppers .number-input-button[data-direction="up"] {
  border-block-end: var(--control-border-width) solid var(--control-border);
}

/* Dimmed by the effective disabled state: its own prop, a disabled Field
   (which disables the input) or a native <fieldset disabled>. The buttons
   are disabled with it and dim once, with the group. */
.number-input:is([data-disabled], :has(.number-input-input:disabled)) .number-input-group {
  opacity:    var(--opacity-disabled);
  background: var(--bg-soft);
  cursor:     not-allowed;
}

.number-input:is([data-disabled], :has(.number-input-input:disabled)) .number-input-button {
  opacity: 1;
}

.number-input[data-readonly] .number-input-group {
  background: var(--bg-soft);
}

.number-input[data-readonly] .number-input-input {
  color: var(--ink-soft);
}

.number-input[data-scrubbing] .number-input-group {
  border-color: var(--focus);
}

.number-input-cursor {
  position:       fixed;
  top:            0;
  left:           0;
  z-index:        2147483647;
  width:          var(--icon-size);
  height:         var(--icon-size);
  color:          var(--ink);
  pointer-events: none;
  transform:      translate(var(--cursor-x), var(--cursor-y)) translate(-50%, -50%);
}

.number-input-hidden {
  display: none;
}

}
