.bs-badge {
  box-sizing: border-box;
  width: 100%;
  background: var(--bs-background);
  border: var(--bs-border);
  border-radius: var(--bs-radius);
  padding: var(--bs-pt) 16px var(--bs-pb);
  margin: var(--bs-mt) 0 var(--bs-mb);
  font-family: var(--bs-font);
  line-height: 1.35;
  color: var(--bs-title-color);
}
.bs-badge * {
  box-sizing: border-box;
}
/* No frame (design.frameless): the badge stands on the page itself,
   without card color, border, corners or side padding. Its card color
   stays the paper of transparent icons and of popups. */
.bs-badge.bs-frameless {
  background: none;
  border: 0;
  border-radius: 0;
  padding-inline: 0;
}
/* Buttons of click actions look like the item or its call to action, never
   like the theme's buttons. */
.bs-badge button {
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  min-width: 0;
  min-height: 0;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: none;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
/* Text stays on one line and scales with --bs-fit, one factor per badge
   (src/text-fit.ts); --bs-fit-cols is the column count it falls back to,
   --bs-fit-heading the smaller factor of a heading too long on its own. */
.bs-heading {
  font-size: calc(
    var(--bs-heading-size) * var(--bs-fit-heading, var(--bs-fit, 1))
  );
  white-space: nowrap;
  color: var(--bs-heading-color);
  font-weight: 600;
  margin: 0 0 var(--bs-heading-gap);
  text-align: center;
  line-height: 1.4;
}
.bs-items {
  display: grid;
  grid-template-columns: repeat(
    var(--bs-fit-cols, var(--bs-cols)),
    minmax(0, 1fr)
  );
  gap: var(--bs-gap);
  align-items: start;
}
.bs-items.bs-auto {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}
.bs-item {
  display: flex;
  min-width: 0;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: inherit;
  text-decoration: none;
  text-align: center;
}
.bs-copy {
  display: flex;
  flex-direction: column;
  min-width: 0;
  max-width: 100%;
  gap: 0;
}
.bs-title {
  font-size: calc(var(--bs-title-size) * var(--bs-fit, 1));
  font-weight: 600;
  color: var(--bs-title-color);
  white-space: nowrap;
}
.bs-subtitle {
  font-size: calc(var(--bs-subtitle-size) * var(--bs-fit, 1));
  font-weight: 400;
  color: var(--bs-subtitle-color);
  white-space: nowrap;
}
.bs-icon {
  color: var(--bs-icon-color);
  background: var(--bs-icon-bg);
  border-radius: var(--bs-icon-radius);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: var(--bs-size);
  height: var(--bs-size);
  /* The frame is a flex item; WebKit otherwise grows it to its content plus
     padding (stamp, glass), so it would no longer be square. */
  min-width: 0;
  min-height: 0;
}
.bs-svg,
.bs-upload {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
/* Native contour motifs (tools/drawings/markup.mjs): filled roles, set
   here on the svg because the storefront draws them as <use> clones. The
   body inherits the fill (--bs-body of the style family, design-system.css).
   Line and detail are stored at the fine weight and grow by a round
   currentColor stroke of --bs-nw: 0 at fine, the drawn contour at regular,
   more at bold (--bs-stroke 0.8, 1, 1.25 of the 0.67 unit contour). Next
   to a narrow gap that bold would close, --bs-kw stops at regular. Parts
   kept at their drawn shape take --bs-xw, which only grows for bold.
   --bs-draw-w (motion.css) widens all of them while Draw traces the
   outlines. Accents take the merchant accent unchanged. */
.bs-svg {
  --bs-nw: max(var(--bs-draw-w, 0), (var(--bs-stroke, 1) - 0.8) * 0.67);
  --bs-kw: max(var(--bs-draw-w, 0), (min(var(--bs-stroke, 1), 1) - 0.8) * 0.67);
  --bs-xw: max(var(--bs-draw-w, 0), (var(--bs-stroke, 1) - 1) * 0.67);
  fill: var(--bs-body, transparent);
  stroke: none;
  stroke-linejoin: round;
}
/* Text of a text seal: icon color in every style, never stroked. */
.bs-svg .bm-text {
  fill: currentColor;
  stroke: none;
  font-family: inherit;
}
.bs-badge .bs-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 32px;
  text-decoration: none;
  max-width: 100%;
  font-size: calc(var(--bs-button-size) * var(--bs-fit, 1));
  color: var(--bs-button-color);
  background: var(--bs-button-bg);
  border-radius: var(--bs-button-radius);
  padding: 6px 14px;
  white-space: nowrap;
}
.bs-banner .bs-items {
  display: block;
}
/* The text keeps a readable width next to a button; where both do not fit,
   the button moves to its own line. */
.bs-banner .bs-item {
  flex-direction: row;
  flex-wrap: wrap;
  text-align: left;
  gap: 14px;
  align-items: center;
}
/* A button sizes to its content unless told otherwise. */
.bs-banner button.bs-item {
  width: 100%;
}
/* Beside the icon (left or right) the text keeps about 10em next to a
   button, or all the room beside the icon in a narrow banner; the button
   then moves to its own line. Above the icon (top) it stays as it was. */
.bs-banner:is(.bs-icon-left, .bs-icon-right) .bs-item > .bs-copy {
  flex: 1 1 0%;
  min-width: min(10em, 100% - var(--bs-size, 36px) - 14px);
}
.bs-minimal .bs-item {
  flex-direction: row;
  gap: 8px;
  text-align: left;
}
.bs-payment .bs-copy:empty {
  display: none;
}
/* Layout: icon placement, text alignment, vertical alignment (row layouts). */
.bs-icon-top .bs-item {
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 8px;
}
.bs-icon-left .bs-item {
  flex-direction: row;
  align-items: center;
  text-align: left;
  gap: 14px;
}
.bs-icon-right .bs-item {
  flex-direction: row-reverse;
  align-items: center;
  text-align: left;
  gap: 14px;
}
.bs-minimal.bs-icon-left .bs-item,
.bs-minimal.bs-icon-right .bs-item {
  gap: 8px;
}
.bs-icon-left .bs-copy,
.bs-icon-right .bs-copy {
  flex: 1;
}
.bs-text-left .bs-item,
.bs-text-left .bs-heading {
  text-align: left;
}
.bs-text-center .bs-item,
.bs-text-center .bs-heading {
  text-align: center;
}
.bs-text-right .bs-item,
.bs-text-right .bs-heading {
  text-align: right;
}
.bs-icon-top.bs-text-left .bs-item {
  align-items: flex-start;
}
.bs-icon-top.bs-text-right .bs-item {
  align-items: flex-end;
}
.bs-valign-start .bs-item {
  align-items: flex-start;
}
.bs-valign-end .bs-item {
  align-items: flex-end;
}
.bs-badge :is(a, button):focus-visible {
  outline: 2px solid var(--bs-title-color, currentColor);
  outline-offset: 4px;
}
.bs-preview-mobile .bs-items {
  grid-template-columns: repeat(
    var(--bs-fit-cols, var(--bs-mobile-cols)),
    minmax(0, 1fr)
  );
}
.bs-preview-mobile .bs-icon:not(.bs-brand-icon) {
  width: var(--bs-mobile-size);
  height: var(--bs-mobile-size);
}
.bs-preview-mobile .bs-badge .bs-icon.bs-brand-icon {
  width: max(60px, calc(var(--bs-mobile-size) * 1.6));
  height: max(38px, var(--bs-mobile-size));
}
.bs-preview-mobile .bs-title {
  font-size: calc(var(--bs-mobile-title-size) * var(--bs-fit, 1));
}
.bs-preview-mobile .bs-subtitle {
  font-size: calc(var(--bs-mobile-subtitle-size) * var(--bs-fit, 1));
}
.bs-preview-mobile .bs-items.bs-auto:not(.bs-mobile-auto) {
  display: grid;
}
.bs-preview-mobile .bs-items.bs-mobile-auto {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
}
@media (max-width: 600px) {
  .bs-items {
    grid-template-columns: repeat(
      var(--bs-fit-cols, var(--bs-mobile-cols)),
      minmax(0, 1fr)
    );
  }
  .bs-items.bs-auto:not(.bs-mobile-auto) {
    display: grid;
  }
  .bs-items.bs-mobile-auto {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
  }
  .bs-banner .bs-items {
    display: block;
  }
  .bs-icon:not(.bs-brand-icon) {
    width: var(--bs-mobile-size);
    height: var(--bs-mobile-size);
  }
  .bs-badge .bs-icon.bs-brand-icon {
    width: max(60px, calc(var(--bs-mobile-size) * 1.6));
    height: max(38px, var(--bs-mobile-size));
  }
  .bs-title {
    font-size: calc(var(--bs-mobile-title-size) * var(--bs-fit, 1));
  }
  .bs-subtitle {
    font-size: calc(var(--bs-mobile-subtitle-size) * var(--bs-fit, 1));
  }
}
/* Text for screen readers only: tooltips and subtitles shown as tooltips. */
.bs-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.bs-item[title] {
  cursor: help;
}
.bs-item[title]:is([href], button) {
  cursor: pointer;
}
/* Motion lives in src/motion.css (yeahbadges-motion.css), which the
   storefront loads with the first badge that moves. Until then a badge
   that reveals itself waits hidden, so its entrance does not flash
   (src/storefront.ts adds bs-in or bs-wait). bs-fade also fades the popup
   backdrop below. */
[data-bs-mount] [data-bs-reveal]:not(.bs-in, .bs-wait) {
  visibility: hidden;
}
/* A badge also waits hidden until its motifs are in the sprite, at most
   600 ms (src/storefront.ts), so no tile shows empty. */
[data-bs-mount][data-bs-load] {
  visibility: hidden !important;
}
/* The full EU notice reserves its room with an inline style
   (src/storefront.ts) and its margin before yeahbadges-eu.css arrives. */
.bs-eu[style] {
  margin: 12px 0;
}
@keyframes bs-fade {
  from {
    opacity: 0;
  }
}
/* Popup of a click action (src/interactions.ts): one shared dialog per page,
   a bottom sheet on small screens. Font and colors come from the badge. */
.bs-dialog {
  box-sizing: border-box;
  width: min(440px, calc(100% - 32px));
  max-width: none;
  max-height: min(640px, calc(100% - 48px));
  margin: auto;
  padding: 0;
  border: 0;
  border-radius: 12px;
  background: var(--bs-background, #ffffff);
  color: var(--bs-title-color, #202223);
  font-family: var(--bs-font, inherit);
  font-size: 15px;
  line-height: 1.5;
  box-shadow: 0 16px 48px #0000002e;
  overflow: auto;
  overscroll-behavior: contain;
}
.bs-dialog::backdrop {
  background: #00000066;
}
.bs-dialog * {
  box-sizing: border-box;
}
.bs-dialog-inner {
  position: relative;
  padding: 24px;
}
.bs-dialog-close {
  position: absolute;
  top: 6px;
  inset-inline-end: 6px;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  box-shadow: none;
  color: inherit;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
.bs-dialog-close svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}
@media (hover: hover) {
  .bs-dialog-close:hover {
    background: color-mix(in srgb, currentColor 8%, transparent);
  }
}
.bs-dialog :is(a, button, input):focus-visible {
  outline: 2px solid var(--bs-title-color, currentColor);
  outline-offset: 2px;
}
.bs-pop-heading {
  margin: 0 0 8px;
  margin-inline-end: 40px;
  font-size: max(18px, var(--bs-title-size, 16px));
  font-weight: 650;
  line-height: 1.3;
  color: var(--bs-heading-color, inherit);
  overflow-wrap: anywhere;
}
.bs-pop-text {
  color: var(--bs-subtitle-color, inherit);
  font-size: max(15px, var(--bs-subtitle-size, 14px));
  overflow-wrap: anywhere;
}
.bs-pop-text p {
  margin: 0 0 12px;
}
.bs-pop-text p:last-child {
  margin: 0;
}
.bs-pop-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: 16px;
  padding: 10px 18px;
  border-radius: var(--bs-button-radius, 4px);
  background: var(--bs-button-bg, #202223);
  color: var(--bs-button-color, #ffffff);
  font-size: max(15px, var(--bs-button-size, 14px));
  font-weight: 600;
  text-decoration: none;
}
.bs-code {
  display: block;
  width: 100%;
  margin: 12px 0 0;
  padding: 10px 12px;
  border: 1px solid currentColor;
  border-radius: 6px;
  background: transparent;
  color: inherit;
  font:
    600 18px/1.4 ui-monospace,
    monospace;
  letter-spacing: 0.04em;
}
.bs-toast {
  position: fixed;
  left: 50%;
  /* Above the home indicator of phones in a theme with viewport-fit=cover;
     elsewhere the inset is 0. */
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  z-index: 2147483647;
  box-sizing: border-box;
  max-width: calc(100% - 32px);
  margin: 0;
  padding: 12px 18px;
  border-radius: 8px;
  background: #202223;
  color: #ffffff;
  font-size: 15px;
  line-height: 1.4;
  box-shadow: 0 8px 24px #00000033;
  opacity: 0;
  transform: translate(-50%, 8px);
  pointer-events: none;
}
.bs-toast.bs-toast-show {
  opacity: 1;
  transform: translate(-50%, 0);
}
@media (max-width: 600px) {
  .bs-dialog {
    width: 100%;
    max-height: 85%;
    margin: auto 0 0;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    border-radius: 16px 16px 0 0;
  }
}
@media screen and (prefers-reduced-motion: no-preference) {
  .bs-dialog[open] {
    animation: bs-dialog-in 200ms cubic-bezier(0.2, 0.7, 0.2, 1);
  }
  .bs-dialog[open]::backdrop {
    animation: bs-fade 200ms ease-out;
  }
  .bs-toast {
    transition:
      opacity 200ms ease-out,
      transform 200ms cubic-bezier(0.2, 0.7, 0.2, 1);
  }
}
@media screen and (prefers-reduced-motion: no-preference) and (max-width: 600px) {
  .bs-dialog[open] {
    animation-name: bs-sheet-in;
  }
}
@keyframes bs-dialog-in {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.98);
  }
}
@keyframes bs-sheet-in {
  from {
    transform: translateY(100%);
  }
}
.bs-masked-icon {
  display: block;
  width: 100%;
  height: 100%;
  background: currentColor;
  mask-size: contain;
  mask-repeat: no-repeat;
  mask-position: center;
  -webkit-mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
}
/* Free position (src/free-position.ts): two layers hold the floating
   badges. A fixed one holds those at a place of the screen, which stay in
   view. One over the whole page (bs-free-page) holds those at a place of
   the page, which scroll with it; the storefront sets its height to the
   page's, and it lies over the content and under what a theme raises above
   it (a sticky header, drawers). Each badge keeps its anchored edges at
   their distance (a share of the width; a share of the screen's height or
   px along the page), at least 8 px inside its layer and the safe area: on
   every side of the screen, at the sides of the page. The storefront
   measures the badge's height (--bs-free-h); one taller than the screen
   scrolls (bs-free-scroll). A frame may be higher than its content
   (--bs-free-bh, a min-height): the content then stands in its middle,
   and a frame lower than its content grows with it. Phones take the
   bs-free-m values when set. A
   badge of the page over a sticky element of the theme hangs inside that
   element (bs-free-in, src/free-carrier.ts): all: revert keeps the theme's
   rules off the mount, not off what the badge holds, and with z-index 2,
   as in the layer, what the element raises higher covers the badge. A
   layer is a block by its own rule: a theme may hide empty elements (Dawn:
   div:empty), and a hidden layer has no size to place a badge in. */
.bs-free-layer {
  display: block !important;
  position: fixed;
  inset: 0;
  z-index: 100;
  pointer-events: none;
}
.bs-free-page {
  position: absolute;
  inset: 0 0 auto;
  z-index: 2;
}
.bs-free {
  --bs-free-ex: calc(
    8px + max(env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px))
  );
  --bs-free-ey: calc(
    8px + max(env(safe-area-inset-top, 0px), env(safe-area-inset-bottom, 0px))
  );
  --bs-free-cx: var(--bs-free-x);
  --bs-free-cy: var(--bs-free-y);
  --bs-free-cw: var(--bs-free-w);
  --bs-free-cbh: var(--bs-free-bh, 0px);
  --bs-free-width: min(var(--bs-free-cw), 100% - 2 * var(--bs-free-ex));
  --bs-free-sx: clamp(
    var(--bs-free-ex),
    var(--bs-free-cx),
    100% - var(--bs-free-ex) - var(--bs-free-width)
  );
  --bs-free-sy: clamp(
    var(--bs-free-ey),
    var(--bs-free-cy),
    100% - var(--bs-free-ey) - var(--bs-free-h, 0px)
  );
  position: absolute;
  box-sizing: border-box;
  width: var(--bs-free-width);
  max-height: calc(100% - 2 * var(--bs-free-ey));
  pointer-events: auto;
}
.bs-free-in {
  all: revert !important;
  position: absolute !important;
  inset: var(--bs-in-y) auto auto var(--bs-in-x) !important;
  z-index: 2 !important;
  box-sizing: border-box !important;
  width: var(--bs-in-w) !important;
  pointer-events: auto !important;
}
.bs-free-page > .bs-free {
  --bs-free-ey: 8px;
  max-height: none;
}
.bs-free > .bs-badge {
  margin: 0;
  min-height: var(--bs-free-cbh);
  align-content: center;
}
.bs-free-scroll {
  overflow-y: auto;
  overscroll-behavior: contain;
}
.bs-free-left {
  left: var(--bs-free-sx);
}
.bs-free-right {
  right: var(--bs-free-sx);
}
.bs-free-top {
  top: var(--bs-free-sy);
}
.bs-free-bottom {
  bottom: var(--bs-free-sy);
}
@media (max-width: 600px) {
  .bs-free-m {
    --bs-free-cx: var(--bs-free-mx);
    --bs-free-cy: var(--bs-free-my);
    --bs-free-cw: var(--bs-free-mw);
    --bs-free-cbh: var(--bs-free-mbh, 0px);
    inset: auto;
  }
  .bs-free-m-left {
    left: var(--bs-free-sx);
  }
  .bs-free-m-right {
    right: var(--bs-free-sx);
  }
  .bs-free-m-top {
    top: var(--bs-free-sy);
  }
  .bs-free-m-bottom {
    bottom: var(--bs-free-sy);
  }
}
/* An icon never grows past its cell: on narrow screens a large icon
   shrinks with it and stays square. Payment logos keep their frame, capped
   the same way; store badges size themselves (design-system.css). */
.bs-badge .bs-icon:not(.bs-store-icon, .bs-brand-icon) {
  max-width: 100%;
  height: auto;
  aspect-ratio: 1;
}
.bs-badge .bs-icon.bs-brand-icon {
  max-width: 100%;
}
/* Card color behind transparent icons: the plain background (--bs-card)
   everywhere, the middle of a gradient (--bs-card-mix, markup.ts) where
   color-mix works. */
@supports (color: color-mix(in srgb, red, blue)) {
  .bs-badge[style*="--bs-card-mix"] .bs-items {
    --bs-card: var(--bs-card-mix);
  }
}

/* Eigene SVG-Ebenen, dieselbe Gestaltung in Editor und Storefront. */
/* Style families with the native contour motifs (docs/zeichenstandard.md,
   roles in tools/drawings/markup.mjs). Line and detail stay in the icon
   color and accents in the mark color (badges.css) in every family; the
   families differ in the body, the object surface. Contour and Seal leave
   it open (transparent), Atelier (duotone) fills it with a light accent
   tint (20 % accent in the tile color, contrast.ts DUOTONE_BODY_SHARE),
   Signal (solid) with the icon color and turns the inner lines
   (detail) into the paper color, Prism (glass) lays a light, translucent
   surface on its tile. Air inside a drawing stays open in every family.
   Declared on the svg, so an item's own colors apply. */
@supports (color: color-mix(in oklab, red, blue)) {
  .bs-style-duotone .bs-svg {
    --bs-body: color-mix(
      in oklab,
      var(--bs-icon-accent) 20%,
      var(--bs-icon-bg)
    );
  }
}
.bs-style-solid .bs-svg {
  --bs-body: currentColor;
  --bs-dc: var(--bs-icon-bg);
}
.bs-style-glass .bs-svg {
  --bs-body: #ffffffa6;
}
.bs-style-solid .bs-title {
  font-weight: 750;
}
.bs-style-stamp .bs-icon:not(.bs-brand-icon) {
  position: relative;
  border: 1px solid currentColor;
  border-radius: 50%;
  padding: 16%;
  padding: calc(var(--bs-size) * 0.16);
  box-shadow:
    inset 0 0 0 3px var(--bs-icon-bg),
    inset 0 0 0 4px var(--bs-icon-accent);
}
.bs-style-stamp .bs-title {
  letter-spacing: 0.015em;
}
.bs-style-glass .bs-icon:not(.bs-brand-icon) {
  padding: calc(var(--bs-size) * 0.12);
  background: #ffffff;
  border: 1px solid #ffffff;
  box-shadow:
    0 3px 8px #234b7512,
    inset 0 1px 2px #ffffff;
}
@supports (color: color-mix(in oklch, white, black)) {
  .bs-style-glass .bs-icon:not(.bs-brand-icon) {
    background: linear-gradient(
      145deg,
      color-mix(in oklch, white 88%, var(--bs-icon-accent)),
      color-mix(in oklch, var(--bs-icon-accent) 25%, white)
    );
    border-color: color-mix(in oklch, white 85%, var(--bs-icon-accent));
  }
}
/* Transparent icon background (design.iconBackgroundTransparent or the
   item's iconBackground "transparent"): no tile, frame, ring or shadow of
   the style family, the motif fills the box. Its paper color (the inner
   lines of Signal, the tint of Atelier) takes the card color (--bs-card,
   the middle of a gradient), so every style stays readable on the card. */
.bs-badge .bs-icon.bs-clear:not(.bs-brand-icon) {
  --bs-icon-bg: var(--bs-card, #ffffff);
  background: none;
  border: 0;
  padding: 0;
  box-shadow: none;
}
.bs-icon.bs-brand-icon {
  background: #ffffff;
  color: initial;
  border: 0;
  border-radius: 4px;
  padding: 4px;
  width: max(60px, calc(var(--bs-size) * 1.6));
  height: max(38px, var(--bs-size));
  box-shadow: none;
  filter: none;
  transform: none;
}
.bs-payment-logo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
/* Offizielle Store-Abzeichen (src/brands.ts), Anfang. Apple und Google
   verlangen die unveraenderte Grafik: kein Hintergrund, Rahmen, Filter,
   Schatten, keine Transformation und keine Bewegung, auch nicht durch
   Stilfamilien oder Hover-Effekte. Hoehe mindestens --bs-store-min (Apple
   40 px, Google Play 28 px, gesetzt aus den Markenregeln), Breite aus dem
   Seitenverhaeltnis; der Freiraum (--bs-store-clear, ein Viertel der Hoehe)
   ist der Innenabstand des Rahmens. prefers-reduced-motion ist ohne Bewegung
   gegenstandslos. */
.bs-badge .bs-item .bs-icon.bs-store-icon {
  --bs-store-height: max(var(--bs-store-min, 40px), var(--bs-size));
  width: auto;
  height: auto;
  max-width: 100%;
  box-sizing: border-box;
  padding: calc(var(--bs-store-height) * var(--bs-store-clear, 0.25));
}
.bs-badge .bs-item .bs-icon.bs-store-icon,
.bs-badge .bs-item:hover .bs-icon.bs-store-icon {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  filter: none;
  transform: none;
  animation: none;
  transition: none;
  opacity: 1;
}
.bs-badge .bs-icon.bs-store-icon::before,
.bs-badge .bs-icon.bs-store-icon::after {
  content: none;
}
.bs-badge .bs-item.bs-store-item,
.bs-badge .bs-item.bs-store-item:hover {
  transform: none;
  transition: none;
}
/* Im Abzeichen mit hoher Spezifitaet, damit Theme-Regeln wie
   ".product-info img { height: auto }" die Grafik nicht verkleinern. */
.bs-store-badge,
.bs-badge .bs-item .bs-store-icon .bs-store-badge {
  display: block;
  width: auto;
  min-width: 0;
  /* Never wider than the container: a container narrower than the artwork
     at its minimum height gets the text fallback below (src/store-fit.ts);
     without a script the image shrinks instead of overflowing. */
  max-width: 100%;
  object-fit: contain;
  min-height: 0;
  max-height: none;
  height: var(
    --bs-store-height,
    max(var(--bs-store-min, 40px), var(--bs-size, 40px))
  );
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  filter: none;
  transform: none;
  animation: none;
  transition: none;
  opacity: 1;
}
.bs-preview-mobile .bs-badge .bs-item .bs-icon.bs-store-icon {
  --bs-store-height: max(var(--bs-store-min, 40px), var(--bs-mobile-size));
}
@media (max-width: 600px) {
  .bs-badge .bs-item .bs-icon.bs-store-icon {
    --bs-store-height: max(var(--bs-store-min, 40px), var(--bs-mobile-size));
  }
}
/* Text fallback: the runtime and the editor preview mark a frame whose
   artwork would fall below the brand minimum (bs-store-text); the link then
   shows the official wording instead of a shrunken badge, at the size of
   the titles and their factor --bs-fit. It appears only where the frame is
   narrower than the artwork, and the wording at that size is wider still:
   on one line it would drop to 3 to 8 px. So it breaks between words,
   never inside one, also against theme rules like word-break or hyphens;
   --bs-fit-store is the smaller factor of a single word too long for its
   frame (src/store-fit.ts). A block, not a flex box, so such a word
   overflows at its end and scrollWidth measures it. */
.bs-badge .bs-item .bs-icon.bs-store-icon.bs-store-text {
  display: block;
  padding: 0;
  width: auto;
  height: auto;
  font-size: calc(var(--bs-title-size) * var(--bs-fit-store, var(--bs-fit, 1)));
  font-weight: 600;
  line-height: 1.3;
  white-space: normal;
  overflow-wrap: normal;
  word-break: normal;
  hyphens: manual;
  text-wrap: balance;
  /* The wording takes the text color of the item, not the icon color, which
     some templates set equal to the card. */
  color: inherit;
}
.bs-preview-mobile .bs-badge .bs-item .bs-icon.bs-store-icon.bs-store-text {
  font-size: calc(
    var(--bs-mobile-title-size) * var(--bs-fit-store, var(--bs-fit, 1))
  );
}
@media (max-width: 600px) {
  .bs-badge .bs-item .bs-icon.bs-store-icon.bs-store-text {
    font-size: calc(
      var(--bs-mobile-title-size) * var(--bs-fit-store, var(--bs-fit, 1))
    );
  }
}
.bs-badge .bs-item .bs-store-icon.bs-store-text .bs-store-badge {
  display: none;
}
.bs-badge .bs-item .bs-icon.bs-store-icon.bs-store-text::after {
  content: attr(data-bs-alt);
  font: inherit;
  color: inherit;
  text-decoration: underline;
}
/* Offizielle Store-Abzeichen, Ende. */
@media (prefers-reduced-motion: reduce) {
  .bs-badge,
  .bs-badge *,
  .bs-badge *::after,
  .bs-dialog,
  .bs-dialog::backdrop,
  .bs-toast,
  .style-card {
    transition: none;
    animation: none;
  }
}

/* Motion (docs/claude-design.md), shipped as yeahbadges-motion.css: the
   storefront loads it with the first badge that moves (data-bs-motion,
   src/storefront.ts); the editor reads it inside badges.css. --bs-motion
   tells the storefront that the rules are already on the page.

   Entrance and attention effects wait for bs-in: the storefront adds it
   when the badge scrolls into view and holds a waiting badge at its first
   frame with bs-wait. bs-seen marks a badge that already played on this
   page, so a remount stays at rest. Only transform and opacity move; Draw
   and Fill change inherited paint properties, which the sprite's <use>
   passes on to the filled contour motifs (tools/drawings/markup.mjs):
   Draw traces the outlines of line and detail with a dashed stroke of
   --bs-draw-w (registered below, so it interpolates; without @property it
   switches in one step) while every fill waits, then the fills come in;
   Fill floods the body, the object surface, with the accent.

   The four slots of an icon (item.motion, markup.ts) run on separate
   layers, so they combine: the tile (.bs-icon) takes entrance and click,
   the motif inside it attention, hover and the dimming of Check mark, its
   ::before the glow ring, .bs-sheen (a clipping layer of its own, so the
   tile never clips the other effects) the shine and .bs-fx the drawn
   click effects. Each class sets its animation in a custom property
   (--bs-e, --bs-c, --bs-a, --bs-h, and --bs-ax, --bs-hx, --bs-cm, --bs-cx
   for the other layers); the gates below pass it on (--bs-*-on) while the
   slot plays. One animation list per layer keeps the effects of a
   finished slot at rest when another slot starts; the slots of one list
   never share a keyframe name (hover Heartbeat runs bs-beat), since equal
   names in one list would not restart. */
:root {
  --bs-motion: 1;
}
@property --bs-draw-w {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}
.bs-badge {
  --bs-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}
.bs-item {
  --bs-delay: calc(var(--bs-i, 0) * 70ms);
}
/* Badge wide hover (design.hover). Official logos never move or glow;
   store badges do the same in design-system.css. */
.bs-hover-glow .bs-icon {
  transition: filter 0.2s ease;
}
@media (hover: hover) {
  .bs-hover-glow .bs-item:hover .bs-icon:not(.bs-brand-icon, .bs-store-icon) {
    filter: drop-shadow(0 0 6px var(--bs-icon-accent))
      drop-shadow(0 0 1px var(--bs-icon-accent));
  }
}
/* Slots: entrance, once when the badge appears. */
.bs-e-pop {
  --bs-e: bs-pop-in 320ms var(--bs-ease) var(--bs-delay) backwards;
}
.bs-e-draw {
  --bs-e: bs-draw 600ms var(--bs-ease) var(--bs-delay) backwards;
}
.bs-e-rise {
  --bs-e: bs-rise-in 480ms var(--bs-ease) var(--bs-delay) backwards;
}
.bs-e-drop {
  --bs-e: bs-drop 640ms var(--bs-ease) var(--bs-delay) backwards;
}
/* Attention: two finite runs shortly after the badge appears. */
.bs-a-pulse {
  --bs-a: bs-pulse 700ms ease-in-out calc(var(--bs-delay) + 300ms) 2;
}
.bs-a-heartbeat {
  --bs-a: bs-heartbeat 1000ms ease-in-out calc(var(--bs-delay) + 300ms) 2;
}
.bs-a-ring {
  --bs-a: bs-ring 900ms ease-in-out calc(var(--bs-delay) + 300ms) 2;
}
.bs-a-shine {
  --bs-ax: bs-shine 900ms ease-in-out calc(var(--bs-delay) + 300ms) 2;
}
/* Hover: on pointer hover, keyboard focus and the editor's Play. */
.bs-h-lift {
  --bs-h: bs-lift 650ms var(--bs-ease);
}
.bs-h-tilt {
  --bs-h: bs-tilt 600ms var(--bs-ease);
}
.bs-h-wiggle {
  --bs-h: bs-wiggle 400ms var(--bs-ease);
}
.bs-h-spin {
  --bs-h: bs-spin 600ms var(--bs-ease);
}
.bs-h-nudge {
  --bs-h: bs-nudge 550ms var(--bs-ease);
}
.bs-h-bounce {
  --bs-h: bs-bounce 700ms ease-out;
}
.bs-h-swing {
  --bs-h: bs-swing 900ms ease-in-out;
}
.bs-h-float {
  --bs-h: bs-float 1400ms ease-in-out;
}
.bs-h-beat {
  --bs-h: bs-beat 900ms ease-in-out;
}
.bs-h-shake {
  --bs-h: bs-shake 450ms linear;
}
.bs-h-twinkle {
  --bs-h: bs-twinkle 700ms var(--bs-ease);
}
.bs-h-sway {
  --bs-h: bs-sway 1200ms ease-in-out;
}
.bs-h-halo {
  --bs-hx: bs-halo 800ms ease-out;
}
.bs-h-draw {
  --bs-h: bs-draw 700ms var(--bs-ease);
}
.bs-h-fill {
  --bs-h: bs-fill 500ms ease-out;
}
/* Click: on every click, tap or keyboard activation (bs-tap). */
.bs-c-press {
  --bs-c: bs-press 380ms var(--bs-ease);
}
.bs-c-burst {
  --bs-c: bs-pulse 300ms ease-out;
  --bs-cx: bs-burst 520ms ease-out;
}
.bs-c-ripple {
  --bs-cx: bs-ripple 650ms ease-out;
}
.bs-c-flip {
  --bs-c: bs-flip 700ms ease-in-out;
}
.bs-c-jelly {
  --bs-c: bs-jelly 650ms ease-out;
}
.bs-c-spin {
  --bs-c: bs-spin 600ms var(--bs-ease);
}
.bs-c-confetti {
  --bs-c: bs-press 380ms var(--bs-ease);
  --bs-cx: bs-confetti 700ms var(--bs-ease);
}
.bs-c-check {
  --bs-cm: bs-dim 900ms ease-in-out;
  --bs-cx: bs-tick 900ms var(--bs-ease);
}
/* Layers: pivots of the motif, and the frames the extra layers draw in. */
.bs-h-swing .bs-icon > :not(.bs-fx, .bs-sheen) {
  transform-origin: 50% 0;
}
:is(.bs-h-sway, .bs-h-tilt) .bs-icon > :not(.bs-fx, .bs-sheen) {
  transform-origin: 50% 100%;
}
.bs-a-ring .bs-icon > :not(.bs-fx, .bs-sheen) {
  transform-origin: 50% 12%;
}
:is(.bs-a-shine, .bs-h-halo, [data-bs-tap]) .bs-icon {
  position: relative;
}
.bs-sheen {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
  pointer-events: none;
}
.bs-sheen::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    105deg,
    transparent 30%,
    #ffffffb3 50%,
    transparent 70%
  );
  opacity: 0;
  transform: translateX(-100%);
  pointer-events: none;
}
.bs-h-halo .bs-icon::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow:
    0 0 0 1.5px currentColor,
    0 0 12px 2px var(--bs-icon-accent);
  opacity: 0;
  pointer-events: none;
}
/* Drawn click effects: sized in em of the icon size. */
.bs-fx {
  position: absolute;
  inset: 0;
  font-size: var(--bs-size);
  pointer-events: none;
}
.bs-fx::before,
.bs-fx::after {
  content: "";
  position: absolute;
  opacity: 0;
}
.bs-c-burst .bs-fx::before {
  inset: 0;
  border: 2px solid currentColor;
  border-radius: 50%;
}
.bs-c-ripple .bs-fx::before {
  inset: 0;
  border-radius: 50%;
  background: currentColor;
}
/* Six dots in two rings of three, the second turned and in the accent. */
.bs-c-confetti .bs-fx::before,
.bs-c-confetti .bs-fx::after {
  top: 50%;
  left: 50%;
  width: 0.08em;
  height: 0.08em;
  margin: -0.04em;
  border-radius: 50%;
  box-shadow:
    0 -0.55em currentColor,
    0.48em 0.28em var(--bs-icon-accent),
    -0.48em 0.28em currentColor;
}
.bs-c-confetti .bs-fx::after {
  rotate: 60deg;
  box-shadow:
    0 -0.5em var(--bs-icon-accent),
    0.43em 0.25em currentColor,
    -0.43em 0.25em var(--bs-icon-accent);
}
.bs-c-check .bs-fx::after {
  top: 50%;
  left: 50%;
  width: 0.22em;
  height: 0.42em;
  margin: -0.26em 0 0 -0.11em;
  border: solid currentColor;
  border-width: 0 0.08em 0.08em 0;
  rotate: 45deg;
}
.bs-preview-mobile .bs-fx {
  font-size: var(--bs-mobile-size);
}
@media (max-width: 600px) {
  .bs-fx {
    font-size: var(--bs-mobile-size);
  }
}
@media screen and (prefers-reduced-motion: no-preference) {
  .bs-wait,
  .bs-wait *,
  .bs-wait *::before,
  .bs-wait *::after {
    animation-play-state: paused !important;
  }
  .bs-enter-fade:is(.bs-in, .bs-wait):not(.bs-seen, .bs-stagger),
  .bs-enter-fade.bs-stagger:is(.bs-in, .bs-wait):not(.bs-seen) .bs-item {
    animation: bs-fade 500ms ease-out var(--bs-delay, 0ms) backwards;
  }
  .bs-enter-rise:is(.bs-in, .bs-wait):not(.bs-seen, .bs-stagger),
  .bs-enter-rise.bs-stagger:is(.bs-in, .bs-wait):not(.bs-seen) .bs-item {
    animation: bs-rise 600ms var(--bs-ease) var(--bs-delay, 0ms) backwards;
  }
  .bs-enter-pop:is(.bs-in, .bs-wait):not(.bs-seen, .bs-stagger),
  .bs-enter-pop.bs-stagger:is(.bs-in, .bs-wait):not(.bs-seen) .bs-item {
    animation: bs-pop 320ms var(--bs-ease) var(--bs-delay, 0ms) backwards;
  }
  .bs-hover-lift .bs-item {
    transition: transform 0.2s ease;
  }
  /* Gates: entrance and attention once the badge is in view. */
  :is(.bs-in, .bs-wait):not(.bs-seen) .bs-item {
    --bs-e-on: var(--bs-e, none);
    --bs-a-on: var(--bs-a, none);
    --bs-ax-on: var(--bs-ax, none);
  }
  /* Hover also answers keyboard focus. bs-hov (src/bootstrap.ts) holds a
     started hover run after the pointer or focus left, until it ends; Fill
     then fades back to the body instead of snapping. */
  .bs-item:is(:focus-visible, :has(:focus-visible), .bs-hov) {
    --bs-h-on: var(--bs-h, none);
    --bs-hx-on: var(--bs-hx, none);
  }
  .bs-h-fill:is(:focus-visible, :has(:focus-visible), .bs-hov) .bs-svg {
    fill: var(--bs-icon-accent);
  }
  .bs-h-fill .bs-svg {
    transition: fill 0.3s ease-out;
  }
  .bs-tap {
    --bs-c-on: var(--bs-c, none);
    --bs-cm-on: var(--bs-cm, none);
    --bs-cx-on: var(--bs-cx, none);
  }
  /* Layers. */
  .bs-icon {
    animation: var(--bs-e-on, none), var(--bs-c-on, none);
  }
  .bs-icon > :not(.bs-fx, .bs-sheen) {
    animation:
      var(--bs-a-on, none), var(--bs-h-on, none), var(--bs-cm-on, none);
  }
  .bs-sheen::after {
    animation: var(--bs-ax-on, none);
  }
  .bs-h-halo .bs-icon::before {
    animation: var(--bs-hx-on, none);
  }
  .bs-fx::before,
  .bs-fx::after {
    animation: var(--bs-cx-on, none);
  }
}
@media screen and (prefers-reduced-motion: no-preference) and (hover: hover) {
  .bs-hover-lift .bs-item:hover {
    transform: translateY(-3px);
  }
  .bs-hover-lift .bs-item:has(.bs-brand-icon):hover {
    transform: none;
  }
  .bs-item:hover {
    --bs-h-on: var(--bs-h, none);
    --bs-hx-on: var(--bs-hx, none);
  }
  .bs-h-fill:hover .bs-svg {
    fill: var(--bs-icon-accent);
  }
}
/* Reduced motion: nothing moves; a click only dims the icon briefly, so
   the visitor sees that it registered. */
@media (prefers-reduced-motion: reduce) {
  .bs-badge .bs-tap .bs-icon {
    animation: bs-dim 300ms ease-out;
  }
}
@keyframes bs-rise {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
}
@keyframes bs-pop {
  from {
    opacity: 0;
    transform: scale(0.94);
  }
}
@keyframes bs-pop-in {
  from {
    opacity: 0;
    transform: scale(0.5);
  }
}
@keyframes bs-rise-in {
  from {
    opacity: 0;
    transform: translateY(35%);
  }
}
@keyframes bs-drop {
  0% {
    opacity: 0;
    transform: translateY(-45%);
  }
  55% {
    opacity: 1;
    transform: translateY(6%);
  }
  78% {
    transform: translateY(-3%);
  }
}
/* 150 covers the longest outline of a motif (32 unit grid); the dash
   pattern starts again on every outline. */
@keyframes bs-draw {
  from {
    stroke-dasharray: 150 150;
    stroke-dashoffset: 151;
    fill-opacity: 0;
    --bs-draw-w: 0.3;
  }
  65% {
    stroke-dasharray: 150 150;
    stroke-dashoffset: 0;
    fill-opacity: 0;
    --bs-draw-w: 0.3;
  }
  to {
    stroke-dasharray: 150 150;
    stroke-dashoffset: 0;
    fill-opacity: 1;
    --bs-draw-w: 0;
  }
}
/* From the resting body of the family to the accent held by the hover. */
@keyframes bs-fill {
  from {
    fill: var(--bs-body, transparent);
  }
}
@keyframes bs-lift {
  35% {
    transform: translateY(-14%) scale(1.06);
  }
  70% {
    transform: translateY(-10%) scale(1.04);
  }
}
@keyframes bs-tilt {
  40% {
    transform: perspective(300px) rotateX(14deg) rotateY(-16deg);
  }
}
@keyframes bs-wiggle {
  25% {
    transform: rotate(-8deg);
  }
  50% {
    transform: rotate(6deg);
  }
  75% {
    transform: rotate(-3deg);
  }
}
@keyframes bs-spin {
  to {
    transform: rotate(360deg);
  }
}
@keyframes bs-nudge {
  30% {
    transform: translateX(16%);
  }
  55% {
    transform: translateX(-4%);
  }
  75% {
    transform: translateX(5%);
  }
}
@keyframes bs-bounce {
  25% {
    transform: translateY(-22%) scale(0.96, 1.04);
  }
  50% {
    transform: scale(1.08, 0.9);
  }
  65% {
    transform: translateY(-8%);
  }
  80% {
    transform: scale(1.02, 0.98);
  }
}
@keyframes bs-swing {
  20% {
    transform: rotate(14deg);
  }
  40% {
    transform: rotate(-10deg);
  }
  60% {
    transform: rotate(6deg);
  }
  80% {
    transform: rotate(-3deg);
  }
}
@keyframes bs-float {
  50% {
    transform: translateY(-10%);
  }
}
@keyframes bs-shake {
  15%,
  45%,
  75% {
    transform: translateX(-7%);
  }
  30%,
  60% {
    transform: translateX(7%);
  }
  90% {
    transform: translateX(-2%);
  }
}
@keyframes bs-twinkle {
  30% {
    opacity: 0.75;
    transform: scale(1.18) rotate(-10deg);
  }
  55% {
    opacity: 1;
    transform: scale(0.94) rotate(6deg);
  }
  80% {
    transform: scale(1.04);
  }
}
@keyframes bs-sway {
  25% {
    transform: rotate(7deg);
  }
  50% {
    transform: rotate(-6deg);
  }
  75% {
    transform: rotate(3deg);
  }
}
@keyframes bs-halo {
  0% {
    opacity: 0;
    transform: scale(0.8);
  }
  40% {
    opacity: 0.8;
  }
  100% {
    opacity: 0;
    transform: scale(1.3);
  }
}
@keyframes bs-pulse {
  50% {
    transform: scale(1.08);
  }
}
@keyframes bs-heartbeat {
  14%,
  42% {
    transform: scale(1.12);
  }
  28%,
  70% {
    transform: none;
  }
}
@keyframes bs-beat {
  15%,
  45% {
    transform: scale(1.1);
  }
  30%,
  75% {
    transform: none;
  }
}
@keyframes bs-ring {
  10% {
    transform: rotate(14deg);
  }
  25% {
    transform: rotate(-12deg);
  }
  40% {
    transform: rotate(8deg);
  }
  55% {
    transform: rotate(-5deg);
  }
  70% {
    transform: rotate(2deg);
  }
  85% {
    transform: none;
  }
}
@keyframes bs-shine {
  from {
    opacity: 1;
    transform: translateX(-100%);
  }
  to {
    opacity: 1;
    transform: translateX(100%);
  }
}
@keyframes bs-press {
  30% {
    transform: scale(0.84);
  }
  65% {
    transform: scale(1.06);
  }
}
@keyframes bs-burst {
  from {
    opacity: 0.7;
    transform: scale(0.6);
  }
  to {
    opacity: 0;
    transform: scale(1.6);
  }
}
@keyframes bs-ripple {
  from {
    opacity: 0.25;
    transform: scale(0);
  }
  to {
    opacity: 0;
    transform: scale(1.5);
  }
}
@keyframes bs-flip {
  50% {
    transform: perspective(400px) rotateY(180deg);
  }
  to {
    transform: perspective(400px);
  }
}
@keyframes bs-jelly {
  25% {
    transform: scale(1.22, 0.8);
  }
  40% {
    transform: scale(0.82, 1.18);
  }
  55% {
    transform: scale(1.1, 0.9);
  }
  70% {
    transform: scale(0.96, 1.04);
  }
  85% {
    transform: scale(1.02, 0.98);
  }
}
@keyframes bs-confetti {
  from {
    opacity: 1;
    transform: scale(0.2);
  }
  70% {
    opacity: 1;
  }
  to {
    opacity: 0;
    transform: scale(1.25);
  }
}
@keyframes bs-tick {
  0% {
    opacity: 0;
    transform: scale(0.4);
  }
  25% {
    opacity: 1;
    transform: scale(1.12);
  }
  40%,
  75% {
    opacity: 1;
    transform: none;
  }
  100% {
    opacity: 0;
  }
}
@keyframes bs-dim {
  20%,
  75% {
    opacity: 0.12;
  }
}
