/* ─── Spinner ─────────────────────────────────────────────────────────────────
   Values: site/tokens.css
   Consumers: site/preview/spinner.html + src/components/Spinner/Spinner.tsx
   States: data-size only (sm / md / lg)
   ─────────────────────────────────────────────────────────────────────────── */

/* ── Root ────────────────────────────────────────────────────────────────────── */

.ds-spinner {
  display:         inline-flex;
  align-items:     center;
  justify-content: center;
  animation:       ds-spinner-appear 0ms var(--ds-spinner-delay, 800ms) both;
  flex-shrink:     0;

  /* Цвет кольца — через внутренние проперти, чтобы data-tone переключал его В ОДНОМ
     месте (включая reduced-motion ниже, который иначе прибит к нейтральному токену). */
  --_sp-track: var(--ds-spinner-track);
  --_sp-head:  var(--ds-spinner-fill);
}

/* tone=inherit — кольцо от currentColor: спиннер обязан совпасть с цветом лейбла носителя.
   Единственный потребитель — Button при loading, где кнопка берёт disabled-токены
   (Button.tsx: isDisabled = disabled || loading), т.е. currentColor = --ds-disabled-text
   во ВСЕХ intent, включая brand. inherit держит спиннер ВНУТРИ disabled-контракта:
   в режиме slot лейбл остаётся виден рядом (button.css скрывает его только при 'center'),
   и разъехавшийся по контрасту спиннер сломал бы однородный disabled-облик.

   ТРЕКА НЕТ намеренно — это измеренный предел, а не упущение.
   Бюджет loading-контекста = Lc(фон ↔ currentColor) = 43..56 (APCA, 4 темы × solid/ghost).
   Кольцу нужно track-vs-bg >= 31 И head-vs-track >= 61 (= эталон нейтрального спиннера
   на Figma-токенах --ds-stroke-low / --ds-neutral-fill, tokens.css:804-805) — итого >= 92.
   92 > 56 → кольцо недостижимо ни при какой альфе; любой трек садится ниже Lc 30
   (при 0.30 — Lc 12..17, т.е. не виден). Поэтому здесь дуга, а не кольцо.
   Не «чинить» подъёмом альфы: это лишь отнимает контраст у дуги (head-vs-track 30..41 → 26..36). */
.ds-spinner[data-tone='inherit'] {
  --_sp-track: transparent;
  --_sp-head:  currentColor;
}

/* ── Sizes ───────────────────────────────────────────────────────────────────── */

.ds-spinner[data-size='sm'] {
  width:  var(--ds-spinner-sm-size);
  height: var(--ds-spinner-sm-size);
}

.ds-spinner[data-size='md'] {
  width:  var(--ds-spinner-md-size);
  height: var(--ds-spinner-md-size);
}

.ds-spinner[data-size='lg'] {
  width:  var(--ds-spinner-lg-size);
  height: var(--ds-spinner-lg-size);
}

/* ── Ring ────────────────────────────────────────────────────────────────────── */

.ds-spinner-ring {
  display:          block;
  width:            100%;
  height:           100%;
  border-radius:    var(--ds-radius-pill);
  border-style:     solid;
  border-color:     var(--_sp-track);
  border-top-color: var(--_sp-head);
  animation:        ds-spinner-rotate var(--ds-spinner-duration, 0.7s) linear infinite;
  box-sizing:       border-box;
}

.ds-spinner[data-size='sm'] .ds-spinner-ring { border-width: var(--ds-spinner-sm-stroke); }
.ds-spinner[data-size='md'] .ds-spinner-ring { border-width: var(--ds-spinner-md-stroke); }
.ds-spinner[data-size='lg'] .ds-spinner-ring { border-width: var(--ds-spinner-lg-stroke); }

/* ── Keyframes ───────────────────────────────────────────────────────────────── */

@keyframes ds-spinner-rotate {
  to { transform: rotate(360deg); }
}

@keyframes ds-spinner-appear {
  from { opacity: 0; visibility: hidden; }
  to   { opacity: 1; visibility: visible; }
}

@media (prefers-reduced-motion: reduce) {
  .ds-spinner-ring {
    animation: none;
    border-top-color: var(--_sp-head);   /* через внутреннюю проперть → верно и при tone=inherit */
    opacity: 1;
  }
}
