/* Прототип «три шутки» на первом экране. Каждая строка — отдельная шутка, её слово зачёркивает свой
   персонаж и пишет правку своим цветом. Строки видны сразу все, зачёркивания идут по очереди.
   Механика та же, что у «на талии» в v14 (shared/media.css, .gs-fix): путь ведёт элемент, прыжок —
   картинка в ::before, черта растёт с той же скоростью, что идёт фигурка.
   Без JS и при «уменьшить движение» — сразу конечное состояние: черты есть, правки на месте. */

/* Первый экран — одна широкая колонка: окна миров справа сняты (владелец 28.09 — рядом с шутками они
   выглядели чужими, а описания персонажей есть ниже). Освободившаяся ширина отдана шуткам: крупнее,
   по одной строке, персонаж рядом с каждой. */
.lh-hero .gs-hero-in { grid-template-columns: minmax(0, 1fr); }

.lh-h1 {
  font-size: max(16px, clamp(28px, 3.65vw, 56px));
  line-height: 1.16;
  letter-spacing: -0.028em;
  font-weight: 900;
}
/* Шутка и место её персонажа — в одном ряду, персонаж сразу за текстом. Grammlin — слева: зачеркнув,
   он разворачивается, бежит к своему месту и приседает. Между шутками воздух: три реплики, не абзац. */
.lh-joke {
  display: flex;
  align-items: center;
  gap: clamp(16px, 2.4vw, 40px);
}
.lh-fix { min-width: 0; }
.lh-joke + .lh-joke { margin-top: clamp(18px, 2.4vw, 40px); }
/* В разметке место стоит перед текстом (для обтекания в D); здесь — после текста, у Grammlin — перед. */
.lh-joke .lh-spot { order: 1; }
.lh-gl .lh-spot { order: -1; }
/* --war — пропорции фигурки, что идёт по черте (ширина к высоте); сама картинка (--img) — в разметке. */
.lh-gf { --c: var(--teal); --war: 0.8; --d: 0.6s; }
.lh-gl { --c: var(--olive); --war: 0.78; --d: 4.1s; }
.lh-gm { --c: var(--coral); --war: 0.73; --d: 7.6s; }

/* Место персонажа: высота одна на всех, ширина — по пропорциям стикера (--ar в разметке). */
.lh-spot { --sh: clamp(96px, 9.6vw, 150px); position: relative; display: block; flex: none; height: var(--sh); aspect-ratio: var(--ar); }
.lh-spot img { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; transition: opacity .25s ease; }
.lh-spot img.on { opacity: 1; }
/* Стикер действия встаёт мгновенно: его первый кадр совпадает с прилетевшей фигуркой, а переход по
   прозрачности показал бы на мгновение двух персонажей. */
.lh-spot .lh-go { transition: none; }
/* Фигурка в полёте: та же, что шла по черте; её ведёт hero.js. */
.lh-fly { position: fixed; left: 0; top: 0; z-index: 30; pointer-events: none; background: var(--img) center bottom / contain no-repeat; transform-origin: 0 0; }
@media (prefers-reduced-motion: reduce) { .lh-spot { display: none; } }

/* Кто они — сразу под шутками, почти заголовком: это ответ на все три шутки. Роли — цветами персонажей. */
.gs-hero .lh-cast {
  margin: clamp(26px, 3vw, 48px) 0 clamp(22px, 2.4vw, 34px);
  max-width: none;
  font-size: max(16px, clamp(20px, 1.9vw, 30px));
  line-height: 1.3;
  color: var(--tx-mut);
  letter-spacing: -0.015em;
}
.gs-hero .lh-cast b { display: block; color: var(--tx); font-weight: 850; font-size: 1.35em; letter-spacing: -0.02em; margin-bottom: 6px; }
/* Кнопки — в ряд: колонка теперь широкая. */
.lh-hero .gs-handoff { margin-top: 0; }
.lh-hero .gs-hf-pair { display: flex; flex-wrap: wrap; gap: 14px; width: min(100%, 800px); }
.lh-hero .gs-hf-pair > .gs-btn { flex: 1 1 300px; width: auto; }

/* Правка корректора: новое слово — над зачёркнутым, мельче, своим цветом, чуть наискосок, как от руки.
   Обёртка — строчный блок с запасом сверху: высоту получает только строка с правкой, соседние строки
   не раздвигаются, и место в самой строке правка не занимает. */
/* Запас сверху — ровно под правку (0,62 em) и зазор в пару пикселей над буквами: при 0,72 правка висела
   слишком далеко от зачёркнутого слова (владелец 28.09). */
.lh-edit { position: relative; display: inline-block; padding-top: 0.52em; }
.lh-glue { white-space: nowrap; }
.lh-ins {
  position: absolute;
  left: 0.05em;
  top: 0.04em;
  font-size: 0.62em;
  line-height: 1;
  font-weight: 850;
  white-space: nowrap;
  text-decoration: none;
  transform: rotate(-3deg);
  transform-origin: left bottom;
}

.lh-del {
  position: relative;
  white-space: nowrap;
  text-decoration: none;
  color: color-mix(in srgb, currentColor 72%, transparent);
}
/* Черта — полупрозрачная (владелец 28.09): зачёркнутое слово должно читаться сквозь неё — в нём и шутка. */
.lh-del::after {
  content: "";
  position: absolute;
  left: -0.08em;
  right: -0.08em;
  top: 52%;
  margin-top: -0.06em;
  height: 0.13em;
  border-radius: 0.07em;
  background: color-mix(in srgb, var(--c) 58%, transparent);
  transform-origin: left center;
}
.lh-walker {
  position: absolute;
  left: 0;
  top: 50%;
  --h: clamp(58px, 1.8em, 90px);
  width: calc(var(--h) * var(--war));
  height: var(--h);
  margin: calc(0.34em - var(--h)) 0 0 calc(var(--h) * var(--war) * -0.5);
  opacity: 0;
  pointer-events: none;
  z-index: 2;
}
.lh-walker::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--img) center bottom / contain no-repeat;
  transform-origin: 50% 100%;
  filter: drop-shadow(0 0.06em 0.1em rgba(40, 20, 10, 0.3));
}

html.js .lh-joke:not(.run) .lh-del { color: inherit; }
html.js .lh-joke:not(.run) .lh-del::after { transform: scaleX(0); }
html.js .lh-joke:not(.run) .lh-ins { opacity: 0; }

/* Ход строки от её старта (--d):
   +0,0        фигурка появляется у начала слова
   +0,1–1,6    идёт по слову, за ней растёт черта, слово бледнеет
   +1,6–1,95   прыжок наверх, к началу правки над словом
   +1,95–2,75  идёт по правке, за спиной она проявляется
   +2,75       уходит на своё место рядом с шуткой (hero.js ловит начало lh-off и ведёт полёт сам). */
.lh-joke.run .lh-del { animation: lh-dim 0.5s ease calc(var(--d) + 1.2s) both; }
@keyframes lh-dim { from { color: inherit; } to { color: color-mix(in srgb, currentColor 72%, transparent); } }
.lh-joke.run .lh-del::after { animation: gs-fix-line 1.5s linear calc(var(--d) + 0.1s) both; }
.lh-joke.run .lh-walker {
  animation:
    gs-fix-in 0.25s ease-out var(--d) both,
    lh-walk 1.5s linear calc(var(--d) + 0.1s) forwards,
    lh-jump 0.35s ease-in-out calc(var(--d) + 1.6s) forwards,
    lh-on 0.8s linear calc(var(--d) + 1.95s) forwards,
    lh-off 0.45s ease-in calc(var(--d) + 2.75s) forwards;
}
.lh-joke.run .lh-ins { animation: gs-fix-write 0.8s linear calc(var(--d) + 1.97s) both; }
/* Прыгают Граммон и Грамфессор; Грамлин бежит — его стикер анимирован сам. */
.lh-gf.run .lh-walker::before,
.lh-gm.run .lh-walker::before { animation: gs-fix-hop 0.4s ease-in-out calc(var(--d) + 0.1s) 4; }

/* --ix/--iy/--iw мерит hero.js; без него — «правка сразу справа, шириной 4em». */
@keyframes lh-walk { from { left: 0; top: 50%; opacity: 1; } to { left: 100%; top: 50%; opacity: 1; } }
@keyframes lh-jump {
  0% { left: 100%; top: 50%; opacity: 1; transform: none; }
  50% { transform: translateY(-0.5em) rotate(-8deg); opacity: 1; }
  100% { left: var(--ix, calc(100% + 0.3em)); top: calc(50% + var(--iy, 0px)); opacity: 1; transform: none; }
}
@keyframes lh-on {
  from { left: var(--ix, calc(100% + 0.3em)); top: calc(50% + var(--iy, 0px)); opacity: 1; }
  to { left: calc(var(--ix, calc(100% + 0.3em)) + var(--iw, 4em)); top: calc(50% + var(--iy, 0px)); opacity: 1; }
}
@keyframes lh-off {
  0% { left: calc(var(--ix, calc(100% + 0.3em)) + var(--iw, 4em)); top: calc(50% + var(--iy, 0px)); opacity: 1; transform: none; }
  96% { left: calc(var(--ix, calc(100% + 0.3em)) + var(--iw, 4em) + 0.6em); top: calc(50% + var(--iy, 0px)); opacity: 0; transform: translateY(-0.9em) rotate(14deg); }
  100% { left: 0; top: 50%; opacity: 0; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .lh-walker { display: none; }
  html.js .lh-joke .lh-del { color: color-mix(in srgb, currentColor 45%, transparent); }
  html.js .lh-joke .lh-del::after { transform: none; animation: none; }
  html.js .lh-joke .lh-ins { opacity: 1; animation: none; }
}

/* ───────────────────────── раскладка D (выбор владельца 28.09; из прототипа lab-hero)
   Базовые правила выше — колонка A, на ней D и стоит. Варианты B и C и их переключатель сняты при
   переносе в v14: выбран D, класс `lh-v-d` ставится на <html> макета (variant.mjs → htmlClass). */
/* D — выбор владельца (28.09). Заголовок — помощники, под ним три шутки плашками. Персонаж — в правом
   верхнем углу плашки и обтекается текстом (float): так шутке достаётся почти вся ширина плашки, и её
   можно набрать крупно. */
.lh-v-d .lh-hero .gs-hero-copy { display: flex; flex-direction: column; }
.lh-v-d .gs-eyebrow { order: -2; }
.lh-v-d .lh-cast { order: -1; }
.lh-v-d .gs-hero .lh-cast { margin: 0 0 clamp(26px, 3vw, 46px); font-size: max(16px, clamp(19px, 1.7vw, 26px)); }
.lh-v-d .gs-hero .lh-cast b { font-size: 2em; line-height: 1.08; letter-spacing: -0.03em; margin-bottom: 12px; }
.lh-v-d .lh-h1 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(14px, 2vw, 30px);
  font-size: max(16px, clamp(24px, 2.55vw, 40px));
  line-height: 1.1;
  margin-bottom: clamp(26px, 3vw, 44px);
}
.lh-v-d .lh-joke {
  display: flow-root;
  margin: 0;
  padding: clamp(16px, 1.7vw, 26px) clamp(16px, 1.7vw, 26px) clamp(20px, 2vw, 30px);
  border-radius: 24px;
  background: color-mix(in srgb, var(--c) 13%, transparent);
}
.lh-v-d .lh-joke + .lh-joke { margin-top: 0; }
/* Текст плашки — три строки владельца (28.09) с ОДИНАКОВЫМ шагом: правка стоит в зазоре над зачёркнутым
   словом и на соседнюю строку не наезжает, поэтому межстрочный зазор общий, а не «запас над правкой».
   Зачёркнутое — не в первой строке («ничего не ем», «такого съесть», «остались на талии»). Строки не
   переносятся; кегль подбирает hero.js (--jfs): самая тесная строка из девяти помещается в плашку
   (две первые — рядом с персонажем, последняя — во всю ширину). */
.lh-v-d .lh-h1 { font-size: var(--jfs, max(16px, clamp(24px, 2.55vw, 40px))); line-height: 1.62; }
.lh-v-d .lh-line { display: block; white-space: nowrap; }
.lh-v-d .lh-edit { padding-top: 0; }
.lh-v-d .lh-ins { top: auto; bottom: calc(100% - 0.42em); }
/* Персонаж в углу — одной высоты у всех троих (Grammon в общей ширине выходил мельче), на две строки. */
.lh-v-d .lh-spot { float: right; order: 0; width: auto; height: 3.05em; margin: -0.05em -0.1em 0 0.3em; }
/* Grammlin — не в самом углу: левее, чуть крупнее и ниже (владелец 28.09). */
.lh-v-d .lh-spot-gl { height: 3.35em; margin: 0.12em 6% 0 0.3em; }
.lh-v-d .lh-joke { padding: clamp(14px, 1.4vw, 22px) clamp(16px, 1.6vw, 24px) clamp(12px, 1.2vw, 18px); }

/* Кнопки — под своими персонажами и их цветом (владелец 28.09): «Собрать свою норму» — бирюзовая, под
   Gramfessor; «Загрузить план из PDF» — оливковая, под Grammlin; «Загрузить фото тарелки» — коралловая,
   под Grammon. Сетка та же, что у плашек. Иконки — круги, как три лица у «нормы». */
.lh-v-d .lh-hero .gs-hf-pair { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(14px, 2vw, 30px); width: 100%; }
.lh-v-d .lh-hero .gs-hf-pair > .gs-btn { width: 100%; flex: none; }
.lh-v-d .gs-hf-onb { order: 1; background: var(--teal); }
.lh-v-d .gs-hf-onb:hover { background: color-mix(in srgb, var(--teal) 88%, #000); }
.lh-v-d .lh-btn-pdf { order: 2; }
.lh-v-d .gs-hf-btn { order: 3; background: var(--coral); }
.lh-v-d .gs-hf-btn:hover { background: color-mix(in srgb, var(--coral) 88%, #000); }
.lh-v-d .gs-hf-onb .gs-onb-faces img { box-shadow: 0 0 0 2px var(--teal); }
.lh-btn-pdf { background: var(--olive); color: var(--on-bright); }
.lh-btn-pdf:hover { background: var(--olive-d, color-mix(in srgb, var(--olive) 88%, #000)); transform: translateY(-1px); }
.lh-ico2 { display: inline-flex; flex: none; }
.lh-ico2 > span { display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%; background: var(--gs-card, var(--bg)); color: var(--tx); box-shadow: 0 0 0 2px var(--bc, currentColor); }
.lh-ico2 > span + span { margin-left: -9px; }
.lh-ico2 .gs-i { width: 17px; height: 17px; }
.lh-btn-pdf .lh-ico2 { --bc: var(--olive); }
.gs-hf-btn .lh-ico2 { --bc: var(--olive); }
.lh-v-d .gs-hf-btn .lh-ico2 { --bc: var(--coral); }

/* Узкий экран (владелец 28.09): плашки те же, что на широком, только столбиком, и под каждой — её
   кнопка: норма под Gramfessor, план из PDF под Grammlin, фото под Grammon. Три колонки держатся от
   1000 px: уже них кнопки в ряд не вмещали текст с иконками (на 800 px вылезали, на 900 — впритык), а кегль шуток падал
   ниже 16 px.
   Кнопки не дублируются и разметка не меняется: заголовок-шутки, блок загрузки и ряд кнопок становятся
   display: contents, плашки и кнопки — прямыми элементами колонки, и порядок им задаёт order. Прочее
   (подпись под кнопками, состояния загрузки фото, ссылки) идёт после пар. Кегль подбирает тот же fit(),
   что на широком: самая тесная строка доходит до персонажа — без пустоты посередине плашки. */
.lh-v-d .lh-hero .gs-hf-state[hidden] { display: none; }
@media (max-width: 999px) {
  .lh-v-d .lh-h1,
  .lh-v-d .lh-hero .gs-handoff,
  .lh-v-d .lh-hero .gs-hf-state[data-hf="idle"]:not([hidden]),
  .lh-v-d .lh-hero .gs-hf-pair { display: contents; }
  .lh-v-d .lh-hero .gs-hero-copy > *,
  .lh-v-d .lh-hero .gs-handoff > *,
  .lh-v-d .lh-hero .gs-hf-state > * { order: 10; }
  .lh-v-d .lh-hero .gs-hero-copy > .gs-eyebrow { order: -2; }
  .lh-v-d .lh-hero .gs-hero-copy > .lh-cast { order: -1; }
  .lh-v-d .lh-hero .lh-h1 > .lh-gf { order: 1; }
  .lh-v-d .lh-hero .gs-hf-pair > .gs-hf-onb { order: 2; }
  .lh-v-d .lh-hero .lh-h1 > .lh-gl { order: 3; }
  .lh-v-d .lh-hero .gs-hf-pair > .lh-btn-pdf { order: 4; }
  .lh-v-d .lh-hero .lh-h1 > .lh-gm { order: 5; }
  .lh-v-d .lh-hero .gs-hf-pair > .gs-hf-btn { order: 6; }
  /* Ширина — как у плашки на широком экране с запасом: на планшете столбик не растягивается во всю
     ширину, иначе кегль, подобранный по плашке, стал бы плакатным. */
  .lh-v-d .lh-hero .lh-joke,
  .lh-v-d .lh-hero .gs-hf-pair > .gs-btn { width: 100%; max-width: 460px; }
  .lh-v-d .lh-hero .lh-joke { margin: 0 0 10px; }
  .lh-v-d .lh-hero .gs-hf-pair > .gs-btn { margin: 0 0 22px; }
  .lh-v-d .gs-hero .lh-cast b { font-size: 1.6em; }
}
