@gutter-width: 1.9em;

// Negative mode.
@neg-colour: #c29088;
@neg-track-border-colour: #704e49;
@neg-knob-colour: #c9513e;
// Highlights.
@neg-colour-h: #e3b8b1;
@neg-track-border-colour-h: #855c56;
@neg-knob-colour-h: #e8634f;

label:has(>.switch), [role=checkbox] > label {
  display: inline-flex;
  align-items: center;
}

// Show focus outline on label when using keyboard navigation.
label:has(>.switch):focus-within:has(:focus-visible) {
  outline: 1px auto currentColor;
}

input[type=checkbox].switch {
  // Remove browser UI from flow.
  position: absolute;
  // Allow inputs to receive focus.
  opacity: 0;

  @checked-colour: #94dfff;
  @track-height: 1.4ex;
  @track-margin: .7ch;
  @transition-time: .15s;

  // Switch UI.
  + span {
    position: relative;

    // Knob.
    &:after {
      content: '';
      position: absolute;
      left: 0;
      top: 50%;
      transform: translateY(-50%);
    }

    // Gutter.
    height: @track-height;
    width: @gutter-width;

    background: #172230;
    border: 1px solid #718fa5;
    border-radius: 1em;

    transition: @transition-time;

    // Knob.
    &:after {
      height: calc(@track-height - 2px);
      width: $height;
      left: 1px;

      background: #a0b7c3;
      border-radius: 1em;
      transition: @transition-time;
    }

    &:hover, &:has(+ span:hover) {
      border-color: #819eb3;

      &:after {
        background: #c0d7e3;
      }
    }
  }

  // Selected text.
  + span + span {
    margin-left: @track-margin;

    &:hover {
      color: #dae8eb;
    }

    // Deselected text.
    + span {
      order: -1;
      margin-right: @track-margin;
    }
  }

  &:checked {
    + span {
      &:after {
        left: calc(@gutter-width - 1px);
        transform: translate(-100%, -50%);
      }
    }

    + span + span {
      color: @checked-colour;
    }

    &:hover + span{
      border-color: #477a9e;

      &:after {
        background: #87dbff;
      }

      + span {
        color: #ade7ff;
      }
    }
  }

  // Negative mode: checkbox represents an option that is exclusionary.
  label.neg >& {
    &:checked {
      + span {
        border-color: @neg-track-border-colour;

        &:after {
          background: @neg-knob-colour;
        }

        &:hover, &:has(+ span:hover) {
          //&:before {
            border-color: @neg-track-border-colour-h;
          //}

          &:after {
            background: @neg-knob-colour-h;
          }
        }
      }

      + span + span {
        color: @neg-colour;
      }

      &:hover + span + span {
        color: @neg-colour-h;
      }
    }
  }

  // Option mode: checkbox represents two either/or options rather than one option in an on/off state.
  label.option >& {
    &:not(:checked) {
      + span + span + span {
        color: @checked-colour;
      }
      + span + span {
        color: inherit;
      }

      &:hover {
        + span + span + span {
          // Copy text highlight colour.
          &:extend(input[type=checkbox].switch:checked:hover + span + span);
        }
        + span {
          // Copy track highlights.
          &:extend(input[type=checkbox].switch:checked:hover + span all);

          + span {
            // Avoid applying text highlight to deselected option.
            color: inherit;
          }
        }
      }
    }
  }

  // In option mode the track never dims because it is never "off". Otherwise, these are just further checked states.
  &:checked, label.option >& {
    + span {
      // Gutter.
      background: #15232b;
      border-color: #396d93;

      // Knob.
      &:after {
        background: #70D1FB;
      }
    }
  }

  ~ span {
    line-height: 1.2;

    transition: color @transition-time;
  }

  // Disabled mode (tri-state currently unsupported).
  &:disabled, label.option >&:disabled {
    + span {
      background: #202020;
      border-color: #555;

      &:after {
        background: #636b6e;
      }

      + span, + span + span {
        color: #828282;
      }
    }
  }
}

// Tri-state mode.
[role=checkbox] {
  // Hide browser radio controls.
  input:extend(input[type=checkbox].switch) {}

  >label {
    > input {
      // Copy track and gutter styles.
      + span:extend(input[type=checkbox].switch + span all) {}

      // Do not allow inputs to gain focus, since enclosing div has a tabindex to receive focus instead.
      visibility: hidden;

      // Indeterminate state.
      &:checked {
        + span:after {
          left: (@gutter-width / 2);
          transform: translate(-50%, -50%);
        }

        &:hover {
          // Copy track unchecked highlights.
          + span:extend(input[type=checkbox].switch + span:hover all) {
            // Copy text unchecked colour.
            + span:extend(input[type=checkbox].switch + span + span:hover) {}
            + span + span:extend(input[type=checkbox].switch + span + span:hover) {}
          }
        }
      }
    }
  }

  // Far-right state.
  &[aria-checked="true"] {
    input:extend(input[type=checkbox].switch:checked all) {}
  }

  // Far-left state.
  &[aria-checked="false"] {
    input + span {
      color: inherit;

      border-color: @neg-track-border-colour;

      &:after {
        // Copy positioning from unchecked state.
        &:extend(input[type=checkbox].switch + span:after);

        transform: translateY(-50%);

        background: @neg-knob-colour;
      }

      + span + span {
        color: @neg-colour;
      }
    }

    &:hover {
      input + span {
        border-color: @neg-track-border-colour-h;

        &:after {
          background: @neg-knob-colour-h;
        }

        + span + span {
          color: @neg-colour-h;
        }
      }
    }
  }
}
