/* ==========================================================================
   Заставка. Живёт отдельным файлом: подключается рано, чтобы первый кадр
   был уже с ней, и никак не связана с остальной раскладкой.

   Три правила, на которых всё держится:
   1. Без JavaScript заставки нет — атрибут data-js ставит скрипт в <head>.
   2. Она снимает себя сама, анимацией: если модуль не догрузится, сайт
      всё равно откроется. Скрипт только убирает узел и даёт пропустить.
   3. В спокойном режиме её нет: это чистое украшение.

   Хореография на пять секунд, фазы намеренно перекрываются:

     0.00–3.20  сетка и пятна света проявляются
     0.15–1.20  три плиты слетаются в стопку
     0.55–1.65  ударная волна от каждой плиты при посадке
     0.75–1.95  веер искр
     1.00–1.90  блик по знаку
     1.15–2.45  буквы разворачиваются
     2.05–3.20  свет бежит по слову
     2.30–3.20  проявляется отражение
     2.50–3.70  знак делает полный оборот
     0.40–4.00  заливается полоса загрузки
     2.70–3.60  подпись спонсора
     3.50–4.50  сканирующая полоса сверху вниз
     4.40–5.00  уход
   ========================================================================== */

.splash { display: none; }

[data-js] .splash {
  position: fixed;
  inset: 0;
  z-index: 999;
  display: grid;
  place-items: center;
  overflow: hidden;
  /* Заставка всегда тёмная: это заставка, а не страница. */
  background: #07060f;
  color: #f2f0ff;
  /* Снимает себя сама — скрипт тут не обязателен. */
  animation: splash-out .6s var(--ease) 4.4s forwards;
}

[data-motion="calm"] .splash,
[data-intro="done"] .splash { display: none !important; }

/* Пропуск по клику или клавише. Имя анимации другое не для красоты:
   с тем же именем браузер не начинает анимацию заново, а продолжает уже
   идущую — вместе с её многосекундной задержкой, и пропуск не работает. */
[data-js] .splash.is-gone { animation: splash-skip .28s var(--ease) forwards; }

@keyframes splash-out {
  to { opacity: 0; transform: scale(1.06); visibility: hidden; pointer-events: none; }
}

@keyframes splash-skip {
  to { opacity: 0; transform: scale(1.04); visibility: hidden; pointer-events: none; }
}

/* --- Фон: сетка, два пятна света и сканирующая полоса ------------------------ */

.splash__grid,
.splash__aurora,
.splash__scan {
  position: absolute;
  pointer-events: none;
}

.splash__grid {
  inset: 0;
  background:
    repeating-linear-gradient(90deg, rgb(255 255 255 / .05) 0 1px, transparent 1px 64px),
    repeating-linear-gradient(0deg,  rgb(255 255 255 / .05) 0 1px, transparent 1px 64px);
  /* Сетка гаснет к краям — иначе она спорит с текстом. */
  mask-image: radial-gradient(75% 65% at 50% 46%, #000 20%, transparent 100%);
  animation: splash-grid 3.2s var(--ease) both;
}

@keyframes splash-grid {
  from { opacity: 0; transform: scale(1.18); }
  to   { opacity: 1; transform: none; }
}

.splash__aurora {
  width: min(46rem, 90vw);
  aspect-ratio: 1;
  border-radius: 50%;
  filter: blur(70px);
  opacity: 0;
  animation: splash-aurora 3.4s var(--ease) both;
}
.splash__aurora--1 {
  background: radial-gradient(circle, hsl(258 92% 62% / .55), transparent 70%);
  inset-block-start: -18%;
  inset-inline-start: -12%;
}
.splash__aurora--2 {
  background: radial-gradient(circle, hsl(var(--css-hue) 92% 60% / .38), transparent 70%);
  inset-block-end: -22%;
  inset-inline-end: -14%;
  animation-delay: .15s;
}

@keyframes splash-aurora {
  0%   { opacity: 0; transform: scale(.7); }
  55%  { opacity: 1; }
  100% { opacity: .85; transform: scale(1); }
}

/* Полоса света, проходящая по всему экрану перед уходом. */
.splash__scan {
  inset-inline: 0;
  inset-block-start: 0;
  height: 26vh;
  background: linear-gradient(to bottom, transparent, rgb(186 148 255 / .11), transparent);
  opacity: 0;
  animation: splash-scan 1s linear 3.5s both;
}

@keyframes splash-scan {
  0%        { opacity: 0; transform: translateY(-40vh); }
  18%, 82%  { opacity: 1; }
  100%      { opacity: 0; transform: translateY(120vh); }
}

.splash__inner {
  position: relative;
  display: grid;
  justify-items: center;
  gap: 1.55rem;
  padding-inline: 1.25rem;
  text-align: center;
  /* Медленное дыхание: пять секунд статики читаются как зависший экран. */
  animation: splash-float 5s ease-in-out both;
}

@keyframes splash-float {
  0%, 100% { transform: translateY(0); }
  55%      { transform: translateY(-7px); }
}

/* --- Знак: три плиты собираются в стопку ------------------------------------- */

/* Сцена держит перспективу, знак внутри неё вращается. Разделено нарочно:
   перспектива на вращающемся элементе относилась бы к его детям, а сам он
   поворачивался бы плоско, без объёма. */
.splash__stage {
  position: relative;
  display: block;
  width: 124px;
  aspect-ratio: 1;
  perspective: 700px;
}

.splash__mark {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  animation: splash-spin 1.2s cubic-bezier(.65, 0, .35, 1) 2.5s both;
}

@keyframes splash-spin {
  from { transform: rotateY(0deg); }
  to   { transform: rotateY(360deg); }
}

.splash__slab {
  position: absolute;
  inset: 16px;
  border-radius: 16px;
  border: 2px solid currentColor;
  animation: splash-slab 1s var(--ease) both;
}
.splash__slab--html {
  color: hsl(var(--html-hue) 92% 62%);
  --x: -14px; --y: -14px;
  box-shadow: 0 0 34px hsl(var(--html-hue) 92% 62% / .35);
}
.splash__slab--css {
  color: hsl(var(--css-hue) 92% 66%);
  --x: 0px; --y: 0px;
  animation-delay: .1s;
  box-shadow: 0 0 34px hsl(var(--css-hue) 92% 66% / .3);
}
.splash__slab--page {
  color: var(--accent-2);
  --x: 14px; --y: 14px;
  background: rgb(176 108 255 / .16);
  animation-delay: .2s;
  box-shadow: 0 0 44px rgb(176 108 255 / .4);
}

/* В переменных лежит конечная позиция, стартовая считается прямо в кадре:
   так одна анимация обслуживает все три плиты, и разлёт получается сам. */
@keyframes splash-slab {
  from {
    opacity: 0;
    transform: translate3d(calc(var(--x) * 7), calc(var(--y) * 7 - 40px), 0)
               rotateX(38deg) rotateZ(-38deg) scale(.4);
  }
  to {
    opacity: 1;
    transform: translate3d(var(--x), var(--y), 0) rotateX(38deg) rotateZ(-38deg);
  }
}

/* Блик, пробегающий по собранному знаку. Обязательно в своей коробке
   с overflow: hidden — иначе полоса вылезает за знак и на тёмном фоне
   читается не как блик, а как серый прямоугольник. Обрезку нельзя вешать
   на сам знак: overflow ломает preserve-3d, и оборот станет плоским. */
.splash__glossbox {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 22px;
  pointer-events: none;
}

.splash__gloss {
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 42%, rgb(255 255 255 / .55) 50%, transparent 58%);
  mix-blend-mode: screen;
  opacity: 0;
  animation: splash-gloss .9s var(--ease) 1s both;
}

@keyframes splash-gloss {
  0%   { opacity: 0; transform: translateX(-120%); }
  35%  { opacity: 1; }
  100% { opacity: 0; transform: translateX(120%); }
}

/* --- Ударная волна от каждой плиты при посадке -------------------------------- */

.splash__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid currentColor;
  opacity: 0;
  pointer-events: none;
  animation: splash-ring 1.1s var(--ease) var(--d) both;
}
.splash__ring--html { color: hsl(var(--html-hue) 92% 62%); }
.splash__ring--css  { color: hsl(var(--css-hue) 92% 66%); }
.splash__ring--page { color: var(--accent-2); }

@keyframes splash-ring {
  0%   { opacity: 0;  transform: scale(.28); }
  12%  { opacity: .7; }
  100% { opacity: 0;  transform: scale(3.4); border-width: .5px; }
}

/* --- Веер искр ---------------------------------------------------------------- */

/* Угол берётся из номера: 24 искры по 15° закрывают полный круг, и вся
   раскладка получается одной формулой, без единой случайной величины. */
.splash__bit {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  width: 2px;
  height: 13px;
  margin: -6px 0 0 -1px;
  border-radius: 2px;
  background: linear-gradient(hsl(calc(190 + var(--i) * 7) 92% 70%), transparent);
  opacity: 0;
  pointer-events: none;
  animation: splash-bit .95s var(--ease) calc(.75s + var(--i) * .008s) both;
}

@keyframes splash-bit {
  0%   { opacity: 0; transform: rotate(calc(var(--i) * 15deg)) translateY(-16px) scaleY(.4); }
  22%  { opacity: 1; }
  100% { opacity: 0; transform: rotate(calc(var(--i) * 15deg)) translateY(-118px) scaleY(1.7); }
}

/* --- Слово: буквы поднимаются и разворачиваются ------------------------------ */

.splash__word {
  position: relative;
  display: flex;
  margin: 0;
  font-family: var(--font-head);
  font-weight: 800;
  font-size: clamp(2.5rem, 10.5vw, 5.25rem);
  line-height: 1.05;
  letter-spacing: -.035em;
  /* Перспектива на строке: буквы поворачиваются в общем объёме, а не
     каждая в своей коробке — крайние наклонены иначе, чем средние. */
  perspective: 900px;
}

.splash__ch,
.splash__mch {
  display: inline-block;
  background: linear-gradient(120deg, #ffffff 12%, var(--accent-2) 52%, hsl(var(--css-hue) 92% 70%) 88%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.splash__ch {
  /* Ось поворота по нижней кромке: буква встаёт от базовой линии,
     а не вертится вокруг своего центра. */
  transform-origin: 50% 100%;
  animation:
    splash-letter .7s var(--ease) calc(1.15s + var(--i) * .055s) both,
    splash-flash .6s var(--ease) calc(2.05s + var(--i) * .05s) both;
}

@keyframes splash-letter {
  from { opacity: 0; transform: translateY(.55em) rotateX(-82deg); }
  to   { opacity: 1; transform: none; }
}

/* Свет, бегущий по слову. Отдельным полупрозрачным слоем это делать нельзя:
   на почти чёрном фоне любой режим наложения даёт видимый прямоугольник
   с краями. Поэтому подсвечиваем сами буквы — по очереди, с задержкой. */
@keyframes splash-flash {
  0%, 100% { filter: none; }
  45%      { filter: brightness(1.9) drop-shadow(0 0 18px rgb(176 108 255 / .75)); }
}

/* --- Отражение ---------------------------------------------------------------- */

/* Копия слова теми же буквами: если набрать её одной строкой, ширина
   разойдётся с суммой отдельных букв, и отражение поедет вбок. */
.splash__mirror {
  position: absolute;
  inset-block-start: 100%;
  inset-inline: 0;
  display: flex;
  justify-content: center;
  /* Сжатое по высоте отражение: полноразмерное лезло на полосу загрузки
     и на подпись, а зеркальные буквы поверх текста читаются как мусор. */
  transform-origin: 50% 0;
  transform: scaleY(-.55);
  /* Маска задана в координатах элемента, до переворота: непрозрачный край —
     тот, что после отражения окажется вплотную к слову. */
  mask-image: linear-gradient(to bottom, transparent 22%, #000 100%);
  opacity: 0;
  filter: blur(1.2px);
  pointer-events: none;
  animation: splash-mirror .9s var(--ease) 2.3s both;
}

@keyframes splash-mirror {
  from { opacity: 0; }
  to   { opacity: .22; }
}

/* --- Полоса загрузки --------------------------------------------------------- */

.splash__line {
  position: relative;
  display: block;
  width: min(21rem, 62vw);
  height: 2px;
  border-radius: 999px;
  background: rgb(255 255 255 / .12);
  overflow: hidden;
}
.splash__line i {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  display: block;
  width: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, hsl(var(--css-hue) 92% 62%), var(--accent-2), hsl(var(--html-hue) 92% 62%));
  box-shadow: 0 0 14px rgb(176 108 255 / .8);
  animation: splash-line 3.6s var(--ease) .4s both;
}

@keyframes splash-line {
  from { width: 0; }
  to   { width: 100%; }
}

/* --- Подпись спонсора -------------------------------------------------------- */

.splash__by {
  margin: 0;
  /* Шрифт задаём явно: заставка не должна зависеть от стилей body. */
  font-family: var(--font-text);
  font-size: clamp(.72rem, 2.4vw, .84rem);
  text-transform: uppercase;
  color: rgb(242 240 255 / .58);
  animation: splash-by .9s var(--ease) 2.7s both;
}

@keyframes splash-by {
  from { opacity: 0; letter-spacing: .5em; transform: translateY(8px); }
  to   { opacity: 1; letter-spacing: .16em; transform: none; }
}

.splash__brand {
  font-weight: 800;
  letter-spacing: inherit;
  background: linear-gradient(100deg, #fff, var(--accent-2));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* Свечение под текстом с прозрачной заливкой рисуем тенью на слое ниже. */
  filter: drop-shadow(0 0 12px rgb(176 108 255 / .55));
}

/* На узких экранах знак меньше, иначе он съедает половину высоты. */
@media (max-width: 480px) {
  .splash__stage { width: 92px; }
  .splash__inner { gap: 1.2rem; }
}
