/* Локальные композиции полного повествования. Общая тема Craft сохранена. */

/* Кегль тезиса выдерживает три-четыре строки без обрезки по высоте. */
.s-statement .type-hero {
  max-width: 25ch;
  font-size: 5.65cqw;
  line-height: 1.12;
  text-wrap: balance;
}
.s-statement .type-note { max-width: 74ch; }
.s-statement .pad { gap: 5cqh; }
/* Пояснение относится к заголовку и читается вместе с ним. */
.n-title-explanation { max-width: 60ch; font-size: 2.3cqw; line-height: 1.4; }

/* Красный отмечает узел текущей страницы, а не середину схемы.
   Связь и следующий узел раскрываются одной экранной страницей. */
.n-architecture .flow { --flow-gap: 8cqw; }
.n-architecture .flow:not(:has(.flow-step[data-shown])) > .flow-node,
.n-architecture .flow-step[data-shown]:not(:has(~ .flow-step[data-shown])) > .flow-node {
  background: var(--accent-fill);
  border-color: var(--accent-fill);
  color: var(--on-accent);
}
/* Bento является одной страницей. Высота плиток одинакова внутри строки.
   Отличается ширина, а не вертикальный размер. Название атомарно. */
.n-bento .pad { padding-top: 16cqh; padding-bottom: 12cqh; }
.n-bento-grid {
  display: grid; grid-template-rows: repeat(4, minmax(0, 1fr));
  gap: 1.1cqw; flex: 1; min-height: 0;
}
.n-bento--editor .n-bento-grid,
.n-bento--data .n-bento-grid { grid-template-rows: repeat(5, minmax(0, 1fr)); }
.n-bento-row {
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 1.1cqw; list-style: none; margin: 0; padding: 0; min-height: 0;
}
.n-bento-card {
  min-width: 0; display: grid; place-items: center; text-align: center;
  padding: 1cqh 1cqw; border: var(--rule) solid var(--line-strong);
  background: var(--surface); color: var(--text);
  font: 600 2.45cqw/1.15 var(--font-display); letter-spacing: -.025em;
}
.n-span-2 { grid-column: span 2; }
.n-span-3 { grid-column: span 3; }
.n-span-4 { grid-column: span 4; }
.n-span-5 { grid-column: span 5; }
.n-span-6 { grid-column: span 6; }
.n-span-7 { grid-column: span 7; }
.n-bento--themes .n-bento-grid { grid-template-rows: repeat(8, minmax(0, 1fr)); gap: .6cqw; }
.n-bento--themes .n-bento-row { grid-template-columns: repeat(24, minmax(0, 1fr)); gap: .6cqw; }
.n-bento--themes .n-bento-card { font-size: 1.5cqw; padding: .5cqh .5cqw; }
.n-bento .type-note { margin: 1.5cqh 0 0; }
@keyframes bento-enter {
  from { opacity: 0; transform: translateY(1.2cqh) scale(.98); }
  to { opacity: 1; transform: none; }
}
/* Только вход вперёд. Прямые ссылки, возврат и сетка показывают всё сразу. */
.deck:not([data-mode]) .n-bento[data-reveal] .n-bento-card {
  animation: bento-enter 280ms cubic-bezier(.16, 1, .3, 1) both;
  animation-delay: calc(var(--order) * 45ms);
}
@media print {
  .n-bento-card { animation: none !important; opacity: 1 !important; transform: none !important; }
}
.comparison-value { --metric-size: 4.5cqw; line-height: 1.12; text-wrap: balance; }
.comparison-title { max-width: 40cqw; }
.comparison-side { padding-bottom: 13cqh; }
.comparison-points { --row-pad: 1.7cqh; font-size: 1.85cqw; }
.comparison-side.is-before { background: var(--bg); }
/* У дисклеймера крупные заголовки и единая линия начала списков. */
.n-user-comparison .comparison-side { justify-content: center; padding-block: var(--pad-y); }
.n-user-comparison .comparison-body { grid-template-rows: 9cqw 24cqh; align-content: start; gap: 1cqh; }
.n-user-comparison .comparison-value { --metric-size: 4cqw; align-self: start; }
.n-user-comparison .comparison-points { align-self: start; }
.s-comparison > .slide-number,
.s-visual-compare > .slide-number { color: var(--muted); }
.s-comparison:has(.is-after[data-shown]) > .slide-number,
.s-visual-compare:has(.is-after[data-shown]) > .slide-number { color: var(--on-accent); }

/* Геометрия экранов ответа и пример кадрирования, не блок-схема процесса. */
.n-answer-layouts .pad, .n-crop-demo .pad { padding-top: 16cqh; padding-bottom: 12cqh; }
.n-answer-layout-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2cqh 3cqw; flex: 1; min-height: 0; }
.n-answer-layout-grid figure, .n-crop-grid figure { margin: 0; min-width: 0; }
.n-answer-layout-grid figcaption, .n-crop-grid figcaption { font: 600 1.8cqw/1.2 var(--font-display); margin-bottom: 1.2cqh; }
.n-answer-layout-grid small { font: 400 1.35cqw/1.2 var(--font-text); color: var(--muted); margin-left: 1cqw; }
.n-answer-layout-grid svg { width: 100%; max-height: 23cqh; display: block; }
.n-answer-layout-grid rect { fill: var(--surface); stroke: var(--muted); stroke-width: 8; }
.n-answer-layout-grid text { fill: var(--text); text-anchor: middle; dominant-baseline: central; font: 500 110px var(--font-display); }
.n-crop-grid { display: grid; grid-template-columns: 1.35fr 1fr .65fr; gap: 3cqw; flex: 1; align-items: center; }
.n-crop-image { height: 50cqh; display: grid; place-items: center; }
.n-crop-image svg, .n-crop-image img { width: 100%; height: 100%; object-fit: contain; }
.n-crop-image rect { fill: none; stroke-width: 5; }
.n-face-box { stroke: var(--on-accent); stroke-dasharray: 12 8; }
.n-wide-crop { stroke: var(--on-accent); }
.n-tall-crop { stroke: var(--accent-mark); }
.n-merge-stage { position: relative; height: 56cqh; width: 100%; column-gap: 3cqw; margin-block: auto; }
.n-merge-photo { position: absolute; top: 0; left: 0; width: calc((100% - 3cqw) / 2); height: auto; aspect-ratio: 16 / 9; transform-origin: top left; transform: var(--merge-end); clip-path: var(--merge-clip); }
.n-merge-before .n-merge-photo { transform: var(--merge-start); clip-path: inset(0); }
@keyframes photo-merge {
  0%, 12% { transform: var(--merge-start); clip-path: inset(0); }
  100% { transform: var(--merge-end); clip-path: var(--merge-clip); }
}
.deck:not([data-mode]) .n-merge-after[data-reveal] .n-merge-photo {
  animation: photo-merge 1800ms cubic-bezier(.16, 1, .3, 1) both;
}
@media print {
  .n-merge-photo { animation: none !important; }
}

/* В шагах нет пустого места под отсутствующего четвёртого пункта. */
.steps:has(> div:nth-child(3):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.steps > div { min-width: 0; }
.flow-node { min-height: 16cqh; padding-inline: 1.2cqw; }
.flow-node > strong { font-size: 2cqw; }
.flow.n-flow-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.flow.n-flow-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.n-perf .bar-chart { width: 75cqw; margin-block: 5cqh; --chart-bar: 7cqh; --chart-gap: 5cqh; }
.n-perf .chart-row > span { font-size: 2.2cqw; }
.n-perf .chart-row > strong { font-size: 3.3cqw; }
.n-audio-weights .chart-layout { gap: 7cqw; }
.n-audio-weights .bar-chart { width: 50%; }
.n-audio-weights .type-lede { font-size: 2cqw; }
.n-audio-weights .chart-row > span, .n-day-one .chart-row > span { color: var(--text); font-size: 1.8cqw; }
.n-code .code { font-size: 1.75cqw; line-height: 1.45; }
.n-code .code-line { min-height: 1.45em; }
.n-code .pad { padding-block: 14cqh 12cqh; gap: 1cqh; }
.n-code .code:has(.code-line.is-highlighted) .code-line:not(.is-highlighted) { opacity: .65; }

/* Владелец обозначен внутри каждого узла. QZP связывает два ряда. */
.n-production-flow { display: grid; gap: 0; }
.n-pipeline-row { display: grid; grid-template-columns: 1fr 4cqw 1fr 4cqw 1fr; align-items: stretch; }
.n-stage { display: grid; place-content: center; text-align: center; gap: 1.7cqh; min-height: 20cqh; padding: 2cqh 1cqw; border: var(--rule) solid var(--line-strong); }
.n-stage strong { font: 600 2.3cqw/1.15 var(--font-display); }
.n-stage span { font: 400 1.6cqw/1.35 var(--font-text); color: var(--muted); }
.n-stage.surface-accent { border-color: var(--accent-fill); }
.n-contract { border-style: dashed; }
.n-link { display: grid; place-items: center; font: 500 2.7cqw/1 var(--font-text); color: var(--muted); }
.n-qzp-transfer { position: relative; height: 11cqh; }
.n-qzp-transfer svg { width: 100%; height: 100%; display: block; }
.n-qzp-transfer path { fill: none; stroke: var(--muted); stroke-width: 1; vector-effect: non-scaling-stroke; }
.n-qzp-transfer .n-transfer-head { stroke-width: 2; }
.n-qzp-transfer p { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); margin: 0; padding: .6cqh 1.5cqw; background: var(--bg); font: 600 2cqw/1.25 var(--font-text); }
.n-system .pad { padding-top: 16cqh; }

/* Роль автора читается отдельно от подписи опыта на чужом стеке. */
.about { grid-template-columns: minmax(0, 1fr) auto; gap: 3cqw; }
.about .handle { font-size: 1.8cqw; margin: 0; }
.s-figures .type-metric { font-size: 6cqw; }
.s-figures .type-note { max-width: 74ch; }
[data-count] { font-variant-numeric: tabular-nums; white-space: nowrap; }
.h-chart { overflow: visible; }

/* Заметки принадлежат спикеру, не попадают в экран и PDF. */
.speaker-notes[hidden] { display: none !important; }
.help-page { width: 7rem; }
.help-page-input { width: 3ch; }

/* Настройку «уменьшить движение» колода не учитывает: анимации здесь
   часть содержания, а показ идёт с машины докладчика. Конечное состояние
   без движения остаётся только для печати и снимков. */
@media print {
  .speaker-notes { display: none !important; }
  .q-video video { visibility: hidden; }
  .q-video { background: var(--bg) url("media/mindsweep-background-graded.jpg") center / cover; }
}


.n-day-one .bar-chart { --chart-gap: 1.4cqh; --chart-bar: 2.2cqh; }
.n-day-one .chart-row { row-gap: .6cqh; }
.n-day-one .chart-row > span { font-size: 1.6cqw; }
.n-day-one .chart-row > strong { font-size: 1.6cqw; }


/* «Готово, запускается»: терминал. При входе вперёд команда набирается
   по буквам за кареткой, после паузы строками выходит вывод. При
   возврате, прямой ссылке и печати всё сразу стоит в конечном состоянии. */
.n-terminal .term-line { display: block; white-space: pre; min-height: 1.65em; }
.n-terminal .term-cmd { display: inline-block; overflow: hidden; white-space: pre; vertical-align: bottom; }
.n-terminal .term-input::after { content: ''; display: inline-block; width: .6ch; height: 1.1em; margin-left: .1ch; vertical-align: text-bottom; background: currentColor; opacity: 0; }
@keyframes term-type { from { width: 0; } to { width: 11ch; } }
@keyframes term-caret { from, to { opacity: 1; } }
@keyframes term-appear { from { opacity: 0; } to { opacity: 1; } }
.n-terminal[data-reveal] .term-cmd { animation: term-type 550ms steps(11, end) 200ms both; }
.n-terminal[data-reveal] .term-input::after { animation: term-caret 1000ms linear; }
.n-terminal[data-reveal] .term-out { animation: term-appear 1ms linear 1000ms both; }
.n-terminal[data-reveal] .term-out.is-key { animation-delay: 1300ms; }
@media print {
  .n-terminal[data-reveal] :is(.term-cmd, .term-out, .term-input::after) { animation: none; }
}


/* «Всё началось с простой задачи»: когда раскрыт подстрочник после
   таймлайна, речь уже не о четвёртом событии, акцент с него снимается. */
.timeline:has(+ .type-note.frag[data-shown]) > .frag > i::after { background: var(--muted); }
.timeline:has(+ .type-note.frag[data-shown]) > .frag h3 { color: var(--text); }

/* Канал: слайд собран как страница канала на YouTube. Шапка с аватаром,
   именем и счётчиками, справа QR, ниже вкладка «Видео» и лента обложек,
   которая едет влево без остановки. Дорожка повторена дважды, цикл
   бесшовный. В печати лента стоит. Цифры
   подписчиков и просмотров сняты с канала на дату из README ассетов. */
.n-channel .yt-page {
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  row-gap: 3cqh;
  align-content: center;
  min-height: 0;
}
.n-channel .yt-head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  column-gap: 2.4cqw;
  align-items: center;
}
.n-channel .yt-avatar { width: 14cqh; height: 14cqh; border-radius: 50%; display: block; }
.n-channel .yt-meta { display: grid; gap: .8cqh; }
.n-channel .yt-meta h3 { margin: 0; font: 700 3cqw/1.1 var(--font-display); letter-spacing: -.02em; }
.n-channel .yt-meta p { margin: 0; font: 400 1.6cqw/1.35 var(--font-text); color: var(--muted); }
.n-channel .yt-meta p b { font-weight: 600; color: var(--text); }
.n-channel .yt-head .qr-link { justify-items: end; gap: .8cqh; align-self: center; }
.n-channel .yt-head .qr { width: 14cqh; }
.n-channel .yt-head .where { font-size: 1.5cqw; }
.n-channel .yt-tabs {
  display: flex;
  align-items: center;
  gap: 1cqw;
  padding-bottom: 1.2cqh;
  border-bottom: var(--rule) solid var(--line);
  font: 500 1.5cqw/1 var(--font-text);
  color: var(--muted);
}
.n-channel .yt-tabs > span:first-child {
  color: var(--text);
  font-weight: 600;
  padding-bottom: 1.2cqh;
  margin-bottom: -1.2cqh;
  margin-inline-end: 1.6cqw;
  border-bottom: var(--rule-strong) solid var(--text);
}
.n-channel .yt-chip { padding: .9cqh 1.3cqw; border-radius: 1cqw; background: var(--surface); }
.n-channel .yt-chip.is-current { background: var(--text); color: var(--bg); }
.n-channel .film-strip { overflow: hidden; min-height: 0; align-self: start; margin-inline: calc(-1 * var(--pad-x)); }
.n-channel .film-track {
  display: flex;
  gap: 1.4cqw;
  width: max-content;
  margin-inline-start: var(--pad-x);
  /* Ход ленты линейный и бесконечный, а плавный разгон даёт вторая
     анимация на отдельном свойстве translate: первые три секунды она
     с замедлением уводит ленту назад ровно на путь линейного хода за
     это время и дальше держит сдвиг, так что суммарная скорость растёт
     от нуля до крейсерской, а лента стартует с места. */
  animation:
    film-strip 60s linear infinite both,
    film-ramp 1.8s cubic-bezier(.333, .667, .667, 1) both;
}
/* Сдвиг равен половине пути линейного хода за время разгона, а кривая
   это квадратичное замедление: её начальная скорость ровно вдвое выше
   средней, то есть равна скорости ленты, и дальше только падает. Так
   суммарное движение никогда не идёт вправо. */
@keyframes film-ramp { from { translate: 0 0; } to { translate: calc(.75% + .0105cqw) 0; } }
.n-channel .yt-card { margin: 0; width: 29cqw; }
.n-channel .yt-card img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; display: block; border-radius: .9cqw; }
.n-channel .yt-card figcaption { display: grid; gap: .4cqh; margin-top: 1.2cqh; font: 400 1.35cqw/1.3 var(--font-text); color: var(--muted); }
.n-channel .yt-card figcaption b { font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@keyframes film-strip { to { transform: translateX(calc(-50% - .7cqw)); } }
@media print { .n-channel .film-track { animation: none; } }
/* Части страницы канала проявляются по очереди при входе вперёд:
   шапка, вкладки, лента. При возврате, прямой ссылке и печати видны сразу. */
@keyframes yt-fade { from { opacity: 0; translate: 0 1.5cqh; } to { opacity: 1; translate: 0 0; } }
[data-reveal] .n-channel .yt-head, .n-channel[data-reveal] .yt-head { animation: yt-fade 600ms cubic-bezier(.22, 1, .36, 1) both; }
[data-reveal] .n-channel .yt-tabs, .n-channel[data-reveal] .yt-tabs { animation: yt-fade 600ms cubic-bezier(.22, 1, .36, 1) 350ms both; }
[data-reveal] .n-channel .film-strip, .n-channel[data-reveal] .film-strip { animation: yt-fade 700ms cubic-bezier(.22, 1, .36, 1) 700ms both; }

/* «Видео по сценам»: каждое нажатие наезжает камерой на одну сцену
   коллажа, последнее возвращает общий план. Состояние задаёт data-step,
   который deck.js ставит на страницу. Каждая страница свёрстана сразу в
   своём масштабе: под камерой фигура разложена в 14 раз крупнее, и кадры
   сцен в полном разрешении лежат поверх ячеек в натуральную величину.
   Движение при входе вперёд это анимация из предыдущего состояния в
   текущее, к концу трансформация нулевая, поэтому браузеру нечего
   перерисовывать и скачка резкости нет. Общий план во всю ширину, боковые
   поля равны промежутку между ячейками, кадр под камерой прижат к левому
   полю, как заголовок слайда. */
.n-zoom .shot { overflow: visible; transform: none; transform-origin: 0 0; aspect-ratio: auto; will-change: transform; }
.n-zoom .shot .scene-frame { position: absolute; display: block; object-fit: cover; }
.n-zoom .zs { position: absolute; width: 0; height: 0; overflow: hidden; }
@keyframes scene-zoom { from { transform: translate(var(--dx), var(--dy)) scale(var(--r)); } to { transform: none; } }
.n-zoom:has(.zs[data-reveal]) .shot { animation: scene-zoom 1100ms cubic-bezier(.65, 0, .25, 1) both; }
/* Gecko декодирует картинку под размер на экране, а для анимированного
   трансформа берёт масштаб, при котором весь слой помещается в экран:
   при наезде кадры сцен едут в 96 px, растянутыми в 14 раз, а в конце
   перекодируются в полный размер, отсюда скачок из мыла в резкость.
   При image-rendering: pixelated Gecko декодирует в натуральную величину,
   поэтому на время наезда и отъезда включаем его, а последним кадром
   возвращаем обычную выборку. Панорамы идут в масштабе 1:1 и без этого.
   Chromium растеризует слой 1:1 всегда, правило только для Gecko. */
@supports (-moz-appearance: none) {
  @keyframes scene-zoom-decoded { from { transform: translate(var(--dx), var(--dy)) scale(var(--r)); image-rendering: pixelated; } 99% { image-rendering: pixelated; } to { transform: none; image-rendering: auto; } }
  .n-zoom[data-step="1"]:has(.zs[data-reveal]) .shot, .n-zoom[data-step="7"]:has(.zs[data-reveal]) .shot { animation-name: scene-zoom-decoded; }
}
.n-zoom[data-step="0"] .shot { left: 0.134cqw; top: 9.668cqw; width: 99.731cqw; height: 36.914cqw; }
.n-zoom[data-step="1"] .shot { left: 1.720cqw; top: 6.592cqw; width: 1396.240cqw; height: 516.797cqw; --dx: -1.586cqw; --dy: 3.076cqw; --r: 0.071429; }
.n-zoom[data-step="2"] .shot { left: -71.766cqw; top: 6.592cqw; width: 1396.240cqw; height: 516.797cqw; --dx: 73.486cqw; --dy: 0.000cqw; --r: 1.000000; }
.n-zoom[data-step="3"] .shot { left: 1.720cqw; top: -36.475cqw; width: 1396.240cqw; height: 516.797cqw; --dx: -73.486cqw; --dy: 43.066cqw; --r: 1.000000; }
.n-zoom[data-step="4"] .shot { left: -71.766cqw; top: -36.475cqw; width: 1396.240cqw; height: 516.797cqw; --dx: 73.486cqw; --dy: 0.000cqw; --r: 1.000000; }
.n-zoom[data-step="5"] .shot { left: -71.766cqw; top: -79.541cqw; width: 1396.240cqw; height: 516.797cqw; --dx: 0.000cqw; --dy: 43.066cqw; --r: 1.000000; }
.n-zoom[data-step="6"] .shot { left: 1.720cqw; top: -467.139cqw; width: 1396.240cqw; height: 516.797cqw; --dx: -73.486cqw; --dy: 387.598cqw; --r: 1.000000; }
.n-zoom[data-step="7"] .shot { left: 0.134cqw; top: 9.668cqw; width: 99.731cqw; height: 36.914cqw; --dx: 1.586cqw; --dy: -476.807cqw; --r: 14.000000; }
/* Подложки под заголовком и номером на карте выпуска: под камерой
   картинка уходит под служебные элементы. Общий план проявляется с фейдом. */
.n-zoom .slide-title::before, .n-zoom .slide-number::before { display: block; }
@keyframes storyboard-fade { from { opacity: 0; } to { opacity: 1; } }
.n-zoom[data-step="0"][data-reveal] > * { animation: storyboard-fade 900ms ease-out both; }


/* Что закреплено на берегу: два ряда, продукт и архитектура. Рамки как на схеме всей системы:
   сплошная у модуля, пунктир у контракта. Оба ряда делят один промежуток. */
.n-fixed .pad { padding-top: 14cqh; padding-bottom: 11cqh; }
.n-fixed-rows { display: grid; align-content: center; gap: 6cqh; }
.n-fixed-row { display: grid; gap: 2cqh; }
.n-fixed-line { display: grid; grid-template-columns: 1fr 3cqw 1fr; align-items: stretch; }
.n-fixed-line > .n-stage:nth-child(2) { grid-column: 3; }
.n-fixed-line--chain { grid-template-columns: 1fr 3cqw 1fr 3cqw 1fr; }
.n-fixed-line--chain > .n-stage:nth-child(2) { grid-column: auto; }
.n-fixed .n-stage { min-height: 0; padding: 3.2cqh 1.2cqw; gap: 1.2cqh; }
.n-fixed .n-stage strong { font-size: 2.1cqw; }
.n-fixed .n-stage span { font-size: 1.5cqw; }

/* Записанный ползунок «до и после» лежит поверх постера в том же кадре;
   на печати остаётся постер. */
.n-demo-frame { position: relative; }
.n-demo-frame > .n-demo-inline { position: absolute; inset: 0; }
@media print { .n-demo-frame > .n-demo-inline { display: none; } }

/* Подпись финала как на обложке; название митапа приглушено, как разделители роли на слайде «О себе». */
.s-end .byline__event { opacity: .55; font-weight: 500; }
/* Разделитель: точка, как маркер ненумерованного списка, но в цвете текста и приглушённая,
   центр по середине строчных букв (x-height ≈ .52em). */
.s-end .byline__mark {
  display: inline-block; width: .26em; height: .26em; border-radius: 50%;
  background: currentColor; opacity: .55; vertical-align: .13em; margin: 0 .3em;
}
/* На финале номер не нужен, как на обложке. */
.s-end .slide-number { display: none; }


/* Правки по комментариям автора от 20 сентября 2026. */

/* Тезис тянется на всю ширину сцены: так строки переносятся ровнее. */
.s-statement .type-hero { max-width: none; }

/* Формат пакета: вложенные прямоугольники, иерархия, не блок-схема. */
.n-nest .pad { padding-top: 14cqh; padding-bottom: 11cqh; }
.n-nest-box { min-width: 0; min-height: 0; display: grid; align-content: start; gap: 1cqh; padding: 1.2cqh 1cqw; border: var(--rule) solid var(--line-strong); }
.n-nest-box > b { font: 600 1.7cqw/1.2 var(--font-display); }
.n-nest-archive { border-style: dashed; grid-template-rows: auto minmax(0, 1fr) auto; }
.n-nest-pack { grid-template-rows: auto minmax(0, 1fr); }
.n-nest-row { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 1cqw; min-height: 0; }
.n-nest-q { display: flex; justify-content: space-between; gap: .5cqw; padding: .7cqh .7cqw; border: var(--rule) solid var(--line); font: 500 1.3cqw/1.2 var(--font-text); }
.n-nest-q i { font-style: normal; color: var(--muted); }
.n-nest-media { margin: 0; font: 400 1.5cqw/1.3 var(--font-text); color: var(--muted); }

/* Слои кадра: три полосы, пересчитанный слой подсвечивается по нажатию. */
.n-layers .pad { padding-top: 16cqh; padding-bottom: 12cqh; }
.n-layers-stack { display: grid; gap: 1.6cqh; align-content: center; }
.n-layer { display: grid; grid-template-columns: 22cqw minmax(0, 1fr) auto; align-items: center; gap: 2cqw; padding: 3.2cqh 2cqw; border: var(--rule) solid var(--line-strong); }
.n-layer strong { font: 600 2.4cqw/1.15 var(--font-display); }
.n-layer span { font: 400 1.7cqw/1.3 var(--font-text); color: var(--muted); }
.n-layer em { font: 600 1.7cqw/1 var(--font-text); font-style: normal; color: var(--muted); }
.n-layer-mark { position: absolute; width: 0; height: 0; overflow: hidden; }
.n-layers:has(.n-layer-mark[data-shown]) .n-layer[data-redo] { background: var(--accent-fill); border-color: var(--accent-fill); color: var(--on-accent); }
.n-layers:has(.n-layer-mark[data-shown]) .n-layer[data-redo] :is(span, em) { color: var(--on-accent); }

/* Каждой задаче своя модель: пары «задача → модель». */
.n-map .pad { padding-top: 16cqh; padding-bottom: 12cqh; }
.n-map-rows { display: grid; gap: 2.4cqh; align-content: center; }
.n-map-row { display: grid; grid-template-columns: 1fr 5cqw 1fr; align-items: stretch; }
.n-map .n-stage { min-height: 13cqh; padding: 2cqh 1cqw; }

/* Вся система в одну строку. */
.flow.n-flow-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); --flow-gap: 3cqw; }
.flow.n-flow-5 .flow-node { padding-inline: .6cqw; }
.flow.n-flow-5 .flow-node > strong { font-size: 1.9cqw; }

/* Bento разной высоты. */
.n-bento--removed .n-bento-grid { grid-template-rows: repeat(3, minmax(0, 1fr)); }
.n-bento--parts .n-bento-grid { grid-template-rows: repeat(2, minmax(0, 1fr)); }
.n-bento--many .n-bento-grid { grid-template-rows: repeat(6, minmax(0, 1fr)); gap: .8cqw; }
.n-bento--many .n-bento-row { gap: .8cqw; }
.n-bento--many .n-bento-card { font-size: 1.75cqw; padding: .6cqh .8cqw; }

/* Таблица: подпись только для доступности. */
.n-table .pad { padding-top: 16cqh; padding-bottom: 12cqh; }
.n-table caption { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.n-table .data-table { font-size: 1.9cqw; }
/* Первое число табло видно сразу, без раскрытия: та же сетка и выравнивание, что у .frag. */
.scoreboard > div > div { display: grid; gap: 1.4cqh; }
.s-figures .scoreboard > div > div { justify-items: end; text-align: end; }
/* Откуда берутся данные: три этапа по центру, без растяжения на всю высоту. */
.n-sources .n-production-flow { margin-block: auto; }
.n-sources .n-stage { min-height: 24cqh; }
.n-table .data-table { font-size: 1.55cqw; }
.n-table .data-table th, .n-table .data-table td { padding: 1.5cqh .9cqw; }
/* Пайплайны на четыре и пять этапов. */
.n-pipeline-row--4 { grid-template-columns: 1fr 3cqw 1fr 3cqw 1fr 3cqw 1fr; }
.n-pipeline-row--5 { grid-template-columns: 1fr 2.4cqw 1fr 2.4cqw 1fr 2.4cqw 1fr 2.4cqw 1fr; }
.n-pipeline-row--4 .n-stage strong, .n-pipeline-row--5 .n-stage strong { font-size: 1.9cqw; }
.n-pipeline-row--4 .n-stage span, .n-pipeline-row--5 .n-stage span { font-size: 1.4cqw; }
.n-pipeline-row--5 .n-link { font-size: 2.2cqw; }
/* Финал: QR в правом нижнем углу, адрес слева от него по нижней кромке кода. */
.s-end .qr-link { top: auto; bottom: var(--pad-y); transform: none; align-items: end; }
.s-end .where { margin: 0; line-height: 1; }

/* Правки по второму видеопроходу 20 сентября. */
/* Служебные заголовки «Проблема» и «Задача»: подложка от левого края, как у названия полноэкранного демо.
   У проблемы акцентная, у задачи цвета текста, надпись цвета фона. */
.n-problem > .slide-title, .n-task > .slide-title { z-index: 3; isolation: isolate; padding-bottom: .2cqh; }
.n-problem > .slide-title::before, .n-task > .slide-title::before {
  content: ""; position: absolute; left: calc(-1 * var(--pad-x)); right: -1.4cqw; top: -.8cqh; bottom: -.8cqh; z-index: -1;
}
.n-problem > .slide-title { color: var(--on-accent); }
.n-problem > .slide-title::before { background: var(--accent-fill); }
.n-task > .slide-title { color: var(--bg); }
.n-task > .slide-title::before { background: var(--text); }
/* Подпись под названием узла схемы. */
.flow-node > span { display: block; margin-top: .8cqh; font: 400 1.35cqw/1.3 var(--font-text); color: inherit; opacity: .75; }
/* Bento на шесть рядов. */
.n-bento--six .n-bento-grid { grid-template-rows: repeat(6, minmax(0, 1fr)); gap: .8cqw; }
.n-bento--six .n-bento-row { gap: .8cqw; }
.n-bento--six .n-bento-card { font-size: 1.7cqw; padding: .5cqh .6cqw; }
/* Схема кадра: зоны кадра, красным то, что рендерится заново. */
.n-frame-scheme .pad { padding-top: 17cqh; padding-bottom: 12cqh; }
.n-frame-scheme .slide-title { max-width: 90cqw; }
.n-frame-wrap { display: grid; justify-items: start; align-content: center; }
.n-blueprint-pair { width: 100%; display: grid; grid-template-columns: 1fr 1fr; gap: 2cqw; }
.n-blueprint.q-video {
  position: relative; inset: auto; width: 100%; aspect-ratio: 16 / 9;
  border: 1px solid var(--line-strong); background: var(--bg);
  --q-paper: var(--text); --q-ink: var(--bg);
}
.n-blueprint.q-video::before, .n-blueprint.q-video::after { display: none; }
.n-blueprint-grid { position: absolute; inset: 0;
  background-image: linear-gradient(var(--line) 1px, transparent 1px), linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 5% 8.8889%; opacity: .35;
}
.n-blueprint :is(.q-badge-round, .q-badge-theme, .q-plate) {
  background: var(--bg); color: var(--text); border: 1px solid var(--line-strong); box-shadow: none; text-shadow: none;
}
.n-blueprint .q-num { border-color: var(--line-strong); }
.n-blueprint .q-timer { text-shadow: none; }
.n-blueprint .q-timer b { -webkit-text-stroke: 1px var(--text); color: transparent; }
.n-blueprint-photo { position: absolute; inset: 0; width: 100%; height: 100%; fill: none; stroke: var(--muted); stroke-width: 2; }
.n-photo-guides { opacity: .65; stroke-dasharray: 10 10; }
.n-blueprint .q-plate { right: auto; width: max-content; max-width: calc(100% - var(--q-margin) * 2); }
.n-blueprint .n-blueprint-answer { clip-path: none; transform: none; opacity: 1; }
.n-blueprint .q-timer { left: 40%; right: 40%; }
.n-frame-scheme:not(:has(.n-layer-mark[data-shown])) .n-blueprint :is(.n-redraw-context, .q-timer, .q-plate) {
  outline: 2px solid var(--accent-mark); outline-offset: 3px;
  background: color-mix(in srgb, var(--accent-fill) 15%, var(--bg));
}
.n-frame-scheme:not(:has(.n-layer-mark[data-shown])) .n-blueprint :is(.n-redraw-context p, .q-plate) { color: var(--accent); border-color: var(--accent-mark); }
.n-frame-scheme:not(:has(.n-layer-mark[data-shown])) .n-blueprint .q-timer b { -webkit-text-stroke-color: var(--accent); }
.n-frame-scheme:not(:has(.n-layer-mark[data-shown])) .n-blueprint-photo { stroke: var(--accent-mark); }
.n-frame-scheme:not(:has(.n-layer-mark[data-shown])) .n-blueprint-grid {
  background-color: color-mix(in srgb, var(--accent-fill) 12%, var(--bg));
  background-image: linear-gradient(color-mix(in srgb, var(--accent-mark) 25%, transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in srgb, var(--accent-mark) 25%, transparent) 1px, transparent 1px);
  opacity: 1;
}
.n-cache-after { display: none; }
.n-frame-scheme:has(.n-layer-mark[data-shown]) .n-cache-before { display: none; }
.n-frame-scheme:has(.n-layer-mark[data-shown]) .n-cache-after { display: inline; }
.n-frame-scheme:has(.n-layer-mark[data-shown]) .n-redraw-context {
  outline: 2px solid var(--accent-mark); outline-offset: 3px;
  background: color-mix(in srgb, var(--accent-fill) 15%, var(--bg));
}
.n-frame-scheme:has(.n-layer-mark[data-shown]) .n-redraw-context p { color: var(--accent); border-color: var(--accent-mark); }
@keyframes n-render-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
@media (prefers-reduced-motion: no-preference) {
  .n-frame-scheme[data-active]:not(:has(.n-layer-mark[data-shown])) .n-blueprint :is(.n-redraw-context, .q-timer, .q-plate, .n-blueprint-photo, .n-blueprint-grid),
  .n-frame-scheme[data-active]:has(.n-layer-mark[data-shown]) .n-redraw-context { animation: n-render-pulse 900ms ease-in-out infinite; }
}
@media print { .n-blueprint *, .n-redraw-context { animation: none !important; } }
/* Каждой задаче своя модель: три столбца, задача сверху, модель снизу, стрелка вниз. */
.n-map-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: auto auto; column-gap: 3cqw; row-gap: 0; align-content: center; }
.n-map-task { grid-row: 1; grid-column: var(--col); }
.n-map-model { grid-row: 2; grid-column: var(--col); position: relative; padding-top: 9cqh; }
.n-map-arrow { position: absolute; top: 0; left: 50%; width: var(--rule); height: 9cqh; transform: translateX(-50%); background: var(--muted); }
.n-map-arrow::after { content: ""; position: absolute; bottom: 0; left: 50%; width: .9cqw; height: .9cqw; transform: translateX(-50%); background: var(--muted); clip-path: polygon(0 0, 100% 0, 50% 100%); }
.n-map-grid > .frag[data-shown]:not(:has(~ .frag[data-shown])) .n-stage { background: var(--accent-fill); border-color: var(--accent-fill); color: var(--on-accent); }
/* Терминал: команда набирается по буквам при своём раскрытии, длина в --len. */
@keyframes term-type-var { from { width: 0; } to { width: var(--len); } }
.n-terminal .frag[data-reveal] .term-cmd { animation: term-type-var 1600ms steps(40, end) both; }
.n-terminal .frag[data-reveal] .term-input::after { animation: term-caret 1800ms linear; }
.n-terminal .frag { display: block; }
.n-terminal .term-out { animation: none; }
/* Терминал: комментарии приглушены, команды ярче. */
.n-terminal .term-comment { display: block; white-space: pre; min-height: 1.65em; color: var(--muted); }
.n-terminal .term-prompt { color: var(--muted); }
.n-terminal .term-cmd { color: var(--text); font-weight: 600; }
/* Формат QZP: вложенные прямоугольники, уровни проявляются по нажатию. */
.n-nest .pad { justify-content: center; }
.n-nest-archive { border-style: dashed; grid-template-rows: auto auto auto; flex: 0 0 auto; }
.n-nest-folder { display: grid; gap: .6cqh; padding: 1.4cqh 1cqw; }
.n-nest-folder > i { font: 400 1.3cqw/1.3 var(--font-text); font-style: normal; color: var(--muted); }
.n-nest-mark { position: absolute; width: 0; height: 0; overflow: hidden; }
.n-nest-pack, .n-nest-rounds, .n-nest-themes, .n-nest-media { opacity: 0; transform: translateY(1.2cqh) scale(.985); transition: opacity 420ms cubic-bezier(.16, 1, .3, 1), transform 420ms cubic-bezier(.16, 1, .3, 1); }
.n-nest:has(.n-nest-mark[data-level="pack"][data-shown]) .n-nest-pack,
.n-nest:has(.n-nest-mark[data-level="rounds"][data-shown]) .n-nest-rounds,
.n-nest:has(.n-nest-mark[data-level="themes"][data-shown]) .n-nest-themes,
.n-nest:has(.n-nest-mark[data-level="media"][data-shown]) .n-nest-media { opacity: 1; transform: none; }
.n-nest:not(:has(.n-nest-mark[data-level="rounds"][data-shown])) .n-nest-rounds { display: none; }
.n-nest:not(:has(.n-nest-mark[data-level="themes"][data-shown])) .n-nest-themes { display: none; }
.n-nest:not(:has(.n-nest-mark[data-level="media"][data-shown])) .n-nest-media { display: none; }
@media print { .n-nest-pack, .n-nest-rounds, .n-nest-themes, .n-nest-media { opacity: 1 !important; transform: none !important; display: grid !important; } }
.n-nest-q { white-space: nowrap; }
.n-nest-q span { overflow: hidden; text-overflow: ellipsis; }
/* Вопрос и ответ в одной карточке, каждый со своими медиа. */
.n-nest-q { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: .8cqw; row-gap: .3cqh; }
.n-nest-q i { text-align: right; }
/* Анимированное раскрытие уровней: строки сетки растут от 0fr до 1fr,
   поэтому вложенные рамки раздвигаются плавно, а не прыгают. */
.n-nest:not(:has(.n-nest-mark[data-level="rounds"][data-shown])) .n-nest-rounds,
.n-nest:not(:has(.n-nest-mark[data-level="themes"][data-shown])) .n-nest-themes,
.n-nest:not(:has(.n-nest-mark[data-level="media"][data-shown])) .n-nest-media { display: grid; }
.n-nest-pack, .n-nest-rounds, .n-nest-themes, .n-nest-media { transform: none; min-height: 0; overflow: hidden; transition: opacity 380ms ease-out; }
.n-nest-archive { grid-template-rows: auto 0fr 0fr; transition: grid-template-rows 520ms cubic-bezier(.16, 1, .3, 1); }
.n-nest:has(.n-nest-mark[data-level="pack"][data-shown]) .n-nest-archive { grid-template-rows: auto 1fr 0fr; }
.n-nest:has(.n-nest-mark[data-level="media"][data-shown]) .n-nest-archive { grid-template-rows: auto 1fr 1fr; }
.n-nest-pack { grid-template-rows: auto 0fr; transition: grid-template-rows 520ms cubic-bezier(.16, 1, .3, 1), opacity 380ms ease-out; }
.n-nest:has(.n-nest-mark[data-level="rounds"][data-shown]) .n-nest-pack { grid-template-rows: auto 1fr; }
.n-nest-round { grid-template-rows: auto 0fr; transition: grid-template-rows 520ms cubic-bezier(.16, 1, .3, 1); }
.n-nest:has(.n-nest-mark[data-level="themes"][data-shown]) .n-nest-round { grid-template-rows: auto 1fr; }
.n-nest-archive > .n-nest-media { margin-top: 0; }
.n-nest:has(.n-nest-mark[data-level="media"][data-shown]) .n-nest-archive > .n-nest-media { margin-top: 0; }
@media print { .n-nest-archive { grid-template-rows: auto 1fr 1fr !important; } .n-nest-pack, .n-nest-round { grid-template-rows: auto 1fr !important; } }
/* Обёртки пакета и папок раскрываются независимо: у архива строки по содержимому. */
.n-nest-archive { grid-template-rows: auto auto auto !important; transition: none; }
.n-nest-wrap { display: grid; grid-template-rows: 0fr; min-height: 0; transition: grid-template-rows 520ms cubic-bezier(.16, 1, .3, 1); }
.n-nest-wrap > * { min-height: 0; overflow: hidden; }
.n-nest:has(.n-nest-mark[data-level="pack"][data-shown]) .n-nest-wrap--pack,
.n-nest:has(.n-nest-mark[data-level="media"][data-shown]) .n-nest-wrap--media { grid-template-rows: 1fr; }
.n-nest-wrap--media { margin-top: 0; }
.n-nest:has(.n-nest-mark[data-level="media"][data-shown]) .n-nest-wrap--media { margin-top: 0; }
@media print { .n-nest-wrap { grid-template-rows: 1fr !important; } }
/* Колода размножает слайд по страницам, переходы между состояниями не срабатывают:
   каждое новое раскрытие это анимация на только что показанной странице (data-reveal). */
@keyframes nest-grow { from { grid-template-rows: 0fr; } to { grid-template-rows: 1fr; } }
@keyframes nest-grow-inner { from { grid-template-rows: auto 0fr; } to { grid-template-rows: auto 1fr; } }
@keyframes nest-fade { from { opacity: 0; } to { opacity: 1; } }
.n-nest:has(.n-nest-mark[data-level="pack"][data-reveal]) .n-nest-wrap--pack,
.n-nest:has(.n-nest-mark[data-level="media"][data-reveal]) .n-nest-wrap--media { animation: nest-grow 560ms cubic-bezier(.16, 1, .3, 1) both; }
.n-nest:has(.n-nest-mark[data-level="rounds"][data-reveal]) .n-nest-pack { animation: nest-grow-inner 560ms cubic-bezier(.16, 1, .3, 1) both; }
.n-nest:has(.n-nest-mark[data-level="themes"][data-reveal]) .n-nest-round { animation: nest-grow-inner 560ms cubic-bezier(.16, 1, .3, 1) both; }
.n-nest:has(.n-nest-mark[data-level="pack"][data-reveal]) .n-nest-pack,
.n-nest:has(.n-nest-mark[data-level="rounds"][data-reveal]) .n-nest-rounds,
.n-nest:has(.n-nest-mark[data-level="themes"][data-reveal]) .n-nest-themes,
.n-nest:has(.n-nest-mark[data-level="media"][data-reveal]) .n-nest-media { animation: nest-fade 420ms ease-out 120ms both; }
@media print { .n-nest-wrap, .n-nest-pack, .n-nest-round, .n-nest-rounds, .n-nest-themes, .n-nest-media { animation: none !important; } }
/* Ряд папок наследует цвет текста: старое правило для подписи n-nest-media делало его серым. */
.n-nest-row.n-nest-media { color: inherit; font: inherit; margin: 0; }

/* Граница между системами: протокол подписан на стрелке, а не стоит отдельным узлом. */
.n-boundary .flow.n-flow-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); --flow-gap: 16cqw; }
.n-arrow-label {
  position: absolute;
  right: 100%;
  top: 50%;
  width: var(--flow-gap);
  transform: translateY(-50%);
  display: grid;
  justify-content: center;
  font: 600 1.8cqw/1.2 var(--font-display);
  font-style: normal;
  letter-spacing: -.02em;
  color: var(--muted);
}
.n-arrow-label > span { background: var(--bg); padding: 0 1cqw; }

/* Подпись паб-квиза появляется вместе с вопросами, тем же нажатием. */
[data-key="pub-package"] .type-note { visibility: hidden; }
[data-key="pub-package"]:has(.q-branch-wrap[data-level="questions"][data-shown]) .type-note { visibility: visible; }

/* Подпись «почти год назад» появляется вместе с последним шагом. */
[data-key="one-package"] .type-note { visibility: hidden; }
[data-key="one-package"]:has(.timeline > li[data-last][data-shown]) .type-note { visibility: visible; }

/* Первый шаг таймлайна виден сразу и красный, пока не раскрыт следующий. */
.timeline:not(:has(> .frag[data-shown])) > li:first-child > i::after { background: var(--accent-mark); }
.timeline:not(:has(> .frag[data-shown])) > li:first-child h3 { color: var(--accent); }
.timeline:not(:has(> .frag[data-shown])) > li:first-child > i::before { display: none; }


/* --- Кадр вопроса первого видео (6 мая 2026), свёрстан по коду экспортёра
   того дня: drawContext, drawTimer, drawTitle, drawAudioIcon в
   video-exporter.ts и полоса прогресса из ffmpeg-фильтра. База 1280×720,
   размеры переведены в cqw кадра (1cqw = 12,8px), как у сегодняшнего
   кадра в .q-video. Футаж тот же, ffmpeg делал eq=brightness=-0.18:
   saturation=0.85, здесь это filter у видео. */
.q-video--embed { position: relative; inset: auto; width: 100%; aspect-ratio: 16 / 9; }
.s-visual-compare--editor .frame:has(> .q-video--embed) { overflow: hidden; }
.v1-frame { --v1-font: Inter, Arial, sans-serif; background: #0f172a; }
.v1-frame::before, .v1-frame::after { display: none; }
.v1-frame .media-cover { filter: brightness(.78) saturate(.85); }
.v1-hud { position: absolute; inset: 0; z-index: 1; font-family: var(--v1-font); }
.v1-hud p { margin: 0; }
/* roundRect(width*0.1, 52, width*0.55, 48, 24), текст 500 22px #cbd5e1 от width*0.12 */
.v1-context {
  position: absolute; left: 10cqw; top: 4.06cqw; width: 55cqw; height: 3.75cqw;
  border-radius: 1.875cqw; background: rgba(15, 23, 42, .65);
  padding-left: 2cqw; display: flex; align-items: center;
  font: 500 1.72cqw/1 var(--v1-font); color: #cbd5e1; white-space: nowrap;
}
/* arc(width-100, 100, 52), lineWidth 3, текст 700 34px #f8fafc; цвет кольца
   меняется на 10 и 5 секундах, как в drawTimer. */
.v1-timer {
  position: absolute; right: 3.75cqw; top: 3.75cqw;
  width: 8.125cqw; height: 8.125cqw; box-sizing: border-box;
  border-radius: 50%; border: .234cqw solid rgba(148, 163, 184, .4);
  background: rgba(15, 23, 42, .65); overflow: hidden;
}
.v1-timer-reel {
  display: grid; justify-items: center; grid-auto-rows: 7.66cqw;
  font: 700 2.66cqw/1 var(--v1-font); color: #f8fafc; font-variant-numeric: tabular-nums;
}
.v1-timer-reel > b { display: grid; place-items: center; width: 100%; height: 7.66cqw; font-weight: 700; }
@keyframes v1-tick { to { transform: translateY(-191.5cqw); } }
@keyframes v1-ring {
  0%, 59.9% { border-color: rgba(148, 163, 184, .4); background: rgba(15, 23, 42, .65); }
  60%, 79.9% { border-color: #f59e0b; background: rgba(245, 158, 11, .18); }
  80%, 100% { border-color: #ef4444; background: rgba(239, 68, 68, .18); }
}
.slide[data-active] .v1-frame .v1-timer-reel { animation: v1-tick 25s steps(25, end) both; }
.slide[data-active] .v1-frame .v1-timer { animation: v1-ring 25s step-end both; }
/* drawTitle(text, width, height*0.38, 46): 700 46px по центру, ширина 72% */
.v1-title {
  position: absolute; left: 14cqw; right: 14cqw; top: 21.4cqw; transform: translateY(-70%);
  text-align: center; font: 700 3.6cqw/1.3 var(--v1-font); color: #f8fafc;
}
/* drawAudioIcon(width/2, height*0.56): круг r=36, ♪ 700 34px #93c5fd */
.v1-audio {
  position: absolute; left: 50%; top: 31.5cqw; translate: -50% -50%;
  width: 5.625cqw; height: 5.625cqw; border-radius: 50%;
  background: rgba(59, 130, 246, .18); color: #93c5fd;
  display: grid; place-items: center; font: 700 2.66cqw/1 var(--v1-font);
}
/* drawbox x=iw*0.15 y=ih-58 w=iw*0.7 h=16 white@0.08, заливка rgb(56,189,248)
   растёт с T/duration, здесь за те же 25 секунд. */
.v1-bar {
  position: absolute; left: 15cqw; bottom: 3.28cqw; width: 70cqw; height: 1.25cqw;
  border-radius: .625cqw; background: rgba(255, 255, 255, .08); overflow: hidden;
}
.v1-bar > i { position: absolute; inset: 0; right: 100%; background: #38bdf8; border-radius: inherit; }
@keyframes v1-progress { to { right: 0; } }
.slide[data-active] .v1-frame .v1-bar > i { animation: v1-progress 25s linear both; }
@media print { .v1-frame { background: #0f172a url("media/cat-window-loop.jpg") center / cover; } }

/* Перемотка демо в начало: кадр слегка гаснет, в углу значок перемотки. */
.n-video-full { position: relative; }
.n-video-full.is-rewinding .n-video-full__media { filter: brightness(.7); transition: filter 150ms ease-out; }
.n-video-full.is-rewinding::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 4;
  width: 9cqw;
  height: 5cqw;
  transform: translate(-50%, -50%);
  background: var(--accent);
  clip-path: polygon(50% 0, 0 50%, 50% 100%, 50% 50%, 100% 100%, 100% 0, 50% 50%);
  animation: n-rewind-blink 260ms steps(2, jump-none) infinite;
}
@keyframes n-rewind-blink { from { opacity: 1; } to { opacity: .25; } }

/* Перебивка «два типа слайдов»: две плашки на разной высоте около середины, две страницы.
   Красная выезжает слева и тянется до 75% ширины, следом серая выезжает справа до 25%. Одна страница.
   Надписи стоят на 50% ширины слайда и едут вместе с плашкой. */
.n-units { position: relative; }
.n-unit {
  position: absolute; margin: 0; z-index: 3; height: 12cqh;
  font: 600 3.6cqw/1.1 var(--font-display); letter-spacing: -.02em; white-space: nowrap;
}
.n-unit > span { position: absolute; top: 50%; transform: translate(-50%, -50%); }
.n-unit--problem { top: calc(50% - 14cqh); left: 0; right: 25cqw; background: var(--accent-fill); color: var(--on-accent); }
.n-unit--problem > span { left: 66.667%; }
.n-unit--task { top: calc(50% + 2cqh); left: 25cqw; right: 0; background: var(--text); color: var(--bg); }
.n-unit--task > span { left: 33.333%; }
.slide[data-active] .n-unit--problem { animation: n-unit-from-left 800ms cubic-bezier(.16, 1, .3, 1) 200ms both; }
.slide[data-active] .n-unit--task { animation: n-unit-from-right 800ms cubic-bezier(.16, 1, .3, 1) 900ms both; }
@keyframes n-unit-from-left { from { transform: translateX(-100%); } to { transform: none; } }
@keyframes n-unit-from-right { from { transform: translateX(100%); } to { transform: none; } }

/* Два отрезка одного трека: громкость по полсекунды из выпуска,
   окна вопроса и ответа раскрываются по очереди. */
.n-wave .pad { justify-content: center; }
.n-wave-box { position: relative; height: 38cqh; margin: 10cqh 0 0; }
.n-wave-box svg { position: absolute; left: 0; width: 100%; top: 0; height: 100%; }
.n-wave-base { fill: var(--muted); opacity: .38; }
.n-wave-window {
  position: absolute; top: 0; bottom: 0;
  left: var(--from); width: calc(var(--to) - var(--from));
}
.n-wave-window::before {
  content: ""; position: absolute; inset: -3cqh 0;
  background: color-mix(in srgb, var(--text) 7%, transparent);
}
.n-wave-window.is-answer::before { background: var(--craft-accent-tint); }
.n-wave-window::after {
  content: ""; position: absolute; left: 0; right: 0; top: -3cqh;
  height: max(2px, .3cqw); background: var(--text);
}
.n-wave-window.is-answer::after { background: var(--accent-mark); }
.n-wave-window svg { fill: var(--text); }
.n-wave-window.is-answer svg { fill: var(--accent-mark); }
.n-wave-label {
  position: absolute; bottom: calc(100% + 5cqh); left: 0; margin: 0; white-space: nowrap;
  font: 650 2.6cqw/1 var(--font-display); letter-spacing: -.02em;
}
.n-wave-window.is-answer .n-wave-label { color: var(--accent); }
/* Слайд без нажатий: при входе вперёд волна прорисовывается слева направо,
   затем сами проявляются окна вопроса и ответа. Подложки полупрозрачные,
   серая волна под ними видна, цветные столбики заполняют её по высоте.
   Назад, по прямой ссылке и в печати всё видно сразу. Как и остальные
   анимации колоды, не зависит от системного «Уменьшить движение». */
.n-wave[data-reveal] .n-wave-base { animation: n-wave-draw 1400ms cubic-bezier(.4, 0, .2, 1) both; }
.n-wave[data-reveal] .n-wave-window { animation: n-wave-fade 700ms ease-out both; animation-delay: var(--delay); }
.n-wave[data-reveal] .n-wave-window svg {
  animation: n-wave-fill 900ms cubic-bezier(.22, 1, .36, 1) both; animation-delay: var(--delay);
  transform-origin: 50% 50%;
}
.n-wave-window.is-question { --delay: 1500ms; }
.n-wave-window.is-answer { --delay: 2600ms; }
@keyframes n-wave-draw { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes n-wave-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes n-wave-fill { from { transform: scaleY(0); } to { transform: none; } }
