/* ============================================================
   PRISMA · globe.css · el mundo: primera sección del home (index.html)
   El globo a pantalla completa, el titular centrado encima (como en la
   referencia) y las cifras en fila abajo. En vertical (móvil, tableta de
   pie) el texto va arriba y el globo asoma debajo hasta las cifras; el
   JS usa el mismo corte (@media (max-width: 699px), (max-aspect-ratio: 4/5)).

   El fondo es EXACTAMENTE el color de la esfera del globo: la composición
   de js/globe.js pinta la tinta (#0A0A0A) de base, así que el borde del
   lienzo y el disco no se distinguen. Si cambias --globe-bg, cambia BASE
   en js/globe.js.

   Estados (script en línea del <head> de index.html, antes del primer
   pintado):
   · html.globe-intro: texto y cifras esperan ocultos.
   · html.globe-hold: el loader está delante y el globo, detenido. Aquí
     no corre ningún reloj de seguridad (bajo el loader no pasa el tiempo).
   · html.globe-go (sustituye a globe-hold cuando el loader empieza a
     fundirse): las animaciones de seguridad cuentan desde que aparece la
     clase, 3 s y 3,6 s. Una página sin loader que reutilice el globo no
     lleva ni hold ni go: cuentan desde el primer pintado, como antes.
   · .is-revealed (go + 450 ms): entra el texto.
   · .is-facts (main.js, go + 900 ms, con la tipografía ya cargada): entran
     las cifras, --globe-facts-delay después (main.js lee esa variable para
     arrancar los contadores a la vez).
   · .is-static (sin WebGL o si falla), .is-lost (contexto perdido) e
     .is-late (el globo llegó tarde: el lienzo entra con un fundido).
   · .globe-hero--pinned: pegado arriba; --gp (0 → 1, lo escribe main.js
     con el scroll) apaga el texto, los rótulos y las cifras mientras la
     cámara se aleja y el manifiesto sube por encima.
   ============================================================ */

.globe-hero {
  --globe-bg: var(--ink);
  --globe-facts-delay: .2s;
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  height: 100vh;
  height: 100svh;
  min-height: 560px;
  overflow: hidden;
  overflow: clip;
  background: var(--globe-bg);
  color: var(--text-on-ink);
  /* Arrastre horizontal = girar el globo. El vertical sigue siendo el
     scroll de la página y el pellizco sigue ampliando. */
  touch-action: pan-y pinch-zoom;
  -webkit-tap-highlight-color: transparent;
}

/* Home: pegado arriba (z 0) y .home-flow (z 1) sube por encima. Un
   sticky nunca sale del viewport (getBoundingClientRect da top 0 a
   cualquier scroll): el progreso se mide con p = scrollY / alto del hero
   (main.js → --gp y PRISMA_GLOBE_VIEW.setScroll). */
.globe-hero--pinned { position: sticky; top: 0; z-index: 0; }

/* ---------- Escenario: lienzo + rótulos ----------
   Sin z-index propio: así el velo de abajo (.globe-hero::after, z 1) queda
   ENTRE el lienzo (z 0) y los rótulos (z 2), y los rótulos no salen
   apagados cerca de las cifras. El texto (z 2, más tarde en el DOM) sigue
   encima de todo. */
.globe-hero__stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
.globe-hero__canvas { position: absolute; inset: 0; z-index: 0; }
.globe-hero__canvas canvas { display: block; width: 100%; height: 100%; }
.globe-hero.is-grab { cursor: grab; }
.globe-hero.is-grabbing,
.globe-hero.is-grabbing * { cursor: grabbing; user-select: none; -webkit-user-select: none; }

/* .globe-hero__fade envuelve a los rótulos: su opacidad sigue al scroll
   (--gp) sin pelear con la transición del revelado, que va en los rótulos */
.globe-hero__fade,
.globe-hero__labels {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}

/* Rótulo de un lugar: pequeño, discreto, sin caja. La posición (esquina
   superior izquierda) la escribe el JS en `transform`, solo si cambia. */
.globe-label {
  position: absolute;
  left: 0;
  top: 0;
  display: flex;
  align-items: baseline;
  gap: 7px;
  white-space: nowrap;
  font-family: var(--f-text);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: .02em;
  color: rgb(var(--fg-rgb) / .9);
  text-shadow: 0 0 3px rgb(var(--ink-rgb) / .95), 0 0 10px rgb(var(--ink-rgb) / .9), 0 0 18px rgb(var(--ink-rgb) / .7);
  opacity: 0;
  /* se va rápido y entra despacio: cuando un rótulo le deja el sitio a
     otro no se ven los dos a la vez */
  transition: opacity .2s var(--ease-exit), color .3s var(--ease-ui);
  will-change: transform, opacity;
}
.globe-label.is-on { opacity: .72; transition: opacity .6s var(--ease-ui), color .3s var(--ease-ui); }
.globe-label.is-lit,
.globe-label.is-open { opacity: 1; color: var(--text-on-ink); }
.globe-label.is-hq { font-size: 12.5px; color: var(--text-on-ink); }
.globe-label.is-hq.is-on { opacity: 1; }
.globe-label__tag {
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--orange);
}
/* Los demás lugares del grupo (p. ej. Quito · Guayaquil bajo Cuenca):
   solo al pasar el ratón o al tocar. Fuera de la caja que se mide para
   colocar el rótulo, así no la agranda. */
.globe-label__sub {
  position: absolute;
  left: 0;
  top: calc(100% + 3px);
  font-size: 11px;
  color: var(--text-on-ink-2);
  opacity: 0;
  transition: opacity .3s var(--ease-ui);
}
.globe-label.is-open .globe-label__sub { opacity: 1; }

/* Velo de tinta abajo: el globo se funde hacia las cifras */
.globe-hero::after {
  content: '';
  position: absolute;
  inset: auto 0 0;
  height: 30%;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(to top, var(--globe-bg) 6%, rgb(var(--ink-rgb) / .72) 42%, rgb(var(--ink-rgb) / 0));
  transition: opacity .9s var(--ease-ui);
}
/* En el vuelo rasante el horizonte de puntos cae justo bajo este velo:
   se aparta hasta que la cámara sube (js/globe.js pone .is-near) */
.globe-hero.is-near::after { opacity: 0; transition: none; }

/* ---------- Texto sobre el globo ---------- */
.globe-hero__copy {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  margin-top: -3vh;
}
/* Velo radial muy suave detrás del texto: baja los puntos lo justo para
   que el lead se lea (4,5:1) sin que el globo se apague. Anclado por
   arriba en px y no centrado con translate: si la fuente llega tarde y el
   lead cambia de alto, su esquina no se mueve (con red lenta ese salto
   contaba ~0,07 de CLS). */
.globe-hero__copy::before {
  content: '';
  position: absolute;
  z-index: -1;
  left: 50%;
  top: -3px;
  bottom: -11%;
  width: min(1180px, 124%);
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgb(var(--ink-rgb) / .58), rgb(var(--ink-rgb) / .5) 60%, rgb(var(--ink-rgb) / 0));
  pointer-events: none;
}
.globe-hero__copy .kicker {
  position: relative;
  margin-bottom: 20px;
  /* el contraste se gana pegado a las letras (sombra cerrada), no con una
     mancha oscura grande detrás */
  text-shadow: 0 0 1px rgb(var(--ink-rgb) / 1), 0 0 3px rgb(var(--ink-rgb) / 1), 0 0 6px rgb(var(--ink-rgb) / 1), 0 0 12px rgb(var(--ink-rgb) / .95), 0 0 22px rgb(var(--ink-rgb) / .85);
}
/* El kicker queda en el borde de arriba del velo general, donde casi no
   tapa: lleva el suyo, para que la tierra densa que pasa detrás no se
   coma las letras naranjas. Sin meseta: con un núcleo casi opaco se veía
   como una píldora negra recortada en la trama de puntos (Asia central,
   Canadá). Así se funde con la tierra y la sombra de las letras hace el
   resto. */
.globe-hero__copy .kicker::before {
  content: '';
  position: absolute;
  inset: -20px -130px;
  z-index: -1;
  background: radial-gradient(closest-side, rgb(var(--ink-rgb) / .94), rgb(var(--ink-rgb) / .8) 40%, rgb(var(--ink-rgb) / .38) 72%, rgb(var(--ink-rgb) / 0));
  pointer-events: none;
}
/* El velo general es una elipse ancha y baja: en la parte alta de la
   primera línea del h1 casi no tapa, y cuando un cúmulo denso (India, a
   los ~55 s) pasa detrás de "Una" el contraste bajaba a 2,7. Este es un
   rectángulo blando pegado a las líneas: no se nota como mancha y no llega
   a los rótulos que quedan al lado del texto. */
.globe-hero__copy .page-hero__title::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: 4px 12px;
  border-radius: 48px;
  background: rgb(var(--ink-rgb) / .4);
  box-shadow: 0 0 34px 22px rgb(var(--ink-rgb) / .4);
  pointer-events: none;
}
.globe-hero__copy .page-hero__title {
  position: relative;
  max-width: 13.5em;
  font-size: clamp(2.15rem, 4.3vw, 4.1rem);
  line-height: 1.06;
  letter-spacing: -.02em;
  text-wrap: balance;
  text-shadow: 0 0 6px rgb(var(--ink-rgb) / .8), 0 0 20px rgb(var(--ink-rgb) / .7), 0 2px 36px rgb(var(--shadow-rgb) / .55);
}
.globe-hero em { font-style: normal; color: var(--orange); }
.globe-hero__copy .page-hero__lead {
  max-width: 56ch;
  margin-top: 24px;
  color: rgb(var(--fg-rgb) / .76);
  text-wrap: pretty;
  text-shadow: 0 0 3px rgb(var(--ink-rgb) / .95), 0 0 10px rgb(var(--ink-rgb) / .9), 0 0 22px rgb(var(--ink-rgb) / .85);
}

/* ---------- Cifras ---------- */
.globe-hero__facts {
  position: absolute;
  left: 0;
  right: 0;
  bottom: clamp(20px, 5vh, 52px);
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}
/* Velo propio de las cifras: en el vuelo rasante el horizonte de puntos
   pasa justo por detrás (el velo de abajo está apartado) y las cifras ya
   van entrando. Aparece con ellas. */
.globe-hero__facts::before {
  content: '';
  position: absolute;
  z-index: -1;
  left: 50%;
  top: 50%;
  width: min(760px, 100%);
  height: 170%;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side, rgb(var(--ink-rgb) / .78), rgb(var(--ink-rgb) / .45) 60%, rgb(var(--ink-rgb) / 0));
  pointer-events: none;
}
.globe-hero__facts-title,
.globe-fact { text-shadow: 0 0 3px rgb(var(--ink-rgb) / .9), 0 0 12px rgb(var(--ink-rgb) / .8); }
.globe-hero__facts-title {
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--text-on-ink-2);
}
.globe-hero__facts-list {
  display: flex;
  justify-content: center;
}
.globe-fact {
  display: flex;
  flex-direction: column-reverse;   /* la cifra arriba, la etiqueta debajo */
  align-items: center;
  gap: 10px;
  padding-inline: clamp(18px, 3.2vw, 48px);
  border-left: 1px solid var(--line-on-ink);
}
.globe-fact:first-child { border-left: 0; }
.globe-fact dd {
  font-size: clamp(1.45rem, 2.3vw, 2.1rem);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -.01em;
  color: var(--text-on-ink);
  font-variant-numeric: tabular-nums;
}
.globe-fact dt {
  font-size: .68rem;
  font-weight: 500;
  line-height: 1;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-on-ink-2);
}

/* ---------- Entrada ----------
   Se oculta el CONTENEDOR del texto, no los hijos: los hijos los anima
   main.js con GSAP (estilos en línea) y no hay que pelear con ellos. Con
   visibility y no con opacidad: si el contenedor estuviera a opacidad 0
   mientras los hijos terminan su fundido, Chrome no volvería a pintar el
   texto al subirla y el h1 nunca contaría como LCP. El fundido lo hacen
   los hijos. */
@keyframes globe-safety { to { opacity: 1; transform: none; } }
@keyframes globe-safety-v { to { visibility: visible; } }
html.globe-intro .globe-hero:not(.is-revealed) .globe-hero__copy { visibility: hidden; }
html.globe-intro:not(.globe-hold) .globe-hero:not(.is-revealed) .globe-hero__copy { animation: globe-safety-v 0s 3s forwards; }
/* El h1 además espera a que main.js lo parta en líneas (o lo marque
   .is-whole si la fuente no llega): nunca se ve entero con la letra de
   respaldo para después esconderse y partirse. */
html.globe-intro .globe-hero__copy h1:not(.split-lines):not(.is-whole) { visibility: hidden; }
html.globe-intro:not(.globe-hold) .globe-hero__copy h1:not(.split-lines):not(.is-whole) { animation: globe-safety-v 0s 3.6s forwards; }
html.globe-intro .globe-hero:not(.is-facts) .globe-hero__facts-title,
html.globe-intro .globe-hero:not(.is-facts) .globe-fact {
  opacity: 0;
  transform: translateY(16px);
}
html.globe-intro:not(.globe-hold) .globe-hero:not(.is-facts) .globe-hero__facts-title,
html.globe-intro:not(.globe-hold) .globe-hero:not(.is-facts) .globe-fact { animation: globe-safety .9s var(--ease-enter) 3.6s forwards; }
html.globe-intro .globe-hero:not(.is-facts) .globe-hero__facts::before { opacity: 0; }
html.globe-intro:not(.globe-hold) .globe-hero:not(.is-facts) .globe-hero__facts::before { animation: globe-safety .9s var(--ease-ui) 3.6s forwards; }
.globe-hero.is-facts .globe-hero__facts::before { transition: opacity .9s var(--ease-ui) calc(var(--globe-facts-delay) - .2s); }
.globe-hero.is-facts .globe-hero__facts-title,
.globe-hero.is-facts .globe-fact {
  transition: opacity .9s var(--ease-ui), transform 1.1s var(--ease-enter);
}
/* los retrasos repiten los data-delay de las cifras (0 / .08 / .16 / .24) */
.globe-hero.is-facts .globe-hero__facts-title { transition-delay: calc(var(--globe-facts-delay) - .15s); }
.globe-hero.is-facts .globe-fact:nth-child(1) { transition-delay: var(--globe-facts-delay); }
.globe-hero.is-facts .globe-fact:nth-child(2) { transition-delay: calc(var(--globe-facts-delay) + .08s); }
.globe-hero.is-facts .globe-fact:nth-child(3) { transition-delay: calc(var(--globe-facts-delay) + .16s); }
.globe-hero.is-facts .globe-fact:nth-child(4) { transition-delay: calc(var(--globe-facts-delay) + .24s); }
.globe-hero.is-facts .globe-fact:nth-child(5) { transition-delay: calc(var(--globe-facts-delay) + .32s); }

.globe-hero:not(.is-revealed) .globe-hero__labels { opacity: 0; }
.globe-hero.is-revealed .globe-hero__labels { transition: opacity 1s var(--ease-ui) .3s; }

/* ---------- Con el scroll (home) ----------
   Solo opacidad y transform (capas compuestas). El texto se va antes que
   el globo: a p ≈ 0,56 el titular ya no está y empiezan a encenderse las
   palabras del manifiesto. */
/* --gz (0 → 1) es el zoom de vuelta a la entrada (js/globe.js, «Zoom»): la
   interfaz se apaga en la primera mitad del acercamiento y vuelve en la
   segunda mitad de la vuelta. Se suma a --gp; los dos los escribe JS por
   fotograma, así que estas reglas siguen sin transición. */
.globe-hero--pinned .globe-hero__fade { opacity: clamp(0, 1 - var(--gp, 0) * 2 - var(--gz, 0) * 2.5, 1); }
.globe-hero--pinned .globe-hero__copy {
  opacity: clamp(0, 1 - var(--gp, 0) * 1.8 - var(--gz, 0) * 2, 1);
  transform: translateY(calc(var(--gp, 0) * -12vh - var(--gz, 0) * 3vh));
  will-change: opacity, transform;
}
.globe-hero--pinned .globe-hero__facts { opacity: clamp(0, 1 - var(--gp, 0) * 3 - var(--gz, 0) * 2.5, 1); }
/* en el zoom el velo de tinta de abajo (el de las cifras) se va con ellas */
.globe-hero--pinned.is-zoomed::after { opacity: calc(1 - var(--gz, 0)); transition: none; }
/* y la cabecera sube (vuelve con Tab, como siempre con :focus-within) */
html.globe-zoomed:not(.menu-open) .header:not(:focus-within) { transform: translateY(-110%); transition: transform .6s var(--ease-exit); }
/* sin WebGL, la insinuación CSS del globo también se apaga (si no, se
   vería a través de la marea del manifiesto y de las secciones sin fondo) */
.globe-hero--pinned.is-static .globe-hero__stage,
.globe-hero--pinned.is-lost .globe-hero__stage { opacity: clamp(0, 1 - var(--gp, 0) * 1.25, 1); }

/* El globo llegó tarde (red lenta): el texto ya está; el lienzo entra
   con un fundido en vez de aparecer de golpe */
@keyframes globe-canvas-in { from { opacity: 0; } }
.globe-hero.is-late .globe-hero__canvas { animation: globe-canvas-in 1s var(--ease-ui) both; }

/* ---------- Sin WebGL (o contexto perdido) ----------
   La sección se sostiene sola: tinta, texto y cifras, con una insinuación
   del globo en CSS (trama de puntos y el borde de luz arriba a la izquierda). */
.globe-hero.is-static .globe-hero__stage::before,
.globe-hero.is-lost .globe-hero__stage::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(75.6svh, 92vw);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background-image: radial-gradient(rgb(var(--fg-rgb) / .2) 1px, transparent 1.6px);
  background-size: 9px 9px;
  -webkit-mask-image: radial-gradient(circle at 38% 30%, #000 0%, rgb(0 0 0 / .5) 45%, transparent 71%);
  mask-image: radial-gradient(circle at 38% 30%, #000 0%, rgb(0 0 0 / .5) 45%, transparent 71%);
  opacity: .55;
}
.globe-hero.is-static .globe-hero__stage::after,
.globe-hero.is-lost .globe-hero__stage::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(min(75.6svh, 92vw) * 1.4);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background:
    radial-gradient(closest-side, transparent 70.4%, rgb(255 232 214 / .2) 71.3%, transparent 72.3%),
    radial-gradient(closest-side, transparent 70%, rgb(255 168 118 / .06) 72.5%, rgb(255 150 90 / .02) 84%, transparent 100%);
  -webkit-mask-image: linear-gradient(135deg, #000 28%, rgb(0 0 0 / .3) 55%, rgb(0 0 0 / .12) 80%);
  mask-image: linear-gradient(135deg, #000 28%, rgb(0 0 0 / .3) 55%, rgb(0 0 0 / .12) 80%);
}
.globe-hero.is-lost .globe-hero__canvas,
.globe-hero.is-lost .globe-hero__labels { visibility: hidden; }

/* ---------- Vertical: texto arriba, globo debajo ---------- */
@media (max-width: 699px), (max-aspect-ratio: 4/5) {
  .globe-hero { place-items: start center; }
  .globe-hero__copy { margin-top: 0; padding-top: calc(70px + clamp(10px, 2.6svh, 34px)); }
  /* en vertical el lead queda sobre la parte alta del globo: velo más firme */
  .globe-hero__copy::before {
    top: -36px;
    bottom: -26%;
    width: 150%;
    background: radial-gradient(closest-side, rgb(var(--ink-rgb) / .72), rgb(var(--ink-rgb) / .56) 62%, rgb(var(--ink-rgb) / 0));
  }
  .globe-hero.is-static .globe-hero__stage::before,
  .globe-hero.is-lost .globe-hero__stage::before,
  .globe-hero.is-static .globe-hero__stage::after,
  .globe-hero.is-lost .globe-hero__stage::after { top: 64%; }
}
@media (max-width: 699px) {
  .globe-hero__copy .kicker { margin-bottom: 14px; }
  .globe-hero__copy .page-hero__title { max-width: 11em; }
  .globe-hero__copy .page-hero__lead { margin-top: 16px; font-size: .95rem; max-width: 34ch; }
  .globe-hero__facts { gap: 12px; bottom: 18px; }
  .globe-hero__facts-title { font-size: .64rem; }
  .globe-fact { padding-inline: clamp(9px, 3.4vw, 18px); gap: 8px; }
  .globe-fact dd { font-size: 1.4rem; }
  .globe-fact dt { font-size: .58rem; letter-spacing: .12em; }
  .globe-label { font-size: 11px; }
  .globe-label.is-hq { font-size: 11.5px; }
  .globe-label__tag { font-size: 10px; }
}
/* Teléfono: cinco cifras no caben en una fila (2026-10-07, se sumaron
   colaboraciones y piezas): tres arriba y dos abajo, centradas. */
@media (max-width: 699px) {
  .globe-hero__facts-list:has(> :nth-child(5)) { display: grid; grid-template-columns: repeat(6, auto); justify-content: center; row-gap: 16px; }
  .globe-hero__facts-list:has(> :nth-child(5)) > .globe-fact { grid-column: span 2; }
  .globe-hero__facts-list:has(> :nth-child(5)) > .globe-fact:nth-child(4) { grid-column: 2 / span 2; border-left: 0; }
  .globe-hero__facts-list:has(> :nth-child(5)) > .globe-fact:nth-child(5) { grid-column: 4 / span 2; }
}
/* Por debajo de 340 px las cuatro cifras no caben en una fila: 2 × 2 */
@media (max-width: 339px) {
  .globe-hero__facts-list:not(:has(> :nth-child(5))) { display: grid; grid-template-columns: repeat(2, auto); row-gap: 14px; }
  .globe-hero__facts-list:not(:has(> :nth-child(5))) .globe-fact:nth-child(3) { border-left: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .globe-hero *,
  .globe-hero.is-revealed * { transition: none !important; animation: none !important; }
  /* quieto: el hero se va con la página, el manifiesto no le pasa por encima */
  .globe-hero--pinned { position: relative; }
}
