/*
 * Сплэш загрузки PlanSchedule: анимация «Сборка» фирменного знака ВРесурсе.
 *
 * ЭТО ЕДИНСТВЕННЫЙ ИСТОЧНИК СТИЛЕЙ ЛОАДЕРА. Файл лежит в `sources/web` (корень статики), потому что его
 * подключают ОБА предзагрузочных HTML — `web/index.html` (до загрузки бандла) и `web/ie.html` — обычным
 * `<link rel="stylesheet">`. Ждать бандла (`dist/styles.css` грузится уже после `config/config.js`) они не
 * могут: смысл сплэша в том, чтобы он был на экране ДО приложения. React-версия (`LoadingSplash` в
 * `sources/src/App.tsx`) использует те же классы и получает те же стили как глобальный CSS документа — React
 * монтируется в тот же документ (`createRoot` заменяет содержимое `#root`), отдельного импорта в бандл не
 * нужно: он дал бы вторую копию этих правил в `dist/styles.css` при нулевой пользе.
 *
 * ГЕОМЕТРИЯ — из мастера `extsolutions/planschedule/styles/logo-vresurse-mark.svg` (viewBox 0 0 48 40,
 * штрих 2, скругления 3/3.5). Разметка знака дублируется в двух HTML и в JSX (инлайновый SVG обязателен:
 * анимируются отдельные фигуры, внешний `<img>`/`<use>` до них не достаёт) — расхождение ловит статический
 * тест `docs/tests/functional/loaderFavicon.test.ts`, он сверяет все три места и мастер.
 *
 * ПОЧЕМУ ТАК:
 *  - цвет — одна переменная `--loader-logo-color` (меняется одной строкой), `stroke`/`fill` наследуются
 *    фигурами от корня `svg`, поэтому в разметке нет презентационных атрибутов;
 *  - положение (центрирование `#loading`, размеры `.loader-mark`) и анимация масштаба живут на РАЗНЫХ узлах:
 *    `transform` есть только у фигур внутри `@keyframes`, ни у контейнера, ни у `svg` его нет — иначе
 *    `transform` контейнера и `transform: scale()` анимации дерутся за одно свойство и знак «уезжает»;
 *  - базовое (без анимации) состояние фигур — полный видимый знак; вступление рисуют кадры с
 *    `animation-fill-mode: both` (до старта действует кадр 0 % — фигура скрыта). Поэтому выключение анимации
 *    (`prefers-reduced-motion`) автоматически даёт целый статичный знак, а не пустое место;
 *  - `pathLength="100"` в разметке нормирует длину каждого пути: `stroke-dasharray/offset: 100 → 0` — это
 *    «нарисовать от начала до конца» независимо от реальной длины конкретного пути.
 *
 * Проверка: docs/tests/completed/loader-favicon-2026-10-26.md.
 */

/* Центрирование сплэша. Живёт здесь (а не в инлайн-стилях HTML), чтобы React-версия не зависела от
   хост-страницы: `#loading` — единственный узел положения, `transform` на нём нет. */
#loading {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  align-items: center;
  justify-content: center;
}

/* Знак. 96×80 = ровно 2,4×(48×40) — пропорция viewBox не искажается. */
.loader-mark {
  --loader-logo-color: #0047bb;
  --loader-logo-cycle: 2.6s;
  display: block;
  width: 96px;
  height: 80px;
  overflow: visible;
  fill: none;
  stroke: var(--loader-logo-color);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Штрих не толстеет/не худеет при масштабировании фигур (scale 0.6 → 1 в кадрах). ОСОЗНАННО: из-за
   `non-scaling-stroke` штрих — ровно 2 CSS px, а не 4 px, как дал бы мастер 48×40, отрисованный в 96×80.
   Так утверждено в превью варианта A (`tmp/loader-logo.html`): тонкий штрих не «толстеет» на вступлении,
   когда квадраты идут от scale 0.6; знак при этом читается легче. Нужен мастеровый вес — снять
   `vector-effect` (тогда штрих станет 4 px, но и анимировать масштаб придётся иначе). */
.loader-mark * {
  vector-effect: non-scaling-stroke;
}

/* Подпись для скринридера: сам знак — декоративная картинка (`aria-hidden` в разметке), состояние
   загрузки объявляет живой регион. Визуально скрыто стандартным приёмом (не `display:none` — иначе
   содержимое не попадёт в дерево доступности). */
.loader-mark__label {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Квадраты: проявляются со сдвигом 0,15 / 0,3 / 0,45 с (scale 0,6 → 1). */
.loader-mark__box {
  opacity: 1;
  transform-box: fill-box;
  transform-origin: center;
  animation: loader-logo-box var(--loader-logo-cycle) infinite ease-out both;
}

.loader-mark__box--top {
  animation-delay: 0.15s;
}

.loader-mark__box--left {
  animation-delay: 0.3s;
}

.loader-mark__box--right {
  animation-delay: 0.45s;
}

/* Провода: левый рисуется с 0,55 с, правый с 0,75 с; нижняя перемычка идёт пунктиром. */
.loader-mark__link {
  stroke-dasharray: 100;
  stroke-dashoffset: 0;
  animation: loader-logo-draw var(--loader-logo-cycle) infinite ease-in-out both;
}

.loader-mark__link--left {
  animation-delay: 0.55s;
}

.loader-mark__link--right {
  animation-delay: 0.75s;
}

.loader-mark__link--bottom {
  stroke-dasharray: 4 4;
  animation-name: loader-logo-dash;
  animation-timing-function: linear;
}

/* Круг — с 1,0 с; галочка прорисовывается с 1,35 с. К 78 % цикла всё стоит, затем плавно гаснет. */
.loader-mark__circle {
  opacity: 1;
  animation: loader-logo-fade var(--loader-logo-cycle) infinite ease-out both;
  animation-delay: 1s;
}

.loader-mark__check {
  stroke-dasharray: 100;
  stroke-dashoffset: 0;
  animation: loader-logo-check var(--loader-logo-cycle) infinite ease-out both;
  animation-delay: 1.35s;
}

@keyframes loader-logo-box {
  0% {
    opacity: 0;
    transform: scale(0.6);
  }

  14% {
    opacity: 1;
    transform: scale(1);
  }

  78% {
    opacity: 1;
    transform: scale(1);
  }

  100% {
    opacity: 0;
    transform: scale(0.6);
  }
}

@keyframes loader-logo-draw {
  0% {
    stroke-dashoffset: 100;
    opacity: 0;
  }

  10% {
    opacity: 1;
  }

  40% {
    stroke-dashoffset: 0;
    opacity: 1;
  }

  78% {
    stroke-dashoffset: 0;
    opacity: 1;
  }

  100% {
    stroke-dashoffset: 0;
    opacity: 0;
  }
}

@keyframes loader-logo-dash {
  0% {
    stroke-dashoffset: 0;
    opacity: 0;
  }

  20% {
    opacity: 1;
  }

  80% {
    opacity: 1;
  }

  100% {
    stroke-dashoffset: -16;
    opacity: 0;
  }
}

@keyframes loader-logo-fade {
  0%,
  100% {
    opacity: 0;
  }

  12% {
    opacity: 1;
  }

  78% {
    opacity: 1;
  }
}

@keyframes loader-logo-check {
  0% {
    stroke-dashoffset: 100;
    opacity: 0;
  }

  8% {
    opacity: 1;
  }

  26% {
    stroke-dashoffset: 0;
    opacity: 1;
  }

  78% {
    stroke-dashoffset: 0;
    opacity: 1;
  }

  100% {
    stroke-dashoffset: 0;
    opacity: 0;
  }
}

/* Системное «уменьшить движение»: анимации нет, знак показан целиком. Сброс свойств продублирован
   явно — не полагаемся на то, что базовые правила останутся «полными» после будущих правок. */
@media (prefers-reduced-motion: reduce) {
  .loader-mark * {
    animation: none !important;
    transition: none !important;
  }

  .loader-mark__box {
    opacity: 1;
    transform: none;
  }

  .loader-mark__link,
  .loader-mark__check {
    stroke-dashoffset: 0;
    opacity: 1;
  }

  /* В статичном знаке перемычка — сплошная: при `non-scaling-stroke` пунктир `4 4` считается в CSS-пикселях,
     а перемычка всего 8 px, поэтому в покое вместо «пунктира» получался разрыв посередине. Пунктир нужен
     только в анимации (там он «бежит»), в reduced-motion знак обязан быть целым. */
  .loader-mark__link--bottom {
    stroke-dasharray: none;
  }

  .loader-mark__circle {
    opacity: 1;
  }
}
