@layer lotek {
  /*
   * The fill colour is carried by `color` on the host, and the filled part
   * reads `currentColor`.
   *
   * The reason is that the filled part has two names,
   * `::-webkit-progress-value` in Chromium and WebKit and
   * `::-moz-progress-bar` in Gecko, and they cannot be in the same selector
   * list: a pseudo-element the engine does not know makes the whole rule
   * invalid. The colour must therefore be decided in one place and
   * inherited, and `currentColor` is the built-in way to do that.
   *
   * `<progress>` has no text, so `color` is free for the job.
   * `data-color` changes `--lt-progress-fill`, which `color` reads.
   */
  .lt-progress {
    box-sizing: border-box;
    appearance: none;
    display: block;
    inline-size: 100%;
    block-size: var(--lt-progress-height, var(--lt-spacing-2));
    border: 0;
    /* The track alone is 1.12:1 against the page, and without an edge nobody
       could see how far the bar goes. `neutral-border` holds 3:1. An inward
       `outline` and not a `border`: with `border-box` the border took 2
       pixels of the height, and a 2 pixel bar lost its fill entirely. */
    /* The longhands, since this is not a focus ring: the shorthand with
       `solid` is reserved for `--lt-focus-ring`, and
       `package-css.browser.test.ts` rejects it. */
    outline-width: 1px;
    outline-style: solid;
    outline-color: var(--lt-progress-border, var(--lt-color-neutral-border));
    outline-offset: -1px;
    border-radius: var(--lt-progress-radius, var(--lt-spacing-1));
    overflow: hidden;
    background: var(--lt-progress-track, var(--lt-color-neutral-surface));
    color: var(--lt-progress-fill, var(--lt-color-accent-fill));
  }

  .lt-progress[data-color="success"] {
    --lt-progress-fill: var(--lt-color-success-fill);
  }

  .lt-progress[data-color="warning"] {
    --lt-progress-fill: var(--lt-color-warning-fill);
  }

  .lt-progress[data-color="danger"] {
    --lt-progress-fill: var(--lt-color-danger-fill);
  }

  /* The track behind, in Chromium and WebKit. */
  .lt-progress::-webkit-progress-bar {
    background: var(--lt-progress-track, var(--lt-color-neutral-surface));
  }

  /* The filled part. One rule per engine, for the reason at the top. */
  .lt-progress::-webkit-progress-value {
    background: currentColor;
    transition: inline-size 200ms ease-out;
  }

  .lt-progress::-moz-progress-bar {
    background: currentColor;
    transition: inline-size 200ms ease-out;
  }

  /*
   * Indeterminate: a bar without `value`. We then do not know how far it has
   * come, and a stripe sweeping across it says "in progress" without
   * promising a number.
   */
  .lt-progress:indeterminate {
    background:
      linear-gradient(90deg, transparent 0%, currentColor 50%, transparent 100%)
      no-repeat,
      var(--lt-progress-track, var(--lt-color-neutral-surface));
    background-size: 40% 100%;
    animation: lt-progress-slide 1400ms ease-in-out infinite;
  }

  /* Without this Chromium and WebKit draw their own track on top of the gradient. */
  .lt-progress:indeterminate::-webkit-progress-bar {
    background: transparent;
  }

  .lt-progress:indeterminate::-moz-progress-bar {
    background: transparent;
  }

  @keyframes lt-progress-slide {
    from {
      background-position: -40% 0;
    }
    to {
      background-position: 140% 0;
    }
  }

  /* As in the spinner: slower rather than still. An indicator that stands
     still no longer says that something is going on. */
  @media (prefers-reduced-motion: reduce) {
    .lt-progress:indeterminate {
      animation-duration: 4200ms;
    }

    .lt-progress::-webkit-progress-value {
      transition: none;
    }

    .lt-progress::-moz-progress-bar {
      transition: none;
    }
  }

  /*
   * High contrast: custom colours are overridden, so the filled part must
   * take its colour from the system colours. `Highlight` is the same as
   * selection elsewhere in the system, and the edge brings back the shape
   * when the background becomes `Canvas`.
   */
  @media (forced-colors: active) {
    .lt-progress,
    .lt-progress[data-color] {
      --lt-progress-fill: Highlight;

      /* The same inward edge as otherwise, in the system text colour. A
         `border` would have taken 2 pixels of the height, see above. */
      outline-color: CanvasText;
    }

    /*
     * The variable above is not enough for the filled part. It reads
     * `currentColor`, and the mode forces the background back to `Canvas`
     * when the value is not a system colour, so the bar looked empty
     * whatever the `value`. The system colour must be on the pseudo-element
     * itself.
     */
    .lt-progress::-webkit-progress-value {
      background: Highlight;
    }

    .lt-progress::-moz-progress-bar {
      background: Highlight;
    }

    /*
     * The stripe in an indeterminate bar is a gradient, and the mode removes
     * gradients. Without the exception an empty frame was left, and nothing
     * said that something was going on. The colours are the system's, so
     * the user's choice still applies.
     */
    .lt-progress:indeterminate {
      forced-color-adjust: none;
      background:
        linear-gradient(90deg, Canvas 0%, Highlight 50%, Canvas 100%) no-repeat,
        Canvas;
      background-size: 40% 100%;
    }
  }
}
