@import '../colours';

@keyframes toggle-opacity-shimmer {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0.4;
  }
  100% {
    opacity: 1;
  }
}

.toggle {
  --toggle-knob-size: 0.875rem;
  --toggle-track-height: calc(var(--toggle-knob-size) + 0.375rem);
  --toggle-track-width: calc(var(--toggle-track-height) * 1.75);
  --toggle-knob-offset: calc(
    (var(--toggle-track-height) - var(--toggle-knob-size)) / 2
  );
  --toggle-knob-shift: calc(
    var(--toggle-track-width) - var(--toggle-track-height)
  );

  // Themable scale knobs. Base values reproduce the original hard-coded
  // sizes; variants (eg. `--compact`) shrink the whole control by
  // redefining these rather than re-stating each property.
  --toggle-padding: clamp(0.25rem, 0.5vw, 1rem);
  --toggle-header-font-size: 1rem;
  --toggle-icon-size: 1rem;
  --toggle-icon-padding: 0.25rem;

  font: inherit;
  cursor: pointer;
  user-select: none;

  --toggle-off-base: var(--fr--color-weldon-blue);
  --toggle-on-base: var(--fr--color-purple-mid);
  --toggle-knob-color: white;

  --toggle-header-color-off: color-mix(
    in srgb,
    var(--toggle-off-base) 70%,
    var(--fr--color-yankees-blue)
  );
  --toggle-background-color-off: color-mix(
    in srgb,
    var(--toggle-off-base) 6%,
    white
  );
  --toggle-border-color-off: color-mix(
    in srgb,
    var(--toggle-off-base) 40%,
    white
  );
  --toggle-switch-color-off: color-mix(
    in srgb,
    var(--toggle-off-base) 80%,
    white
  );

  --toggle-header-color-on: color-mix(
    in srgb,
    var(--toggle-on-base) 80%,
    black
  );
  --toggle-background-color-on: color-mix(
    in srgb,
    var(--toggle-on-base) 6%,
    white
  );
  --toggle-border-color-on: color-mix(
    in srgb,
    var(--toggle-on-base) 80%,
    white
  );
  --toggle-switch-color-on: var(--toggle-on-base);

  --toggle-header-color: var(--toggle-header-color-off);
  --toggle-background-color: var(--toggle-background-color-off);
  --toggle-border-color: var(--toggle-border-color-off);
  --toggle-switch-color: var(--toggle-switch-color-off);

  padding: var(--toggle-padding);
  border: 2px solid var(--toggle-border-color);
  border-radius: 1rem;
  background-color: var(--toggle-background-color);
  text-align: left;

  transition:
    background-color 0.25s ease,
    border-color 0.25s ease,
    color 0.25s ease,
    opacity 0.25s ease;

  &:focus-visible {
    outline-offset: 3px;
  }

  &__content {
    display: flex;
    align-items: center;
    gap: clamp(0.25rem, 0.5vw, 1rem);
    width: 100%;
  }

  &__icon {
    flex-shrink: 0;
    background-color: var(--toggle-switch-color);
    padding: var(--toggle-icon-padding);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background-color 180ms ease;

    svg {
      width: var(--toggle-icon-size);
      height: var(--toggle-icon-size);
      overflow: visible;
      fill: var(--toggle-switch-color);
      stroke: white;
    }
  }

  &__header {
    flex: 1 1 auto;
    font-size: var(--toggle-header-font-size);
    font-weight: 600;
    white-space: nowrap;
    color: var(--toggle-header-color);
    min-width: 0;

    // Invisible decoy that pegs the header's (and therefore the toggle's)
    // intrinsic width to a caller-supplied label, so reflow doesn't happen
    // when `header` swaps between strings of different widths. Opt in via
    // the `stableWidthLabel` prop.
    //
    // `visibility: hidden` is intentionally redundant alongside
    // `height: 0; overflow: hidden;` — it's defense-in-depth that removes
    // the decoy from the accessibility tree on user agents that mishandle
    // aria-hidden. Don't strip it during a future cleanup.
    &__stable {
      display: block;
      height: 0;
      overflow: hidden;
      visibility: hidden;
    }
  }

  &--on {
    --toggle-header-color: var(--toggle-header-color-on);
    --toggle-background-color: var(--toggle-background-color-on);
    --toggle-border-color: var(--toggle-border-color-on);
    --toggle-switch-color: var(--toggle-switch-color-on);
  }

  // Default behaviour is to hug content; opt into stretching with `fullWidth`.
  &--full-width {
    width: 100%;
  }

  // Compact variant: redefines the scale variables so every dimension
  // (knob, track, label, padding) shrinks in lockstep. Padding is
  // intentionally asymmetric (tighter vertical than horizontal) — that's
  // the pill shape we want in dense toolbar contexts.
  &--compact {
    --toggle-knob-size: 0.7rem;
    --toggle-padding: 0.25rem 0.6rem;
    --toggle-header-font-size: 0.8rem;
    --toggle-icon-size: 0.8rem;
    --toggle-icon-padding: 0.2rem;
  }

  &--disabled {
    cursor: not-allowed;

    --toggle-header-color: color-mix(
      in srgb,
      var(--toggle-off-base) 40%,
      white
    );
    --toggle-background-color: color-mix(
      in srgb,
      var(--toggle-off-base) 5%,
      white
    );
    --toggle-border-color: color-mix(
      in srgb,
      var(--toggle-off-base) 30%,
      white
    );
    --toggle-switch-color: color-mix(
      in srgb,
      var(--toggle-off-base) 20%,
      white
    );
  }

  &__switch {
    width: var(--toggle-track-width);
    height: var(--toggle-track-height);
    position: relative;
    flex-shrink: 0;
    pointer-events: none;
  }

  .slider {
    position: absolute;
    inset: 0;
    background-color: var(--toggle-switch-color);
    border-radius: var(--toggle-track-height);
    transition: background-color 180ms ease;

    &::before {
      content: '';
      position: absolute;
      width: var(--toggle-knob-size);
      height: var(--toggle-knob-size);
      left: var(--toggle-knob-offset);
      bottom: var(--toggle-knob-offset);
      background-color: var(--toggle-knob-color);
      border-radius: 50%;
      transition:
        transform 180ms ease,
        background-color 180ms ease;
    }
  }

  &--on .slider::before {
    transform: translateX(var(--toggle-knob-shift));
  }

  &--loading {
    animation: toggle-opacity-shimmer 1.8s ease-in-out infinite;
    will-change: opacity;

    --toggle-header-color: var(--toggle-header-color-on);
    --toggle-background-color: var(--toggle-background-color-on);
    --toggle-border-color: var(--toggle-border-color-on);
    --toggle-switch-color: var(--toggle-switch-color-on);
  }
}
