.switch {
  /* Public API (allowed to be overridden) */
  --_op-switch-height-small: calc(4 * var(--op-size-unit)); /* 16px */
  --_op-switch-height-large: calc(6 * var(--op-size-unit)); /* 24px */
  --_op-switch-width-small: calc(7 * var(--op-size-unit)); /* 28px */
  --_op-switch-width-large: calc(11 * var(--op-size-unit)); /* 44px */
  --_op-switch-opacity-disabled: var(--op-opacity-disabled);
  --_op-switch-switch-padding: var(--op-space-2x-small);

  /* Private API (don't touch these) */
  --__op-switch-width: var(--_op-switch-width-large);
  --__op-switch-height: var(--_op-switch-height-large);
  --__op-switch-switch-size: calc(var(--__op-switch-height) - var(--_op-switch-switch-padding));
  --__op-switch-half-switch-padding: calc(var(--_op-switch-switch-padding) / 2);

  position: relative;
  display: flex;
  align-items: center;

  label {
    position: relative;
    display: block;
    width: var(--__op-switch-width);
    height: var(--__op-switch-height);
    border-radius: var(--op-radius-pill);
    background: var(--op-color-neutral-base);
    box-shadow: inset var(--op-border-all) var(--op-color-neutral-plus-three);
    text-indent: -9999px; /* Normally text would not be put in the label, but this hides it in case you do put text in the label */

    &::after {
      position: absolute;
      width: var(--__op-switch-switch-size);
      height: var(--__op-switch-switch-size);
      border-radius: var(--op-radius-circle);
      background-color: var(--op-color-neutral-plus-eight);
      content: '';
      inset-block-start: var(--__op-switch-half-switch-padding);
      inset-inline-start: var(--__op-switch-half-switch-padding);
      transition: var(--op-transition-input);
    }
  }

  /* Prevent labels after the toggle being full width */
  & + label {
    width: fit-content;
  }

  input {
    width: 0;
    height: 0;
    margin-inline-end: calc(-1 * var(--op-space-x-small));

    &:disabled {
      visibility: hidden;
    }

    &:disabled + label {
      cursor: not-allowed;
      opacity: var(--_op-switch-opacity-disabled);
    }

    &:checked + label {
      background-color: var(--op-color-primary-base);
      box-shadow: none;

      &::after {
        left: calc(100% - var(--__op-switch-half-switch-padding));
        transform: translateX(-100%);
      }
    }

    &:hover + label {
      &::after {
        background-color: var(--op-color-primary-plus-five);
      }
    }

    &:focus-visible + label {
      box-shadow:
        0 0 0 var(--op-border-width-large) var(--op-color-primary-plus-six),
        inset var(--op-border-all) var(--op-color-primary-minus-three);

      &::after {
        background-color: var(--op-color-neutral-plus-five);
        box-shadow: var(--op-border-all) var(--op-color-primary-minus-three);
      }
    }

    &:focus-visible:checked + label {
      &::after {
        background-color: var(--op-color-primary-plus-six);
        box-shadow: var(--op-border-all) var(--op-color-primary-minus-two);
      }
    }
  }

  /* Size Modifiers */
  &.switch--small {
    --__op-switch-width: var(--_op-switch-width-small);
    --__op-switch-height: var(--_op-switch-height-small);
  }

  &.switch--large {
    --__op-switch-width: var(--_op-switch-width-large);
    --__op-switch-height: var(--_op-switch-height-large);
  }
}
