/* ============================================================
   96 — Галерея изображений: общий закон поведения

   Одна сущность во всех блоках. В покое видно только кадр. При
   наведении приходит хром: дорожка сегментов сверху (активный
   заполняется, как в stories) и счётчик N/M со стрелками снизу.
   Клик по дорожке — прыжок на кадр.

   Хром — стекло: полупрозрачная светлая плашка с размытием и
   волосяной кромкой. Материал обязан быть вписан в кадр: галерея
   клипует по своему радиусу, хром отступает от кромок.

   Файл идёт после блочных: правит поведение медиа-слотов, но не
   лезет в их исходники. Разметку строит js/gallery.js.
   ============================================================ */

.gal {
  --gal-dwell: 6s;        /* кадр держится дольше (правка Alexa: +3 с) */
  --gal-fade: 460ms;      /* перекрёстное затухание между кадрами (правка Alexa: медленнее) */
  --gal-chrome: 220ms;    /* приход и уход материала */
  --gal-ease: cubic-bezier(0.4, 0, 0.2, 1);

  /* Стекло — чёрно-белое (правка Alexa: цветной отлив выбивался из
     стилистики). Размытие остаётся, насыщенность НЕ поднимаем:
     именно она давала «зеркальный» цветной блик. Гамма хрома
     переключается по яркости кадра, на котором он лежит. */
  --gal-glass: rgba(255, 255, 255, 0.16);
  --gal-glass-edge: rgba(255, 255, 255, 0.30);
  --gal-blur: 20px;
  --gal-sat: 100%;
  --gal-shadow: 0 6px 20px rgba(0, 0, 0, 0.28);
  --gal-ink: #EAEAEA;                    /* цвет надписей и стрелок */

  --gal-seg-empty: rgba(255, 255, 255, 0.26);
  --gal-seg-full: #EAEAEA;

  --gal-inset: 2px;       /* верхняя дорожка: 2px сверху и по бокам */
  --gal-inset-bottom: 16px;  /* нижняя переключалка стоит свободнее (правка Alexa) */
  --gal-radius: 16px;     /* радиус кадра-слота; хром скругляется концентрично */
  --gal-bar: 22px;        /* высота дорожки */
  --gal-seg-h: 4px;
  --gal-nav: 55px;        /* было 76 — правка −28% */

  isolation: isolate;
  /* Материал обязан быть вписан в кадр. Слоты приходят с разным
     overflow (у .svc-screen он visible), поэтому клип задаёт сама
     галерея, а не блок. */
  overflow: hidden;
}

/* НЕ ПЕРЕНОСИТЬ `position` обратно в `.gal`. Специфичность там равна
   блочной, а файл идёт по каскаду позже — и слоты, которые блок ставит
   абсолютом (`.se-frame`, `.qp-saas-panel`, `.qp-m-saas-media`),
   теряют позиционирование и падают в поток. Именно так панель Saas
   дважды уезжала на чипсы. `:where()` = нулевая специфичность: своя
   система координат появляется только там, где блок её не задал. */
:where(.gal) {
  position: relative;
}

/* ---------- кадры ---------- */

.gal-frame {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--gal-fade) var(--gal-ease);
  pointer-events: none;
}

/* Кадр, который был в слоте изначально, сохраняет авторскую геометрию
   (кроп коллажа, макет телефона) — общий object-fit его бы сломал. */
.gal-frame--native {
  position: static;
  inset: auto;
}

.gal-frame.is-on {
  opacity: 1;
}

/* Только у кадров, которые построил скрипт. Нативный кадр — это
   перенесённое содержимое слота со своей вёрсткой, и общее правило
   картинки его ломает: в кейсах под него попадал курсор-аннотация
   и переставал скрываться. */
.gal-frame:not(.gal-frame--native) > img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}

/* ---------- хром ---------- */

.gal-chrome {
  position: absolute;
  inset: 0;
  z-index: 2;
  opacity: 0;              /* в покое хрома нет: лишний шум на кадре */
  visibility: hidden;
  transition:
    opacity var(--gal-chrome) var(--gal-ease),
    visibility 0s linear var(--gal-chrome);
}

.gal:hover > .gal-chrome,
.gal:focus-within > .gal-chrome,
.gal--touch > .gal-chrome {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s, 0s;
}

/* Один кадр — не галерея: хрома нет ни в покое, ни на наведении */
.gal--single > .gal-chrome {
  display: none;
}

/* ---------- сам материал ---------- */

.gal-track,
.gal-switch {
  background: var(--gal-glass);
  border: 1px solid var(--gal-glass-edge);
  box-shadow: var(--gal-shadow);
  -webkit-backdrop-filter: blur(var(--gal-blur)) saturate(var(--gal-sat));
  backdrop-filter: blur(var(--gal-blur)) saturate(var(--gal-sat));
  /* Стекло не проявляется, а приходит: размытие и масштаб идут
     вместе, иначе материал читается как наклейка с прозрачностью. */
  transition:
    transform var(--gal-chrome) var(--gal-ease),
    -webkit-backdrop-filter var(--gal-chrome) var(--gal-ease),
    backdrop-filter var(--gal-chrome) var(--gal-ease);
}

.gal:not(:hover):not(:focus-within):not(.gal--touch) .gal-track,
.gal:not(:hover):not(:focus-within):not(.gal--touch) .gal-switch {
  -webkit-backdrop-filter: blur(0px) saturate(100%);
  backdrop-filter: blur(0px) saturate(100%);
}

/* Свет ловит верхнюю кромку материала — как у настоящего стекла */
.gal-track::after,
.gal-switch::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(rgba(255, 255, 255, 0.10), rgba(255, 255, 255, 0) 46%);
}

/* ---------- дорожка сегментов ---------- */

.gal-track {
  position: absolute;
  top: var(--gal-inset);
  left: var(--gal-inset);
  right: var(--gal-inset);
  box-sizing: border-box;
  height: var(--gal-bar);
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 10px;
  box-shadow: none;   /* тень «съедала» зазор в углу — зазор должен читаться ровным */
  /* Скругление концентрично кадру: внешний радиус минус отступ.
     Капсула (999px) спорила с углом кадра, на котором лежит хром. */
  /* Верхние углы обязаны повторять кромку кадра: радиус = радиус кадра
     минус отступ. Браузер режет радиусы, только если их СУММА по стороне
     больше высоты, поэтому нижние углы берут остаток: top + bottom = высота.
     Так полоса остаётся низкой, а её верхний угол точно концентричен кадру. */
  --gal-top-r: min(calc(var(--gal-radius) - var(--gal-inset)), var(--gal-bar));
  border-radius: var(--gal-top-r) var(--gal-top-r)
                 calc(var(--gal-bar) - var(--gal-top-r)) calc(var(--gal-bar) - var(--gal-top-r));
  /* Нажимается вся плашка, а не полоска в 4px: кадр выбирается
     по горизонтали, промахнуться нечем. */
  cursor: pointer;
  opacity: .82;
}

.gal:hover .gal-track,
.gal:focus-within .gal-track,
.gal--touch .gal-track {
  opacity: 1;
}

.gal-seg {
  position: relative;
  flex: 1 0 0;
  min-width: 1px;
  height: var(--gal-seg-h);
  padding: 0;
  border: 0;
  border-radius: 12px;
  background: var(--gal-seg-empty);
  overflow: hidden;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: height 140ms var(--gal-ease);
}

/* Дорожка под курсором — сегменты слегка набирают тело: видно, что
   это орган управления, а не индикатор. */
.gal-track:hover .gal-seg {
  height: calc(var(--gal-seg-h) + 2px);
}

.gal-seg.is-past {
  background: var(--gal-seg-full);
}

.gal-seg-fill {
  position: absolute;
  inset: 0;
  border-radius: 12px;
  background: var(--gal-seg-full);
  transform: scaleX(0);
  transform-origin: left center;
}

/* Заливка идёт только пока галерея под курсором. Уходит курсор —
   сегмент замирает на достигнутом, а не отматывается назад. */
.gal:hover .gal-seg.is-at .gal-seg-fill,
.gal:focus-within .gal-seg.is-at .gal-seg-fill {
  animation: gal-fill var(--gal-dwell) linear forwards;
}

@keyframes gal-fill {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* ---------- счётчик со стрелками ---------- */

.gal-switch {
  position: absolute;
  bottom: var(--gal-inset-bottom);
  left: 50%;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  border-radius: 999px;    /* капсула — как в макете, скругление кадра тут ни при чём */
  transform: translateX(-50%);
  opacity: .82;
}

.gal:hover .gal-switch,
.gal:focus-within .gal-switch,
.gal--touch .gal-switch {
  opacity: 1;
}

.gal-nav {
  position: relative;
  flex: none;
  width: var(--gal-nav);
  height: var(--gal-nav);
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.gal-nav-ring,
.gal-nav-arrow {
  position: absolute;
  left: 50%;
  top: 50%;
  display: block;
  transition: opacity 160ms var(--gal-ease);
}

.gal-nav-ring {
  width: calc(var(--gal-nav) * 0.84);
  height: calc(var(--gal-nav) * 0.84);
  transform: translate(-50%, -50%);
  opacity: 0.6;
}

.gal-nav--prev .gal-nav-ring {
  width: calc(var(--gal-nav) * 0.74);
  height: calc(var(--gal-nav) * 0.74);
}

.gal-nav-arrow {
  width: calc(var(--gal-nav) * 0.12);
  height: calc(var(--gal-nav) * 0.21);
}

.gal-nav--prev .gal-nav-arrow {
  transform: translate(calc(-50% - 2px), -50%) rotate(180deg);
}

.gal-nav--next .gal-nav-arrow {
  transform: translate(calc(-50% + 2px), -50%);
}

.gal-nav:hover .gal-nav-ring,
.gal-nav:focus-visible .gal-nav-ring {
  opacity: 1;
}

/* Вибрантность: поверх меняющегося кадра плоский серый не живёт —
   белый, трекинг с прибавкой и тень под буквой. Вес лёгкий: тонкие
   цифры держатся на тени и трекинге, а не на массе штриха.
   Воздух между цифрами и слэшем добавлен в самой строке счётчика. */
.gal-count {
  position: relative;
  padding: 0 2px;
  font-weight: 300;
  font-size: 14px;
  line-height: 18px;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;   /* счётчик не должен дёргаться на смене цифры */
  text-align: center;
  white-space: nowrap;
  color: var(--gal-ink);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.28);
}

/* ---------- размер материала от ширины слота, не от окна ---------- */

.gal[data-gal-size="md"] {
  --gal-bar: 20px;
  --gal-nav: 44px;
  --gal-blur: 16px;
  --gal-shadow: 0 4px 14px rgba(0, 0, 0, 0.20);
}
.gal[data-gal-size="md"] .gal-track { gap: 5px; padding: 0 8px; }
.gal[data-gal-size="md"] .gal-count { font-size: 13px; line-height: 17px; }

.gal[data-gal-size="sm"] {
  --gal-bar: 16px;
  --gal-seg-h: 3px;
  --gal-nav: 32px;
  --gal-blur: 12px;
  --gal-shadow: 0 3px 10px rgba(0, 0, 0, 0.18);
}
.gal[data-gal-size="sm"] .gal-track { gap: 4px; padding: 0 6px; }
.gal[data-gal-size="sm"] .gal-count { font-size: 11px; line-height: 14px; letter-spacing: 0.06em; }

/* ---------- старый хром секций гасим ---------- */

/* Таймлайны и счётчики были нарисованы внутри блоков поштучно.
   Теперь их строит галерея — статичные копии убираем. */
.cs-media .cs-timeline,
.cs-media .cs-switch,
.se-frame .se-timeline {
  display: none;
}

/* Курсор из макета — аннотация, показывавшая, что слот реагирует на
   наведение, а не элемент интерфейса. Один и тот же файл разложен по
   четырём блокам; реальное поведение теперь есть, картинка не нужна.
   Селекторы с тегом: в блоках есть правила вида `.imp img`, и они
   специфичнее голого класса. Порядок файлов тут не спасает. */
img.cs-cursor,
img.imp-cursor,
img.sol-cursor,
img.ads-cursor {
  display: none;
}

/* ---------- доступность ---------- */

.gal-seg:focus-visible,
.gal-nav:focus-visible {
  outline: 2px solid #FFFFFF;
  outline-offset: 3px;
}

/* Прозрачность отключена системно — стекло становится плотным,
   размытие снимается, иначе материал теряет смысл и вредит. */
@media (prefers-reduced-transparency: reduce) {
  .gal-track,
  .gal-switch {
    background: rgba(20, 20, 22, 0.94);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .gal-track::after,
  .gal-switch::after { content: none; }
}

@media (prefers-contrast: more) {
  .gal {
    --gal-glass-edge: #FFFFFF;
    --gal-seg-empty: rgba(0, 0, 0, 0.6);
  }
  .gal-track,
  .gal-switch { background: rgba(16, 16, 18, 0.96); }
}

@media (prefers-reduced-motion: reduce) {
  .gal-frame,
  .gal-chrome,
  .gal-track,
  .gal-switch,
  .gal-seg {
    transition-duration: 1ms;
  }
  /* Без движения лента сама не идёт: заливки нет, кадр меняется
     только руками. */
  .gal:hover .gal-seg.is-at .gal-seg-fill,
  .gal:focus-within .gal-seg.is-at .gal-seg-fill {
    animation: none;
    transform: scaleX(1);
  }
}



/* ============================================================
   Хром всегда контрастен тому, на чём лежит (правка Alexa).
   Класс ставит js/gallery.js по замеренной яркости кадра в той
   полосе, где хром физически находится. Чёрно-белая гамма,
   размытие сохраняется в обоих состояниях.
   ============================================================ */
.gal--on-light {
  --gal-glass: rgba(23, 23, 25, 0.42);
  --gal-glass-edge: rgba(23, 23, 25, 0.28);
  --gal-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
  --gal-ink: #EAEAEA;
  --gal-seg-empty: rgba(234, 234, 234, 0.34);
  --gal-seg-full: #EAEAEA;
}

.gal--on-dark {
  --gal-glass: rgba(234, 234, 234, 0.18);
  --gal-glass-edge: rgba(234, 234, 234, 0.30);
  --gal-shadow: 0 6px 20px rgba(0, 0, 0, 0.32);
  --gal-ink: #EAEAEA;
  --gal-seg-empty: rgba(234, 234, 234, 0.26);
  --gal-seg-full: #EAEAEA;
}

/* Радиус кадра выводится из высоты дорожки. Браузер клампит радиус
   элемента до половины его высоты: при дорожке 22px радиус больше 11
   не применится, и хром перестанет быть концентричным кадру — в углу
   зазор схлопывается. Поэтому кадру задаётся R = высота/2 + отступ. */
.gal { border-radius: calc(var(--gal-bar) / 2 + var(--gal-inset)); }
.gal { --gal-radius: calc(var(--gal-bar) / 2 + var(--gal-inset)); }


/* Тень остаётся только у нижнего счётчика: у верхней дорожки она
   расходилась по контуру и в углу зрительно сокращала зазор до кромки
   кадра — зазор обязан читаться одинаковым и на стороне, и в углу. */
.gal-track { box-shadow: none; }

/* ============================================================
   Кейсы: цепочка скруглений карточка → кадр → хром.
   Кадр отстоит от карточки на 4, хром от кадра на 2. Чтобы контуры
   были концентричны на всём периметре, радиусы связаны:
     R(карточка) = R(кадр) + 4 = R(хром) + 6,
   а R(хром) не может превышать половину высоты дорожки — поэтому
   дорожка в крупном кадре кейса выше, чем в остальных слотах.
   ============================================================ */
.cs-media.gal {
  --gal-bar: 24px;                   /* правка Alexa: высота полосы ниже на 6 */
  --gal-radius: 20px;                /* скругление кадра прежнее: 24 карточки − 4 отступа */
  border-radius: 20px;
}
.cs-card { border-radius: 24px; }    /* макетный радиус карточки — не трогаем */
