@import "./bones.css";

/* ---------------------------------------------------------------------------
   auto.css — skeletonize unmarked markup under [aria-busy="true"].

   data-bone marks shape, aria-busy marks state; this layer keys on state so a
   page with zero data-bone attributes still gets skeletons. Escape hatches:
   [data-bones-auto="off"] exempts a subtree, and explicit [data-bone] markup
   is always left to bones.css. Every rule lives in @layer bones-auto so page
   CSS outranks it without !important.
--------------------------------------------------------------------------- */

@layer bones-auto {
  /* Text default: any element with no child elements, minus exemptions and
     the replaced/control elements that get block treatment below. Same bar
     geometry as [data-bone="text"] in bones.css — restated because CSS cannot
     alias an attribute selector; the test suite pins both copies. */
  [aria-busy="true"]
    :not(:has(*)):not(
      [data-bone],
      [data-bone] *,
      [data-bones-auto="off"],
      [data-bones-auto="off"] *
    ):not(
      img,
      svg,
      video,
      canvas,
      picture,
      iframe,
      embed,
      object,
      audio,
      button,
      input,
      select,
      textarea,
      progress,
      meter,
      hr,
      br,
      svg *,
      picture *,
      select *,
      object *
    ) {
    color: transparent;
    position: relative;
    min-width: 4ch;
    min-height: 1lh;
  }

  [aria-busy="true"]
    :not(:has(*)):not(
      [data-bone],
      [data-bone] *,
      [data-bones-auto="off"],
      [data-bones-auto="off"] *
    ):not(
      img,
      svg,
      video,
      canvas,
      picture,
      iframe,
      embed,
      object,
      audio,
      button,
      input,
      select,
      textarea,
      progress,
      meter,
      hr,
      br,
      svg *,
      picture *,
      select *,
      object *
    )::before {
    content: "\200b";
  }

  [aria-busy="true"]
    :not(:has(*)):not(
      [data-bone],
      [data-bone] *,
      [data-bones-auto="off"],
      [data-bones-auto="off"] *
    ):not(
      img,
      svg,
      video,
      canvas,
      picture,
      iframe,
      embed,
      object,
      audio,
      button,
      input,
      select,
      textarea,
      progress,
      meter,
      hr,
      br,
      svg *,
      picture *,
      select *,
      object *
    )::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    top: calc((1lh + 1cap) / 2 - 1ex);
    height: 1ex;
    background-color: var(--bone-base);
    border-radius: var(--bone-radius);
    pointer-events: none;
  }
}

@layer bones-auto {
  /* Block override: replaced elements and form controls fill their own box.
     A text bar across an avatar or a button looks wrong. Leafness is not
     required — svg and select routinely have element children. */
  [aria-busy="true"]
    :is(
      img,
      svg,
      video,
      canvas,
      picture,
      iframe,
      embed,
      object,
      audio,
      button,
      input,
      select,
      textarea,
      progress,
      meter
    ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
    color: transparent;
    background-color: var(--bone-base);
    border-radius: var(--bone-radius);
    border-color: transparent;
  }

  /* Width variance: text leaves cycle 85 / 100 / 92 / 60 so runs of lines
     look organic. Takes effect on block-level leaves; inline leaves keep
     their content-derived width, which already varies. */
  [aria-busy="true"]
    :not(:has(*)):not(
      [data-bone],
      [data-bone] *,
      [data-bones-auto="off"],
      [data-bones-auto="off"] *
    ):not(
      img,
      svg,
      video,
      canvas,
      picture,
      iframe,
      embed,
      object,
      audio,
      button,
      input,
      select,
      textarea,
      progress,
      meter,
      hr,
      br,
      svg *,
      picture *,
      select *,
      object *
    ):nth-child(4n + 1) {
    width: 85%;
  }

  [aria-busy="true"]
    :not(:has(*)):not(
      [data-bone],
      [data-bone] *,
      [data-bones-auto="off"],
      [data-bones-auto="off"] *
    ):not(
      img,
      svg,
      video,
      canvas,
      picture,
      iframe,
      embed,
      object,
      audio,
      button,
      input,
      select,
      textarea,
      progress,
      meter,
      hr,
      br,
      svg *,
      picture *,
      select *,
      object *
    ):nth-child(4n + 2) {
    width: 100%;
  }

  [aria-busy="true"]
    :not(:has(*)):not(
      [data-bone],
      [data-bone] *,
      [data-bones-auto="off"],
      [data-bones-auto="off"] *
    ):not(
      img,
      svg,
      video,
      canvas,
      picture,
      iframe,
      embed,
      object,
      audio,
      button,
      input,
      select,
      textarea,
      progress,
      meter,
      hr,
      br,
      svg *,
      picture *,
      select *,
      object *
    ):nth-child(4n + 3) {
    width: 92%;
  }

  [aria-busy="true"]
    :not(:has(*)):not(
      [data-bone],
      [data-bone] *,
      [data-bones-auto="off"],
      [data-bones-auto="off"] *
    ):not(
      img,
      svg,
      video,
      canvas,
      picture,
      iframe,
      embed,
      object,
      audio,
      button,
      input,
      select,
      textarea,
      progress,
      meter,
      hr,
      br,
      svg *,
      picture *,
      select *,
      object *
    ):nth-child(4n) {
    width: 60%;
  }
}

@layer bones-auto {
  /* Auto bones default to shimmer. bones.css only animates inside a
     [data-bone-animate] scope; a zero-markup page has no such attribute, so
     the default lives here and the scopes below mirror bones.css for pages
     that do set it. */
  [aria-busy="true"]
    :not(:has(*)):not(
      [data-bone],
      [data-bone] *,
      [data-bones-auto="off"],
      [data-bones-auto="off"] *
    ):not(
      img,
      svg,
      video,
      canvas,
      picture,
      iframe,
      embed,
      object,
      audio,
      button,
      input,
      select,
      textarea,
      progress,
      meter,
      hr,
      br,
      svg *,
      picture *,
      select *,
      object *
    )::before,
  [aria-busy="true"]
    :not(:has(*)):not(
      [data-bone],
      [data-bone] *,
      [data-bones-auto="off"],
      [data-bones-auto="off"] *
    ):not(
      img,
      svg,
      video,
      canvas,
      picture,
      iframe,
      embed,
      object,
      audio,
      button,
      input,
      select,
      textarea,
      progress,
      meter,
      hr,
      br,
      svg *,
      picture *,
      select *,
      object *
    )::after,
  [aria-busy="true"]
    :is(
      img,
      svg,
      video,
      canvas,
      picture,
      iframe,
      embed,
      object,
      audio,
      button,
      input,
      select,
      textarea,
      progress,
      meter
    ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
    animation: bone-shimmer var(--bone-duration) ease-in-out infinite;
    background: linear-gradient(
      90deg,
      var(--bone-base) 25%,
      var(--bone-highlight) 50%,
      var(--bone-base) 75%
    );
    background-size: 200% 100%;
  }

  @scope ([data-bone-animate="shimmer"]) to ([data-bone-animate]:not([data-bone-animate="shimmer"])) {
    [aria-busy="true"]
      :not(:has(*)):not(
        [data-bone],
        [data-bone] *,
        [data-bones-auto="off"],
        [data-bones-auto="off"] *
      ):not(
        img,
        svg,
        video,
        canvas,
        picture,
        iframe,
        embed,
        object,
        audio,
        button,
        input,
        select,
        textarea,
        progress,
        meter,
        hr,
        br,
        svg *,
        picture *,
        select *,
        object *
      )::before,
    [aria-busy="true"]
      :not(:has(*)):not(
        [data-bone],
        [data-bone] *,
        [data-bones-auto="off"],
        [data-bones-auto="off"] *
      ):not(
        img,
        svg,
        video,
        canvas,
        picture,
        iframe,
        embed,
        object,
        audio,
        button,
        input,
        select,
        textarea,
        progress,
        meter,
        hr,
        br,
        svg *,
        picture *,
        select *,
        object *
      )::after,
    [aria-busy="true"]
      :is(
        img,
        svg,
        video,
        canvas,
        picture,
        iframe,
        embed,
        object,
        audio,
        button,
        input,
        select,
        textarea,
        progress,
        meter
      ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
      animation: bone-shimmer var(--bone-duration) ease-in-out infinite;
      background: linear-gradient(
        90deg,
        var(--bone-base) 25%,
        var(--bone-highlight) 50%,
        var(--bone-base) 75%
      );
      background-size: 200% 100%;
    }

    @media (prefers-reduced-motion: reduce) {
      [aria-busy="true"]
        :not(:has(*)):not(
          [data-bone],
          [data-bone] *,
          [data-bones-auto="off"],
          [data-bones-auto="off"] *
        ):not(
          img,
          svg,
          video,
          canvas,
          picture,
          iframe,
          embed,
          object,
          audio,
          button,
          input,
          select,
          textarea,
          progress,
          meter,
          hr,
          br,
          svg *,
          picture *,
          select *,
          object *
        )::before,
      [aria-busy="true"]
        :not(:has(*)):not(
          [data-bone],
          [data-bone] *,
          [data-bones-auto="off"],
          [data-bones-auto="off"] *
        ):not(
          img,
          svg,
          video,
          canvas,
          picture,
          iframe,
          embed,
          object,
          audio,
          button,
          input,
          select,
          textarea,
          progress,
          meter,
          hr,
          br,
          svg *,
          picture *,
          select *,
          object *
        )::after,
      [aria-busy="true"]
        :is(
          img,
          svg,
          video,
          canvas,
          picture,
          iframe,
          embed,
          object,
          audio,
          button,
          input,
          select,
          textarea,
          progress,
          meter
        ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
        animation: bone-pulse 2s ease-in-out infinite;
        background: var(--bone-base);
        background-size: auto;
      }
    }

    @media (forced-colors: active) {
      [aria-busy="true"]
        :not(:has(*)):not(
          [data-bone],
          [data-bone] *,
          [data-bones-auto="off"],
          [data-bones-auto="off"] *
        ):not(
          img,
          svg,
          video,
          canvas,
          picture,
          iframe,
          embed,
          object,
          audio,
          button,
          input,
          select,
          textarea,
          progress,
          meter,
          hr,
          br,
          svg *,
          picture *,
          select *,
          object *
        )::after,
      [aria-busy="true"]
        :is(
          img,
          svg,
          video,
          canvas,
          picture,
          iframe,
          embed,
          object,
          audio,
          button,
          input,
          select,
          textarea,
          progress,
          meter
        ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
        background-color: GrayText;
        forced-color-adjust: none;
      }
    }
  }

  @scope ([data-bone-animate="pulse"]) to ([data-bone-animate]:not([data-bone-animate="pulse"])) {
    [aria-busy="true"]
      :not(:has(*)):not(
        [data-bone],
        [data-bone] *,
        [data-bones-auto="off"],
        [data-bones-auto="off"] *
      ):not(
        img,
        svg,
        video,
        canvas,
        picture,
        iframe,
        embed,
        object,
        audio,
        button,
        input,
        select,
        textarea,
        progress,
        meter,
        hr,
        br,
        svg *,
        picture *,
        select *,
        object *
      )::before,
    [aria-busy="true"]
      :not(:has(*)):not(
        [data-bone],
        [data-bone] *,
        [data-bones-auto="off"],
        [data-bones-auto="off"] *
      ):not(
        img,
        svg,
        video,
        canvas,
        picture,
        iframe,
        embed,
        object,
        audio,
        button,
        input,
        select,
        textarea,
        progress,
        meter,
        hr,
        br,
        svg *,
        picture *,
        select *,
        object *
      )::after,
    [aria-busy="true"]
      :is(
        img,
        svg,
        video,
        canvas,
        picture,
        iframe,
        embed,
        object,
        audio,
        button,
        input,
        select,
        textarea,
        progress,
        meter
      ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
      animation: bone-pulse var(--bone-duration) ease-in-out infinite;
      background: var(--bone-base);
      background-size: auto;
    }

    @media (prefers-reduced-motion: reduce) {
      [aria-busy="true"]
        :not(:has(*)):not(
          [data-bone],
          [data-bone] *,
          [data-bones-auto="off"],
          [data-bones-auto="off"] *
        ):not(
          img,
          svg,
          video,
          canvas,
          picture,
          iframe,
          embed,
          object,
          audio,
          button,
          input,
          select,
          textarea,
          progress,
          meter,
          hr,
          br,
          svg *,
          picture *,
          select *,
          object *
        )::before,
      [aria-busy="true"]
        :not(:has(*)):not(
          [data-bone],
          [data-bone] *,
          [data-bones-auto="off"],
          [data-bones-auto="off"] *
        ):not(
          img,
          svg,
          video,
          canvas,
          picture,
          iframe,
          embed,
          object,
          audio,
          button,
          input,
          select,
          textarea,
          progress,
          meter,
          hr,
          br,
          svg *,
          picture *,
          select *,
          object *
        )::after,
      [aria-busy="true"]
        :is(
          img,
          svg,
          video,
          canvas,
          picture,
          iframe,
          embed,
          object,
          audio,
          button,
          input,
          select,
          textarea,
          progress,
          meter
        ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
        animation: bone-pulse 2s ease-in-out infinite;
        background: var(--bone-base);
        background-size: auto;
      }
    }

    @media (forced-colors: active) {
      [aria-busy="true"]
        :not(:has(*)):not(
          [data-bone],
          [data-bone] *,
          [data-bones-auto="off"],
          [data-bones-auto="off"] *
        ):not(
          img,
          svg,
          video,
          canvas,
          picture,
          iframe,
          embed,
          object,
          audio,
          button,
          input,
          select,
          textarea,
          progress,
          meter,
          hr,
          br,
          svg *,
          picture *,
          select *,
          object *
        )::after,
      [aria-busy="true"]
        :is(
          img,
          svg,
          video,
          canvas,
          picture,
          iframe,
          embed,
          object,
          audio,
          button,
          input,
          select,
          textarea,
          progress,
          meter
        ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
        background-color: GrayText;
        forced-color-adjust: none;
      }
    }
  }

  @scope ([data-bone-animate="none"]) to ([data-bone-animate]:not([data-bone-animate="none"])) {
    [aria-busy="true"]
      :not(:has(*)):not(
        [data-bone],
        [data-bone] *,
        [data-bones-auto="off"],
        [data-bones-auto="off"] *
      ):not(
        img,
        svg,
        video,
        canvas,
        picture,
        iframe,
        embed,
        object,
        audio,
        button,
        input,
        select,
        textarea,
        progress,
        meter,
        hr,
        br,
        svg *,
        picture *,
        select *,
        object *
      )::before,
    [aria-busy="true"]
      :not(:has(*)):not(
        [data-bone],
        [data-bone] *,
        [data-bones-auto="off"],
        [data-bones-auto="off"] *
      ):not(
        img,
        svg,
        video,
        canvas,
        picture,
        iframe,
        embed,
        object,
        audio,
        button,
        input,
        select,
        textarea,
        progress,
        meter,
        hr,
        br,
        svg *,
        picture *,
        select *,
        object *
      )::after,
    [aria-busy="true"]
      :is(
        img,
        svg,
        video,
        canvas,
        picture,
        iframe,
        embed,
        object,
        audio,
        button,
        input,
        select,
        textarea,
        progress,
        meter
      ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
      animation: none;
      background: var(--bone-base);
      background-size: auto;
    }

    @media (forced-colors: active) {
      [aria-busy="true"]
        :not(:has(*)):not(
          [data-bone],
          [data-bone] *,
          [data-bones-auto="off"],
          [data-bones-auto="off"] *
        ):not(
          img,
          svg,
          video,
          canvas,
          picture,
          iframe,
          embed,
          object,
          audio,
          button,
          input,
          select,
          textarea,
          progress,
          meter,
          hr,
          br,
          svg *,
          picture *,
          select *,
          object *
        )::after,
      [aria-busy="true"]
        :is(
          img,
          svg,
          video,
          canvas,
          picture,
          iframe,
          embed,
          object,
          audio,
          button,
          input,
          select,
          textarea,
          progress,
          meter
        ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
        background-color: GrayText;
        forced-color-adjust: none;
      }
    }
  }

  @media (prefers-reduced-motion: reduce) {
    [aria-busy="true"]
      :not(:has(*)):not(
        [data-bone],
        [data-bone] *,
        [data-bones-auto="off"],
        [data-bones-auto="off"] *
      ):not(
        img,
        svg,
        video,
        canvas,
        picture,
        iframe,
        embed,
        object,
        audio,
        button,
        input,
        select,
        textarea,
        progress,
        meter,
        hr,
        br,
        svg *,
        picture *,
        select *,
        object *
      )::before,
    [aria-busy="true"]
      :not(:has(*)):not(
        [data-bone],
        [data-bone] *,
        [data-bones-auto="off"],
        [data-bones-auto="off"] *
      ):not(
        img,
        svg,
        video,
        canvas,
        picture,
        iframe,
        embed,
        object,
        audio,
        button,
        input,
        select,
        textarea,
        progress,
        meter,
        hr,
        br,
        svg *,
        picture *,
        select *,
        object *
      )::after,
    [aria-busy="true"]
      :is(
        img,
        svg,
        video,
        canvas,
        picture,
        iframe,
        embed,
        object,
        audio,
        button,
        input,
        select,
        textarea,
        progress,
        meter
      ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
      animation: bone-pulse 2s ease-in-out infinite;
      background: var(--bone-base);
      background-size: auto;
    }
  }

  /* High-contrast modes strip author backgrounds; keep bones visible with a
     system color and opt the surfaces out of forced-color adjustment. */
  @media (forced-colors: active) {
    [aria-busy="true"]
      :not(:has(*)):not(
        [data-bone],
        [data-bone] *,
        [data-bones-auto="off"],
        [data-bones-auto="off"] *
      ):not(
        img,
        svg,
        video,
        canvas,
        picture,
        iframe,
        embed,
        object,
        audio,
        button,
        input,
        select,
        textarea,
        progress,
        meter,
        hr,
        br,
        svg *,
        picture *,
        select *,
        object *
      )::after,
    [aria-busy="true"]
      :is(
        img,
        svg,
        video,
        canvas,
        picture,
        iframe,
        embed,
        object,
        audio,
        button,
        input,
        select,
        textarea,
        progress,
        meter
      ):not([data-bone], [data-bone] *, [data-bones-auto="off"], [data-bones-auto="off"] *) {
      background-color: GrayText;
      forced-color-adjust: none;
    }
  }
}

@layer bones-auto {
  /* precision="measured" hides a boundary's content with inherited
     visibility from the shadow side. Visibility, unlike display, can be
     switched back on by a descendant, so the opt-out contract survives
     measured mode: exempt subtrees stay visible under the overlay. */
  bones-boundary[data-bones-measured] [data-bones-auto="off"] {
    visibility: visible;
  }
}
