/* ── Dot-matrix loader · Lumen LoadingState ───────────────────────────────
   Vanilla-порт идеи sv-matrix (SikandarJODD/sv-matrix, MIT): сетка 5×5 точек,
   рисунок задаёт pattern, движение — CSS-keyframes с задержкой по «кольцу»
   (расстояние от центра). Никакого JS в анимации — только разметка.
   Разметка: <span class="dmx" data-pattern="diamond" data-anim="ripple" aria-label="Загружаем"></span>
   JS (dot-matrix.js) раскладывает 25 <i> с переменными --ring/--row/--col.
   Размер: --dmx-size (сторона матрицы), --dmx-dot (диаметр точки), цвет — currentColor. */
.dmx{
  --dmx-size:22px; --dmx-dot:3px; --dmx-cycle:1400ms;
  --dmx-base:.14; --dmx-mid:.34; --dmx-peak:1;
  display:inline-grid; grid-template-columns:repeat(5,1fr); grid-template-rows:repeat(5,1fr);
  width:var(--dmx-size); height:var(--dmx-size); vertical-align:middle; color:currentColor;
  place-items:center; flex:none;
}
.dmx i{display:block;width:var(--dmx-dot);height:var(--dmx-dot);border-radius:999px;background:currentColor;
  opacity:calc(.5*(var(--dmx-base) + var(--dmx-mid)));will-change:opacity}
.dmx i.off{opacity:0;visibility:hidden;animation:none !important}

/* ripple — волна от центра наружу по кольцам */
.dmx[data-anim="ripple"] i{animation:dmx-ripple var(--dmx-cycle) cubic-bezier(.42,0,.58,1) infinite;
  animation-delay:calc(var(--ring,0) * .16 * var(--dmx-cycle))}
@keyframes dmx-ripple{0%,100%{opacity:var(--dmx-base)}35%{opacity:var(--dmx-peak)}70%{opacity:var(--dmx-mid)}}

/* wave — построчно сверху вниз */
.dmx[data-anim="wave"] i{animation:dmx-ripple var(--dmx-cycle) ease-in-out infinite;
  animation-delay:calc(var(--row,0) * .12 * var(--dmx-cycle))}

/* sweep — слева направо по колонкам */
.dmx[data-anim="sweep"] i{animation:dmx-ripple var(--dmx-cycle) ease-in-out infinite;
  animation-delay:calc(var(--col,0) * .12 * var(--dmx-cycle))}

/* pulse — все вместе, для «ждём данных» в KPI */
.dmx[data-anim="pulse"] i{animation:dmx-pulse var(--dmx-cycle) ease-in-out infinite}
@keyframes dmx-pulse{0%,100%{opacity:var(--dmx-base)}50%{opacity:var(--dmx-peak)}}

/* spin — бег по углу (полярный угол → задержка) */
.dmx[data-anim="spin"] i{animation:dmx-ripple var(--dmx-cycle) linear infinite;
  animation-delay:calc(var(--ang,0) * var(--dmx-cycle))}

/* static — без движения (пустое состояние, иконка «нет данных») */
.dmx[data-anim="static"] i{opacity:var(--dmx-mid)}

/* размеры */
.dmx.lg{--dmx-size:34px;--dmx-dot:5px}
.dmx.xl{--dmx-size:56px;--dmx-dot:8px}
.dmx.muted{color:var(--tx3,#92928C)}

/* состояния-обёртки: загрузка / пусто (Lumen: LoadingState, EmptyState) */
.dmx-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;
  padding:36px 20px;color:var(--tx3,#92928C);font-size:13px;text-align:center}
.dmx-state b{color:var(--tx2,#666661);font-weight:500}
.dmx-state.inline{flex-direction:row;padding:14px 0;gap:9px;justify-content:flex-start}

@media (prefers-reduced-motion:reduce){
  .dmx i{animation:none !important;opacity:var(--dmx-mid)}
}
