/* ═══════════════════════════════════════════════════════════
   Экран сборки интерфейса.

   Бумага под ним та же самая, что под инструментом (--paper), поэтому
   «перехода» между экраном и интерфейсом нет: меняется только то, что
   на бумаге нарисовано. Полноэкранное тёмное здесь пробовать нельзя —
   SPEC §8.3 этот ход уже отверг: светлая бумага с чёрным сверху уводит
   продукт в чёрно-белое.

   Нарисовано на ней то, что и так есть в шапке: горизонт недели и дятел
   на нём. Экран не представляет инструмент, он и есть его первый кадр.
   ═══════════════════════════════════════════════════════════ */

/* Доля собранного — число, а не строка: только так её можно перегонять
   плавно. Браузер без @property просто переставит линию вехами — она
   всё равно правильная, только без перегона. */
@property --p{syntax:'<number>';inherits:true;initial-value:0}

.boot{
  position:fixed;inset:0;z-index:200;background:var(--paper);
  display:flex;align-items:center;justify-content:center;
  transition:background-color var(--t-page) var(--ease);
}
/* Долю перегоняет корень: её ставит строка в head, а не этот блок. */
html{transition:--p var(--t-page) var(--ease)}
/* Слово для диктора: на экране его нет, но «страница молчит» — это
   не то, что должен слышать человек с экранным чтением. */
.boot-say{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;
}

/* Имя стоит в небе над горизонтом, а не в столбик с ним, и не по
   середине: по центру оно делит экран пополам и спорит с птицей за
   внимание. Слева вверху получается диагональ — имя, пустое небо,
   птица на гребне справа, — и композиция читается сразу. */
.boot-in{
  position:absolute;left:12%;top:22%;z-index:1;
  display:flex;flex-direction:column;align-items:center;gap:26px;
}
/* Горизонт во всю ширину и низом к нижнему краю: небо сверху, поле снизу. */
.boot-scene{
  position:absolute;left:0;right:0;bottom:0;height:min(52svh,460px);z-index:0;
}

/* Весь механизм «не мигать»: содержимое ждёт метки, которую ставит
   строка в head через 250 мс после начала навигации. Замер на этой
   машине: тёплая загрузка готова на 119 мс — метка не успевает
   появиться, и экран уходит, ни разу не показавшись. Показать и снять
   за две десятых секунды — моргок, а не экран. */
.boot-in{opacity:0}
.boot-lit .boot-in{animation:bootIn var(--t-page) var(--ease) both}
@keyframes bootIn{
  from{opacity:0;transform:translate3d(0,6px,0)}
  to{opacity:1;transform:none}
}

.boot-line{position:absolute;inset:0;display:block;width:100%;height:100%;overflow:visible}
/* Тот же штрих, что у кривой недели в шапке: это она и есть. */
.boot-line .ln{
  fill:none;stroke:var(--ink-2);stroke-width:1.5;stroke-linecap:round;opacity:.9;
}
/* Весь горизонт — бледной чертой: видно, сколько ещё собирать. */
.boot-line.track .ln{stroke:var(--rule);opacity:.85}
/* Поле под собранным. В шапке этот же градиент идёт до .28 — здесь поле
   в полэкрана, и такая плотность заливала бы бумагу. */
.boot-g-a{stop-color:var(--ink);stop-opacity:.14}
.boot-g-b{stop-color:var(--ink);stop-opacity:0}
.boot-line .fill{fill:url(#boot-g)}
/* Линейка по нижнему краю: часовые засечки шахматки, только тише. */
.boot-ticks{
  position:absolute;left:0;right:0;bottom:0;height:7px;
  background:repeating-linear-gradient(90deg,
    var(--rule) 0 1px, transparent 1px 46px);
  opacity:.5;
  -webkit-mask-image:linear-gradient(90deg,
    #000 calc(var(--p,0) * 100% - 7%), transparent calc(var(--p,0) * 100%));
          mask-image:linear-gradient(90deg,
    #000 calc(var(--p,0) * 100% - 7%), transparent calc(var(--p,0) * 100%));
}
/* Собранное открывается маской, а не рисуется штрихом: при
   preserveAspectRatio="none" пунктир растягивается неравномерно, и
   передний край вставал бы не там, где доля. Маска точна по построению,
   и это тот же приём, каким в шапке проявляется кривая недели.

   Край не обрублен, а растушёван на 16 px: линия дорисовывается, а не
   обрезается посередине. Ради этого доля объявлена ниже настоящим
   числовым свойством — иначе её нечем перегонять, и заполнение
   прыгало бы вехами. */
.boot-line.draw{
  --edge:7%;
  -webkit-mask-image:linear-gradient(90deg,
    #000 calc(var(--p,0) * 100% - var(--edge)), transparent calc(var(--p,0) * 100%));
          mask-image:linear-gradient(90deg,
    #000 calc(var(--p,0) * 100% - var(--edge)), transparent calc(var(--p,0) * 100%));
}
/* Надпись показывается, как только приедет: она в приоритете загрузки
   и весит 25 КБ. Гейт «дождись полной расшифровки» тут стоял и был снят —
   ставил его модуль, а он приезжает последним из сотни запросов, и на
   медленном канале надпись не показывалась вовсе. Защита, которая не
   успевает к моменту, от которого защищает, хуже её отсутствия.

   Птица ждёт своей доли горизонта: она стоит на 65 %, и пока собранное
   не дошло до её места, ей стоять не на чем. К этой доле её 131 КБ
   обычно уже здесь; не приехали — на бумаге остаются горизонт и
   надпись, и ничего не выглядит недоделанным. */
.boot-bird{opacity:0;transition:opacity var(--t-move) var(--ease)}
.perched .boot-bird{opacity:1}
/* Птица стоит на кривой, а не рядом: точка взята с самого пути. */
.boot-bird{
  position:absolute;left:65.3%;top:50.7%;
  width:96px;height:82px;transform:translate(-50%,-100%);
  background:url(../assets/ritmelo-mascot.png) bottom center/contain no-repeat;
}
/* Взлёт лежит поверх стоящей птицы и совпадает с ней: числа сведены из
   двух картинок — в PNG птица занимает 375×482 из 405×512, в клипе
   стоящая поза занимает 798×1014 из холста 852×1076. Отсюда 64.1×81.0
   на отметке 16 px внутри того же бокса 96×82. Промахнись эти числа —
   на подмене птица дёрнулась бы. */
.boot-fly{
  position:absolute;left:15.7px;top:-.5px;width:64.6px;height:81.6px;
  opacity:0;pointer-events:none;
}
/* На уходе стоящая гаснет мгновенно, а клип показывается: между позами
   шва нет, потому что первый кадр клипа — та же поза. */
.boot.is-flying .boot-bird{background-image:none}
.boot.is-flying .boot-fly{opacity:1}
/* Имя объекта под знаком: экран открывает не «программу вообще», а
   конкретную усадьбу. Тот же тихий голос, что у разделов колонки. */
.boot-venue{
  font-size:12.5px;font-weight:500;
  color:var(--ink-3);
}
/* Это буквенная часть утверждённого lockup, а не попытка набрать название
   похожим веб-шрифтом. Знак к ней не приставлен: на этом экране он уже
   стоит живой птицей на горизонте, и плоская копия того же дятла рядом со
   словом называла бы продукт дважды. Полный lockup стоит там, где он
   работает: в меню интерфейса и в шапке экрана входа. */
.boot-word{
  --w:250px;
  display:block;width:var(--w);height:auto;
}
/* Сезон меняет птицу, но не форму и цвет фирменного слова. */
html[data-mascot-theme="winter"] .boot-bird{
  background-image:url(../assets/ritmelo-mascot-winter.png);
}

/* Уход. Экран не гаснет целиком: каждая часть садится на своё место в
   интерфейсе — горизонт в прибор шапки, надпись в знак меню. Сдвиг и
   масштаб приходят из boot-screen.mjs, посчитанные по настоящим
   прямоугольникам: подвинется шапка — уедет и экран. */
/* Уходит бумага, а не «экран целиком»: гаси всю плиту разом — и птица,
   которая ещё летит, погасла бы вместе с ней на первой трети полёта. */
.boot.is-done{background-color:transparent;pointer-events:none}
.boot.is-done .boot-in{opacity:0;transition:opacity var(--t-move) var(--ease)}
.boot.is-done .boot-scene,
.boot.is-done .boot-word{
  animation:none;
  transform:translate3d(var(--to-x,0),var(--to-y,0),0) scale(var(--to-s,1));
  opacity:0;
  transition:transform var(--t-page) var(--ease), opacity var(--t-move) var(--ease);
}
.boot.is-done .boot-in{animation:none}

/* Тише: экран остаётся — он и есть содержание, — но никуда не едет.
   Проявление и уход становятся сменой непрозрачности. */
@media (prefers-reduced-motion:reduce){
  .boot-lit .boot-in{animation:bootCalm var(--t-page) var(--ease) both}
  @keyframes bootCalm{from{opacity:0}to{opacity:1}}
  .boot.is-done .boot-scene,
  .boot.is-done .boot-word{transform:none;transition:opacity var(--t-move) var(--ease)}
}
