/* ==========================================================================
   ViewChat — секция Global Community: ночная network-сцена
   Палитра Night Network: near-black space → ночная Земля → тёплые связи

   Изолированный слой: вся композиция живёт внутри .vc-global-globe. Секция —
   отдельный тёмный breakout-экран между светлыми соседями, поэтому примыкающие
   .divider скрываются (иначе светлая линия читается как шов).

   Тексты и CTA приходят из i18n (index.community.*) и здесь не задаются.
   Список стран и связей живёт в разметке секции, см. index.html.

   Состояния, которые ставит js/viewchat-global-globe.js:
     .is-globe-ready — сцена собрана, канвас проявляется, CSS-заглушка уходит;
     .is-static      — 3D отключён (reduce motion / нет WebGL / слабое
                       устройство / Save-Data / ошибка загрузки текстур):
                       остаётся тёмный силуэт Земли со световыми отметками.
   ========================================================================== */

.vc-global-globe {
  /* --- Токены оформления: палитра Night Network -------------------------- */
  /* near-black space → глубокая ночная Земля → тёплые связи между людьми.
     Секция почти чёрная: самое яркое в кадре — городские огни и дуги связей,
     всё остальное уходит в тень. Бирюзовый cast прежней палитры снят целиком.

     ВАЖНО: значения ниже продублированы в js/viewchat-global-globe-3d.js
     литералами (COLOR_OCEAN, COLOR_LAND, COLOR_LIGHTS, COLOR_ARC,
     COLOR_ARC_HOT, COLOR_RIM). Считывать их оттуда через getComputedStyle
     нельзя: у --vcg-rim значащая альфа, а THREE.Color.setStyle() её молча
     отбрасывает, и промах по имени токена дал бы чёрный океан на чёрном фоне,
     то есть молчаливую ошибку. Меняешь здесь — меняешь и там. */
  --vcg-space: #020304;
  --vcg-space-2: #06090d;
  --vcg-space-3: #090d12;
  /* Дымка только локальная, у левой части шара, без ровного налёта по секции. */
  --vcg-haze: rgba(24, 40, 58, 0.14);
  /* Земля: те же значения, что у albedo материала в JS. */
  --vcg-ocean: #050b13;
  --vcg-land: #172331;
  /* Тёплая сторона палитры: огни городов, дуги связей и коралловый акцент. */
  --vcg-lights: #ffe6bc;
  --vcg-arc: #fff0d8;
  --vcg-arc-hot: #fff9eb;
  --vcg-coral: #f2565c;
  --vcg-coral-hi: #ff6d73;
  --vcg-ivory: #eaf2f8;
  --vcg-ivory-soft: rgba(206, 224, 238, 0.78);
  --vcg-rim: rgba(152, 177, 194, 0.52);
  --vcg-chip: rgba(4, 7, 11, 0.9);
  --vcg-chip-line: rgba(152, 177, 194, 0.26);
  /* Карточки демо-активности: поверхность чуть плотнее чипа подписи, чтобы
     текст читался поверх городских огней. */
  --vcg-card: rgba(9, 22, 25, 0.82);
  --vcg-card-line: rgba(150, 205, 212, 0.22);
  --vcg-card-muted: rgba(198, 218, 226, 0.62);
  --vcg-card-leader: rgba(160, 214, 218, 0.34);

  --vcg-max: 1440px;
  /* Потолок размера сцены. Реальный размер берётся от ширины колонки, а высота
     выводится через aspect-ratio — канвас обязан быть квадратным, иначе при
     аспекте меньше единицы горизонтальный FOV срезает сферу по бокам.
     При 1920px колонка даёт около 805px, то есть шар ~750px в диаметре. */
  --vcg-stage: 820px;
  /* Координаты активной точки внутри .vc-global-globe__stage. Значения каждый
     кадр пишет JS; до первого кадра чип встаёт по центру. */
  --vcg-node-x: 50%;
  --vcg-node-y: 50%;

  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  min-height: 820px;
  /* Нижняя часть шара намеренно срезается границей секции. */
  overflow: hidden;
  /* Владелец WebGL-канваса: paint-containment надёжно обрезает compositor
     canvas по границе самой Globe-секции, не меняя её размеры или интеракции. */
  contain: paint;
  color: var(--vcg-ivory);
  /* Дымка держится вокруг левой части Земли и быстро сходит на нет: ровный
     налёт по всей секции читался бы как зелёный туман. */
  background:
    radial-gradient(
      82% 70% at 27% 48%,
      var(--vcg-haze) 0%,
      rgba(2, 3, 4, 0) 58%
    ),
    linear-gradient(180deg, var(--vcg-space-2) 0%, var(--vcg-space) 48%, var(--vcg-space-3) 100%);
}

/* Светлые разделители шаблона по краям тёмного блока выглядят швом. :has()
   поддержан во всех целевых браузерах; где нет — линия просто останется. */
.vc-global-globe + hr.divider,
hr.divider:has(+ .vc-global-globe) {
  display: none;
}

.vc-global-globe__inner {
  display: grid;
  /* Шар слева и заметно крупнее, текстовый блок справа. */
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.78fr);
  align-items: center;
  gap: clamp(24px, 4vw, 64px);
  width: min(var(--vcg-max), 100% - 10vw);
  margin: 0 auto;
  padding: 70px 0;
}

/* Порядок задаётся здесь, а не в разметке: в DOM текст идёт первым, поэтому
   Tab ведёт «заголовок → CTA → страны», а визуально шар всё равно слева
   (и сверху на мобильных). */
.vc-global-globe__stage {
  order: 1;
}

.vc-global-globe__copy {
  order: 2;
}

/* --- Текстовая колонка ---------------------------------------------------- */
/* Классы h2-xl / p-lg / btn / advantages — шаблонные: типографика остаётся
   такой же, как у соседних секций, меняются только цвета под тёмный фон. */

.vc-global-globe__title {
  margin: 0 0 20px;
  color: var(--vcg-ivory);
  text-wrap: balance;
}

.vc-global-globe__text {
  margin: 0;
  max-width: 34em;
  color: var(--vcg-ivory-soft);
}

.vc-global-globe__cta {
  margin-top: clamp(26px, 3vw, 38px);
}

/* Шаблонный .advantages отцентрован и рассчитан на светлый фон. */
.vc-global-globe__cta .advantages {
  margin-top: 18px;
  text-align: left;
}

.vc-global-globe__cta .advantages li {
  float: none;
  margin: 0;
  padding: 0;
}

.vc-global-globe__cta .advantages li p {
  color: rgba(198, 218, 234, 0.66);
}

/* CTA только этой секции: шаблонный .btn--theme красится в magenta-pink
   (--theme-color в pink-theme.css) и на тёмной сцене выглядит чужим объектом,
   а .hover--tra-black на hover ставит чёрный текст на прозрачном фоне — на
   тёмном это нечитаемо. Переводим кнопку в брендовый коралл и закрываем оба
   состояния. Селектор привязан к .vc-global-globe__cta, поэтому глобальные
   кнопки и другие секции не задеты. !important нужен потому, что тема тоже
   пишет через !important; специфичность здесь выше (0-3-0 против 0-2-0) и
   файл подключается после темы. */
.vc-global-globe__cta .btn--theme,
.vc-global-globe__cta .btn--theme:focus,
.vc-global-globe__cta .btn--theme:focus-visible {
  background-color: var(--vcg-coral) !important;
  border-color: var(--vcg-coral) !important;
  color: #fff !important;
}

.vc-global-globe__cta .btn--theme:hover {
  background-color: var(--vcg-coral-hi) !important;
  border-color: var(--vcg-coral-hi) !important;
  color: #fff !important;
}

.vc-global-globe__cta .btn--theme:focus-visible {
  outline: 2px solid var(--vcg-rim);
  outline-offset: 3px;
}

/* --- Сцена ---------------------------------------------------------------- */

.vc-global-globe__stage {
  position: relative;
  /* Квадрат от ширины колонки: сфера не должна срезаться по бокам. */
  width: 100%;
  max-width: var(--vcg-stage);
  aspect-ratio: 1 / 1;
  /* Отрицательный отступ снизу уменьшает вклад квадратного канваса в высоту
     строки: иначе секция вырастала бы до полной высоты канваса. Шар при этом
     больше не срезается — он занимает 0.835 полувысоты кадра (см. CAM_Z), то
     есть внутри канваса остаётся собственное поле сверху и снизу.
     Значение подобрано под требование «сфера целиком, не меньше 48px сверху и
     40px снизу от границ секции»: при -13% нижний зазор падал до ~31px. */
  margin: 0 auto -11%;
}

/* Холодное свечение у шара плюс едва тёплая нота. Делается фоном, а не
   постпроцессингом: bloom на такую задачу — неоправданный расход кадра. */
.vc-global-globe__glow {
  position: absolute;
  inset: -16%;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(
      circle at 50% 50%,
      rgba(25, 67, 69, 0.22) 0%,
      rgba(25, 67, 69, 0.08) 44%,
      rgba(0, 0, 0, 0) 68%
    ),
    radial-gradient(
      circle at 38% 32%,
      rgba(255, 225, 196, 0.05) 0%,
      rgba(255, 225, 196, 0) 56%
    );
}

.vc-global-globe__canvas {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 700ms ease;
  /* Ключевое для мобильных: вертикальный свайп остаётся браузеру, поэтому
     страница скроллится сквозь секцию, а горизонтальный жест достаётся
     глобусу. preventDefault в обработчиках не вызывается никогда. */
  touch-action: pan-y;
}

.vc-global-globe.is-globe-ready .vc-global-globe__canvas {
  opacity: 1;
}

/* --- Тёмная заглушка ------------------------------------------------------ */
/* Видна до готовности сцены и остаётся навсегда в .is-static. Ни спиннера, ни
   пустого места, ни светлого шара: тёмный силуэт Земли с холодным лимбом и
   несколькими световыми отметками, собранный одним фоном без запросов. */

.vc-global-globe__fallback {
  position: absolute;
  inset: 7%;
  z-index: 1;
  border-radius: 50%;
  pointer-events: none;
  background:
    /* Двенадцать световых отметок — по числу локаций секции. Раскладка
       подогнана под новую Eurasia-центричную позу, но координаты остаются
       композиционными, а не географическими. Две коралловые (Korea и
       Kazakhstan — узел-хаб и конечная точка стартовой дуги), остальные ivory. */
    radial-gradient(circle at 71% 38%, rgba(255, 236, 224, 0.98) 0 2.6px, rgba(242, 86, 92, 0.4) 7px, rgba(242, 86, 92, 0) 14px),
    radial-gradient(circle at 51% 32%, rgba(255, 236, 224, 0.95) 0 2.4px, rgba(242, 86, 92, 0.34) 7px, rgba(242, 86, 92, 0) 13px),
    radial-gradient(circle at 77% 36%, rgba(255, 238, 210, 0.9) 0 2.4px, rgba(255, 225, 196, 0.22) 6px, rgba(255, 225, 196, 0) 12px),
    radial-gradient(circle at 65% 50%, rgba(255, 238, 210, 0.88) 0 2.4px, rgba(255, 225, 196, 0.2) 6px, rgba(255, 225, 196, 0) 12px),
    radial-gradient(circle at 44% 30%, rgba(255, 238, 210, 0.85) 0 2.2px, rgba(255, 225, 196, 0.2) 6px, rgba(255, 225, 196, 0) 11px),
    radial-gradient(circle at 39% 34%, rgba(255, 238, 210, 0.8) 0 2.2px, rgba(255, 225, 196, 0.18) 6px, rgba(255, 225, 196, 0) 11px),
    radial-gradient(circle at 49% 38%, rgba(255, 238, 210, 0.78) 0 2px, rgba(255, 225, 196, 0.16) 5px, rgba(255, 225, 196, 0) 10px),
    radial-gradient(circle at 73% 49%, rgba(255, 232, 202, 0.7) 0 1.9px, rgba(255, 225, 196, 0.14) 5px, rgba(255, 225, 196, 0) 10px),
    radial-gradient(circle at 62% 52%, rgba(255, 232, 202, 0.62) 0 1.8px, rgba(255, 225, 196, 0) 8px),
    radial-gradient(circle at 68% 61%, rgba(255, 232, 202, 0.58) 0 1.8px, rgba(255, 225, 196, 0) 8px),
    radial-gradient(circle at 27% 56%, rgba(255, 232, 202, 0.55) 0 1.7px, rgba(255, 225, 196, 0) 8px),
    radial-gradient(circle at 86% 44%, rgba(255, 232, 202, 0.34) 0 1.5px, rgba(255, 225, 196, 0) 7px),
    /* Тело: ночной navy-силуэт Земли, свет смещён к верхне-левому лимбу. Тон
       согласован с albedo сцены (--vcg-land #172331 / --vcg-ocean #050b13):
       иначе статика и WebGL-сцена выглядели бы двумя разными планетами. */
    radial-gradient(circle at 36% 30%, #1c2a3a 0%, #131d29 42%, #0a1119 76%, #04070b 100%);
  /* Холодный лимб ослаблен так же, как rim в сцене: тонкая кромка вместо
     синего контура вокруг всей сферы. Оттенок взят из --vcg-rim. */
  box-shadow:
    inset 0 0 0 1px rgba(152, 177, 194, 0.1),
    inset 14px 16px 44px rgba(152, 177, 194, 0.07),
    inset -20px -24px 64px rgba(0, 0, 0, 0.6),
    0 0 90px rgba(120, 148, 170, 0.05);
  transition: opacity 500ms ease;
}

.vc-global-globe.is-globe-ready .vc-global-globe__fallback {
  opacity: 0;
}

/* Звёзды для статики. В 3D их рисует сцена (THREE.Points), поэтому CSS-слой
   включается только в .is-static — иначе поля наложились бы друг на друга.
   Отдельного ассета нет: четырнадцать точек собраны градиентами, все вынесены
   за диск Земли. Псевдоэлемент, чтобы не переписывать базовый glow. */
.vc-global-globe.is-static .vc-global-globe__glow::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(circle at 6% 10%, rgba(230, 236, 239, 0.5) 0 1px, rgba(230, 236, 239, 0) 3px),
    radial-gradient(circle at 14% 26%, rgba(230, 236, 239, 0.34) 0 1px, rgba(230, 236, 239, 0) 3px),
    radial-gradient(circle at 4% 52%, rgba(168, 196, 210, 0.4) 0 1.5px, rgba(168, 196, 210, 0) 4px),
    radial-gradient(circle at 9% 80%, rgba(230, 236, 239, 0.3) 0 1px, rgba(230, 236, 239, 0) 3px),
    radial-gradient(circle at 22% 92%, rgba(230, 236, 239, 0.42) 0 2px, rgba(230, 236, 239, 0) 5px),
    radial-gradient(circle at 38% 96%, rgba(230, 236, 239, 0.26) 0 1px, rgba(230, 236, 239, 0) 3px),
    radial-gradient(circle at 30% 6%, rgba(242, 86, 92, 0.34) 0 1.5px, rgba(242, 86, 92, 0) 4px),
    radial-gradient(circle at 48% 3%, rgba(230, 236, 239, 0.36) 0 1px, rgba(230, 236, 239, 0) 3px),
    radial-gradient(circle at 64% 7%, rgba(230, 236, 239, 0.28) 0 1px, rgba(230, 236, 239, 0) 3px),
    radial-gradient(circle at 78% 16%, rgba(168, 196, 210, 0.32) 0 1px, rgba(168, 196, 210, 0) 3px),
    radial-gradient(circle at 92% 30%, rgba(230, 236, 239, 0.44) 0 2px, rgba(230, 236, 239, 0) 5px),
    radial-gradient(circle at 88% 62%, rgba(230, 236, 239, 0.26) 0 1px, rgba(230, 236, 239, 0) 3px),
    radial-gradient(circle at 72% 88%, rgba(230, 236, 239, 0.3) 0 1px, rgba(230, 236, 239, 0) 3px),
    radial-gradient(circle at 56% 90%, rgba(230, 236, 239, 0.24) 0 1px, rgba(230, 236, 239, 0) 3px);
}

/* --- Подписи -------------------------------------------------------------- */
/* HTML поверх канваса, а не текст внутри сцены: подпись остаётся выделяемой,
   переводимой и не зависит от разрешения рендера. Тёмный чип со светлым
   текстом — на кинематографичной сцене белая таблетка выбивалась бы. */

.vc-global-globe__tip,
.vc-global-globe__node-btn {
  position: absolute;
  z-index: 3;
  margin: 0;
  padding: 6px 12px;
  border: 1px solid var(--vcg-chip-line);
  border-radius: 999px;
  background: var(--vcg-chip);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.45);
  color: var(--vcg-ivory);
  /* Кнопке нужно явно наследовать шрифт: иначе браузер подставит системный. */
  appearance: none;
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  /* Чип центрируется по своей точке и приподнимается над ней. */
  transform: translate(-50%, calc(-100% - 12px));
}

.vc-global-globe__tip {
  left: var(--vcg-node-x);
  top: var(--vcg-node-y);
  pointer-events: none;
}

.vc-global-globe__tip[hidden] {
  display: none;
}

/* --- Демо-карточки активности --------------------------------------------- */
/* Слой лежит над канвасом и под подписью/чипом фокуса. Событий не ловит вообще:
   hover и tap глобуса проверяют e.target === canvas, поэтому любой перехваченный
   указатель молча убил бы и подсказку, и тап по точке. touch-action здесь не
   задаётся ни на одном элементе — он остаётся только на канвасе.
   Разметку собирает js/viewchat-global-globe.js; цифры демонстрационные. */

.vc-global-globe__activity {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  /* Слой сам ничего не рисует — только задаёт систему координат. Она совпадает
     с канвасом: тот занимает сцену целиком, без рамок и полей. */
  contain: layout style;
}

/* Якорь нулевого размера стоит ровно в точке узла; каждый кадр JS двигает только
   его. translate3d поднимает карточку в слой композитора: текст растеризуется
   один раз и не дрожит на дробных координатах вращающегося глобуса. */
.vc-global-globe__activity-anchor {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translate3d(var(--vcg-act-x, 0px), var(--vcg-act-y, 0px), 0);
  will-change: transform, opacity;
}

/* Карточка не входит в набор текущего брейкпоинта. */
.vc-global-globe__activity-anchor.is-off {
  display: none;
}

/* Выноска от точки к карточке: длина и угол — константы своего брейкпоинта,
   считаются при раскладке, а не в кадре. Начало отодвинуто от самой точки, чтобы
   линия не упиралась в её свечение. */
.vc-global-globe__activity-leader {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--vcg-act-len, 0px);
  height: 1px;
  transform-origin: 0 50%;
  transform: rotate(var(--vcg-act-ang, 0rad)) translateX(7px);
  background: linear-gradient(
    90deg,
    rgba(160, 214, 218, 0) 0%,
    var(--vcg-card-leader) 38%,
    var(--vcg-card-leader) 100%
  );
}

.vc-global-globe__activity-card {
  position: absolute;
  left: 0;
  top: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 7px 11px;
  border: 1px solid var(--vcg-card-line);
  border-radius: 10px;
  background: var(--vcg-card);
  /* Мягкая небольшая тень. Никакого backdrop-filter: полноэкранное стекло над
     вращающейся сценой — это перерисовка всего кадра ради декора. */
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.34);
  white-space: nowrap;
  user-select: none;
  pointer-events: none;
  /* Карточка стоит на своём слоте относительно точки. */
  transform: translate(
    calc(-50% + var(--vcg-act-dx, 0px)),
    calc(-50% + var(--vcg-act-dy, 0px))
  );
}

.vc-global-globe__activity-city {
  color: #fff;
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.25;
}

.vc-global-globe__activity-meta {
  display: flex;
  align-items: center;
  gap: 5px;
  color: var(--vcg-card-muted);
  font-size: 0.72rem;
  font-weight: 500;
  line-height: 1.25;
}

/* Нейтральная пиктограмма «люди»: голова и плечи двумя фигурами. Отдельного
   ассета нет — как и у CSS-заглушки Земли в этой же секции. */
.vc-global-globe__activity-icon {
  position: relative;
  flex: none;
  width: 10px;
  height: 10px;
}

.vc-global-globe__activity-icon::before,
.vc-global-globe__activity-icon::after {
  content: "";
  position: absolute;
  left: 50%;
  background: currentColor;
  opacity: 0.85;
}

.vc-global-globe__activity-icon::before {
  top: 0;
  width: 4px;
  height: 4px;
  margin-left: -2px;
  border-radius: 50%;
}

.vc-global-globe__activity-icon::after {
  bottom: 0;
  width: 9px;
  height: 5px;
  margin-left: -4.5px;
  border-radius: 4.5px 4.5px 1px 1px;
}

/* --- Match-моменты -------------------------------------------------------- */
/* Декоративный демо-сюжет: по одной паре анонимных людей за раз — два крупных
   круглых портрета в нижней центральной части диска Земли, тонкая нить между
   ними, надпись MATCHED и подпись пары. Это НЕ реальные пользователи и не живые
   совпадения — та же договорённость, что у демо-карточек активности выше.

   Здесь только материал. Вся геометрия и всё время живут в
   js/viewchat-global-globe.js, и слой намеренно не содержит ни @keyframes, ни
   transition: вне вьюпорта кадры секции остановлены, а CSS-анимация в этот
   момент продолжала бы идти сама и по возвращении отыгрывала бы пропущенное.
   Поэтому появление, уход, дыхание, прорисовка нити и частицы приезжают сюда
   готовыми числами в переменных.

   Композиция привязана к диску Земли, а не к проекции узлов: круги стоят на
   своих местах внутри кадра и при вращении не ползают. */

.vc-global-globe__match {
  --vcgm-thread: rgba(255, 216, 208, 0.5);
  --vcgm-ring: rgba(234, 242, 248, 0.3);
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  /* Слой сам ничего не рисует — задаёт систему координат, совпадающую с
     канвасом (тот занимает сцену целиком, без рамок и полей). */
  contain: layout style;
}

/* Контейнер одной пары. Показана всегда не больше одной: остальные лежат
   с visibility: hidden и в кадре не читаются и не пишутся. */
.vc-global-globe__match-pair {
  position: absolute;
  inset: 0;
  visibility: hidden;
  pointer-events: none;
}

/* Нить между кругами. pathLength="1" ставится в разметке, поэтому прорисовка —
   это stroke-dashoffset от 1 к 0 в безразмерных единицах: getTotalLength() в
   кадре не нужен. Линия заметно легче постоянных дуг глобуса. */
.vc-global-globe__match-thread {
  position: absolute;
  left: 0;
  top: 0;
  overflow: visible;
  pointer-events: none;
}

.vc-global-globe__match-path {
  fill: none;
  stroke: var(--vcgm-thread);
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: var(--vcgm-draw, 1);
  opacity: var(--vcgm-thread-a, 0);
  /* Тонкая линия поверх ярких дуг иначе теряется; тень мягкая, без неона. */
  filter: drop-shadow(0 0 5px rgba(255, 190, 178, 0.55));
}

/* Круглый портрет. Позиция статична (её пишет раскладка), в кадре меняются
   только прозрачность, масштаб, дыхание и сила кораллового rim-света.
   translate3d поднимает круг в слой композитора: фотография растеризуется один
   раз и не дрожит на дробных координатах. */
.vc-global-globe__match-orb {
  position: absolute;
  left: 0;
  top: 0;
  width: 104px;
  height: 104px;
  border-radius: 50%;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  /* Тонкое ivory-кольцо, глубокая мягкая тень и коралловый rim только на
     match-фазе: его силу (--vcgm-rim) выставляет кадр. */
  box-shadow:
    0 0 0 1.5px var(--vcgm-ring),
    0 18px 38px rgba(0, 0, 0, 0.55),
    0 0 24px 2px rgba(242, 86, 92, var(--vcgm-rim, 0));
  transform:
    translate3d(var(--vcgm-x, 0px), calc(var(--vcgm-y, 0px) + var(--vcgm-ty, 0px)), 0)
    translate(-50%, -50%)
    scale(var(--vcgm-s, 1));
  will-change: transform, opacity;
}

/* Фотография: та же обработка, что у портретов Live Community Network, — сцена
   ночная, необработанное фото в ней светится чужим. */
.vc-global-globe__match-photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(0.22) brightness(0.86) contrast(1.05);
}

/* Сигнальная точка: один короткий проход к середине нити за момент. */
.vc-global-globe__match-dot {
  position: absolute;
  left: 0;
  top: 0;
  width: 3.5px;
  height: 3.5px;
  margin: -1.75px 0 0 -1.75px;
  border-radius: 50%;
  background: var(--vcg-arc-hot);
  box-shadow: 0 0 6px rgba(255, 240, 216, 0.7);
  opacity: 0;
  transform: translate3d(var(--vcgm-x, 0px), var(--vcgm-y, 0px), 0);
  will-change: transform, opacity;
}

/* Текст момента. Подложки нет намеренно — это не плашка интерфейса: читаемость
   поверх ярких дуг держит тень. Блок стоит над кругами и центрирован по ним. */
.vc-global-globe__match-copy {
  position: absolute;
  left: 0;
  top: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  opacity: 0;
  white-space: nowrap;
  text-align: center;
  user-select: none;
  pointer-events: none;
  text-shadow: 0 1px 5px rgba(0, 0, 0, 0.9), 0 0 14px rgba(0, 0, 0, 0.65);
  transform:
    translate3d(var(--vcgm-x, 0px), calc(var(--vcgm-y, 0px) + var(--vcgm-ty, 0px)), 0)
    translate(-50%, -100%);
  will-change: transform, opacity;
}

.vc-global-globe__match-kicker {
  color: var(--vcg-coral-hi);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.22em;
  line-height: 1;
  text-transform: uppercase;
}

.vc-global-globe__match-word {
  color: var(--vcg-ivory);
  font-size: 25px;
  font-weight: 700;
  letter-spacing: 0.08em;
  line-height: 1.04;
  text-transform: uppercase;
}

.vc-global-globe__match-names {
  color: var(--vcg-ivory-soft);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.14em;
  line-height: 1;
  text-transform: uppercase;
}

/* Закрывающая строка момента. По умолчанию её нет в раскладке вовсе:
   элемент собирается всегда, но виден только ниже 768px — широкий экран
   обязан остаться таким же, каким был. */
.vc-global-globe__match-connected {
  display: none;
}

/* Частица: не emoji и не иконка, а маленькая мягкая коралловая форма. Наружная
   обёртка везёт позицию, внутренняя — саму фигуру, поэтому поворот -45° не
   спорит с translate позиции. */
.vc-global-globe__match-heart {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  opacity: 0;
  transform: translate3d(var(--vcgm-x, 0px), var(--vcgm-y, 0px), 0);
  will-change: transform, opacity;
}

.vc-global-globe__match-heart i {
  position: absolute;
  left: -3.5px;
  top: -3.5px;
  width: 7px;
  height: 7px;
  background: var(--vcg-coral);
  transform: rotate(-45deg) scale(var(--vcgm-hs, 1));
}

.vc-global-globe__match-heart i::before,
.vc-global-globe__match-heart i::after {
  content: "";
  position: absolute;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: inherit;
}

.vc-global-globe__match-heart i::before {
  top: -3.5px;
  left: 0;
}

.vc-global-globe__match-heart i::after {
  top: 0;
  left: 3.5px;
}

/* --- Список стран: данные и клавиатура ------------------------------------ */
/* Кнопки — единственный источник данных о локациях (data-lat / data-lon /
   data-featured) и одновременно клавиатурный интерфейс секции. Отдельной
   видимой полосы чипов под шаром нет: подпись появляется только при
   взаимодействии. */

/* Список накрывает сцену и сам событий не ловит: перетаскивание глобуса и
   хит-тест точек остаются за канвасом. Из потока список выведен полностью,
   поэтому на размер сцены он не влияет ни в одном состоянии. */
.vc-global-globe__nodes {
  position: absolute;
  inset: 0;
  z-index: 2;
  margin: 0;
  padding: 0;
  list-style: none;
  pointer-events: none;
}

.vc-global-globe__nodes li {
  margin: 0;
  padding: 0;
}

/* Скрытое состояние написано вручную, а не через .visually-hidden: у
   бутстраповского .visually-hidden-focusable в состоянии фокуса снимается
   position: absolute, кнопка возвращается в поток и дёргает layout. Здесь
   position остаётся absolute всегда, поэтому раскрытие по фокусу не стоит
   ни одного пикселя сдвига. */
.vc-global-globe__node-btn {
  left: var(--vcg-node-x);
  top: var(--vcg-node-y);
  width: 1px;
  height: 1px;
  padding: 0;
  border-color: transparent;
  overflow: hidden;
  clip-path: inset(50%);
  background: transparent;
  box-shadow: none;
  color: transparent;
  cursor: pointer;
  /* Родительский список события не ловит — кнопке возвращаем. */
  pointer-events: auto;
}

/* Сфокусированная кнопка и есть видимая подпись: пользователь клавиатуры
   всегда видит, где находится, а JS дополнительно доворачивает эту страну
   к фронту глобуса и подсвечивает её связи. */
.vc-global-globe__node-btn:focus-visible {
  width: auto;
  height: auto;
  padding: 6px 12px;
  border-color: var(--vcg-chip-line);
  overflow: visible;
  clip-path: none;
  background: rgba(6, 16, 28, 0.94);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.45);
  color: var(--vcg-ivory);
  outline: 2px solid var(--vcg-coral);
  outline-offset: 3px;
}

/* Браузеры без :focus-visible иначе остались бы вовсе без индикатора. */
@supports not selector(:focus-visible) {
  .vc-global-globe__node-btn:focus {
    width: auto;
    height: auto;
    padding: 6px 12px;
    border-color: var(--vcg-chip-line);
    overflow: visible;
    clip-path: none;
    background: rgba(6, 16, 28, 0.94);
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.45);
    color: var(--vcg-ivory);
    outline: 2px solid var(--vcg-coral);
    outline-offset: 3px;
  }
}

/* В статике сцену крутить нечем, поэтому подписи под курсором нет. Фокус
   по-прежнему раскрывает чип — в невидимый фокус секция не уходит. */
.vc-global-globe.is-static .vc-global-globe__tip {
  display: none;
}

/* В статике проекции точек нет, а раскладывать выдуманные карточки «на глаз»
   поверх CSS-заглушки — значит на каком-нибудь промежуточном размере налезть на
   колонку с заголовком. Слой скрыт целиком: ни одной цифры и ни намёка на живое
   обновление. JS в этом режиме карточки и не собирает. */
.vc-global-globe.is-static .vc-global-globe__activity {
  display: none;
}

/* Match-моменты в статике не воспроизводятся по той же причине, что и карточки:
   проекции узлов нет, а поставить пару «на глаз» поверх CSS-заглушки значит
   выдумать её место. JS слой в этом режиме не собирает, правило — страховка. */
.vc-global-globe.is-static .vc-global-globe__match {
  display: none;
}

/* --- Мобильная композиция ------------------------------------------------- */
/* Крупный шар сверху, текст и CTA под ним. Порядок задан order выше и на
   одноколоночной сетке работает так же. */

@media (max-width: 991.98px) {
  .vc-global-globe {
    --vcg-stage: min(88vw, 380px);
    min-height: 0;
  }

  .vc-global-globe__inner {
    grid-template-columns: minmax(0, 1fr);
    width: min(var(--vcg-max), 100% - 48px);
    gap: 36px;
    padding: 72px 0;
  }

  /* На мобильных шар за границу не уходит: он и так первый в композиции. */
  .vc-global-globe__stage {
    margin-bottom: 0;
  }

  .vc-global-globe__text {
    max-width: none;
  }

  /* На узком экране подпись показывается только у активной точки — этим
     занимается JS, здесь лишь делаем её компактнее. */
  .vc-global-globe__tip,
  .vc-global-globe__node-btn:focus-visible {
    font-size: 0.78rem;
  }

  /* Сцена сжимается до min(88vw, 380px), и карточка обязана ужаться вместе с
     ней: Сеул и Токио стоят на глобусе в 12.7° друг от друга, то есть всего в
     ~20 px на мобильном шаре. Разводятся они по вертикали (см. слоты в JS), но
     широкая карточка всё равно не оставила бы места. */
  .vc-global-globe__activity-card {
    padding: 6px 9px;
    border-radius: 9px;
  }

  .vc-global-globe__activity-city {
    font-size: 0.72rem;
  }

  .vc-global-globe__activity-meta {
    gap: 4px;
    font-size: 0.66rem;
  }

  /* Круги ужимаются вместе со сценой, но остаются КРУПНЫМИ: на диске ~286 px
     они должны читаться как портреты с первого взгляда, а не как маркеры карты.
     Разнос между ними задаёт JS от диаметра диска. */
  .vc-global-globe__match-orb {
    width: 80px;
    height: 80px;
    box-shadow:
      0 0 0 1.5px var(--vcgm-ring),
      0 12px 26px rgba(0, 0, 0, 0.55),
      0 0 18px 2px rgba(242, 86, 92, var(--vcgm-rim, 0));
  }

  /* Слово MATCHED обязано читаться и здесь — сердце его не заменяет. */
  .vc-global-globe__match-word {
    font-size: 19px;
  }

  .vc-global-globe__match-kicker {
    font-size: 9px;
    letter-spacing: 0.2em;
  }

  .vc-global-globe__match-names {
    font-size: 11px;
    letter-spacing: 0.12em;
  }
}

@media (max-width: 575.98px) {
  .vc-global-globe__inner {
    width: min(var(--vcg-max), 100% - 32px);
  }

  .vc-global-globe__cta .btn {
    width: 100%;
  }
}

/* --- Узкий экран: Земля как главный объект кадра --------------------------- */

/* Отдельный порог 768px, а не общий 992px: диапазон 768–991 остаётся ровно
   таким, каким был. Всё, что ниже, — про одну задачу: планета обязана быть
   главным объектом кадра, а не маленьким шаром в пустом поле.

   Арифметика диска. Силуэт Земли занимает 0.835 стороны квадратной сцены
   (CAM_Z = 4.3, FOV = 32°, см. viewchat-global-globe-3d.js). Значит, чтобы диск
   получился 94.4vw, сцена обязана быть 113vw — ШИРЕ колонки контента и шире
   самого экрана. Пустые углы квадрата уезжают за края и срезаются
   overflow: hidden секции; сам диск при этом целиком в кадре с запасом
   (390px -> диск 368px, 412px -> 389px), горизонтальной прокрутки не
   появляется.

   Потолок 470px нужен у верхней границы диапазона: без него на 767px сцена
   выросла бы до 866px, а диск — до 724px, и переход к раскладке 768px
   превратился бы в обрыв. С потолком правило «диск ≈ 94vw» держится до ~415px,
   дальше диск замирает на 392px. */

@media (max-width: 767.98px) {
  .vc-global-globe {
    --vcg-stage: min(113vw, 470px);
  }

  /* Сцена выходит из колонки контента симметрично в обе стороны: центр диска
     остаётся центром экрана. Отрицательные поля, а не transform: scale — канвас
     обязан физически иметь свой размер, иначе растяжение съело бы резкость
     текстур и сдвинуло бы проекцию точек относительно DOM-слоёв.

     Нижнее поле выводится из той же константы: под диском внутри квадрата
     остаётся (1 - 0.835) / 2 = 0.0825 стороны пустоты, и мы забираем её,
     оставляя ровно 24px до заголовка. */
  .vc-global-globe__stage {
    width: var(--vcg-stage);
    max-width: none;
    margin-left: calc((100% - var(--vcg-stage)) / 2);
    margin-right: calc((100% - var(--vcg-stage)) / 2);
    margin-bottom: calc(24px - var(--vcg-stage) * 0.0825);
  }

  /* Зазор между сценой и текстом теперь целиком в margin-bottom сцены. */
  .vc-global-globe__inner {
    gap: 0;
  }

  /* Типографика ужимается ОТНОСИТЕЛЬНО выросшей планеты: абсолютный размер
     остаётся премиальным, но заголовок больше не спорит с Землёй за главную
     роль в кадре. */
  /* Селектор с тегом НАМЕРЕННО: шаблон задаёт размер через h2.h2-xl
     (0-1-1), и голый класс секции ему проиграл бы по специфичности. */
  .vc-global-globe h2.vc-global-globe__title {
    margin-bottom: 16px;
    font-size: clamp(29px, 7.5vw, 34px);
    line-height: 1.14;
  }

  .vc-global-globe__text {
    font-size: 17px;
    line-height: 1.6;
  }

  /* --- Текст под планетой -------------------------------------------- */
  /* На широком экране колонка стоит справа от шара, и левое выравнивание
     естественно. На узком текст оказывается ПОД центрированной Землёй,
     и та же левая кромка читается как сбитая ось композиции. Центрируем всю
     колонку целиком: заголовок, текст, CTA и подпись под ним. */
  .vc-global-globe__copy {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
  }

  /* Ширина строки ограничена не ради экономии места, а ради баланса:
     вместе с text-wrap: balance из базового правила это даёт три соразмерные
     строки, а не две длинные и одну короткую. Размер и интерлиньяж не трогаем. */
  .vc-global-globe__title,
  .vc-global-globe__text {
    max-width: 340px;
    margin-inline: auto;
    text-align: center;
  }

  .vc-global-globe__cta {
    width: 100%;
    text-align: center;
  }

  /* Шаблонный .advantages секция разворачивает влево для широкой
     раскладки — возвращаем его по центру вместе со всей колонкой. */
  .vc-global-globe__cta .advantages,
  .vc-global-globe__cta .advantages li p {
    text-align: center;
  }

  /* --- Match-момент ------------------------------------------------------- */
  /* Текст переезжает ПОД круги (на широком экране он стоит над ними): на диске
     в 389px между кругами всего ~76px, и слово MATCHED там не поместилось бы,
     не задев портреты. Порядок строк при этом тот же сверху вниз:
     It's a match -> MATCHED -> Seoul ↔ Tokyo -> Connected. */
  .vc-global-globe__match-copy {
    gap: 4px;
    transform:
      translate3d(var(--vcgm-x, 0px), calc(var(--vcgm-y, 0px) + var(--vcgm-ty, 0px)), 0)
      translate(-50%, 0);
  }

  .vc-global-globe__match-kicker {
    font-size: 12px;
    letter-spacing: 0.18em;
    line-height: 1.2;
  }

  /* Главный акцент момента и потолок брифа: 19px на 390px. */
  .vc-global-globe__match-word {
    font-size: 19px;
    line-height: 1.16;
  }

  .vc-global-globe__match-names {
    font-size: 13px;
    letter-spacing: 0.1em;
    line-height: 1.2;
  }

  /* Четвёртая строка существует только здесь. Выше 768px она display: none и
     в раскладку не входит вовсе — десктоп остаётся прежним до пикселя. */
  .vc-global-globe__match-connected {
    display: block;
    color: var(--vcg-ivory-soft);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.14em;
    line-height: 1.2;
    text-transform: uppercase;
    opacity: 0.86;
  }
}

/* --- Уважение к настройкам пользователя ----------------------------------- */
/* При reduce сцена не импортируется вовсе (см. viewchat-global-globe.js) —
   здесь снимаем оставшиеся переходы, чтобы не было проявлений и мигания. */

@media (prefers-reduced-motion: reduce) {
  .vc-global-globe__canvas,
  .vc-global-globe__fallback {
    transition: none;
  }
}
