
/* ============================================================
   РАЗДЕЛ «ЭФФЕКТЫ И ТИТРЫ» timesavervfx.com/effects/ — витрина.
   Встраиваемый фрагмент. Токены наследуются из .tsv-root
   (design/tokens.css) — внутри ничего глобального не объявляем.
   Все селекторы заскоуплены под .tsv-ehub, включая ресет и медиа.
   Обложки паков — прямые ссылки на timesavervfx.com,
   свои кадры — в assets/img/.

   Структура: герой → схема-таймлайн → паки в четырёх группах →
   что с чем работает → это встанет в ваш проект → FAQ → финал.

   Заголовок первого уровня стилизован ПО КЛАССУ .tsv-eh-h1,
   а не по тегу h1: если тема хоста начнёт выводить свой <h1>,
   наш понижается до <h2> одной правкой разметки — стили не поедут.

   Кнопок на странице ноль: карточки работают ссылками целиком,
   финал — текстовыми ссылками. Прерываний фона ноль.
   backdrop-filter не используется ни разу.
   ============================================================ */

.tsv-ehub *, .tsv-ehub *::before, .tsv-ehub *::after { box-sizing: border-box; }

.tsv-ehub {
    position: relative;
    color: var(--tsv-fg);
    font-family: var(--tsv-sans);
    font-size: 16px;
    line-height: 1.6;
    background:
        radial-gradient(ellipse 70% 45% at 50% 0%, var(--tsv-accent-soft) 0%, transparent 62%),
        var(--tsv-bg);
    border: 1px solid var(--tsv-border-soft);
    border-radius: var(--tsv-radius-lg);
    overflow: hidden;
    box-shadow: 0 10px 32px -18px rgba(0, 0, 0, 0.5);
}

.tsv-ehub h1,
.tsv-ehub h2,
.tsv-ehub h3,
.tsv-ehub p { margin: 0; }
.tsv-ehub ul { margin: 0; padding: 0; list-style: none; }
.tsv-ehub img { max-width: 100%; }
.tsv-ehub a { color: inherit; }

/* Фокус с клавиатуры — одинаковый на всех ссылках, без анимации */
.tsv-ehub a:focus-visible {
    outline: 2px solid var(--tsv-accent-bright);
    outline-offset: 3px;
}

/* ---------- Общая типографика ---------- */
.tsv-ehub .tsv-eh-kicker {
    display: block;
    margin: 0 0 10px;
    font-family: var(--tsv-mono);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 2.5px;
    text-transform: uppercase;
    color: var(--tsv-accent-bright);
}
.tsv-ehub h2 {
    font-size: clamp(22px, 2.6vw, 28px);
    font-weight: 800;
    letter-spacing: -0.015em;
    line-height: 1.2;
    color: var(--tsv-fg);   /* градиента у h2 нет — он только в h1 */
}
.tsv-ehub .tsv-eh-lead-sec {
    max-width: 620px;
    margin: 12px 0 0;
    font-size: 16px;
    line-height: 1.55;
    color: var(--tsv-fg-dim);
}

/* ---------- Секции ---------- */
.tsv-ehub .tsv-eh-section { padding: 48px; }
.tsv-ehub .tsv-eh-head {
    max-width: 1040px;
    margin: 0 auto 24px;
}
.tsv-ehub .tsv-eh-wrap {
    max-width: 1040px;
    margin: 0 auto;
}

/* Ленивый рендер: браузер не считает то, что ниже экрана.
   На герое content-visibility НЕ ставим — это первый экран. */
.tsv-ehub .tsv-eh-section  { content-visibility: auto; }
.tsv-ehub .tsv-eh-s-map    { contain-intrinsic-size: auto 520px; }
/* 3650 — замер по семи карточкам с крупной обложкой, а не оценка на глаз */
.tsv-ehub .tsv-eh-s-packs  { contain-intrinsic-size: auto 3650px; }
.tsv-ehub .tsv-eh-s-pairs  { contain-intrinsic-size: auto 420px; }
.tsv-ehub .tsv-eh-s-common { contain-intrinsic-size: auto 1400px; }
.tsv-ehub .tsv-eh-s-faq    { contain-intrinsic-size: auto 560px; }


/* ============================================================
   1. ГЕРОЙ — картинки нет, кнопок нет, выключка влево.
   content-visibility не ставим: это первый экран.
   ============================================================ */
.tsv-ehub .tsv-eh-hero { padding: 56px 48px 40px; }
.tsv-ehub .tsv-eh-hero-inner { max-width: 1040px; margin: 0 auto; }
.tsv-ehub .tsv-eh-h1 {
    font-size: clamp(26px, 4.4vw, 44px);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.14;
    color: var(--tsv-fg);
}
/* Градиентный <em> используется на всей странице ровно один раз — здесь */
.tsv-ehub .tsv-eh-h1 em {
    font-style: normal;
    /* второй конец — светлый тон того же акцента, а не остаток фиолетовой темы */
    background: linear-gradient(135deg, var(--tsv-accent-bright), #dcf1ef);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
}
.tsv-ehub .tsv-eh-hero-lead {
    max-width: 620px;
    margin: 14px 0 0;
    font-size: 17px;
    color: var(--tsv-fg-dim);
}
/* Разделители «·» — обычные символы в тексте, не псевдоэлементы */
.tsv-ehub .tsv-eh-facts {
    max-width: 720px;
    margin-top: 18px;
    font-family: var(--tsv-mono);
    font-size: 11.5px;
    letter-spacing: 0.06em;
    color: var(--tsv-fg-mute);
}

/* ============================================================
   2. СХЕМА МЕСТА НА ТАЙМЛАЙНЕ — инлайновый SVG.
   Один рисунок на обе схемы: крупную в этой секции и маленькую
   в шапке каждой из семи карточек. Устройство одно — пустая
   дорожка титров сверху, четыре клипа снизу; меняется только
   подсвеченное место. Схема aria-hidden: смысл целиком несут
   метки под ней и подписи в карточках.

   ПОЧЕМУ SVG, А НЕ НАБОР SPAN-ОВ, КАК БЫЛО.
   Прежняя схема собиралась из вложенных элементов, а геометрия
   задавалась процентами: на карточке шириной 986.67px клип
   получал 325.55px, и рамка в 1px ложилась на нецелый пиксель —
   вместо линии выходила размазня в два ряда полусерого. Сверху
   на обычный блок ставился подсвеченный, и их рамки складывались
   в двойную. Ещё поверх шли box-shadow-ореолы: три источника
   свечения на 46px высоты. В SVG координаты целые, штрих один,
   а vector-effect держит его ровно в 1px на любом масштабе —
   отсюда чистая линия и там, где схема тянется по ширине колонки.

   СЕТКА. Обе схемы построены на одной разметке по горизонтали:
   клипы 31 / 76 / 35 / 51 при зазоре 5 — крупная ровно в пять
   раз шире (155 / 380 / 175 / 255 при зазоре 25). Поэтому
   четыре подсвеченные зоны крупной схемы попадают каждая в свою
   колонку меток под ней, а маленькая читается как её фрагмент.
   Клипы разной длины: это кусок таймлайна, а не три равных плитки.

   ЦВЕТ. Только токены. Пустая дорожка титров залита фоном
   страницы — жёлоб; клипы залиты приподнятой поверхностью —
   блоки. Ореолов нет ни одного: подсвеченное место отличают
   акцентная обводка и мягкая заливка, а не свечение.
   ============================================================ */

/* --- общий язык обеих схем --- */
.tsv-ehub .tsv-eh-map-rail,
.tsv-ehub .tsv-eh-rail {
    --eh-lit: var(--tsv-accent);
    display: block;   /* иначе inline-SVG стоит на базовой линии и ловит просвет */
}
.tsv-ehub .tsv-eh-map-rail *,
.tsv-ehub .tsv-eh-rail * {
    /* штрих не масштабируется вместе с рисунком: волосок остаётся волоском */
    vector-effect: non-scaling-stroke;
    stroke-width: 1;
}

/* пустая дорожка титров — утопленный жёлоб */
.tsv-ehub .tsv-eh-rail-lane {
    fill: var(--tsv-bg);
    stroke: var(--border-subtle);
}
/* клипы видеодорожки — приподнятые блоки */
.tsv-ehub .tsv-eh-rail-clips rect {
    fill: var(--tsv-bg-elev-2);
    stroke: var(--border-strong);
}

/* --- подсвеченное место: семь примитивов на восемь состояний ---
   Семи карточкам и четырём зонам крупной схемы хватает одного
   набора: заливка, приглушённая заливка, занятая область, рамка
   шлейфа, линия деления, точка входа, стык. Ничего сверх этого
   в рисунке нет — ни градиентов, ни ореолов, ни фильтров. */
.tsv-ehub .tsv-eh-rail-lit {
    transform-box: fill-box;      /* масштаб при проявлении — от своего центра, */
    transform-origin: center;     /* а не от угла viewBox */
}
.tsv-ehub .tsv-eh-rail-lit * {
    transition: fill var(--dur-base) var(--ease-out),
                stroke var(--dur-base) var(--ease-out);
}
.tsv-ehub .tsv-eh-rail-fill  { fill: var(--eh-lit); }                              /* плашка, метка */
.tsv-ehub .tsv-eh-rail-mute  { fill: var(--tsv-accent-dim); }                      /* второстепенная метка */
.tsv-ehub .tsv-eh-rail-box   { fill: var(--tsv-accent-soft); stroke: var(--eh-lit); } /* занятая область */
.tsv-ehub .tsv-eh-rail-frame { fill: none; stroke: var(--eh-lit); }                /* шлейф движения */
.tsv-ehub .tsv-eh-rail-line  { fill: none; stroke: var(--eh-lit); opacity: 0.5; }  /* деление кадра */
.tsv-ehub .tsv-eh-rail-bar   { stroke: var(--eh-lit); stroke-width: 3; }           /* точка входа */
.tsv-ehub .tsv-eh-rail-seam  { stroke: var(--eh-lit); stroke-linecap: round; }     /* стык */
/* Толщина стыка задана в пикселях, а не в единицах viewBox: колонка
   должна оставаться колонкой и на 1440, и на 390, где крупная схема
   сжата втрое. 8px — ровно ширина зазора между клипами на узком
   экране, поэтому метка садится в стык, а не наезжает на соседей. */
.tsv-ehub .tsv-eh-map-rail .tsv-eh-rail-seam { stroke-width: 8; }
.tsv-ehub .tsv-eh-rail .tsv-eh-rail-seam     { stroke-width: 7; }

/* --- крупная схема: ширина по колонке ---
   Высота идёт за шириной по пропорции viewBox, поэтому от 1040px
   до 655px схема просто уменьшается — искажения нет вовсе, и ни
   одного переопределения по брейкпоинтам ей не нужно. Ниже 655px
   включается min-height: на экране 390px схема пропорционально
   стала бы полоской в 32px, а это последнее место, где её можно
   уронить, — она объясняет всю страницу. Там рисунок тянется по
   вертикали, клипы становятся короче и выше; preserveAspectRatio
   у SVG стоит none именно ради этого, а штрихи от растяжения не
   толстеют — их держит vector-effect выше. */
.tsv-ehub .tsv-eh-map-rail {
    width: 100%;
    height: auto;
    aspect-ratio: 1040 / 108;
    min-height: 68px;
    margin-top: 26px;
}
/* --- маленькая схема в шапке карточки ---
   Фиксированные 208×44 при viewBox 208×44 — масштаб ровно 1:1,
   поэтому каждая линия попадает в целый пиксель на любом экране.
   Во всю ширину карточки её больше не растягиваем: указателю места
   хватает размера подписи, а 987px схемы над каждой из семи карточек
   были не схемой, а полосой поперёк страницы. */
.tsv-ehub .tsv-eh-rail {
    width: 208px;
    height: 44px;
    margin-bottom: 18px;
}

/* --- четвёрка меток: указатель, а не товар --- */
.tsv-ehub .tsv-eh-zones {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 16px;
    margin-top: 26px;
}
.tsv-ehub .tsv-eh-zone {
    display: grid;
    grid-template-columns: 18px minmax(0, 1fr) auto;
    column-gap: 9px;
    row-gap: 6px;
    align-items: start;
    padding-top: 12px;
    border-top: 2px solid var(--tsv-accent-soft);
    text-decoration: none;
    transition: border-top-color var(--dur-base) var(--ease-out);
}
/* номер — span, а не символ ①: кружки в части шрифтов отваливаются в квадрат */
.tsv-ehub .tsv-eh-num {
    grid-column: 1;
    grid-row: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    margin-top: 1px;
    border: 1px solid var(--tsv-border);
    border-radius: 999px;
    font-family: var(--tsv-mono);
    font-size: 10px;
    line-height: 1;
    color: var(--tsv-fg-mute);
}
.tsv-ehub .tsv-eh-zone-name {
    grid-column: 2;
    grid-row: 1;
    font-size: 15px;
    font-weight: 600;
    line-height: 1.3;
    color: var(--tsv-fg);
    transition: color var(--dur-base) var(--ease-out);
}
.tsv-ehub .tsv-eh-zone-count {
    grid-column: 3;
    grid-row: 1;
    padding-top: 2px;
    font-family: var(--tsv-mono);
    font-size: 10.5px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    white-space: nowrap;
    color: var(--tsv-fg-mute);
}
.tsv-ehub .tsv-eh-zone-desc {
    grid-column: 2 / -1;
    grid-row: 2;
    font-size: 13px;
    line-height: 1.45;
    color: var(--tsv-fg-dim);
}
.tsv-ehub .tsv-eh-quiet-line {
    margin-top: 22px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--tsv-fg-mute);
}

/* ============================================================
   3. СЕМЬ ПАКОВ — одна колонка, карточка во всю ширину.
   Карточка целиком — один <a>, вложенных ссылок внутри нет.
   ============================================================ */
.tsv-ehub .tsv-eh-group + .tsv-eh-group { margin-top: 0; }
.tsv-ehub .tsv-eh-ghead {
    margin: 34px 0 18px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--tsv-border-soft);
    scroll-margin-top: 24px;
}
.tsv-ehub .tsv-eh-group:first-child .tsv-eh-ghead { margin-top: 0; }
.tsv-ehub .tsv-eh-gname {
    font-size: 18px;
    font-weight: 600;
    line-height: 1.3;
    color: var(--tsv-fg);
}
.tsv-ehub .tsv-eh-gnote {
    max-width: 72ch;
    margin-top: 6px;
    font-size: 14px;
    line-height: 1.55;
    color: var(--tsv-fg-dim);
}

.tsv-ehub .tsv-eh-list {
    display: grid;
    gap: 20px;
    max-width: 1040px;
    margin: 0 auto;
    list-style: none;
    padding: 0;
}
.tsv-ehub .tsv-eh-item { scroll-margin-top: 24px; }

/* ---------- Раскладка карточки: обложка-герой слева, содержание справа ----------
   ЧТО БЫЛО. Схема во всю ширину сверху, текст, а обложка — в подвале,
   колодцем 168px, картинкой 156px. Пак — товар с лицом, и лицо стояло
   сноской: на 156px обложка не показывала ни сюжет, ни характер, работала
   пятном. Свободного места в карточке при этом хватало.

   ЧТО СТАЛО. Карточка делится по вертикали.
   Схема места на таймлайне стоит в шапке карточки, но больше не тянется
   во всю её ширину: 208×44 над колонкой обложки. Она различает семь паков
   раньше, чем прочитано название, и для этого ей хватает размера подписи —
   а 987px схемы над каждой из семи карточек читались уже не схемой,
   а полосой поперёк страницы, семь раз подряд.
   Ниже два столбца: слева обложка в клетке 1:1 — теперь единственный
   крупный объект карточки; справа сверху вниз готовая иерархия
   «где работает → как называется → что это → что внутри и что подставляете».
   Разделитель перед парами больше не пересекает карточку целиком,
   а закрывает только текстовый столбец: он отделяет описание от состава,
   а не текст от картинки.

   ПОЧЕМУ 240px, А НЕ БОЛЬШЕ. Исходники обложек 500×500. На ретине (dpr 2)
   250 CSS-пикселей — это ровно 1:1 по пикселям файла; всё, что крупнее,
   растягивает картинку и даёт мыло. 240px оставляет запас.
   У «Мультиэкрана» исходник 768px, он мог бы дорасти до 384px — но клетка
   у семи паков одна. Одинаковая оправа и есть единственное, что собирает
   семь чужих обложек в серию; разнокалиберные клетки её ломают.
   Его запас уходит в резкость (3.2× против 2.08× у остальных), а не в размер.

   ПОЧЕМУ БЕЗ ТЕМАТИЧЕСКОГО ЦВЕТА ПАКА. Своя акцентная группа в
   design/accents.css есть у шести лендингов из семи — у «Мультиэкрана» её
   нет. Покрасить шесть карточек и оставить седьмую серой — то же самое,
   что показать гарантию у шести и умолчать у одного: витрина сама назначит
   ему худшее место. Цвет на странице один, бирюзовый, общий.

   Обложка не двигается при наведении ни на пиксель: во все семь вшит текст,
   любой сдвиг или масштаб внутри клетки его подрезает. Оживает градация.
   ------------------------------------------------------------------------- */
.tsv-ehub .tsv-eh-card {
    /* сторона картинки внутри колодца; колодец = сторона + 16px паспарту */
    --eh-cover: 240px;
    position: relative;
    display: block;
    padding: 22px 26px;
    border-radius: var(--tsv-radius);
    border: 1px solid var(--tsv-border);
    background: linear-gradient(180deg, rgba(31, 24, 56, 0.55) 0%, rgba(21, 16, 42, 0.55) 100%);
    text-decoration: none;
    color: inherit;
    transition: transform var(--dur-slow) var(--ease-out),
                border-color var(--dur-base) var(--ease-out),
                box-shadow var(--dur-slow) var(--ease-out);
}

/* ---------- Схема места на таймлайне ----------
   Стили обеих схем — маленькой в шапке карточки и крупной
   в секции 2 — лежат вместе, в разделе 2 этого файла: рисунок
   у них общий, и разносить его по двум местам значит однажды
   поправить только одно. Здесь остаются семь модификаторов
   .tsv-eh-rail--* — они не несут геометрии, вся она в разметке
   SVG; модификатор нужен, чтобы состояние читалось в коде
   и находилось поиском. */

/* ---------- Слои карточки ---------- */
/* Тело карточки: слева колодец обложки, справа весь текст.
   Колонка обложки задана жёстко, текстовая забирает остаток —
   поэтому обложки всех семи карточек стоят по одной вертикали
   и на одной высоте от верха карточки, без подпорок вроде margin-top: auto. */
.tsv-ehub .tsv-eh-body {
    display: grid;
    grid-template-columns: calc(var(--eh-cover) + 16px) minmax(0, 1fr);
    column-gap: 28px;
}
.tsv-ehub .tsv-eh-main {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.tsv-ehub .tsv-eh-where {
    display: block;
    margin: 2px 0 10px;
    font-family: var(--tsv-mono);
    font-size: 10.5px;
    letter-spacing: 1.6px;
    text-transform: uppercase;
    color: var(--tsv-accent-bright);
}
.tsv-ehub .tsv-eh-name {
    font-size: 22px;
    font-weight: 600;
    line-height: 1.2;
    color: var(--tsv-fg);
}
.tsv-ehub .tsv-eh-lead {
    display: block;
    max-width: 62ch;
    margin: 7px 0 0;
    font-size: 15px;
    line-height: 1.55;
    color: var(--tsv-fg-dim);
}

/* Колодец обложки: паспарту 8px, клетка строго 1:1, кадрирования нет.
   align-self: start — иначе растянутый по строке грид-элемент потеряет квадрат. */
.tsv-ehub .tsv-eh-cover {
    position: relative;
    display: block;
    align-self: start;
    width: calc(var(--eh-cover) + 16px);
    max-width: 100%;
    height: auto;
    aspect-ratio: 1 / 1;
    padding: 8px;
    background: #0e0b12;
    border-radius: 14px;
    outline: 1px solid rgba(255, 255, 255, 0.06);
}
.tsv-ehub .tsv-eh-cover img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: 8px;
    /* одинаковая градация собирает семь чужих обложек в серию.
       На 240px гасить так же жёстко, как на 156px, уже нельзя:
       крупная картинка от этого мутнеет. Снято до минимума, при котором
       семь разных обложек ещё читаются одной серией. */
    filter: saturate(0.7) brightness(0.86);
    transition: filter var(--dur-slow) var(--ease-out);
}
/* вуаль и нижняя виньетка — обычные слои, без mix-blend-mode */
.tsv-ehub .tsv-eh-cover::after {
    content: "";
    position: absolute;
    inset: 8px;
    pointer-events: none;
    border-radius: 8px;
    background:
        linear-gradient(180deg, rgba(10, 6, 18, 0) 58%, rgba(10, 6, 18, 0.46) 100%),
        linear-gradient(0deg, var(--tsv-accent-soft), var(--tsv-accent-soft));
    transition: opacity var(--dur-slow) var(--ease-out);
}

/* Состав пака: разделитель закрывает только текстовый столбец —
   он отделяет описание от содержания, а не текст от картинки */
.tsv-ehub .tsv-eh-pairs {
    display: grid;
    row-gap: 14px;
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--tsv-border-soft);
}
.tsv-ehub .tsv-eh-pair {
    display: grid;
    row-gap: 10px;
}
.tsv-ehub .tsv-eh-key {
    font-family: var(--tsv-mono);
    /* 9.5px читались с трудом и выпадали из шкалы микроподписей самого
       лендинга (10 / 10.5px). Приведено к 10.5px — как у соседних меток */
    font-size: 10.5px;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    line-height: 1;
    color: var(--tsv-fg-mute);
}
.tsv-ehub .tsv-eh-val {
    font-size: 13.5px;
    line-height: 1.5;
    color: var(--tsv-fg-dim);
}
/* Подпись одинакова у всех семи: сравнивают паки, а не формулировки.
   margin-top: auto прижимает её к низу текстового столбца — на карточках,
   где текст короче обложки, строка встаёт вровень с нижним краем колодца. */
.tsv-ehub .tsv-eh-more {
    display: block;
    margin-top: auto;
    padding-top: 18px;
    font-family: var(--tsv-mono);
    font-size: 11.5px;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    text-align: right;
    white-space: nowrap;
    color: var(--tsv-accent-bright);
}
.tsv-ehub .tsv-eh-arr {
    display: inline-block;
    transition: transform var(--dur-base) var(--ease-out);
}

/* ============================================================
   4. ЧТО С ЧЕМ РАБОТАЕТ — четыре наблюдения хайрлайнами.
   Ни картинок, ни кнопок, ни плашек «комплект».
   ============================================================ */
.tsv-ehub .tsv-eh-obs {
    max-width: 76ch;
    padding: 16px 0;
    border-top: 1px solid var(--tsv-border-soft);
    font-size: 15px;
    line-height: 1.6;
    color: var(--tsv-fg-dim);
}
.tsv-ehub .tsv-eh-obs:first-child { border-top: 0; }
.tsv-ehub .tsv-eh-obs a {
    font-weight: 600;
    color: var(--tsv-fg);
    text-decoration: underline;
    text-decoration-color: var(--tsv-accent-soft);
    text-underline-offset: 3px;
    transition: color var(--dur-base) var(--ease-out),
                text-decoration-color var(--dur-base) var(--ease-out);
}
.tsv-ehub .tsv-eh-obs-note {
    max-width: 76ch;
    margin-top: 20px;
    padding-top: 16px;
    border-top: 1px solid var(--tsv-border-soft);
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--tsv-fg-mute);
}

/* ============================================================
   5. ЭТО ВСТАНЕТ В ВАШ ПРОЕКТ — три ряда, кадр слева/справа/слева.
   Прерывания фона нет: все три ряда на общей подложке контейнера.
   Текста поверх фотографии нет нигде.
   ============================================================ */
.tsv-ehub .tsv-eh-row {
    display: grid;
    grid-template-columns: minmax(0, 460px) minmax(0, 1fr);
    gap: 32px;
    align-items: center;
}
.tsv-ehub .tsv-eh-row + .tsv-eh-row { margin-top: 40px; }
/* стороны чередуются: direction не трогаем, меняем order */
.tsv-ehub .tsv-eh-row--flip { grid-template-columns: minmax(0, 1fr) minmax(0, 460px); }
.tsv-ehub .tsv-eh-row--flip .tsv-eh-row-media { order: 2; }
.tsv-ehub .tsv-eh-row--flip .tsv-eh-row-body  { order: 1; }

.tsv-ehub .tsv-eh-shot {
    position: relative;
    height: auto;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border: 1px solid var(--tsv-border-soft);
    border-radius: var(--tsv-radius-sm);
    background: #0e0b12;
}
.tsv-ehub .tsv-eh-shot img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    filter: saturate(0.78) brightness(0.88);
}
.tsv-ehub .tsv-eh-shot img[src$="-info-20261004.svg"] {
    object-fit: contain;
    filter: none;
}
.tsv-ehub .tsv-eh-rh {
    margin-bottom: 14px;
    font-size: 18px;
    font-weight: 600;
    line-height: 1.3;
    color: var(--tsv-fg);
}
/* Ряд 1 — бенто-грид бейджей. Ни иконок, ни галочек. */
.tsv-ehub .tsv-eh-badges {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
}
.tsv-ehub .tsv-eh-badge {
    padding: 14px 16px;
    border: 1px solid var(--tsv-border-soft);
    border-radius: var(--tsv-radius-sm);
    background: var(--tsv-bg-glass);
}
.tsv-ehub .tsv-eh-badge-t {
    display: block;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.4;
    color: var(--tsv-fg);
}
.tsv-ehub .tsv-eh-badge-d {
    display: block;
    margin-top: 4px;
    font-size: 13px;
    line-height: 1.45;
    color: var(--tsv-fg-dim);
}
/* Ряды 2 и 3 — хайрлайны */
.tsv-ehub .tsv-eh-step {
    padding: 13px 0;
    border-top: 1px solid var(--tsv-border-soft);
    font-size: 14.5px;
    line-height: 1.55;
    color: var(--tsv-fg-dim);
}
.tsv-ehub .tsv-eh-step-t {
    font-weight: 600;
    color: var(--tsv-fg);
}
.tsv-ehub .tsv-eh-step a {
    font-weight: 600;
    color: var(--tsv-fg);
    text-decoration: underline;
    text-decoration-color: var(--tsv-accent-soft);
    text-underline-offset: 3px;
    transition: color var(--dur-base) var(--ease-out),
                text-decoration-color var(--dur-base) var(--ease-out);
}

/* ============================================================
   6. ЧАСТЫЕ ВОПРОСЫ — нативные details, без JS и ARIA-акробатики
   ============================================================ */
.tsv-ehub .tsv-eh-faq { max-width: 820px; }
.tsv-ehub .tsv-eh-faq details { border-top: 1px solid var(--tsv-border-soft); }
.tsv-ehub .tsv-eh-q {
    position: relative;
    padding: 16px 34px 16px 0;
    font-size: 16px;
    font-weight: 600;
    line-height: 1.4;
    color: var(--tsv-fg);
    cursor: pointer;
    list-style: none;
}
.tsv-ehub .tsv-eh-q::-webkit-details-marker { display: none; }
/* свой знак: плюс из двух псевдоэлементов, в минус при [open] */
.tsv-ehub .tsv-eh-q::before,
.tsv-ehub .tsv-eh-q::after {
    content: "";
    position: absolute;
    right: 4px;
    top: 50%;
    width: 12px;
    height: 1.5px;
    background: var(--tsv-fg-mute);
    transition: transform var(--dur-base) var(--ease-out);
}
.tsv-ehub .tsv-eh-q::before { transform: translateY(-50%); }
.tsv-ehub .tsv-eh-q::after  { transform: translateY(-50%) rotate(90deg); }
.tsv-ehub details[open] .tsv-eh-q::after { transform: translateY(-50%) rotate(0deg); }
.tsv-ehub .tsv-eh-a {
    max-width: 76ch;
    padding: 0 0 18px;
    font-size: 14.5px;
    line-height: 1.6;
    color: var(--tsv-fg-dim);
}
.tsv-ehub .tsv-eh-a a {
    font-weight: 600;
    color: var(--tsv-fg);
    text-decoration: underline;
    text-decoration-color: var(--tsv-accent-soft);
    text-underline-offset: 3px;
    transition: color var(--dur-base) var(--ease-out),
                text-decoration-color var(--dur-base) var(--ease-out);
}








/* ============================================================
   Наведение — только там, где есть настоящий курсор.
   Обложку не двигаем: любое движение в клетке 1:1 режет вшитый текст.
   ============================================================ */
@media (hover: hover) and (pointer: fine) {
    .tsv-ehub .tsv-eh-card:hover {
        transform: translateY(-2px);
        border-color: var(--tsv-accent-dim);
        box-shadow: 0 12px 32px -16px rgba(0, 0, 0, 0.62);
    }
    /* оживает только градация — единственная награда за наведение */
    .tsv-ehub .tsv-eh-card:hover .tsv-eh-cover img { filter: saturate(0.98) brightness(1); }
    .tsv-ehub .tsv-eh-card:hover .tsv-eh-cover::after { opacity: 0.5; }
    /* подсвеченное место схемы светлеет — одной подменой токена
       на все семь состояний, без ореолов и без смены геометрии */
    .tsv-ehub .tsv-eh-card:hover .tsv-eh-rail { --eh-lit: var(--tsv-accent-bright); }
    .tsv-ehub .tsv-eh-card:hover .tsv-eh-arr { transform: translateX(3px); }

    /* Метки схемы: только цвет и граница, без подъёма и тени */
    .tsv-ehub .tsv-eh-zone:hover { border-top-color: var(--tsv-accent-dim); }
    .tsv-ehub .tsv-eh-zone:hover .tsv-eh-zone-name { color: var(--tsv-accent-bright); }

    .tsv-ehub .tsv-eh-obs a:hover,
    .tsv-ehub .tsv-eh-step a:hover,
    .tsv-ehub .tsv-eh-a a:hover {
        color: var(--tsv-accent-bright);
        text-decoration-color: var(--tsv-accent-bright);
    }
    
}

/* ============================================================
   Движение. Бесконечных анимаций на странице нет ни одной.
   Скрытое состояние живёт только под классом is-armed, который
   вешает JS: без JS и при reduce схемы и карточки видны сразу.
   ============================================================ */
.tsv-ehub.is-armed .tsv-eh-card {
    opacity: 0;
    transform: translateY(10px);
    transition: opacity var(--dur-slow) var(--ease-out) calc(var(--i, 0) * 60ms),
                transform var(--dur-slow) var(--ease-out) calc(var(--i, 0) * 60ms);
}
.tsv-ehub.is-armed .tsv-eh-card.is-in {
    opacity: 1;
    transform: none;
    /* после проявления карточка возвращается к обычным переходам наведения */
    transition: transform var(--dur-slow) var(--ease-out),
                border-color var(--dur-base) var(--ease-out),
                box-shadow var(--dur-slow) var(--ease-out);
}
/* Подсвеченное место проявляется вместе с карточкой — одно правило
   на все семь состояний вместо частного случая для стыка. */
.tsv-ehub.is-armed .tsv-eh-card .tsv-eh-rail-lit {
    opacity: 0;
    transform: scale(0.94);
    transition: opacity 420ms var(--ease-out),
                transform 420ms var(--ease-out);
}
.tsv-ehub.is-armed .tsv-eh-card.is-in .tsv-eh-rail-lit { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
    .tsv-ehub *, .tsv-ehub *::before, .tsv-ehub *::after {
        transition: none !important;
        animation: none !important;
    }
    .tsv-ehub .tsv-eh-card { opacity: 1 !important; transform: none !important; }
}

/* ============================================================
   Брейкпоинты: 1099 / 899 / 760 / 699.
   Обложка сжимается ступенями, потому что текстовому столбцу
   нужен разумный минимум: ниже ~380px строка состава рвётся в лапшу.
   На каждой ступени клетка остаётся квадратной и не превышает
   250 CSS-пикселей — потолок резкости для исходников 500×500.
   ============================================================ */
@media (max-width: 1099px) {
    .tsv-ehub .tsv-eh-card { --eh-cover: 216px; }
    .tsv-ehub .tsv-eh-body { column-gap: 24px; }
}
/* 899, а не 900: тот же порог, что на главной, «о проекте», консультациях
   и в хабе курсов — иначе ровно на 900px соседние лендинги ведут себя по-разному */
@media (max-width: 899px) {
    /* 761–899 ряд ещё в две колонки, и на текст остаётся ~178px:
       два бейджа в строке дают по 81px — слова «Бесплатная редакция…»
       не влезают и вылезают за карточку. Ниже 900px бейджи в одну колонку. */
    .tsv-ehub .tsv-eh-badges { grid-template-columns: minmax(0, 1fr); }
    .tsv-ehub .tsv-eh-card { --eh-cover: 192px; }
}
@media (max-width: 760px) {
    .tsv-ehub .tsv-eh-section { padding: 36px 20px; }
    .tsv-ehub .tsv-eh-hero { padding: 36px 20px 28px; }
    .tsv-ehub .tsv-eh-hero-lead { font-size: 15.5px; }

    /* Мобильные интринсики держим в медиа-выборке, иначе прыгает скроллбар */
    .tsv-ehub .tsv-eh-s-map    { contain-intrinsic-size: auto 760px; }
    /* 761–899 карточка ещё в две колонки — это её высота */
    .tsv-ehub .tsv-eh-s-packs  { contain-intrinsic-size: auto 3900px; }
    .tsv-ehub .tsv-eh-s-pairs  { contain-intrinsic-size: auto 620px; }
    .tsv-ehub .tsv-eh-s-common { contain-intrinsic-size: auto 2400px; }
    .tsv-ehub .tsv-eh-s-faq    { contain-intrinsic-size: auto 640px; }
    

    /* Метки схемы: 2 × 2, счётчик уезжает под подстрочник */
    .tsv-ehub .tsv-eh-zones { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
    .tsv-ehub .tsv-eh-zone { grid-template-columns: 18px minmax(0, 1fr); }
    .tsv-ehub .tsv-eh-zone-count { grid-column: 2; grid-row: 3; padding-top: 0; }
    .tsv-ehub .tsv-eh-zone-desc { grid-column: 2; }

    /* Сплиты секции 5: кадр сверху, текст под ним — во всех трёх рядах */
    .tsv-ehub .tsv-eh-row,
    .tsv-ehub .tsv-eh-row--flip { grid-template-columns: minmax(0, 1fr); gap: 22px; }
    .tsv-ehub .tsv-eh-row--flip .tsv-eh-row-media { order: 0; }
    .tsv-ehub .tsv-eh-row--flip .tsv-eh-row-body  { order: 0; }
    .tsv-ehub .tsv-eh-row + .tsv-eh-row { margin-top: 32px; }
    .tsv-ehub .tsv-eh-badges { grid-template-columns: minmax(0, 1fr); }

    
}
@media (max-width: 699px) {
    /* Карточка встала в одну колонку и подросла — интринсик пересчитан */
    .tsv-ehub .tsv-eh-s-packs { contain-intrinsic-size: auto 6000px; }

    /* Карточка */
    .tsv-ehub .tsv-eh-card { --eh-cover: 248px; padding: 18px 16px; }
    .tsv-ehub .tsv-eh-name { font-size: 19px; }
    .tsv-ehub .tsv-eh-lead { font-size: 14px; }
    .tsv-ehub .tsv-eh-rail { margin-bottom: 16px; }

    /* Тело в одну колонку: обложка сверху, текст под ней.
       248px — это ровно потолок: на ретине 496 из 500 пикселей исходника,
       ещё чуть шире — и пойдёт мыло. На телефоне колодец упирается
       в ширину колонки и занимает её целиком; на планшете в портрете
       колонка шире потолка, и остаток раскладывается симметрично по бокам:
       поле с двух сторон читается как поле, поле с одной — как обрубок. */
    .tsv-ehub .tsv-eh-body {
        grid-template-columns: minmax(0, 1fr);
        row-gap: 16px;
    }
    .tsv-ehub .tsv-eh-cover {
        margin-left: auto;
        margin-right: auto;
    }
    .tsv-ehub .tsv-eh-more {
        display: flex;
        align-items: center;
        min-height: 44px;
        margin-top: 14px;
        padding-top: 0;
        border-top: 1px solid var(--tsv-border-soft);
        text-align: left;
        white-space: normal;
    }
}
@media (max-width: 420px) {
    .tsv-ehub .tsv-eh-section { padding: 36px 16px; }
    .tsv-ehub .tsv-eh-hero { padding: 36px 16px 28px; }
}
