/* Form basics: input, select, textarea, label, fieldset, legend */

:root,
:host {
  --pico-form-label-font-weight: 500;
}

/* Text-like controls get a wide, soft focus ring around the colored border */
input:not(
  [type="submit"],
  [type="button"],
  [type="reset"],
  [type="checkbox"],
  [type="radio"],
  [type="file"]
),
:where(select, textarea) {
  --pico-outline-width: 0.1875rem;
}

/* Buttons, checkboxes, radios and file inputs use the primary focus color */
input:is(
  [type="submit"],
  [type="button"],
  [type="reset"],
  [type="checkbox"],
  [type="radio"],
  [type="file"]
) {
  --pico-form-element-focus-color: var(--pico-primary-focus);
}

input,
optgroup,
select,
textarea {
  margin: 0;
  font-size: 1rem;
  line-height: var(--pico-line-height);
  font-family: inherit;
  letter-spacing: inherit;
}

input {
  overflow: visible;
}

select {
  text-transform: none;
}

legend {
  max-width: 100%;
  padding: 0;
  color: inherit;
  white-space: normal;
}

textarea {
  overflow: auto;
}

[type="checkbox"],
[type="radio"] {
  padding: 0;
}

::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
  height: auto;
}

[type="search"] {
  appearance: textfield;
  outline-offset: -2px;

  &::-webkit-search-decoration {
    appearance: none;
  }
}

::file-selector-button {
  font: inherit;
}

/* Firefox: remove its own inner focus border, focus ring and invalid glow */
::-moz-focus-inner {
  padding: 0;
  border-style: none;
}

:-moz-focusring {
  outline: none;
}

:-moz-ui-invalid {
  box-shadow: none;
}

[type="file"],
[type="range"] {
  padding: 0;
  border-width: 0;
}

input:not([type="checkbox"], [type="radio"], [type="range"]) {
  block-size: calc(
    1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * 2 +
      var(--pico-border-width) * 2
  );
}

fieldset {
  inline-size: 100%;
  margin: 0;
  margin-block-end: var(--pico-spacing);
  padding: 0;
  border: 0;
}

label,
fieldset legend {
  display: block;
  margin-block-end: calc(var(--pico-spacing) * 0.375);
  color: var(--pico-color);
  font-weight: var(--pico-form-label-font-weight, var(--pico-font-weight));
}

fieldset legend {
  margin-block-end: calc(var(--pico-spacing) * 0.5);
}

input:not([type="checkbox"], [type="radio"]),
button[type="submit"],
select,
textarea {
  inline-size: 100%;
}

input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]),
select,
textarea {
  appearance: none;
  padding: var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);
}

/* Colors, border and ring go through custom properties so states only swap tokens */
input,
select,
textarea {
  --pico-background-color: var(--pico-form-element-background-color);
  --pico-border-color: var(--pico-form-element-border-color);
  --pico-color: var(--pico-form-element-color);
  --pico-box-shadow: none;
  border: var(--pico-border-width) solid var(--pico-border-color);
  border-radius: var(--pico-border-radius);
  outline: none;
  background-color: var(--pico-background-color);
  box-shadow: var(--pico-box-shadow);
  color: var(--pico-color);
  font-weight: var(--pico-font-weight);
  transition:
    background-color var(--pico-transition),
    border-color var(--pico-transition),
    color var(--pico-transition),
    box-shadow var(--pico-transition);
}

/* Read-only fields look inert: a muted fill and the normal border */
input:not(
    [type="submit"],
    [type="button"],
    [type="reset"],
    [type="checkbox"],
    [type="radio"],
    [type="range"],
    [type="file"]
  )[readonly],
textarea[readonly] {
  --pico-background-color: var(--pico-form-element-selected-background-color);
  --pico-border-color: var(--pico-form-element-border-color);
}

input:not(
    [type="submit"],
    [type="button"],
    [type="reset"],
    [type="checkbox"],
    [type="radio"],
    [readonly]
  ):is(:active, :focus),
:where(select, textarea):not([readonly]):is(:active, :focus) {
  --pico-background-color: var(--pico-form-element-active-background-color);
}

input:not([type="submit"], [type="button"], [type="reset"], [role="switch"], [readonly]):is(
    :active,
    :focus
  ),
:where(select, textarea):not([readonly]):is(:active, :focus) {
  --pico-border-color: var(--pico-form-element-active-border-color);
}

input:not(
    [type="submit"],
    [type="button"],
    [type="reset"],
    [type="checkbox"],
    [type="radio"],
    [type="range"],
    [type="file"],
    [readonly]
  ):focus,
:where(select, textarea):not([readonly]):focus {
  --pico-box-shadow: 0 0 0 var(--pico-outline-width)
    color-mix(in oklab, var(--pico-form-element-focus-color) 25%, transparent);
}

/* Hover darkens the border a little, the focus and validation colors win over it */
:where(
    input:not(
      [type="submit"],
      [type="button"],
      [type="reset"],
      [type="checkbox"],
      [type="radio"],
      [type="range"],
      [type="file"]
    ),
    select,
    textarea
  ):hover:not(:focus, [readonly], :disabled, [aria-invalid]) {
  --pico-border-color: color-mix(
    in oklab,
    var(--pico-form-element-border-color),
    var(--pico-color) 30%
  );
}

input:not([type="submit"], [type="button"], [type="reset"])[disabled],
select[disabled],
textarea[disabled],
label[aria-disabled="true"],
:where(fieldset[disabled])
  :is(input:not([type="submit"], [type="button"], [type="reset"]), select, textarea) {
  opacity: var(--pico-form-element-disabled-opacity);
  pointer-events: none;
}

label[aria-disabled="true"] input[disabled] {
  opacity: 1;
}

/* Valid and invalid states: icon gutter, icon and border colors */
:where(input, select, textarea):not(
    [type="checkbox"],
    [type="radio"],
    [type="date"],
    [type="datetime-local"],
    [type="month"],
    [type="time"],
    [type="week"],
    [type="range"]
  )[aria-invalid] {
  padding-inline-start: var(--pico-form-element-spacing-horizontal) !important;
  padding-inline-end: calc(var(--pico-form-element-spacing-horizontal) + 1.5rem) !important;
  background-position: center right 0.75rem;
  background-size: 1rem auto;
  background-repeat: no-repeat;
}

:where(input, select, textarea):not(
    [type="checkbox"],
    [type="radio"],
    [type="date"],
    [type="datetime-local"],
    [type="month"],
    [type="time"],
    [type="week"],
    [type="range"]
  )[aria-invalid="false"]:not(select) {
  background-image: var(--pico-icon-valid);
}

:where(input, select, textarea):not(
    [type="checkbox"],
    [type="radio"],
    [type="date"],
    [type="datetime-local"],
    [type="month"],
    [type="time"],
    [type="week"],
    [type="range"]
  )[aria-invalid="true"]:not(select) {
  background-image: var(--pico-icon-invalid);
}

:where(input, select, textarea) {
  &[aria-invalid="false"] {
    --pico-border-color: var(--pico-form-element-valid-border-color);

    &:is(:active, :focus) {
      --pico-border-color: var(--pico-form-element-valid-active-border-color) !important;

      &:not([type="checkbox"], [type="radio"]) {
        --pico-box-shadow: 0 0 0 var(--pico-outline-width)
          color-mix(in oklab, var(--pico-form-element-valid-focus-color) 25%, transparent) !important;
      }
    }
  }

  &[aria-invalid="true"] {
    --pico-border-color: var(--pico-form-element-invalid-border-color);

    &:is(:active, :focus) {
      --pico-border-color: var(--pico-form-element-invalid-active-border-color) !important;

      &:not([type="checkbox"], [type="radio"]) {
        --pico-box-shadow: 0 0 0 var(--pico-outline-width)
          color-mix(in oklab, var(--pico-form-element-invalid-focus-color) 25%, transparent) !important;
      }
    }
  }
}

/* background-position has no logical form, so the icon side is flipped by hand */
[dir="rtl"]
  :where(input, select, textarea):not([type="checkbox"], [type="radio"]):is(
    [aria-invalid],
    [aria-invalid="true"],
    [aria-invalid="false"]
  ) {
  background-position: center left 0.75rem;
}

input::placeholder,
textarea::placeholder,
select:invalid {
  color: var(--pico-form-element-placeholder-color);
  opacity: 1;
}

input:not([type="checkbox"], [type="radio"]),
select,
textarea {
  margin-block-end: var(--pico-spacing);
}

select {
  &:not([multiple], [size]) {
    padding-inline-start: var(--pico-form-element-spacing-horizontal);
    padding-inline-end: calc(var(--pico-form-element-spacing-horizontal) + 1.5rem);
    background-image: var(--pico-icon-chevron);
    background-position: center right 0.75rem;
    background-size: 1rem auto;
    background-repeat: no-repeat;
  }

  &[multiple] option:checked {
    background: color-mix(in oklab, var(--pico-primary-background) 14%, transparent);
    color: var(--pico-color);
  }
}

[dir="rtl"] select:not([multiple], [size]) {
  background-position: center left 0.75rem;
}

textarea {
  display: block;
  resize: vertical;

  /* The icon sits at the top, sized like a single line input */
  &[aria-invalid] {
    --pico-icon-height: calc(
      1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * 2 +
        var(--pico-border-width) * 2
    );
    background-position: top right 0.75rem !important;
    background-size: 1rem var(--pico-icon-height) !important;
  }
}

/* Helper text right after a control */
:where(input, select, textarea, fieldset, .grid) {
  + small {
    display: block;
    inline-size: 100%;
    margin-block-start: calc(var(--pico-spacing) * -0.75);
    margin-block-end: var(--pico-spacing);
    color: var(--pico-muted-color);
    font-weight: var(--pico-font-weight);
  }

  &[aria-invalid="false"] + small {
    color: var(--pico-ins-color);
    font-weight: 500;
  }

  &[aria-invalid="true"] + small {
    color: var(--pico-del-color);
    font-weight: 500;
  }
}

label > :where(input, select, textarea) {
  margin-block-start: calc(var(--pico-spacing) * 0.25);
}
