/* ═══════════════════════════════════════════════════════════
   ДИЗАЙН-СИСТЕМА · суйканен артём
   Единственный источник правды по цвету, шрифтам, отступам,
   шапке, подвалу и общим компонентам. Подключается на ВСЕХ страницах.
   Специфика конкретной страницы — в её <style>.
   ═══════════════════════════════════════════════════════════ */

@font-face {
  font-family: "Benzin";
  src: url("../fonts/benzin-bold.otf") format("opentype");
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("../fonts/GeistMono-VariableFont_wght.ttf") format("truetype");
  font-weight: 100 900;
  font-display: swap;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }

/* ─────────────────────────────────────────
   ТОКЕНЫ. Все переменные живут здесь.
   ───────────────────────────────────────── */
.sk-root {
  /* цвет */
  --sk-bg: #fffbed;          /* бумага */
  --sk-paper: #fffdf6;       /* плашки и окошки */
  --sk-blue: #3440e8;        /* акцент */
  --sk-blue-bar: #dfe3fc;    /* титлбар окошка */
  --sk-ink: #16161c;         /* текст */
  --sk-gray: #8a8a90;        /* второстепенный текст */
  --sk-line: rgba(22,22,28,.14);   /* тонкая линия */

  /* шрифты */
  --sk-display: "Benzin", system-ui, sans-serif;
  --sk-mono: "Geist Mono", "IBM Plex Mono", ui-monospace, monospace;

  /* сетка и отступы */
  --sk-pad: clamp(20px, 4vw, 64px);    /* поле страницы */
  --sk-rail: 168px;                     /* ширина левой полосы меню */
  --sk-content: calc(var(--sk-pad) + var(--sk-rail));  /* левый отступ контента */
  --sk-head: 104px;                     /* высота, которую занимает шапка */
  --sk-max: 1400px;                     /* максимальная ширина контента */

  /* вертикальный ритм: используем ТОЛЬКО эти три */
  --sk-gap-s: clamp(14px, 1.8vh, 22px);
  --sk-gap-m: clamp(26px, 3.2vh, 44px);
  --sk-gap-l: clamp(56px, 9vh, 110px);

  /* прочее */
  --sk-border: 1.5px solid var(--sk-blue);
  --sk-shadow: 0 10px 28px rgba(22,22,28,.10);
  --sk-shadow-hover: 0 10px 22px rgba(52,64,232,.18);
  --sk-ease: cubic-bezier(.2,.7,.2,1);

  /* фон-полотно: клетка на весь сайт */
  background-color: var(--sk-bg);
  background-image:
    linear-gradient(rgba(22,22,28,.055) 1px, transparent 1px),
    linear-gradient(90deg, rgba(22,22,28,.055) 1px, transparent 1px);
  background-size: 26px 26px;

  color: var(--sk-ink);
  font-family: var(--sk-mono);
  font-size: 15px;
  line-height: 1.6;
  overflow-x: clip;
  min-height: 100svh;
}

/* ⛔ НИКОГДА не задавать фон блокам контента — сайт это одно сплошное полотно */

.sk-root ::selection { background: var(--sk-blue); color: var(--sk-bg); }
.sk-root a { color: inherit; text-decoration: none; }
.sk-root img { max-width: 100%; height: auto; display: block; }

/* ─────────────────────────────────────────
   СЛОИ (z-index)
   0 точки · 1 контент · 128 индикатор · 129 меню · 130 шапка · 400 переход
   ───────────────────────────────────────── */
.sk-dots { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; }
.sk-main { position: relative; z-index: 1; }
/* Переход между страницами — рентген-инверсия.
   Форма та же, что была у шейдера: рваное облако из центра с синей каймой.
   Изменилась только заливка: вместо непрозрачной «бумаги» — инверсия того,
   что под слоем, поэтому контент виден весь переход.
   hue-rotate возвращает синему синеву — после чистого invert он желтеет. */
.sk-wipe, .sk-wipe-edge {
  position: fixed; inset: 0; width: 100%; height: 100%;
  z-index: 400; pointer-events: none; display: none;
}
.sk-wipe {
  -webkit-backdrop-filter: invert(1) hue-rotate(185deg) saturate(1.6) contrast(1.05);
  backdrop-filter: invert(1) hue-rotate(185deg) saturate(1.6) contrast(1.05);
  -webkit-mask: url(#skCloud);
  mask: url(#skCloud);
}
/* светящаяся кайма по рваному краю облака */
/* Кромка не закрашивается краской, а ЗАСВЕЧИВАЕТ то, что под ней.
   В разобранном эталоне у самой линии реза цвет умножается на 2-40
   (`outputColor * glowMult`) — отсюда и сияние. Здесь тот же приём
   средствами CSS: узкое кольцо с backdrop-filter, который поднимает
   яркость реальных пикселей страницы. Синяя подложка осталась слабой
   примесью, чтобы свечение читалось нашим цветом. */
.sk-wipe-edge {
  z-index: 401;
  /* Синий держим плотным — кромка это линия реза, а не дымка.
     .82 оставляет ровно столько прозрачности, чтобы сквозь неё
     пробивалось свечение от backdrop-filter, но цвет читался нашим. */
  background: rgba(52, 64, 232, .82);
  -webkit-backdrop-filter: brightness(3.4) saturate(1.6) contrast(1.2);
  backdrop-filter: brightness(3.4) saturate(1.6) contrast(1.2);
  -webkit-mask: url(#skEdge);
  mask: url(#skEdge);
  filter: blur(2px);
}
.sk-wipe.sk-on, .sk-wipe-edge.sk-on { display: block; }

/* ─────────────────────────────────────────
   ШАПКА: лого слева, кнопки справа. Одинаково на всех страницах.
   ───────────────────────────────────────── */
.sk-corner { position: fixed; top: 16px; left: var(--sk-pad); z-index: 130; }
.sk-corner-l1 {
  display: block; width: fit-content;
  font-family: var(--sk-display); font-weight: 700;
  font-size: 15px; line-height: 1.05; text-transform: lowercase;
}
.sk-corner-l2 {
  display: block; width: fit-content;
  font-family: var(--sk-display); font-weight: 700;
  font-size: 11px; line-height: 1.05; margin-top: 4px;
  color: var(--sk-blue); text-transform: lowercase;
}

.sk-cta-dock { position: fixed; top: 14px; right: var(--sk-pad); z-index: 130; display: flex; gap: 10px; }
.sk-btn-mini {
  font-family: var(--sk-mono); font-size: 10.4px; padding: 8px 14.4px;
  border: var(--sk-border); background: var(--sk-blue); cursor: pointer;
  transition: transform .2s ease, box-shadow .2s ease;
}
.sk-root a.sk-btn-mini { color: var(--sk-paper); }
.sk-btn-mini:hover { transform: translateY(-1px); box-shadow: 0 6px 14px rgba(52,64,232,.25); }
.sk-btn-mini.sk-ghost { background: var(--sk-paper); }
.sk-root a.sk-btn-mini.sk-ghost { color: var(--sk-blue); }

/* ─────────────────────────────────────────
   МЕНЮ: вертикальный стек под лого
   ───────────────────────────────────────── */
.sk-dock {
  position: fixed; left: var(--sk-pad); top: 62px; z-index: 129;
  display: flex; flex-direction: column; gap: 8px;
}
.sk-chip {
  display: block; width: 128px;
  border: var(--sk-border); background: var(--sk-paper);
  box-shadow: 0 6px 16px rgba(22,22,28,.08);
  cursor: pointer;
  transition: transform .25s var(--sk-ease), box-shadow .25s;
}
.sk-chip:hover { transform: translateY(-2px); box-shadow: var(--sk-shadow-hover); }
.sk-chip.sk-chip-on { background: var(--sk-blue-bar); }
.sk-chip-bar {
  height: 16px; background: var(--sk-blue-bar);
  border-bottom: var(--sk-border);
  display: flex; align-items: center; justify-content: flex-end;
  padding: 0 5px; font-size: 9px; color: var(--sk-blue);
}
.sk-chip-label { padding: 6px 9px 7px; font-size: 12.5px; }

/* ─────────────────────────────────────────
   ОКОШКО — главный мотив сайта
   ───────────────────────────────────────── */
.sk-win { border: var(--sk-border); background: var(--sk-paper); box-shadow: var(--sk-shadow); }
.sk-win-bar {
  height: 22px; background: var(--sk-blue-bar);
  border-bottom: var(--sk-border);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 8px; font-size: 9.5px; letter-spacing: .04em;
  color: var(--sk-blue); user-select: none;
}

/* ─────────────────────────────────────────
   ТИПОГРАФИКА
   ───────────────────────────────────────── */
.sk-h1 {
  font-family: var(--sk-display); font-weight: 700;
  font-size: clamp(30px, 5vw, 68px); line-height: 1.02;
  text-transform: lowercase;
}
.sk-h2 {
  font-family: var(--sk-display); font-weight: 700;
  font-size: clamp(20px, 2.4vw, 32px); line-height: 1.1;
  text-transform: lowercase;
}
.sk-label {
  display: inline-block; font-size: 11px; color: var(--sk-blue);
  border: var(--sk-border); background: var(--sk-blue-bar); padding: 3px 10px;
}
.sk-num-label { font-size: 11px; color: var(--sk-blue); letter-spacing: .08em; }
.sk-p { max-width: 56ch; }
.sk-muted { color: var(--sk-gray); }

/* ─────────────────────────────────────────
   СЕКЦИЯ: единый отступ контента на всех страницах
   ───────────────────────────────────────── */
.sk-section {
  padding-left: var(--sk-content);
  padding-right: var(--sk-pad);
  max-width: var(--sk-max);
}

/* ─────────────────────────────────────────
   ИНДИКАТОР СКРОЛЛА
   Маленький, по центру по вертикали. В футер не залетает:
   когда футер попадает в кадр — гаснет (см. common.js).
   ───────────────────────────────────────── */
.sk-scroll {
  position: fixed; right: var(--sk-pad); top: 50%;
  transform: translateY(-50%);
  z-index: 128; pointer-events: none;
  display: flex; flex-direction: column; gap: 7px;
  transition: opacity .3s var(--sk-ease);
}
.sk-scroll.sk-scroll-off { opacity: 0; }
.sk-scroll i {
  width: 5px; height: 5px; background: rgba(52,64,232,.20);
  transition: background .25s, transform .25s;
}
.sk-scroll i.on { background: var(--sk-blue); transform: scale(1.4); }

/* ─────────────────────────────────────────
   ЛЕНТА-ГАЛЕРЕЯ — на всех страницах кейсов.
   Скролл, а не кнопки: подпись «листайте», тени по краям, живой ползунок.
   ───────────────────────────────────────── */
.sk-strip { position: relative; }
/* тени по краям: подсказывают, что лента продолжается */
.sk-strip::before, .sk-strip::after {
  content: ""; position: absolute; top: 0; bottom: 26px; width: 56px;
  pointer-events: none; z-index: 2; opacity: 0; transition: opacity .3s ease;
}
.sk-strip::before { left: 0;  background: linear-gradient(90deg, var(--sk-bg), transparent); }
.sk-strip::after  { right: 0; background: linear-gradient(270deg, var(--sk-bg), transparent); }
.sk-strip[data-l]::before { opacity: 1; }
.sk-strip[data-r]::after  { opacity: 1; }

.sk-strip-track {
  display: flex; gap: 14px; overflow-x: auto; padding-bottom: 14px;
  cursor: grab; scroll-snap-type: x proximity;
  scrollbar-width: thin; scrollbar-color: var(--sk-blue) var(--sk-blue-bar);
}
.sk-strip-track.sk-grab { cursor: grabbing; scroll-snap-type: none; }
.sk-strip-track::-webkit-scrollbar { height: 8px; }
.sk-strip-track::-webkit-scrollbar-track { background: var(--sk-blue-bar); border: 1px solid var(--sk-blue); }
.sk-strip-track::-webkit-scrollbar-thumb { background: var(--sk-blue); }

.sk-strip-item { flex: 0 0 auto; scroll-snap-align: start; }
.sk-strip-item img { height: clamp(220px, 38vh, 400px); width: auto; }
.sk-strip-cap { padding: 7px 9px 9px; font-size: 11px; color: var(--sk-gray); max-width: 34ch; }
/* подпись под всей лентой, а не под кадром */
.sk-strip + .sk-strip-cap { padding: 0; margin-top: 8px; }

/* подсказка нужна, только если лента правда листается —
   иначе висит зря под кадрами, которые и так все видны */
.sk-strip-hint {
  display: none; align-items: center; gap: 8px;
  margin-top: 8px; font-size: 11px; color: var(--sk-blue);
}
.sk-strip-hint.sk-on { display: flex; }
.sk-strip-hint::after {
  content: "→"; animation: sk-nudge 1.6s var(--sk-ease) infinite;
}
@keyframes sk-nudge { 0%,100% { transform: translateX(0) } 50% { transform: translateX(5px) } }

/* ─────────────────────────────────────────
   ПОДВАЛ — одинаковый везде
   ───────────────────────────────────────── */
.sk-footer {
  border-top: var(--sk-border);
  padding: 16px var(--sk-pad);
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 16px; font-size: 12.5px;
}
.sk-footer-links { display: flex; flex-wrap: wrap; gap: 24px; }
.sk-footer a:hover { color: var(--sk-blue); }

/* ─────────────────────────────────────────
   СТРАНИЦА КЕЙСА — одинаковая для всех шести.
   Специфика конкретного кейса — в его <style>.
   ───────────────────────────────────────── */

/* кнопка назад — на месте меню */
.cs-back {
  position: fixed; left: var(--sk-pad); top: 62px; z-index: 129;
  display: inline-flex; align-items: center; gap: 8px;
  border: var(--sk-border); background: var(--sk-paper);
  padding: 7px 13px; font-size: 12px; color: var(--sk-blue);
  box-shadow: 0 6px 16px rgba(22,22,28,.08);
  transition: transform .25s var(--sk-ease), box-shadow .25s;
}
.cs-back:hover { transform: translateX(-3px); box-shadow: var(--sk-shadow-hover); }

/* hero */
.cs-hero { padding-top: 148px; }
.cs-hero .sk-h1 { max-width: 14ch; }
.cs-lead { max-width: 52ch; font-size: clamp(14px,1.15vw,16px); }

/* мета-строка */
.cs-meta {
  display: flex; flex-wrap: wrap; gap: clamp(20px,3.5vw,54px);
  margin-top: var(--sk-gap-m); padding: 16px 0;
  border-top: var(--sk-border); border-bottom: var(--sk-border);
  max-width: 920px;
}
.cs-meta div { display: flex; flex-direction: column; gap: 2px; }
.cs-meta dt { font-size: 10px; color: var(--sk-gray); text-transform: uppercase; letter-spacing: .05em; }
.cs-meta dd { font-size: 13px; }
.cs-meta .big { font-family: var(--sk-display); font-weight: 700; font-size: clamp(15px,1.6vw,20px); color: var(--sk-blue); }

/* блок: текст слева, медиа справа */
.cs-block {
  padding-top: var(--sk-gap-l);
  display: grid; grid-template-columns: minmax(240px, 340px) 1fr;
  gap: clamp(28px, 4vw, 64px); align-items: start;
}
.cs-block-text .sk-p { font-size: 14px; }

/* блок с лентой: текст сверху, лента во всю ширину контента —
   иначе в узкой колонке видно полкадра и непонятно, что это листается.
   `minmax(0, 1fr)`, а не `1fr`: у `1fr` автоминимум — это min-content
   дорожки, и колонка раздувалась до 570px на экране 375. Текст уезжал
   под правый край и обрезался `overflow: clip` у `.sk-root`. */
.cs-block-stack { grid-template-columns: minmax(0, 1fr); }
.cs-block-stack .cs-block-text { max-width: 62ch; }

@media (max-width: 1024px) { .cs-block { grid-template-columns: minmax(0, 1fr); } }

.cs-media { max-width: 620px; }
.cs-media img { width: 100%; }
.cs-media-wide { max-width: 100%; }

/* ═══ ВИДЕО ═══
   Одна сцена, одна галерея, ничего не гаснет и не подменяется.
   В центре голова, вокруг разбросаны превью. Правое нижнее превью —
   это уже первый ролик галереи, просто маленький и внизу.
   По скроллу он растёт и встаёт чуть левее центра, а справа из угла
   выходит следующий. Дальше скролл листает галерею в обе стороны.
   Голова и разбросанные превью не исчезают — они уезжают вверх. */
/* `gap-l` — отступ МЕЖДУ секциями. Здесь же заголовок «генерация видео»
   и сама лента роликов — это один блок, разнесённый по двум тегам ради
   липкой сцены. По системе между блоками одной секции идёт `gap-m`;
   с `gap-l` между описанием и первым кадром зияло 73px. */
.vs { position: relative; margin-top: var(--sk-gap-m); }
/* ⛔ содержимое не режем: карточки должны наезжать друг на друга и
   выходить за края. Горизонтальное переполнение гасит .sk-root. */
.vs-stage { position: sticky; top: 0; height: 100svh; }

/* слой с головой и превью — уезжает вверх, opacity не трогаем */
.vs-orbit {
  position: absolute; inset: 0;
  transform: translateY(calc(var(--up, 0) * -1px));
  will-change: transform;
}
.vs-head {
  position: absolute; left: 50%; top: 50%;
  /* 34vw давали 261px на планшете — голова терялась среди превью.
     46vw держат её крупной на любой ширине: 353 на 768, 589 на 1280. */
  width: clamp(360px, 46vw, 700px); height: auto;
  transform: translate(-50%, -50%);
  pointer-events: none; filter: drop-shadow(0 18px 40px rgba(22,22,28,.18));
}
.vs-card {
  position: absolute; left: 50%; top: 50%; width: var(--w, 140px);
  border: var(--sk-border); background: var(--sk-paper);
  box-shadow: var(--sk-shadow); overflow: hidden; will-change: transform;
  transform:
    translate(-50%, -50%)
    translate(calc((var(--x) * var(--k, 1) + var(--mx, 0) * var(--d, 1)) * 1px),
              calc((var(--y) * var(--k, 1) + var(--my, 0) * var(--d, 1)) * 1px))
    rotate(calc((var(--r, 0) + var(--mx, 0) * var(--d, 1) * .05) * 1deg));
}
.vs-card img { display: block; width: 100%; height: auto; }
.vs-card .sk-win-bar { font-size: 8.5px; height: 18px; }

/* галерея: ряд панелей, положение и размер считает скрипт */
.vs-rail {
  position: absolute; left: 0; top: 0;
  display: flex; align-items: center; gap: clamp(16px, 2.4vw, 40px);
  will-change: transform;
}
/* Все панели одной высоты, ширина — по аспекту ролика. Иначе
   вертикальные кадры разрастаются на весь экран и съедают рамку. */
.vs-panel {
  position: relative; flex: 0 0 auto;
  display: flex; flex-direction: column;
  border: var(--sk-border); background: var(--sk-paper); box-shadow: var(--sk-shadow);
}
.vs-panel video, .vs-panel img {
  display: block; height: var(--ph, 62svh); width: auto;
  max-width: 46vw; background: var(--sk-ink); object-fit: cover;
}
/* первая панель начинает маленькой — это то самое правое нижнее превью */
.vs-panel:first-child video, .vs-panel:first-child img { height: var(--ph0, 120px); }
/* пока первая растёт, остальные отодвинуты за край экрана: следующий
   ролик должен выйти из угла, а не стоять рядом с головой */
.vs-panel + .vs-panel { margin-left: var(--extra, 0px); }

/* подпись и звук выезжают ИЗ-ПОД нижней кромки самой карточки:
   обёртка режет всё, что ниже, поэтому элементы именно всплывают. */
.vs-metawrap {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 12px; overflow: hidden; pointer-events: none;
}
.vs-meta {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 12px;
  transform: translateY(calc((1 - var(--meta, 0)) * 130%));
  transition: transform .35s var(--sk-ease);
}
.vs-cap {
  background: var(--sk-paper); border: var(--sk-border);
  padding: 7px 12px; font-size: 12px; line-height: 1.25;
}
.vs-cap i { font-style: normal; display: block; color: var(--sk-gray); font-size: 10.5px; }
.vs-mute {
  width: 46px; height: 46px; padding: 0; flex: 0 0 46px;
  border: var(--sk-border); background: var(--sk-blue); color: var(--sk-paper);
  cursor: pointer; display: grid; place-items: center; pointer-events: auto;
  transition: background .2s, color .2s;
}
.vs-mute svg { width: 20px; height: 20px; display: block; fill: currentColor; }
.vs-mute .vs-ico-on { display: none; }
.vs-mute[aria-pressed="true"] { background: var(--sk-paper); color: var(--sk-blue); }
.vs-mute[aria-pressed="true"] .vs-ico-on { display: block; }
.vs-mute[aria-pressed="true"] .vs-ico-off { display: none; }

/* ── режим просмотра со звуком ──
   Вуаль-негатив ложится на весь сайт, а активный ролик ПЕРЕЕЗЖАЕТ
   в слой поверх неё. Через z-index этого не добиться: панель лежит
   внутри ленты с transform, а он создаёт свой контекст наложения —
   поэтому вуаль накрывала и само видео. */
/* Вуаль: тёмный негатив с размытием на весь экран, просто проявляется.
   Без маски и без кругового роста — так решил Артём. */
.sk-veil {
  position: fixed; inset: 0; z-index: 200; pointer-events: none;
  -webkit-backdrop-filter: invert(1) hue-rotate(185deg) saturate(1.5) blur(10px);
  backdrop-filter: invert(1) hue-rotate(185deg) saturate(1.5) blur(10px);
  opacity: 0; transition: opacity .45s var(--sk-ease);
}
.sk-veil.is-on { opacity: 1; }

.vs-focus {
  position: fixed; inset: 0; z-index: 210;
  display: none; place-items: center; padding: 4svh 2vw 13svh;
}
.vs-focus.is-on { display: grid; }
/* подпись и звук в этом слое всегда на месте: --meta со сцены сюда
   не наследуется, панель ведь физически переехала */
.vs-focus { --meta: 1; --metaPE: auto; }
.vs-focus .vs-panel { transform: none; }
.vs-focus .vs-panel video {
  height: min(80svh, 960px); width: auto; max-width: 94vw;
}

/* мини-карта: полоска кадров поверх вуали, не размывается */
.vs-mini {
  position: absolute; left: 50%; bottom: 3.5svh; transform: translateX(-50%);
  display: flex; gap: 6px; padding: 7px;
  border: var(--sk-border); background: var(--sk-paper); box-shadow: var(--sk-shadow);
  max-width: 92vw; overflow-x: auto;
}
.vs-mini button {
  width: 46px; height: 32px; padding: 0; flex: 0 0 auto; cursor: pointer;
  border: 1.5px solid transparent; background: var(--sk-ink); overflow: hidden;
  transition: border-color .2s, transform .2s var(--sk-ease);
}
.vs-mini img { width: 100%; height: 100%; object-fit: cover; display: block; }
.vs-mini button[aria-current="true"] { border-color: var(--sk-blue); transform: translateY(-2px); }

.vs-arrow {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  width: 46px; height: 46px; padding: 0;
  border: var(--sk-border); background: var(--sk-paper); color: var(--sk-blue);
  font-family: var(--sk-mono); font-size: 20px; line-height: 1;
  cursor: pointer; display: grid; place-items: center;
  opacity: var(--meta, 0); pointer-events: var(--metaPE, none);
  transition: background .2s, color .2s;
}
.vs-arrow:hover { background: var(--sk-blue); color: var(--sk-paper); }
/* ─── разлёт превью вокруг головы ───
   Координаты карточек заданы в пикселях от центра и рассчитаны
   на широкий экран: самая левая стоит на −620px, и уже при 1440
   её левый край заезжал под меню, а при 1280 уходил за край экрана.
   Множитель `--k` поджимает разлёт под ширину. Числа подобраны так,
   чтобы левый край крайней карточки не заходил левее 190px:
   vw/2 − 620·k − 57 ≥ 190. */
.vs { --k: 1; }
@media (max-width: 1600px) { .vs { --k: .84; } }
@media (max-width: 1500px) { .vs { --k: .74; } }
@media (max-width: 1400px) { .vs { --k: .66; } }
@media (max-width: 1300px) { .vs { --k: .58; } }
@media (max-width: 1200px) { .vs { --k: .50; } }
@media (max-width: 1100px) { .vs { --k: .42; } }

.vs-arrow.is-prev { left: clamp(10px, 2vw, 28px); }
.vs-arrow.is-next { right: clamp(10px, 2vw, 28px); }

/* стрелки режима просмотра: живут в слое фокуса, поэтому видимость
   у них своя, а не унаследованная от --meta ленты */
.vs-farrow { opacity: 1; pointer-events: auto; z-index: 4; }

@media (prefers-reduced-motion: reduce) {
  /* эти две крутились бесконечно даже при выключенной анимации:
     стрелка в подсказке и качание облачка в мобильной шапке */
  .sk-strip-hint::after, .mb-cloud svg { animation: none !important; }
  .vs-stage { position: static; height: auto; padding: var(--sk-gap-l) 0; }
  .vs-orbit { display: none; }
  .vs-rail { position: static; transform: none; overflow-x: auto; }
}

/* ─────────────────────────────────────────
   ФОКУС С КЛАВИАТУРЫ
   Своих стилей не было вовсе: держались на дефолтном кольце браузера,
   а оно почти не видно на синей заливке — активный фильтр, кнопки-мини,
   плашки меню. Кольцо рисуем сами: снаружи элемента, чтобы не резалось
   рамкой окошка, и в цвете, который контрастен и на бумаге, и на синем.
   ───────────────────────────────────────── */
:where(a, button, [tabindex], summary, input, select, textarea):focus-visible {
  outline: 2px solid var(--sk-blue);
  outline-offset: 2px;
  border-radius: 1px;
}
/* на синей заливке синее кольцо не видно — выворачиваем на бумагу */
.sk-btn:focus-visible,
.sk-btn-mini:not(.sk-ghost):focus-visible,
.cl-filter[aria-pressed="true"]:focus-visible,
.vs-mute:not([aria-pressed="true"]):focus-visible {
  outline-color: var(--sk-paper);
  outline-offset: -4px;
}

/* ═══ БЕСКОНЕЧНАЯ ЛЕНТА `.wk-strip` ═══
   Крутится сама, зажатие разгоняет, клик проматывает на кадр, тянется мышью.
   Живёт на странице работ и в кейсах — поэтому здесь, а не в <style> страницы.
   Логика — initMarquee() в common.js, список кадров в data-items. */
.wk-strip {
  margin-top: var(--sk-gap-m);   /* было clamp(24,4vh,46) — своя шкала мимо системы */
  height: clamp(320px, 62vh, 620px);
  overflow: hidden;
  position: relative;
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
}
.wk-strip.wk-drag { cursor: grabbing; }
.wk-track {
  display: flex;
  align-items: stretch;
  gap: clamp(14px, 2vw, 34px);
  height: 100%;
  width: max-content;
  will-change: transform;
  padding-left: var(--sk-pad);
}

/* карточка — то же окошко, что и везде */
.wk-card {
  flex: 0 0 auto;
  height: 100%;
  display: flex;
  flex-direction: column;
  border: var(--sk-border);
  background: var(--sk-paper);
  box-shadow: var(--sk-shadow);
}
.wk-card-bar {
  height: 22px; flex: 0 0 22px;
  background: var(--sk-blue-bar);
  border-bottom: var(--sk-border);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 8px;
  font-size: 9.5px; letter-spacing: 0.04em; color: var(--sk-blue);
}
/* Пока кадр не приехал, карточка держит место в клетку, а не белым
   пятном: размеры известны заранее из data-sizes, поэтому ширина
   правильная с первого кадра и лента не дёргается. */
.wk-card:not([data-ready]) {
  background-color: var(--sk-bg);
  background-image:
    linear-gradient(rgba(52, 64, 232, .10) 1px, transparent 1px),
    linear-gradient(90deg, rgba(52, 64, 232, .10) 1px, transparent 1px);
  background-size: 26px 26px;
}
.wk-card:not([data-ready]) img { opacity: 0; }
.wk-card img { transition: opacity .25s ease; }

.wk-card img {
  height: 100%; width: auto; flex: 1 1 auto;
  min-height: 0; object-fit: cover;
  pointer-events: none; -webkit-user-drag: none;
}

/* подсказка следует за курсором, пока он над лентой */
.wk-tip {
  position: fixed; left: 0; top: 0; z-index: 200;
  pointer-events: none; opacity: 0;
  transform: translate(-50%, -160%);
  background: var(--sk-blue); color: #fffdf6;
  border: 1.5px solid var(--sk-blue);
  padding: 5px 11px; font-size: 11px; white-space: nowrap;
  transition: opacity 0.2s ease;
}
.wk-tip.wk-tip-on { opacity: 1; }

/* сетка кадров — для мелких скриншотов кнопок и результатов.
   Ленту им не даём: листать нечего, они должны стоять все сразу.
   .sk-win-wide растягивает кадр на обе колонки — для главного экрана. */
.cs-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px; align-items: stretch;
}
/* окошки в паре тянутся до общей высоты, кадр добирает остаток и кропается
   снизу — иначе соседи разной высоты и ряд разъезжается */
.cs-grid .sk-win { display: flex; flex-direction: column; }
.cs-grid img {
  display: block; width: 100%; flex: 1; min-height: 0;
  object-fit: cover; object-position: left top;
}
.cs-grid .sk-win-wide { grid-column: 1 / -1; }
@media (max-width: 620px) { .cs-grid { grid-template-columns: 1fr; } }

/* «что внутри» — стек списком, а не прозой: HR проскроллит, технарь прочитает */
.cs-specs { list-style: none; max-width: 62ch; }
/* Линия только МЕЖДУ строками — торцы списка открыты, см. раздел
   «Разделители в списках» в ДИЗАЙН-СИСТЕМЕ. Стояло `border-bottom`
   на каждой плюс `border-top` первой: список получался обведённым
   сверху и снизу, чего правило прямо запрещает. */
.cs-specs li {
  position: relative; padding: 9px 0 9px 18px;
  font-size: 13px; line-height: 1.5;
}
.cs-specs li + li { border-top: 1px solid var(--sk-line); }
.cs-specs li::before { content: "·"; position: absolute; left: 3px; color: var(--sk-blue); }

/* результат — окошками, а не строчками */
.cs-results {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px; max-width: 1100px;
}
.cs-res-card { border: var(--sk-border); background: var(--sk-paper); box-shadow: var(--sk-shadow); }
/* ⛔ Цифра результата НИКОГДА не переносится на вторую строку.
   Если не влезает — карточка становится шире, а не цифра ломается. */
.cs-res-card b {
  display: block; font-family: var(--sk-display); font-weight: 700;
  font-size: clamp(22px, 2.6vw, 34px); color: var(--sk-blue);
  padding: 14px 16px 2px; line-height: 1; white-space: nowrap;
}
.cs-res-card span { display: block; padding: 0 16px 14px; font-size: 12px; color: var(--sk-ink); }


/* ─────────────────────────────────────────
   ВЕРТИКАЛЬНЫЙ РИТМ ЗАГОЛОВКОВ
   Одна система на весь сайт. Отступ задаёт ПАРА «что после чего»,
   а не отдельный блок — поэтому h2 везде отбит одинаково,
   независимо от того, на какой он странице.
   ⛔ Не дописывать margin инлайном в разметке.
   ───────────────────────────────────────── */
.sk-label + .sk-h1,
.sk-label + .sk-h2        { margin-top: 16px; }
.sk-h1 + .cs-lead,
.sk-h1 + .sk-p            { margin-top: 18px; }
.sk-num-label + .sk-h2    { margin-top: 8px; }
.sk-num-label + .cs-results { margin-top: 14px; }
.sk-h2 + *                { margin-top: 12px; }
.sk-h3 + *                { margin-top: 10px; }
.cs-lead + .cs-lead,
.sk-p + .sk-p             { margin-top: 10px; }
.sk-p + .sk-label,
.sk-p + .sk-num-label     { margin-top: var(--sk-gap-s); }
/* список — такой же блок, как абзац: пары в обе стороны, иначе
   срабатывает margin:0 из ресета и текст липнет к последней строке */
.cs-specs + *,
.sk-p + .cs-specs         { margin-top: var(--sk-gap-s); }
/* лента внутри кейса отбивается как секция, а не как элемент внутри неё.
   Снизу её не трогаем: у .cs-sec свой padding-top, иначе отступ удвоится. */
.cs-sec + .wk-strip,
.cs-block + .wk-strip     { margin-top: var(--sk-gap-l); }

/* секция без двухколоночной сетки — отбивается как .cs-block */
.cs-sec { padding-top: var(--sk-gap-l); }

/* следующий проект */
.cs-next {
  margin-top: var(--sk-gap-l); border-top: var(--sk-border);
  padding: 24px var(--sk-pad) 24px var(--sk-content);
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
}
.cs-next-l { font-size: 10.5px; color: var(--sk-gray); text-transform: uppercase; letter-spacing: .06em; }
.cs-next-t {
  font-family: var(--sk-display); font-weight: 700;
  font-size: clamp(20px, 3vw, 40px); text-transform: lowercase;
  display: inline-block; transition: transform .3s var(--sk-ease), color .2s;
}
/* Стрелку рисуем псевдоэлементом моноширинным шрифтом: в benzin-bold.otf
   глифа U+2192 нет, и в разметке она падала на системный шрифт — чужая
   гарнитура вплотную к заголовку в 40px. */
.cs-next-t::after {
  content: " →";
  font-family: var(--sk-mono);
  font-weight: 400;
}
.cs-next:hover .cs-next-t { transform: translateX(14px); color: var(--sk-blue); }

/* ─────────────────────────────────────────
   ПОЯВЛЕНИЕ ПРИ СКРОЛЛЕ
   ───────────────────────────────────────── */
.sk-reveal { opacity: 0; transform: translateY(22px); transition: opacity .6s ease, transform .6s var(--sk-ease); }
.sk-reveal.sk-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .sk-reveal { opacity: 1; transform: none; transition: none; }
  .sk-wipe { display: none !important; }
}



/* ═══════════════════════════════════════════
   МОБИЛЬНАЯ ВЕРСИЯ
   Стилистика та же, что на десктопе: бумага в клетку, синие окошки,
   пиксельные детали. Никакого чужого чёрного и «плоского» бургера.
   ═══════════════════════════════════════════ */

.mb-bar, .mb-panel { display: none; }

/* Планшет в альбомной шире 1024, но управляется пальцем. Всё, что
   рассчитано на мышь — скролл-хореография видео, разгон ленты
   удержанием, ховер-превью, — там не работает. Поэтому мобильные
   правила включаются и по грубому указателю, а не только по ширине.
   Меню при этом остаётся десктопным: места на планшете хватает. */
@media (max-width: 1024px), (pointer: coarse) {
  .sk-dock, .sk-cta-dock, .sk-corner { display: none !important; }
  .sk-root { --sk-content: var(--sk-pad); }

  /* шапка — полоска бумаги с синей линией снизу */
  .mb-bar {
    display: flex; align-items: center; justify-content: space-between;
    position: fixed; inset: 0 0 auto 0; z-index: 200;
    /* высота задана числом: от неё считаются отступ контента под шапкой
       и посадка кнопки «все кейсы». Меняешь высоту — меняй обе. */
    height: 60px; padding: 0 var(--sk-pad);
    background: #fffbed;
    border-bottom: 1.5px solid #3440e8;
  }
  .mb-name {
    display: flex; flex-direction: column; justify-content: center;
    align-self: stretch;                     /* тач-цель во всю высоту шапки */
    font-family: var(--sk-display); font-weight: 700; font-size: 13px;
    line-height: 1.05; text-transform: lowercase; color: #16161c;
  }
  .mb-name i { display: block; font-style: normal; font-size: 10px; color: #3440e8; }

  /* кнопка — наше окошко: синяя рамка, внутри пиксельные полосы */
  .mb-burger {
    width: 46px; height: 44px; padding: 11px 9px; cursor: pointer;
    border: 1.5px solid #3440e8; background: #fffdf6;
    display: grid; align-content: space-between; gap: 4px;
  }
  .mb-burger span {
    display: block; height: 4px; background: #3440e8;
    transition: transform .2s steps(3), width .2s steps(3);
  }
  /* верхняя длинная, нижняя короче — в кресте обе выравниваются */
  .mb-burger span:last-child { width: 62%; }
  .mb-burger[aria-expanded="true"] span:last-child { width: 100%; }
  /* две линии складываются в крест — так чище, чем через три */
  /* сдвиг до пересечения = половина расстояния между полосами.
     Внутри 46×44 с полями 11/9 и рамкой 1,5 остаётся 19px:
     полосы по 4px стоят по краям, их центры в 2 и 17 — сходятся на 9,5. */
  .mb-burger[aria-expanded="true"] span:first-child { transform: translateY(7.5px) rotate(45deg); }
  .mb-burger[aria-expanded="true"] span:last-child  { transform: translateY(-7.5px) rotate(-45deg); }

  /* панель — та же бумага в клетку, что и сайт */
  .mb-panel {
    display: flex; flex-direction: column; gap: 10px;
    position: fixed; inset: 0; z-index: 199;
    padding: calc(var(--sk-pad) + 62px) var(--sk-pad) var(--sk-pad);
    background-color: #fffbed;
    background-image:
      linear-gradient(rgba(22, 22, 28, 0.055) 1px, transparent 1px),
      linear-gradient(90deg, rgba(22, 22, 28, 0.055) 1px, transparent 1px);
    background-size: 26px 26px;
    /* появление мгновенное: в пиксельной эстетике плавный фейд лишний,
       да и полупрозрачная панель просвечивает страницу под собой */
    visibility: hidden; opacity: 0; pointer-events: none;
    /* содержимое панели на 320×568 выше экрана: посчитано 584px при 568.
       Почта, телеграм и переключатель языка уезжали за нижний край,
       а доскроллить было нечем — body под панелью заблокирован */
    overflow-y: auto; overscroll-behavior: contain;
  }
  .mb-panel.mb-open { visibility: visible; opacity: 1; pointer-events: auto; }

  /* пункты — те же окошки, что в десктопном меню */
  .mb-link {
    display: block; border: 1.5px solid #3440e8; background: #fffdf6;
    color: #16161c; font-size: 17px; padding: 0;
    box-shadow: 0 6px 16px rgba(22, 22, 28, .08);
  }
  .mb-link::before {
    content: "×"; display: flex; justify-content: flex-end; align-items: center;
    height: 18px; padding: 0 6px; font-size: 10px; color: #3440e8;
    background: #dfe3fc; border-bottom: 1.5px solid #3440e8;
  }
  .mb-link i { display: block; font-style: normal; padding: 9px 12px 11px; }

  .mb-foot { margin-top: auto; display: flex; flex-direction: column; gap: 12px; font-size: 13px; }
  .mb-foot a { color: #3440e8; border-bottom: 1px solid #3440e8; width: fit-content; }
  /* «ru · en» и ссылки подвала были 20px в высоту — ниже минимума 24px
     из WCAG 2.5.8. Поля добираем паддингом, вид плашки не меняется */
  .mb-lang { display: flex; gap: 8px; font-size: 12px; color: #16161c; }
  .mb-lang a, .mb-lang b { display: inline-block; padding: 6px 8px; margin: -6px -8px; }
  .mb-foot a { display: inline-block; padding: 6px 0; }
  .mb-lang b { font-weight: 500; opacity: .45; }
  .mb-lang a { color: #3440e8; }


  /* лента: на телефоне карточка в 62vh съедает весь экран,
     из-за чего не видно, что это лента.
     Высоту считаем от ШИРИНЫ экрана, а не от высоты: при общей высоте
     на всю ленту широкий кадр вылезал далеко за правый край (3:2 давал
     413px на экране 375, 16:9 в кейсе обучения — 425px). Делитель 1,6 —
     между 3:2 и 16:9: самые широкие кадры занимают ровно ширину экрана,
     остальные уже.
     Белых полей нет: кадр по-прежнему `cover`, то есть увеличивается
     пропорционально и обрезается по краю, а не вписывается с полями. */
  /* ─── лента кадров на телефоне ───
     Было: у ленты фиксированная высота, ширина карточки — что останется
     от пропорций. Горизонтальный кадр упирался в ширину экрана и терял
     бока, вертикальный при высоте 187 получал 105px ширины и читался
     как приплюснутый столбик.
     Стало: ширину задаём карточке, высоту считает `aspect-ratio`.
     Кадры разной высоты стоят по центру ленты — так каждый виден целиком
     и настолько крупным, насколько позволяет его форма. */
  .wk-strip { height: auto; }
  .wk-track { height: auto; align-items: center; }
  .wk-card {
    height: auto;
    width: min(calc(100vw - var(--sk-pad) * 2), calc(46svh * var(--ar, 1.6)));
    max-width: calc(100vw - var(--sk-pad) * 2);
  }
  .wk-card img {
    height: auto; width: 100%; flex: 0 0 auto;
    aspect-ratio: var(--ar, 16 / 9);
  }
  /* `max-width: 74vw` сжимал ширину кадра, а высота оставалась заданной
     через clamp — картинка сплющивалась. Замер: кадр 1100×737 (1,49)
     показывался как 275×309 (0,89), то есть терял 40% пропорции.
     Ленте ограничение ширины и не нужно: она листается вбок, кадр шире
     экрана — это нормально. Ограничиваем только высоту. */
  .sk-strip-item { max-width: none; }
  /* Высоту не задаём: она равняла кадры в ряд, но вертикальный снимок
     при высоте 211 получал 131px ширины — на телефоне это марка, а не
     кадр. Вместо высоты — две границы, и браузер сам подбирает размер
     по пропорциям файла: горизонтальный упирается в ширину экрана,
     вертикальный — в половину высоты. Ни обрезки, ни сжатия. */
  .sk-strip-item img {
    width: auto; height: auto;
    max-width: calc(100vw - var(--sk-pad) * 2);
    max-height: 52svh;
  }

  /* видео: панель в 62vh на узком экране тоже великовата */
  .vs-panel video, .vs-panel img { height: clamp(240px, 46vh, 420px); max-width: 82vw; }


  /* ─── облачко из 404 живёт и в меню ───
     Маленькое, в правом углу, на одной линии с переключателем языка:
     отсылка, а не иллюстрация. Раньше оно стояло в полэкрана посреди
     панели и перебирало эмоции раз в 1,4 с — читалось как баннер.
     Теперь ведёт себя как на 404: качается, моргает, ахает ртом,
     а лицо меняет редко. */
  .mb-tail {
    margin-top: auto; display: flex; align-items: center;
    justify-content: space-between; gap: 12px;
  }
  .mb-cloud { width: 54px; flex: 0 0 54px; cursor: pointer; }
  .mb-cloud svg {
    width: 100%; height: auto; display: block;
    transform-origin: 50% 100%;
    animation: mb-bob 4.2s ease-in-out infinite;
    /* Тело бумажное, лицо синее — как просил Артём. На бумажном фоне
       белое облако пропало бы, поэтому обводим: четыре drop-shadow
       со смещением в 1,5px дают ровный синий контур по силуэту.
       Обводить сами rect'ы нельзя — тело склеено из полос,
       и обводка нарисовала бы сетку внутри облака. */
    filter:
      drop-shadow( 1.5px 0 0 #3440e8) drop-shadow(-1.5px 0 0 #3440e8)
      drop-shadow(0  1.5px 0 #3440e8) drop-shadow(0 -1.5px 0 #3440e8);
  }
  @keyframes mb-bob {
    0%, 100% { transform: translateY(0)    rotate(0deg); }
    50%      { transform: translateY(-3px) rotate(-1.4deg); }
  }
  /* Тело склеено из горизонтальных полос. При уменьшении 272→54
     между ними остаются субпиксельные щели, и обводка пролезает внутрь
     полосками. Обводим каждую полосу её же цветом — щели закрываются,
     наружу выходит только силуэт. */
  .mb-cloud .mb-body rect { fill: #fffdf6; stroke: #fffdf6; stroke-width: 1.2; }
  .mb-cloud .mb-eyes rect, .mb-cloud .mb-mouth rect { fill: #3440e8; }
  /* transform-box: fill-box — сжимаются сами глаза, а не всё облако */
  .mb-eyes  { transform-box: fill-box; transform-origin: center; transition: transform .09s ease; }
  .mb-eyes.mb-blink { transform: scaleY(.06); }
  .mb-mouth { transform-box: fill-box; transform-origin: center; }
  .mb-mouth.mb-gasp { animation: mb-gasp .22s ease-out; }
  @keyframes mb-gasp {
    0%   { transform: scaleY(1); }
    45%  { transform: scaleY(1.45); }
    100% { transform: scaleY(1); }
  }


  /* ─── видео на телефоне ───
     Десктопная хореография (первая панель растёт из угла, рельс едет
     трансформом) на узком экране не читается: первый ролик оставался
     размером со спичечный коробок. Здесь — обычная лента со свайпом
     и прилипанием, все панели одного размера. */
  .vs-stage {
    height: auto; overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .vs-stage::-webkit-scrollbar { display: none; }
  .vs-rail {
    position: static; transform: none !important;
    display: flex; gap: 12px; padding: 0 var(--sk-pad); width: max-content;
  }
  /* ─── размер кадра считается от пропорций ролика ───
     Было: фиксированная высота + `max-width: 78vw` + `object-fit: cover`.
     Для 16:9 при высоте 440 естественная ширина 782px упиралась в 292 —
     и `cover` срезал ролику бока: горизонтальные кадры показывались
     обрезанным столбиком, вертикальные — приплюснутыми.
     Стало: ширину задаём панели, высоту считает `aspect-ratio`.
     `--ar` проставляет скрипт по метаданным ролика (до загрузки 9:16).
     Вертикальные дополнительно ограничены по высоте, иначе на 812px
     экрана один кадр занимал бы две трети прокрутки. */
  .vs-panel {
    flex: 0 0 auto; scroll-snap-align: center; transform: none !important;
    width: min(78vw, calc(58svh * var(--ar, .5625)));
    transition: width .28s var(--sk-ease);
  }
  .vs-panel video, .vs-panel img,
  .vs-panel:first-child video, .vs-panel:first-child img {
    width: 100%; height: auto; max-width: none;
    aspect-ratio: var(--ar, 9 / 16);
    object-fit: cover;
  }
  /* ─── раскрытая карточка ───
     Тап увеличивает кадр, не разворачивая его на весь экран: соседи
     остаются видны краями, и понятно, что это лента, а не плеер. */
  .vs-panel.is-open { width: min(92vw, calc(74svh * var(--ar, .5625))); }
  /* кнопка звука живёт только в раскрытом кадре: в ленте звука нет
     ни у кого, показывать там нечего, а 46px съедали ширину подписи */
  .vs-mute { display: none; }
  .vs-panel.is-open .vs-mute { display: grid; }
  /* 38px были ниже рекомендованных 44 для пальца — вернули размер,
     а место освободили за счёт подписи рядом */
  .vs-mute { width: 44px; height: 44px; flex: 0 0 44px; }
  .vs-mute svg { width: 17px; height: 17px; }
  /* подпись на 375px занимала треть кадра — кегль и поля ужаты */
  .vs-cap { font-size: 11px; padding: 5px 9px; }
  .vs-cap i { font-size: 9.5px; }
  .vs-panel + .vs-panel { margin-left: 0 !important; }
  /* Полный ролик со звуком лежит поверх превью и проявляется, когда
     готов играть. Так подмена не гасит кадр: превью видно до последнего
     момента. Размеры те же, что у превью, — панель не прыгает. */
  .vs-panel { position: relative; }
  .vs-panel video.vs-full {
    /* кладём ролик ровно на превью, а не на всю панель: `top: 0` накрывал
       титлбар с именем файла — при включении звука он пропадал и обратно
       уже не возвращался. Считаем от нижней кромки и держим пропорции. */
    position: absolute; left: 0; right: 0; bottom: 0; top: auto;
    width: 100%; height: auto; aspect-ratio: var(--ar, 9 / 16);
    object-fit: cover;
    opacity: 0; transition: opacity .18s ease;
    pointer-events: none;
  }
  .vs-panel video.vs-full.vs-on { opacity: 1; }

  .vs-head, .vs-card, .vs-arrow { display: none; }   /* декор и стрелки: на свайпе не нужны */
  .vs-meta { transform: none !important; }           /* подпись видна сразу, без выезда */

  body.mb-locked { overflow: hidden; }
  .sk-main { padding-top: 60px; }

  /* подсказки про мышь на телефоне не показываем: мыши там нет */
  .sk-fine-only { display: none; }

  /* ─── ряды кадров на телефоне становятся каруселью ───
     Сетка из четырёх-пяти окошек в столбик — это пять экранов пролистывания
     ради одного блока. Горизонтальная лента со снапом показывает ровно один
     кадр и краем следующего, как в остальных лентах сайта.
     Отрицательные поля выводят карусель к самым краям экрана — иначе
     обрезанный кадр упирается в невидимую границу и выглядит как ошибка. */
  .cs-grid, .vr-pickup, .cs-slide {
    display: flex; flex-wrap: nowrap; align-items: center;
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    gap: 12px;
    margin-inline: calc(var(--sk-pad) * -1);
    padding-inline: var(--sk-pad);
    scrollbar-width: none;
    grid-template-columns: none;      /* перебиваем сетку десктопа */
  }
  .cs-grid::-webkit-scrollbar,
  .vr-pickup::-webkit-scrollbar,
  .cs-slide::-webkit-scrollbar { display: none; }

  .cs-grid > *, .vr-pickup > *, .cs-slide > * {
    flex: 0 0 calc(100vw - var(--sk-pad) * 2);
    max-width: calc(100vw - var(--sk-pad) * 2);
    /* `start` со сдвигом на поле, а не `center`: при `center` карточка
       во всю ширину контента вставала вплотную к левому краю экрана,
       а справа оставалось двойное поле */
    scroll-snap-align: start;
    grid-column: auto;                /* .sk-win-wide больше не растягивается */
  }
  .cs-grid, .vr-pickup, .cs-slide { scroll-padding-inline: var(--sk-pad); }

  /* Карточки одной высоты, кадр внутри вписан целиком.
     Пропорции кадров в кейсах разбегаются от 0,92 (pdf-разбор) до 8,15
     (полоска уведомления) — обрезать `cover` нельзя, у скриншота
     интерфейса смысл по всей площади. Поэтому фиксируем высоту бокса
     и вписываем `contain`: поля выходят цвета бумаги внутри рамки окна
     и читаются как паспарту, а не как дыра.
     0,62 ширины — медиана пропорций: широкие кадры почти заполняют бокс,
     высокие не вылезают. */
  /* Было: общая высота 0,62 ширины и `contain` — кадры разной формы
     вставали в один бокс, а разницу добирали поля. Вертикальный скриншот
     занимал середину бокса и читался как приплюснутый.
     Стало: тот же приём, что в остальных лентах, — две границы вместо
     высоты. Кадр показывается в своих пропорциях и настолько крупным,
     насколько позволяет экран. */
  .cs-grid img, .cs-slide img {
    flex: 0 0 auto;
    width: auto; height: auto;
    max-width: 100%; max-height: 52svh;
    object-fit: contain; object-position: center;
    background: var(--sk-bg);
  }
  .vr-pickup img { flex: 0 0 auto; height: auto; width: 100%; object-fit: fill; }

  /* индикатор скролла на телефоне убираем: он стоит по правому краю,
     а текст на узком экране идёт во всю ширину — точки ложились
     прямо на строки. Полосы прокрутки телефону хватает. */
  .sk-scroll { display: none; }

  /* «← все кейсы» на десктопе висит в пустой левой полосе. На телефоне
     полосы нет, и фиксированная плашка ездила поверх абзацев —
     ставим её в поток первой строкой страницы. */
  .cs-back {
    position: static; display: inline-flex;
    margin: 74px var(--sk-pad) 0;      /* 60 шапки + 14 воздуха */
    padding: 11px 15px; font-size: 13px;
  }
  /* отступ под шапку уже отработала кнопка — второй раз его не берём */
  .cs-back + .sk-main { padding-top: 0; }
  .cs-hero { padding-top: 26px; }

  /* «следующий проект»: при 20px самый длинный заголовок занимает
     ровно 335px — доступную ширину, и стрелка срывалась на свою строку.
     4,8vw даёт 18px на 375 (316px строки) и 15px на 320 (271px). */
  .cs-next-t { font-size: clamp(15px, 4.8vw, 20px); }

  /* ─── тач-цели ───
     Палец накрывает ~9мм, это 44px по гайдам Apple и Android.
     Всё, во что тыкают, доводим до 44 по меньшей стороне.
     Кегль подписей на кнопках поднимаем до 12: 10,4 на телефоне
     ниже минимума дизайн-системы (11) и читается как сноска. */
  .sk-btn-mini { font-size: 12px; padding: 12px 16px; }
  .sk-footer { padding: 20px var(--sk-pad); }
  .sk-footer-links { gap: 6px 24px; }
  .sk-footer a { display: inline-block; padding: 10px 0; }
}

@media (hover: none) {
  .cl-row:hover::before { transform: scaleY(0); }
  .cl-row:hover { color: inherit; }
  .cl-row:hover .cl-what { color: var(--sk-gray); }
  .cl-row:hover .cl-res { color: var(--sk-blue); }
}
