/* ============================================================
   АТМОСФЕРА
   Всё, что лежит позади и поверх контента: фоновые слои,
   CRT-наложение, загрузчик, курсорный свет, стикеры.
   Ни один слой не ловит указатель — везде pointer-events: none.
   ============================================================ */

/* ------------------------------------------------------------
   1. ФОНОВЫЕ СЛОИ
   ------------------------------------------------------------ */
.bg {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

/* Дальнее свечение: холодный верхний левый угол + тёплый низ. */
.bg__glow {
  position: absolute;
  inset: -20%;
  background:
    radial-gradient(48% 38% at 8% 4%,
      color-mix(in srgb, var(--acid) 16%, transparent) 0%, transparent 70%),
    radial-gradient(46% 42% at 96% 22%,
      color-mix(in srgb, var(--violet) 20%, transparent) 0%, transparent 72%),
    radial-gradient(60% 46% at 52% 108%,
      color-mix(in srgb, var(--pink) 13%, transparent) 0%, transparent 74%);
  filter: blur(24px);
  animation: glow-breathe 16s ease-in-out infinite;
}
@keyframes glow-breathe {
  0%, 100% { opacity: .85; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.06); }
}

/* Техническая сетка — тонкие линии, как разметка макета. */
.bg__grid {
  position: absolute;
  inset: -10%;
  background:
    linear-gradient(rgba(255, 255, 255, .028) 1px, transparent 1px) 0 0 / 100% 88px,
    linear-gradient(90deg, rgba(255, 255, 255, .028) 1px, transparent 1px) 0 0 / 88px 100%;
  mask-image: radial-gradient(circle at 50% 40%, #000 20%, transparent 78%);
}

/* Пиксельный дизеринг по краям — приём из постеров автора. */
.bg__dither {
  position: absolute;
  inset: 0;
  background-image:
    repeating-conic-gradient(rgba(255,255,255,.05) 0% 25%, transparent 0% 50%);
  background-size: 8px 8px;
  opacity: .5;
  mask-image:
    linear-gradient(90deg, #000 0, transparent 22%, transparent 78%, #000 100%),
    linear-gradient(180deg, #000 0, transparent 26%, transparent 74%, #000 100%);
  -webkit-mask-composite: source-in;
          mask-composite: intersect;
}

/* Редкая «пыль» — точки, медленно всплывающие вверх. */
.bg__dust {
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(1.4px 1.4px at 12% 18%, rgba(255,255,255,.5), transparent),
    radial-gradient(1.2px 1.2px at 78% 32%, color-mix(in srgb, var(--cyan) 70%, transparent), transparent),
    radial-gradient(1.6px 1.6px at 42% 72%, rgba(255,255,255,.4), transparent),
    radial-gradient(1.2px 1.2px at 88% 84%, color-mix(in srgb, var(--pink) 70%, transparent), transparent),
    radial-gradient(1.3px 1.3px at 26% 92%, rgba(255,255,255,.35), transparent),
    radial-gradient(1.1px 1.1px at 62% 12%, color-mix(in srgb, var(--butter) 70%, transparent), transparent);
  background-size: 100% 100%;
  animation: dust 26s linear infinite;
}
@keyframes dust {
  from { transform: translateY(0); }
  to   { transform: translateY(-88px); }
}

/* Пробег строки развёртки — вертикальный ход яркой полосы. */
.bg__roll {
  position: absolute;
  left: 0; right: 0;
  height: 26vh;
  background: linear-gradient(180deg,
    transparent,
    rgba(255, 255, 255, .022) 42%,
    rgba(255, 255, 255, .04) 50%,
    rgba(255, 255, 255, .022) 58%,
    transparent);
  animation: roll 9s linear infinite;
}
@keyframes roll {
  from { transform: translateY(-30vh); }
  to   { transform: translateY(130vh); }
}

/* ------------------------------------------------------------
   2. CRT-НАЛОЖЕНИЕ
   Скан-линии, виньетка и лёгкая хроматическая кайма по краям.
   ------------------------------------------------------------ */
.crt {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  /* Полосы уже чёрные с альфой, поэтому mix-blend-mode: multiply здесь
     ничего не добавляет визуально, зато поднимает весь экран в отдельный
     композитный слой на каждом кадре. Обходимся обычной альфой. */
  background:
    repeating-linear-gradient(180deg,
      rgba(0, 0, 0, .17) 0 1px,
      transparent 1px 3px);
  opacity: .8;
}

.crt::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 100% at 50% 50%, transparent 58%, rgba(0, 0, 0, .55) 100%);
}

/* ------------------------------------------------------------
   3. КУРСОРНЫЙ СВЕТ
   Мягкое пятно, идущее за указателем. Только для точного ввода:
   на тач-экранах координаты не обновляются и пятно бы застряло.
   ------------------------------------------------------------ */
.spot {
  position: fixed;
  z-index: 1;
  left: 0; top: 0;
  width: 620px; height: 620px;
  margin: -310px 0 0 -310px;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(circle,
    color-mix(in srgb, var(--cyan) 12%, transparent) 0%,
    color-mix(in srgb, var(--violet) 8%, transparent) 38%,
    transparent 66%);
  transition: opacity 500ms ease;
  will-change: transform;
}
.spot.is-on { opacity: 1; }

@media (hover: none), (pointer: coarse) {
  .spot { display: none; }
}

/* ------------------------------------------------------------
   3b. СВОЙ КУРСОР
   Две метки: точка идёт ровно за указателем, кольцо догоняет.
   Родной курсор гасим только когда JS действительно поставил свой —
   иначе при сбое скрипта страница осталась бы вообще без курсора.
   ------------------------------------------------------------ */
html.has-cursor,
html.has-cursor * { cursor: none; }

.cur {
  position: fixed;
  left: 0; top: 0;
  z-index: 500;                 /* выше CRT, лайтбокса и загрузчика */
  pointer-events: none;
  opacity: 0;
  transition: opacity 220ms ease;
  will-change: transform;
}
.cur.is-live { opacity: 1; }

/* Указатель ушёл за пределы окна — метки не должны залипать у края. */
html.cur-out .cur { opacity: 0; }

.cur__dot {
  width: 6px; height: 6px;
  margin: -3px 0 0 -3px;
  border-radius: 50%;
  background: var(--acid);
  box-shadow: 0 0 10px -1px color-mix(in srgb, var(--acid) 80%, transparent);
}

.cur__ring {
  width: 34px; height: 34px;
  margin: -17px 0 0 -17px;
  border: 1px solid rgba(255, 255, 255, .38);
  border-radius: 50%;
  transition:
    opacity 220ms ease,
    width 260ms var(--e-back),
    height 260ms var(--e-back),
    margin 260ms var(--e-back),
    border-color 200ms ease;
}

/* Над интерактивным кольцо раскрывается и подсвечивается. */
.cur__ring.is-hot {
  width: 56px; height: 56px;
  margin: -28px 0 0 -28px;
  border-color: color-mix(in srgb, var(--cyan) 75%, transparent);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--violet) 30%, transparent),
    0 0 24px -6px color-mix(in srgb, var(--cyan) 70%, transparent);
}

/* Нажатие — кольцо поджимается. */
.cur__ring.is-down {
  width: 22px; height: 22px;
  margin: -11px 0 0 -11px;
  border-color: var(--acid);
}

/* ------------------------------------------------------------
   4. ЗАГРУЗЧИК — «раскрутка диска»
   ------------------------------------------------------------ */
.boot {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  place-items: center;
  padding: var(--gutter);
  background: var(--bg);
  transition: opacity 520ms var(--e-out), visibility 520ms;
}
.boot.is-done { opacity: 0; visibility: hidden; }

.boot__inner {
  display: grid;
  gap: var(--sp-6);
  justify-items: center;
  width: min(100%, 520px);
}

/* Крутящийся диск-болванка: тот же приём, что и в hero, но мельче. */
.boot__disc {
  position: relative;
  width: clamp(96px, 20vw, 148px);
  aspect-ratio: 1;
  border-radius: 50%;
  background:
    repeating-conic-gradient(from 0deg,
      rgba(255,255,255,.06) 0deg 1.2deg,
      rgba(0,0,0,.06) 1.2deg 2.4deg),
    conic-gradient(from 200deg,
      var(--pink), var(--butter), var(--acid),
      var(--cyan), var(--violet), var(--pink));
  box-shadow: 0 0 0 1px rgba(255,255,255,.2) inset,
              0 0 70px -18px color-mix(in srgb, var(--cyan) 70%, transparent);
  animation: boot-spin 1.5s cubic-bezier(.34, .8, .3, 1) infinite;
}
.boot__disc::before {
  content: '';
  position: absolute;
  inset: 33%;
  border-radius: 50%;
  background: radial-gradient(circle,
    var(--bg) 0 32%,
    rgba(255,255,255,.16) 32% 34%,
    #14141c 34% 100%);
}
@keyframes boot-spin { to { transform: rotate(360deg); } }

.boot__log {
  margin: 0;
  width: 100%;
  min-height: 11em;
  font: 400 clamp(11px, 1.3vw, 13px)/1.85 var(--f-mono);
  color: var(--acid);
  white-space: pre-wrap;
  text-shadow: 0 0 12px color-mix(in srgb, var(--acid) 45%, transparent);
}
.boot__log b { color: var(--fg); font-weight: 700; }

.boot__bar {
  width: 100%;
  height: 2px;
  background: rgba(255, 255, 255, .12);
  overflow: hidden;
}
.boot__bar span {
  display: block;
  width: 0;
  height: 100%;
  background: var(--holo);
  background-size: 300% 100%;
  animation: holo-drift 3s linear infinite;
  transition: width 220ms var(--e-out);
}

.boot__skip {
  min-height: 44px;
  padding: 10px 22px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--fg-3);
  font: 500 11px/1 var(--f-mono);
  letter-spacing: .18em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color var(--t-hover) var(--e-out), border-color var(--t-hover) var(--e-out);
}
.boot__skip:hover { color: var(--acid); border-color: var(--acid); }

/* ------------------------------------------------------------
   5. СТИКЕРЫ
   Мелкие Y2K-наклейки, разложенные по секциям. Декор — из потока
   выключены и скрыты от скринридера в разметке.
   ------------------------------------------------------------ */
.sticker {
  position: absolute;
  z-index: 3;
  display: grid;
  place-items: center;
  padding: 7px 14px;
  border-radius: var(--r-pill);
  background: var(--holo);
  background-size: 300% 100%;
  color: #000;
  font: 700 10px/1 var(--f-mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  white-space: nowrap;
  box-shadow: 0 8px 24px -10px color-mix(in srgb, var(--pink) 70%, transparent);
  animation: holo-drift 9s linear infinite, sticker-wobble 7s ease-in-out infinite;
  pointer-events: none;
}
.sticker::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--gloss);
}

@keyframes sticker-wobble {
  0%, 100% { transform: rotate(var(--rot, -6deg)) translateY(0); }
  50%      { transform: rotate(calc(var(--rot, -6deg) * .4)) translateY(-5px); }
}

/* ------------------------------------------------------------
   6. REDUCED MOTION
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .bg__roll, .bg__dust, .bg__glow { animation: none; }
  .crt { opacity: .3; }
  .spot { display: none; }
  .boot__disc { animation: none; }
  .sticker { animation: none; transform: rotate(var(--rot, -6deg)); }
}
