/* ─── Stepper ──────────────────────────────────────────────────────────────────
   Values:    site/tokens.css (--ds-stepper-* tokens)
   Primary consumers: site/preview/stepper.html + src/components/Stepper/Stepper.tsx
   States:    data-attributes only
   Source:    Figma isVYOT7tW0RTaIofg7FAqM, страница 2693:2027 «↳ Stepper»
              (.Parts/Point 2824:27780 · .Step/Horizontal 2832:27947 ·
               .Step/Vertical 2832:29335 · сборки 2832:31303 / 2832:31697)

   Тёмной темы здесь НЕТ намеренно — тот же законный путь, что у badge.css: все цвета
   взяты токенами, а --ds-* сами переключаются во всех 4 темах. Ни одного литерала цвета,
   поэтому и переопределять нечего. Если когда-нибудь понадобится тёмная форма — она
   обязана быть ДВОЙНОЙ ([data-theme=dark] + @media prefers-color-scheme), одиночная
   дефектна в обе стороны (never-do.md).

   Ось semantic названа neutral | warning | negative — по словарю Badge/Tag/Alert/
   Notification/ProgressBar. С 2026-09-09 так же и в макете: ось Status переименована в
   Semantic, значение Error — в Negative (решение владельца после переписи по всем 41
   странице: у оси Semantic 14 наборов из 14 несут Neutral и Negative, у оси Validation
   27 из 27 несут None и Error — это разные семейства, Stepper во втором быть не должен).
   ─────────────────────────────────────────────────────────────────────────── */

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

.ds-stepper {
  display:      flex;
  gap:          var(--ds-stepper-md-step-gap);
  align-items:  stretch;
  font-family:  inherit;
  margin:       0;
  padding:      0;
  list-style:   none;
  /* Базовый цвет задаётся здесь намеренно. Лейбл, описание и индикатор красятся сами,
     а вот слот несёт произвольный контент потребителя — без этой строки он наследовал бы
     цвет от браузера, то есть от СИСТЕМНОЙ темы, а не от нашей. Замер 2026-09-09 показал
     ровно это: в light-invert текст слота выходил чёрным на тёмном фоне, в dark-invert —
     белым на светлом. Видно только замером computed-цвета в 4 темах, глазами в Light и
     Dark всё выглядит правильно. */
  color:        var(--ds-text-primary);
}

/* Шаг — элемент списка: семантику несёт <ol>/<li>, а раскладку и состояния —
   вложенный .ds-stepper-step (button или div, смотря кликаем ли шаг). */
.ds-stepper-item {
  display:   flex;
  flex:      1 1 0;
  min-width: 0;
}

.ds-stepper[data-orientation='vertical'] .ds-stepper-item {
  flex: 0 0 auto;
}

.ds-stepper[data-size='sm'] {
  gap: var(--ds-stepper-sm-step-gap);
}

.ds-stepper[data-orientation='vertical'] {
  flex-direction: column;
}

/* ── Step ──────────────────────────────────────────────────────────────────── */

.ds-stepper-step {
  display:        flex;
  flex-direction: column;
  flex:           1 1 0;
  min-width:      0;
  position:       relative;
  padding:        0;
  border:         0;
  background:     none;
  text-align:     left;
  font:           inherit;
  color:          inherit;
}

/* Кликабельным шаг делает разметка (button), а не CSS. Некликабельный вариант —
   бывший тип «Simple» — приезжает как <div> и курсора не меняет. */
.ds-stepper-step[data-interactive] {
  cursor: pointer;
}

.ds-stepper-step[data-disabled] {
  cursor: not-allowed;
}

.ds-stepper[data-orientation='vertical'] .ds-stepper-step {
  flex-direction: row;
  align-items:    stretch;
  gap:            var(--ds-stepper-md-gap);
  flex:           0 0 auto;
}

.ds-stepper[data-orientation='vertical'][data-size='sm'] .ds-stepper-step {
  gap: var(--ds-stepper-sm-gap);
}

/* ── Row (Figma «Group»): индикатор + то, что стоит с ним в одну строку ─────── */

.ds-stepper-row {
  display:     flex;
  align-items: center;
  gap:         var(--ds-stepper-md-gap);
  min-width:   0;
}

/* Top: лейбл с описанием стоит справа от индикатора и может быть многострочным,
   поэтому выравнивание по верху, а не по центру (Figma: у сборки counterAxisAlignItems
   = MIN, тогда как у Inline и Bottom — CENTER). */
.ds-stepper-step[data-label-place='top'] > .ds-stepper-row {
  align-items: flex-start;
}

.ds-stepper[data-size='sm'] .ds-stepper-row {
  gap: var(--ds-stepper-sm-gap);
}

/* В вертикали «Group» — это колонка «точка + линия под ней», линия тянется на всю
   оставшуюся высоту шага (в Figma Line_Vertical имеет layoutSizingVertical FILL). */
.ds-stepper[data-orientation='vertical'] .ds-stepper-row {
  flex-direction: column;
  align-items:    center;
  flex:           0 0 auto;
  align-self:     stretch;
}

/* ── Point: индикатор шага ─────────────────────────────────────────────────── */

.ds-stepper-point {
  flex:            0 0 auto;
  display:         inline-flex;
  align-items:     center;
  justify-content: center;
  inline-size:     var(--ds-stepper-md-point);
  block-size:      var(--ds-stepper-md-point);
  border-radius:   var(--ds-stepper-point-r);
  background:      var(--ds-surface-neutral-medium);
  color:           var(--ds-text-primary);
  font-size:       var(--ds-stepper-md-fs);
  line-height:     var(--ds-stepper-md-lh);
  font-weight:     500;
  font-variant-numeric: tabular-nums;
  transition:      background var(--ds-dur-1) var(--ds-ease),
                   color      var(--ds-dur-1) var(--ds-ease);
}

.ds-stepper[data-size='sm'] .ds-stepper-point {
  inline-size: var(--ds-stepper-sm-point);
  block-size:  var(--ds-stepper-sm-point);
  font-size:   var(--ds-stepper-sm-fs);
  line-height: var(--ds-stepper-sm-lh);
}

.ds-stepper-point svg {
  inline-size:  var(--ds-stepper-md-icon);
  block-size:   var(--ds-stepper-md-icon);
  stroke-width: var(--ds-stepper-md-stroke);
  stroke:       currentColor;
  fill:         none;
}

/* Точечный маркер (Point Type=Dot) — залитый глиф, не обводка */
.ds-stepper-step[data-point-type='dot'] .ds-stepper-point svg {
  fill:   currentColor;
  stroke: none;
}

.ds-stepper[data-size='sm'] .ds-stepper-point svg {
  inline-size:  var(--ds-stepper-sm-icon);
  block-size:   var(--ds-stepper-sm-icon);
  stroke-width: var(--ds-stepper-sm-stroke);
}

/* ── Line: соединитель между шагами ────────────────────────────────────────── */

.ds-stepper-line {
  flex:         1 1 auto;
  block-size:   var(--ds-stepper-line-stroke);
  min-inline-size: var(--ds-stepper-md-gap);
  background:   var(--ds-stroke-mid);
  border-radius: var(--ds-stepper-line-stroke);
}

.ds-stepper[data-orientation='vertical'] .ds-stepper-line {
  inline-size:     var(--ds-stepper-line-stroke);
  block-size:      auto;
  min-inline-size: 0;
  min-block-size:  var(--ds-stepper-md-gap);
}

/* ── Body: лейбл и описание ────────────────────────────────────────────────── */

.ds-stepper-body {
  display:        flex;
  flex-direction: column;
  min-width:      0;
}

/* Вертикаль: колонка «лейбл + описание + слот», занимает всю оставшуюся ширину */
.ds-stepper[data-orientation='vertical'] .ds-stepper-body {
  flex: 1 1 auto;
  gap:  var(--ds-stepper-md-gap);
}

.ds-stepper[data-orientation='vertical'][data-size='sm'] .ds-stepper-body {
  gap: var(--ds-stepper-sm-gap);
}

/* Текстовая пара «лейбл + описание» в вертикали: между ними зазора нет, зазор
   отделяет её от слота (Figma: Label Item VERTICAL gap 0, Core VERTICAL gap Step/Gap). */
.ds-stepper-text {
  display:        flex;
  flex-direction: column;
  min-width:      0;
}

.ds-stepper-label {
  font-size:   var(--ds-stepper-md-fs);
  line-height: var(--ds-stepper-md-lh);
  font-weight: 500;
  color:       var(--ds-text-tertiary);
  overflow-wrap: anywhere;
}

.ds-stepper[data-size='sm'] .ds-stepper-label {
  font-size:   var(--ds-stepper-sm-fs);
  line-height: var(--ds-stepper-sm-lh);
}

.ds-stepper-caption {
  font-size:   var(--ds-stepper-caption-fs);
  line-height: var(--ds-stepper-caption-lh);
  font-weight: 400;
  color:       var(--ds-text-tertiary);
  overflow-wrap: anywhere;
}

/* Inline: описание уходит под индикатор и выравнивается по левому краю лейбла —
   отступ равен ширине точки плюс зазор (Figma: paddingLeft 32 при точке 24 и gap 8). */
.ds-stepper-step[data-label-place='inline'] .ds-stepper-caption {
  padding-inline-start: calc(var(--ds-stepper-md-point) + var(--ds-stepper-md-gap));
}

.ds-stepper[data-size='sm'] .ds-stepper-step[data-label-place='inline'] .ds-stepper-caption {
  padding-inline-start: calc(var(--ds-stepper-sm-point) + var(--ds-stepper-sm-gap));
}

/* Top: линия стоит отдельной строкой под группой. В Figma это вектор нулевой высоты,
   поэтому в раскладку он не входит вовсе — здесь тот же эффект даёт absolute, иначе
   шаг стал бы на 2px выше макета. */
.ds-stepper-step[data-label-place='top'] {
  padding-block-end: var(--ds-stepper-md-gap);
}

.ds-stepper[data-size='sm'] .ds-stepper-step[data-label-place='top'] {
  padding-block-end: var(--ds-stepper-sm-gap);
}

.ds-stepper-step[data-label-place='top'] > .ds-stepper-line {
  position:    absolute;
  inset-block-end: 0;
  inset-inline: 0;
  flex:        none;
}

/* ── Slot: произвольный контент, только в вертикали ────────────────────────── */

.ds-stepper-slot {
  min-width: 0;
}

/* ── Состояния ─────────────────────────────────────────────────────────────────
   Красятся ТОЛЬКО индикатор и линия. Лейбл и описание семантику не индицируют —
   тот же инвариант, что у Radio/Checkbox/Switch (never-do.md: лейбл валидацией
   не красится никогда). Проверено замером по всем 24 вариантам макета.
   ─────────────────────────────────────────────────────────────────────────── */

/* Hover — меняются лейбл И линия; точка — нет. Линия при наведении — Static/Border/
   Neutral-Blue/High: так в самих мастерах шага, .Step / Horizontal 2832:27947 и .Step /
   Vertical 2832:29335, где вариант State=Hover переопределяет обводку экземпляра линии
   (use_figma 2026-09-23: узел Line видимый и единственный, w 2; в Default — Medium).
   ИСТОРИЯ, чтобы не повторить: 2026-09-09 это правило сняли как выдуманное, пересчитав
   ручным обходом только мастера-ЧАСТИ — .Parts/Point (14), .Parts/Line_Horizontal и
   _Vertical (по 5), — у которых State=Hover действительно нет. Переопределения в мастерах
   шага в тот знаменатель не входили, и вывод «линии при наведении нет» был сделан по
   заместителю. Вернула правило сверка якорей (16 клеток RAMP: код Medium против High). */
.ds-stepper-step[data-state='hover'] .ds-stepper-label {
  color: var(--ds-text-primary);
}
.ds-stepper-step[data-state='hover'] .ds-stepper-line {
  background: var(--ds-stroke-high);
}

/* Active */
.ds-stepper-step[data-state='active'] .ds-stepper-point {
  /* Роль, а не значение. Здесь стоял --ds-sb-high — токен ряда Static Border, красивший
     заливку. Значения у него и у --ds-neutral-fill совпадают во всех четырёх темах
     (#222629 · #FFFFFF · #FFFFFF · #1C2023), поэтому подмена была невидима глазом и
     прошла все замеры цвета. Макет биндит сюда Static/Surface/Neutral-Blue/Accent
     (.Parts / Point 2824:27780, Point Type=Number|Dot, State=Active) — это заливка;
     --ds-neutral-fill объявлен именно под неё (tokens.css:699, ср. --ds-spinner-fill).
     Совпадение значений — не тождество ролей: разойдись ряды Border и Surface в
     следующей правке палитры, бордерный токен утащил бы за собой заливку индикатора.
     Заменено 2026-09-09 по решению владельца «возьми токен из цвета заливки». */
  background: var(--ds-neutral-fill);
  color:      var(--ds-text-invert);
}

.ds-stepper-step[data-state='active'] .ds-stepper-line {
  background: var(--ds-stroke-high);
}

.ds-stepper-step[data-state='active'] .ds-stepper-label {
  color: var(--ds-text-neutral-ghost);
}

.ds-stepper-step[data-state='active'] .ds-stepper-caption {
  color: var(--ds-text-secondary);
}

/* Semantic: negative — приглушённый фон в покое, акцентный в active */
.ds-stepper-step[data-semantic='negative'] .ds-stepper-point {
  background: var(--ds-surface-nb-medium);
  color:      var(--ds-surface-neg-text);
}

.ds-stepper-step[data-semantic='negative'] .ds-stepper-line {
  background: var(--ds-stroke-neg-mid);
}

.ds-stepper-step[data-semantic='negative'][data-state='active'] .ds-stepper-point {
  background: var(--ds-surface-neg-accent);
  color:      var(--ds-icon-invert);
}

/* Semantic: warning */
.ds-stepper-step[data-semantic='warning'] .ds-stepper-point {
  background: var(--ds-surface-nb-medium);
  color:      var(--ds-warn-soft-text);
}

.ds-stepper-step[data-semantic='warning'] .ds-stepper-line {
  background: var(--ds-stroke-warn-high);
}

.ds-stepper-step[data-semantic='warning'][data-state='active'] .ds-stepper-point {
  background: var(--ds-surface-warn-accent);
  color:      var(--ds-icon-invert);
}

/* Disabled — перекрывает и состояние, и семантику: недоступный шаг не индицирует
   ни наведение, ни ошибку. Правило то же, что у полей: error и disabled не сочетаются. */
.ds-stepper-step[data-disabled] .ds-stepper-point {
  background: var(--ds-disabled-fill);
  color:      var(--ds-disabled-text);   /* цифра — Text/Disable/Neutral (Blue) */
}

/* Иконка статусной точки и глиф Dot — роль иконки, не текста: в макете (.Parts / Point
   2824:27780) у Disabled=On цифра привязана к Text/Disable, а Vector — к Icon/Disable. В
   светлых темах это разные цвета (#8f969b и #aeb5bd), в тёмных совпадают. До 2026-09-23 одно
   правило красило обе роли цветом иконки (строка STEPPER-DISABLED-NUMBER-USES-ICON-COLOR). */
.ds-stepper-step[data-disabled] .ds-stepper-point svg {
  color: var(--ds-disabled-icon);
}

.ds-stepper-step[data-disabled] .ds-stepper-line {
  background: var(--ds-nba-border-disabled);
}

.ds-stepper-step[data-disabled] .ds-stepper-label,
.ds-stepper-step[data-disabled] .ds-stepper-caption {
  color: var(--ds-disabled-text);
}

/* ── Focus ─────────────────────────────────────────────────────────────────────
   Состояния фокуса в макете НЕТ (у .Step только Default/Hover/Active), но
   клавиатурная навигация требуется документацией компонента — берём системное
   кольцо ДС, а не рисуем своё.
   ─────────────────────────────────────────────────────────────────────────── */

.ds-stepper-step[data-focus-visible],
.ds-stepper-step:focus-visible {
  outline:        none;
  box-shadow:     var(--ds-focus-ring);
  border-radius:  var(--ds-radius-sm);
}

/* ── Stepper / Progress ────────────────────────────────────────────────────────
   Отдельный мастер макета (Stepper/Progress 2824:26920, два варианта по оси
   «Height big»), а НЕ размер шагового степпера: у него нет ни шагов, ни точек,
   ни линий — заголовок, полоса и подпись следующего шага.

   Полоса здесь не своя: это компонент ProgressBar (size=md, validation=none).
   Значения сверены с макетом по всем 4 темам — трек Fill/Neutral-Blue/Soft/Default
   совпал с --ds-progress-track 4/4, заливка Static/Surface/Neutral-Blue/Accent —
   с --ds-progress-fill-none 4/4. Своя полоса завела бы invert-десинк заново
   (never-do.md: композит переиспользует детей, а не копирует их стилями).

   Типографика лейбла от размера степпера НЕ зависит: мастер сам пришпиливает
   ❖ Dropdown menus = SM, поэтому лейбл всегда 14/20 — отсюда --ds-stepper-sm-*
   при любом data-size. Это не совпадение значений, а та же переменная макета
   (↔ Control/Label/L2/Size), поэтому переиспользование токена законно.
   ─────────────────────────────────────────────────────────────────────────── */

.ds-stepper-progress {
  display:        flex;
  flex-direction: column;
  gap:            calc(var(--ds-comp-unit) * 2);   /* 8 — Figma root itemSpacing */
  /* Тот же довод, что у .ds-stepper: цвет задаётся явно, иначе потомки унаследуют
     его от браузера, то есть от СИСТЕМНОЙ темы, и разъедутся в обоих invert. */
  color:          var(--ds-text-primary);
}

/* Height big=On — заголовок и счётчик столбиком, зазора между ними нет
   (Figma: .Parts/Label Item VERTICAL, itemSpacing 0 → 20 + 16 = 36). */
.ds-stepper-progress-head {
  display:        flex;
  flex-direction: column;
  min-width:      0;
}

/* Height big=Off — заголовок и счётчик в одну строку: заголовок тянется, счётчик
   по содержимому, оба прижаты к нижнему краю (Figma: Frame 17 HORIZONTAL,
   itemSpacing 8, counterAxisAlignItems MAX, Label Item FILL, Caption HUG → 20). */
.ds-stepper-progress[data-height-big='off'] .ds-stepper-progress-head {
  flex-direction: row;
  align-items:    flex-end;
  gap:            calc(var(--ds-comp-unit) * 2);
}

.ds-stepper-progress-label {
  font-size:     var(--ds-stepper-sm-fs);
  line-height:   var(--ds-stepper-sm-lh);
  font-weight:   500;
  color:         var(--ds-text-neutral-ghost);
  flex:          1 1 auto;
  min-width:     0;
  overflow-wrap: anywhere;
}

.ds-stepper-progress-counter {
  font-size:     var(--ds-stepper-caption-fs);
  line-height:   var(--ds-stepper-caption-lh);
  font-weight:   400;
  color:         var(--ds-text-secondary);
  flex:          0 0 auto;
}

.ds-stepper-progress-next {
  font-size:     var(--ds-stepper-caption-fs);
  line-height:   var(--ds-stepper-caption-lh);
  font-weight:   400;
  color:         var(--ds-text-tertiary);
  overflow-wrap: anywhere;
}

/* ── Motion ────────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .ds-stepper-point {
    transition: none;
  }
}
