/* ===========================================================================
   sphera.css — hoja de estilo de la ficha de producto SPHERA
   Cargada por /sphera.html y /en/sphera.html.

   Esta página NO carga styles.css ni home.css: es un sistema de diseño
   autocontenido. Antes vivía como <style> inline duplicado a mano en ambos
   idiomas, lo que ya había producido deriva real (la regla .lang-tag existía
   sólo en la versión inglesa). Al extraerla hay una sola fuente de verdad.

   IMPORTANTE: el <link> a este archivo debe ir DESPUÉS de floating-contact.css.
   El <style> inline que reemplaza estaba después, y gana los empates de cascada.
   =========================================================================== */

:root {
  --bg-0: #070a12;
  --bg-1: #0b0f14;
  --bg-2: #111a36;
  --ink: #eef5ff;
  --muted: #9bb0c9;
  --cyan: #76d1ff;
  --orange: #ff9a3d;
  --amber: #ffb768;
  --purple: #b46fb6;
  --purple-deep: #913793;

  /* Bordes: antes había 21 recetas para lo que el ojo lee como dos. */
  --line: rgba(182, 225, 255, 0.28);
  --line-soft: rgba(190, 225, 255, 0.16);

  /* Superficies: antes 11 fondos de tarjeta distintos. Ahora dos niveles. */
  --surface: rgba(10, 18, 38, 0.72);
  --surface-1: linear-gradient(155deg, rgba(16, 29, 61, 0.72), rgba(10, 19, 42, 0.8));
  --surface-2: rgba(11, 22, 44, 0.42);

  /* Radios y espaciado: el sistema no tenía ninguno. */
  --r-sm: 8px;
  --r-md: 16px;
  --r-pill: 999px;
  --sp-3: clamp(14px, 2vw, 20px);
  --sp-4: clamp(18px, 2.4vw, 26px);
  --sp-5: clamp(22px, 3vw, 34px);
  --sp-6: clamp(28px, 4vw, 44px);

  /* Movimiento: una elevación y una duración, no cuatro y ocho. */
  --lift: -2px;
  --dur: 0.22s;
}

* { box-sizing: border-box; }

html, body { width: 100%; min-height: 100%; }

body {
  position: relative;
  margin: 0;
  color: var(--ink);
  font-family: "Inter", system-ui, sans-serif;
  background:
    radial-gradient(1200px 800px at 80% 10%, rgba(145, 55, 147, 0.12), transparent 60%),
    radial-gradient(1000px 700px at 10% 90%, rgba(249, 146, 28, 0.10), transparent 55%),
    linear-gradient(165deg, var(--bg-0), var(--bg-1) 38%, var(--bg-2));
  overflow-x: hidden;
}

#star-container { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }

#color-wash {
  position: fixed;
  top: -22vh; left: -8vw;
  width: 116vw; height: 150vh;
  z-index: 1; pointer-events: none; opacity: 0.32;
  background:
    radial-gradient(960px 680px at 14% 16%, rgba(145, 55, 147, 0.30), transparent 62%),
    radial-gradient(980px 680px at 78% 74%, rgba(249, 146, 28, 0.22), transparent 63%);
  will-change: transform;
}

.star {
  position: absolute; border-radius: 50%; background: #eaf4ff;
  box-shadow: 0 0 8px rgba(189, 228, 255, 0.45); opacity: 0.7;
  transform-origin: center; transform: scaleY(var(--stretch, 1));
  animation: twinkle var(--duration, 3.2s) infinite ease-in-out;
  will-change: top, opacity, transform;
}

@keyframes twinkle { 0%, 100% { opacity: 0.28; } 50% { opacity: 0.95; } }

.page { position: relative; z-index: 2; }

.shell { width: min(1120px, 92vw); margin: 0 auto; }

.section { position: relative; padding: clamp(64px, 8vw, 110px) 0; }

.section-title {
  margin: 0 0 14px;
  font-family: "Space Grotesk", sans-serif;
  font-size: clamp(1.7rem, 3.7vw, 2.7rem);
  line-height: 1.08; letter-spacing: 0.01em;
}

.section-copy {
  margin: 0; color: #d6e4f7; line-height: 1.72;
  font-size: clamp(1rem, 1.42vw, 1.14rem);
}

.section-copy + .section-copy { margin-top: 14px; }

/* ===== HERO WEBGL ===== */
.hero-sphera {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  display: grid; align-items: center;
  overflow: hidden;
}

.hero-canvas { position: absolute; inset: 0; z-index: 0; }
.hero-canvas canvas { display: block; width: 100%; height: 100%; }

.hero-overlay {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(115% 80% at 50% 42%, rgba(1, 10, 31, 0.34) 0%, rgba(1, 10, 31, 0.42) 34%, rgba(1, 10, 31, 0.6) 70%, rgba(1, 10, 31, 0.94) 100%),
    linear-gradient(180deg, rgba(1, 10, 31, 0.58) 0%, rgba(1, 10, 31, 0.18) 28%, rgba(1, 10, 31, 0.18) 52%, rgba(1, 10, 31, 0.97) 100%);
}

.hero-content {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: 1.04fr 0.96fr;
  align-items: center; gap: clamp(20px, 4vw, 52px);
  padding: 104px 0 48px; text-align: left;
}

.hero-left h1 {
  margin: 0 0 14px;
  font-family: "Space Grotesk", sans-serif;
  font-size: clamp(2.6rem, 7vw, 5.2rem);
  line-height: 0.98; letter-spacing: -0.015em;
  text-shadow: 0 6px 40px rgba(0, 0, 0, 0.55);
}

.hero-lead {
  margin: 0 0 10px; max-width: 24ch;
  font-family: "Space Grotesk", sans-serif;
  font-size: clamp(1.15rem, 2.6vw, 1.7rem);
  line-height: 1.2; color: #f3f8ff;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.5);
}

.hero-sub {
  margin: 0; max-width: 56ch;
  color: #d4e2f6; line-height: 1.72;
  font-size: clamp(1rem, 1.45vw, 1.16rem);
  text-shadow: 0 2px 16px rgba(0, 0, 0, 0.55);
}

.hero-actions {
  margin-top: 28px; display: flex; flex-wrap: wrap;
  gap: 14px; justify-content: flex-start;
}

/* ===== Logo SPHERA: anillo de texto 3D (derecha) ===== */
.hero-right {
  --radius: clamp(100px, 12vw, 178px);
  --radius-text: calc(var(--radius) * 1.18);
  --ring-font: calc(var(--radius) * 0.64);
  --spin: 22s;
  --speedX: 0; --speedY: -2; --speedZ: 0;
  --step: 20deg; /* separación angular entre letras: menor = más juntas */
  position: relative; display: grid; place-items: center;
  perspective: 1100px; min-height: calc(2.5 * var(--radius));
}

.sphera-ring { position: relative; display: grid; place-items: center; transform-style: preserve-3d; }
.sphera-ring > * { grid-area: 1 / 1; }

.sphera-ring__disc {
  width: calc(2 * var(--radius)); aspect-ratio: 1; border-radius: 50%;
  border: 1px solid rgba(180, 111, 182, 0.45);
  background: radial-gradient(circle at 50% 50%, rgba(6, 11, 28, 0.72) 16%, rgba(6, 11, 28, 0.32) 52%, rgba(6, 11, 28, 0) 73%);
  box-shadow: inset 0 0 70px rgba(118, 209, 255, 0.12), 0 0 70px rgba(145, 55, 147, 0.28);
}

.sphera-ring__text {
  position: relative; transform-style: preserve-3d; color: transparent;
  font-family: "Space Grotesk", sans-serif; font-weight: 700;
  font-size: var(--ring-font); text-transform: uppercase;
  will-change: transform;
  animation: spheraSpin var(--spin) linear infinite;
}

.sphera-ring__text span {
  position: absolute; top: 50%; left: 50%;
  transform: translate3d(-50%, -50%, 0) rotateY(calc(var(--i) * var(--step))) translateZ(var(--radius-text));
  backface-visibility: visible;
  color: #f3f8ff;
  text-shadow: 0 0 18px rgba(118, 209, 255, 0.5), 0 2px 12px rgba(0, 0, 0, 0.65);
}

@keyframes spheraSpin {
  0%   { transform: rotateX(0deg) rotateZ(0deg) rotateY(0deg); }
  100% { transform: rotateX(calc(360deg * var(--speedX))) rotateZ(calc(360deg * var(--speedZ))) rotateY(calc(360deg * var(--speedY))); }
}

.btn-primary, .btn-ghost {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 50px; padding: 12px 24px; border-radius: 12px;
  font-family: "Space Grotesk", sans-serif; font-weight: 700;
  text-decoration: none; letter-spacing: 0.01em;
  transition: transform var(--dur) ease, box-shadow var(--dur) ease, filter var(--dur) ease;
}

.btn-primary {
  border: 1px solid rgba(190, 220, 255, 0.75); color: #05263a;
  background: linear-gradient(135deg, var(--cyan), #92fff7);
  box-shadow: 0 0 0 1px rgba(213, 234, 255, 0.45) inset, 0 14px 28px rgba(73, 131, 235, 0.28);
}

.btn-primary:hover { transform: translateY(var(--lift)); filter: brightness(1.04); }

.btn-ghost {
  border: 1px solid rgba(216, 196, 255, 0.55); color: #f1e6ff;
  background: rgba(40, 14, 46, 0.35); backdrop-filter: blur(6px);
}

.btn-ghost:hover { transform: translateY(var(--lift)); border-color: rgba(216, 196, 255, 0.9); }

.hero-acronym {
  margin: -2px 0 20px; max-width: 42ch;
  font-family: "Roboto Mono", monospace;
  font-size: clamp(0.62rem, 1.5vw, 0.8rem);
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--cyan); text-shadow: 0 2px 14px rgba(0, 0, 0, 0.6);
}

.alliance {
  display: grid; grid-template-columns: 0.95fr 1.05fr;
  gap: clamp(24px, 5vw, 56px); align-items: center;
}

.alliance-logos {
  display: flex; align-items: center; justify-content: center;
  flex-wrap: nowrap; gap: clamp(10px, 2.5vw, 34px);
}
.logo-halo {
  position: relative; display: grid; place-items: center;
  flex: 1 1 0; min-width: 0; max-width: clamp(140px, 17vw, 212px);
  aspect-ratio: 1 / 1;
}
.logo-halo::before {
  content: ""; position: absolute; inset: -6%; border-radius: 50%;
  background: var(--halo); filter: blur(16px); z-index: 0;
  mix-blend-mode: screen;
}
.logo-halo img {
  position: relative; z-index: 1; width: 88%; height: 88%;
  object-fit: contain; display: block;
  filter: drop-shadow(0 6px 16px rgba(0, 0, 0, 0.5));
}
.logo-halo--altitud {
  --halo: radial-gradient(circle at 50% 50%, rgba(255, 178, 86, 0.68) 0%, rgba(249, 92, 40, 0.46) 36%, rgba(249, 92, 40, 0) 70%);
}
.logo-halo--falp {
  --halo: radial-gradient(circle at 50% 50%, rgba(216, 234, 255, 0.62) 0%, rgba(150, 198, 255, 0.42) 32%, rgba(74, 142, 236, 0.22) 56%, rgba(74, 142, 236, 0) 76%);
}
.logo-halo--falp::before { inset: -11%; }
.alliance-x {
  color: #b9c2d6; font-family: "Space Grotesk", sans-serif;
  font-size: clamp(1.4rem, 2.6vw, 2rem); font-weight: 700; flex: 0 0 auto;
}

.alliance-text h2 { margin-bottom: 14px; }

/* ===== CONTENT LAYOUTS ===== */
.split-50 {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(20px, 4vw, 46px); align-items: center;
}

.video-card {
  position: relative; display: block; width: 100%; aspect-ratio: 16 / 9;
  border-radius: 16px; overflow: hidden; text-decoration: none;
  border: 1px solid rgba(196, 225, 253, 0.16); background: #0a1020;
  box-shadow: 0 24px 50px rgba(0, 0, 0, 0.45);
}
.video-embed {
  position: absolute; inset: 0; width: 100%; height: 100%;
  border: 0; display: block; pointer-events: none;
}
.video-card::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(circle at 50% 50%, transparent 56%, rgba(2, 8, 22, 0.3));
  opacity: 0; transition: opacity 0.25s ease;
}
.video-card:hover::after { opacity: 1; }
.video-cta {
  position: absolute; right: 12px; bottom: 12px; z-index: 2; pointer-events: none;
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 14px; border-radius: 999px;
  background: rgba(7, 12, 27, 0.74); border: 1px solid rgba(216, 238, 255, 0.4);
  color: #f1f8ff; font-family: "Roboto Mono", monospace;
  font-size: 0.72rem; letter-spacing: 0.04em;
  transition: background 0.25s ease, border-color 0.25s ease;
}
.video-card:hover .video-cta { background: rgba(145, 55, 147, 0.68); border-color: rgba(216, 196, 255, 0.7); }

.card-cap {
  margin: 12px 4px 2px; color: var(--muted);
  font-family: "Roboto Mono", monospace; font-size: 0.72rem; letter-spacing: 0.04em;
}

.note {
  margin-top: 18px; padding: 14px 18px;
  border-left: 3px solid var(--purple-deep); border-radius: 8px;
  background: rgba(145, 55, 147, 0.1); color: #e2d2ea;
  font-size: 0.92rem; line-height: 1.65;
}

.head-center { max-width: 920px; margin: 0 auto 28px; text-align: center; }

/* pipeline — el número de columnas es una custom property, no un modificador por
   cada variante. Uso: <div class="pipeline" style="--cols:5">. Sirve para
   adquisición (3), piloto (5), estrategia de entrada (4), riesgos (4) y proceso (3).
   Las custom properties inline ya son idioma de esta hoja (.sphera-ring__text usa --i). */
.pipeline { display: grid; grid-template-columns: repeat(var(--cols, 4), minmax(0, 1fr)); gap: clamp(14px, 2vw, 20px); }
.pipe-step {
  position: relative; border-radius: var(--r-md);
  border: 1px solid var(--line-soft);
  background: var(--surface-1);
  padding: 22px 18px;
}
.pipe-num { font-family: "Roboto Mono", monospace; font-size: 0.78rem; letter-spacing: 0.12em; color: var(--cyan); }
.pipe-step h3 { margin: 8px 0 6px; font-family: "Space Grotesk", sans-serif; font-size: 1.05rem; }
.pipe-step p { margin: 0; color: #c7d7ec; line-height: 1.6; font-size: 0.94rem; }

/* Capacidades — índice editorial */
.caps-grid { display: grid; grid-template-columns: 0.82fr 1.55fr; gap: clamp(28px, 5vw, 74px); align-items: start; }
.caps-intro { position: sticky; top: 96px; }
.caps-eyebrow {
  display: inline-flex; align-items: center; gap: 11px; margin: 0 0 16px;
  font-family: "Roboto Mono", monospace; font-size: 0.72rem;
  letter-spacing: 0.22em; text-transform: uppercase; color: var(--purple);
}
.caps-eyebrow::before { content: ""; width: 28px; height: 1px; background: currentColor; opacity: 0.7; }
.caps-intro .section-copy { max-width: 32ch; }

.caps-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.cap-row {
  position: relative; display: grid; grid-template-columns: auto 1fr;
  gap: clamp(16px, 2.4vw, 36px); align-items: start;
  padding: clamp(20px, 2.6vw, 30px) clamp(6px, 1.2vw, 16px);
  border-bottom: 1px solid var(--line); overflow: hidden;
  transition: background 0.4s ease, padding-left 0.4s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.6s ease, transform 0.6s ease;
}
.cap-row::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
  background: linear-gradient(180deg, var(--cyan), var(--purple-deep));
  transform: scaleY(0); transform-origin: top; transition: transform 0.45s ease;
}
.cap-row:hover { background: linear-gradient(90deg, rgba(118, 209, 255, 0.06), rgba(118, 209, 255, 0) 72%); padding-left: clamp(20px, 2vw, 30px); }
.cap-row:hover::before { transform: scaleY(1); }

.cap-index {
  font-family: "Roboto Mono", monospace; font-weight: 700; line-height: 1;
  font-size: clamp(1.6rem, 3vw, 2.5rem); letter-spacing: -0.02em; min-width: 2.2ch;
  color: transparent; -webkit-text-stroke: 1.2px rgba(180, 111, 182, 0.6);
  transition: color 0.4s ease, -webkit-text-stroke-color 0.4s ease;
}
.cap-row:hover .cap-index { color: var(--cyan); -webkit-text-stroke-color: transparent; }

.cap-kicker { display: block; margin-bottom: 9px; font-family: "Roboto Mono", monospace; font-size: 0.66rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--purple); }
.cap-title { margin: 0 0 8px; font-family: "Space Grotesk", sans-serif; font-size: clamp(1.15rem, 1.9vw, 1.5rem); line-height: 1.12; color: #f3f8ff; }
.cap-desc { margin: 0; color: #c4d4ea; line-height: 1.62; font-size: 0.96rem; max-width: 54ch; }

@media (max-width: 900px) {
  .caps-grid { grid-template-columns: 1fr; gap: 20px; }
  .caps-intro { position: static; }
}

.chips { margin: 16px 0 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 8px; }
.chips li {
  font-family: "Roboto Mono", monospace; font-size: 0.72rem; letter-spacing: 0.03em;
  padding: 6px 11px; border-radius: 999px; color: #d8e7fb;
  border: 1px solid rgba(178, 220, 255, 0.3); background: rgba(11, 22, 44, 0.5);
}

/* stats / validation */
.champion-banner { padding: clamp(50px, 8vw, 80px) 0; }
.champion-box {
  border: 1px solid rgba(180, 111, 182, 0.36); border-radius: 18px;
  padding: clamp(20px, 4vw, 34px);
  background:
    linear-gradient(120deg, rgba(8, 14, 34, 0.92), rgba(26, 11, 40, 0.9)),
    radial-gradient(circle at 90% 50%, rgba(145, 55, 147, 0.18), transparent 48%);
}
.champion-box p { margin: 0; font-size: clamp(1.05rem, 1.65vw, 1.32rem); line-height: 1.68; color: #efe7ff; text-wrap: pretty; }

.stat-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 26px; }
.stat { text-align: center; padding: 20px 12px; border-radius: var(--r-md); border: 1px solid var(--line-soft); background: var(--surface-2); }
.stat b { display: block; font-family: "Roboto Mono", monospace; font-size: clamp(1.5rem, 3.4vw, 2.1rem); color: var(--amber); }
.stat span { color: #cbdbf0; font-size: 0.86rem; line-height: 1.4; display: block; margin-top: 4px; }

/* team — sin cajas, editorial */
.team-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(26px, 4vw, 56px); }
.team-card {
  --accent: var(--cyan);
  position: relative; display: flex; flex-direction: column;
  text-decoration: none; color: inherit; padding-top: 22px;
  border-top: 1px solid var(--line);
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.6s ease;
}
.team-card::before {
  content: ""; position: absolute; top: -1px; left: 0; width: 46px; height: 2px;
  background: var(--accent); transition: width 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}
.team-card:hover { transform: translateY(-4px); }
.team-card:hover::before { width: 100%; }
.team-card--cyan { --accent: var(--cyan); }
.team-card--purple { --accent: var(--purple); }
.team-card--orange { --accent: var(--orange); }

.team-role { display: block; font-family: "Roboto Mono", monospace; font-size: 0.66rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent); margin-bottom: 8px; }
.team-name { margin: 0 0 10px; font-family: "Space Grotesk", sans-serif; font-size: 1.22rem; line-height: 1.15; color: #f3f8ff; }
.team-bio { margin: 0 0 18px; color: #c4d4ea; line-height: 1.62; font-size: 0.93rem; flex: 1; }
.team-link { margin-top: auto; display: inline-flex; align-items: center; gap: 8px; font-family: "Roboto Mono", monospace; font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase; color: #cdddf2; }
.team-link i { font-style: normal; color: var(--accent); transition: transform 0.3s ease; }
.team-card:hover .team-link i { transform: translateX(5px); }

@media (max-width: 820px) { .team-grid { grid-template-columns: 1fr; gap: 30px; } }

/* footer CTA */
.footer-cta { text-align: center; padding-top: clamp(58px, 8vw, 86px); padding-bottom: clamp(40px, 6vw, 64px); }
.footer-box {
  max-width: 920px; margin: 0 auto; padding: clamp(22px, 4vw, 38px);
  border: 1px solid rgba(180, 111, 182, 0.3); border-radius: 20px;
  background: linear-gradient(145deg, rgba(20, 12, 38, 0.85), rgba(8, 14, 29, 0.9));
}
.footer-box .section-title { margin-bottom: 12px; }
.footer-box p { margin: 0 auto 22px; max-width: 58ch; color: #e7e0f4; line-height: 1.7; font-size: clamp(1rem, 1.45vw, 1.18rem); }
.footer-actions { display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; }

.site-footer {
  position: relative; z-index: 2;
  padding: 26px 0 46px; text-align: center; color: var(--muted);
  font-size: 0.82rem; line-height: 1.9;
}
.site-footer a { color: #cfe0f5; text-decoration: none; }
.site-footer a:hover { text-decoration: underline; }

/* reveal */
.reveal { opacity: 0; transform: translateY(26px); transition: opacity 0.6s ease, transform 0.6s ease; }
.reveal.is-visible { opacity: 1; transform: translateY(0); }

/* ===========================================================================
   COMPONENTES DEL DOSSIER DE EVALUACIÓN 2026
   Añadidos para que la ficha web sostenga el mismo contenido y la misma postura
   epistémica del dossier: lo construido, lo observado, lo pendiente.
   =========================================================================== */

/* ── .feat-grid ──────────────────────────────────────────────────────────────
   Tenía reglas en las media queries pero le faltaba la regla base: era un
   componente muerto. Se le da base y trabajo, con las columnas parametrizadas. */
.feat-grid {
  display: grid;
  grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr));
  gap: clamp(14px, 2vw, 20px);
  align-items: stretch;
}

.feat-card {
  display: flex; flex-direction: column;
  padding: var(--sp-4);
  border-radius: var(--r-md);
  border: 1px solid var(--line-soft);
  background: var(--surface-1);
}
.feat-card h3 {
  margin: 8px 0 10px;
  font-family: "Space Grotesk", sans-serif;
  font-size: clamp(1.05rem, 1.7vw, 1.28rem); line-height: 1.16; color: #f3f8ff;
}
.feat-card p { margin: 0; color: #c7d7ec; line-height: 1.66; font-size: 0.95rem; }
.feat-card p + p { margin-top: 10px; }

/* Variante oscura: para los límites de uso y advertencias de encuadre.
   Más contraste hacia el negro = se lee como nota institucional, no como feature. */
.feat-card--dark {
  border-color: rgba(180, 111, 182, 0.34);
  background:
    linear-gradient(120deg, rgba(8, 14, 34, 0.94), rgba(26, 11, 40, 0.92)),
    radial-gradient(circle at 88% 46%, rgba(145, 55, 147, 0.2), transparent 52%);
}

/* ── .ledger — "lo que existe hoy" / "lo que aún debe demostrarse" ───────────
   El dispositivo firma del dossier: aparece cuatro veces. Las dos columnas
   llevan DELIBERADAMENTE el mismo peso visual. La honestidad es el diseño: si la
   columna de brechas pareciera nota al pie, el componente mentiría con la forma. */
.ledger { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(16px, 2.4vw, 26px); }

/* Con un solo bloque, la rejilla de dos columnas lo dejaría a media anchura. */
.ledger--single { grid-template-columns: 1fr; }

.ledger__col {
  position: relative; overflow: hidden;
  padding: clamp(20px, 2.6vw, 30px);
  border-radius: var(--r-md);
  border: 1px solid var(--line-soft);
  background: var(--surface-2);
}
.ledger__col::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 2px;
  background: var(--ledger-accent);
}
.ledger__col::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(140% 60% at 50% 0%, var(--ledger-wash), transparent 62%);
}
.ledger__col > * { position: relative; z-index: 1; }

.ledger__col--have { --ledger-accent: var(--cyan);   --ledger-wash: rgba(118, 209, 255, 0.1); }
.ledger__col--gap  { --ledger-accent: var(--orange); --ledger-wash: rgba(255, 154, 61, 0.09); }

.ledger__head {
  margin: 0 0 16px;
  font-family: "Roboto Mono", monospace; font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--ledger-accent);
}
.ledger__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.ledger__list li {
  position: relative; padding-left: 26px;
  color: #cbdbf0; line-height: 1.62; font-size: 0.95rem; text-wrap: pretty;
}
.ledger__list li::before {
  /* El glifo por defecto va en la regla base: .ledger__list también se usa fuera
     de una .ledger__col (dependencias, modelo de adopción), y sin content los
     ítems quedaban con sangría pero sin viñeta. */
  content: "\2192";
  position: absolute; left: 0; top: 0.05em;
  font-family: "Roboto Mono", monospace; font-weight: 700;
  color: var(--ledger-accent, var(--cyan));
}
/* ✓ para lo construido, → para lo pendiente. Nunca ✗: el encuadre es
   "todavía no demostrado", no "fallido". */
.ledger__col--have .ledger__list li::before { content: "\2713"; }
.ledger__col--gap  .ledger__list li::before { content: "\2192"; }

/* ── .ways — invertir / pilotear / aportar capacidades ───────────────────────
   .way__num reutiliza el tratamiento de .cap-index para que toda la página
   hable un único idioma de numeral (índice editorial, pipeline y ways). */
.ways { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(18px, 2.6vw, 28px); }

.way {
  --accent: var(--cyan);
  display: flex; flex-direction: column;
  padding-top: 22px; border-top: 1px solid var(--line);
}
.way--cyan   { --accent: var(--cyan); }
.way--purple { --accent: var(--purple); }
.way--orange { --accent: var(--orange); }

.way__num {
  display: block; margin-bottom: 12px;
  font-family: "Roboto Mono", monospace; font-weight: 700; line-height: 1;
  font-size: 0.78rem; letter-spacing: 0.12em;
  color: var(--accent);
}
.way__title {
  margin: 0 0 10px;
  font-family: "Space Grotesk", sans-serif; font-size: 1.22rem; line-height: 1.15; color: #f3f8ff;
}
.way__desc { margin: 0 0 20px; color: #c4d4ea; line-height: 1.62; font-size: 0.94rem; }
.way__eyebrow {
  display: block; margin-bottom: 10px;
  font-family: "Roboto Mono", monospace; font-size: 0.64rem;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent);
}
.way__checks { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.way__checks li {
  position: relative; padding-left: 22px;
  color: #bfd0e6; line-height: 1.55; font-size: 0.89rem;
}
.way__checks li::before {
  content: "\2713"; position: absolute; left: 0; top: 0.05em;
  font-family: "Roboto Mono", monospace; color: var(--accent);
}

/* ── .sources — referencias numeradas ────────────────────────────────────────
   Contraste bajo a propósito: son verificables, no protagonistas. */
.sources-panel {
  padding: clamp(20px, 3vw, 32px);
  border-radius: 18px;
  border: 1px solid rgba(178, 220, 255, 0.18);
  background: var(--surface);
}
.sources-panel .caps-eyebrow { margin-bottom: 18px; }

.sources { counter-reset: src; list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.sources li {
  position: relative; padding-left: 34px;
  color: var(--muted); font-size: 0.82rem; line-height: 1.75; text-wrap: pretty;
}
.sources li::before {
  counter-increment: src; content: counter(src, decimal-leading-zero);
  position: absolute; left: 0; top: 0;
  font-family: "Roboto Mono", monospace; font-size: 0.76rem; color: var(--cyan);
}
.sources a { color: #cfe0f5; text-decoration: underline; text-decoration-color: rgba(118, 209, 255, 0.4); text-underline-offset: 2px; }
.sources a:hover { text-decoration-color: var(--cyan); }
.sources cite { font-style: italic; }

/* ── .legal-note ─────────────────────────────────────────────────────────────
   Colofón mono discreto, no caja de advertencia. Una caja gritona se lee
   defensiva; un colofón se lee institucional, que es lo que espera un evaluador. */
.legal-note {
  margin: clamp(26px, 4vw, 40px) 0 0;
  padding-top: 18px; max-width: 78ch;
  border-top: 1px solid var(--line);
  font-family: "Roboto Mono", monospace; font-size: 0.72rem; line-height: 1.8;
  color: var(--muted); text-wrap: pretty;
}

/* ── .figure-plate — las figuras del dossier sobre fondo oscuro ──────────────
   Todas las figuras vienen con fondo opaco casi blanco (~rgb(253,253,253)).
   Cinco losas blancas sobre #070a12 se ven rotas salvo que sean intencionales:
   se enmarcan como hoja impresa flotando, lo que además liga visualmente la
   página con el PDF del dossier.
   NO invertir ni hue-rotate: son ilustraciones médicas y alterar el color del
   tejido es un problema de corrección, no una decisión de estilo. */
.figure-plate {
  background: #fbfcfe;
  border-radius: 16px;
  padding: clamp(10px, 1.6vw, 18px);
  border: 1px solid rgba(200, 232, 255, 0.22);
  box-shadow: 0 28px 60px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.9);
}
.figure-plate img { display: block; width: 100%; height: auto; border-radius: 8px; }

/* Miniaturas de documento (manuscrito y abstract): misma placa, más contenida. */
.doc-thumb { max-width: min(100%, 420px); margin-inline: auto; }

/* Enlace de descarga con su peso declarado — convención de honestidad de la casa.
   Los botones son inline-flex en fila, así que un hijo `display:block` se sentaría
   AL LADO de la etiqueta, no debajo: la variante --stack pasa el botón a columna. */
.btn-primary--stack, .btn-ghost--stack {
  flex-direction: column; justify-content: center;
  gap: 2px; padding-top: 9px; padding-bottom: 9px; line-height: 1.25;
}
.btn-meta {
  display: block;
  font-family: "Roboto Mono", monospace; font-size: 0.66rem; font-weight: 500;
  letter-spacing: 0.08em; opacity: 0.75; text-transform: none;
}

/* Rendimiento: la página creció mucho. Se le da al navegador permiso para no
   maquetar lo que está fuera de pantalla. La altura estimada evita saltos de scroll. */
.section--defer { content-visibility: auto; contain-intrinsic-size: 0 900px; }


@media (max-width: 980px) {
  .ledger, .ways { grid-template-columns: 1fr; }
  .split-50, .alliance { grid-template-columns: 1fr; }
  .pipeline { grid-template-columns: 1fr 1fr; }
  .feat-grid { grid-template-columns: 1fr 1fr; }
  .hero-content { grid-template-columns: 1fr; text-align: center; }
  .hero-left h1, .hero-acronym, .hero-lead, .hero-sub { margin-left: auto; margin-right: auto; }
  .hero-actions { justify-content: center; }
  .hero-right { --radius: clamp(108px, 26vw, 178px); order: -1; }
}

@media (max-width: 640px) {
  .shell { width: min(1120px, 94vw); }
  .hero-sphera { min-height: 100vh; min-height: 100dvh; }
  .hero-content { padding-top: 96px; }
  .pipeline, .feat-grid, .team-grid, .stat-row { grid-template-columns: 1fr; }
  .hero-right { --radius: clamp(92px, 32vw, 150px); }
  /* En móvil la placa blanca ocupa casi todo el ancho: se reduce el marco para
     no robarle píxeles a la figura, que ya es el elemento más denso de la página. */
  .figure-plate { padding: 8px; border-radius: 12px; }
  .sources li { padding-left: 28px; }
}

@media (prefers-reduced-motion: reduce) {
  .star, .sphera-ring__text { animation: none; }
}

/* ── Botón de idioma ───────────────────────────────────────────────
   Esta página no tiene barra de navegación, así que el botón va fijo
   arriba a la derecha. Al estar solo (nada compite con él) se puede
   permitir ser grande: es el reclamo de "aquí se cambia el idioma".
   Relleno blanco sólido = único elemento claro sobre el fondo oscuro. */
.lang-fab {
  position: fixed;
  top: 22px;
  right: 22px;
  z-index: 50;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 14px 24px;
  border: 2px solid #ffffff;
  border-radius: 999px;
  background: #ffffff;
  color: #070a12;
  font-family: "Roboto Mono", ui-monospace, monospace;
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  /* Sombra neutra: el relleno blanco sólido ya lo despega del fondo oscuro.
     El halo pulsante se retiró: el botón de contacto ya tiene uno abajo. */
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.55);
  transition: background .22s ease, border-color .22s ease, color .22s ease,
              transform .22s ease, box-shadow .22s ease;
}

.lang-fab__globe {
  display: flex;
  align-items: center;
  color: var(--purple-deep);
  transition: color .22s ease;
}
.lang-fab__globe svg { display: block; width: 20px; height: 20px; }

.lang-fab:hover,
.lang-fab:focus-visible {
  background: var(--cyan);
  border-color: var(--cyan);
  color: #070a12;
  transform: translateY(var(--lift));
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.55);
}
.lang-fab:hover .lang-fab__globe,
.lang-fab:focus-visible .lang-fab__globe { color: #070a12; }
.lang-fab:focus-visible { outline: 2px solid #fff; outline-offset: 4px; }
.lang-fab:active { transform: translateY(0); }

@media (max-width: 640px) {
  .lang-fab {
    top: 14px;
    right: 14px;
    padding: 11px 17px;
    font-size: 12px;
    letter-spacing: 0.06em;
    gap: 8px;
  }
  .lang-fab__globe svg { width: 17px; height: 17px; }
}
@media (prefers-reduced-motion: reduce) {
  .lang-fab { transition: none; }
  .lang-fab:hover, .lang-fab:focus-visible { transform: none; }
}

/* Badge "ES": marca enlaces que llevan a páginas sólo en español. */
.lang-tag {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 5px;
  font-family: "Roboto Mono", ui-monospace, monospace;
  font-size: 0.72em;
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1.5;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 4px;
  vertical-align: 1px;
}

/* ── Marca · vuelve a la portada ────────────────────────────────────
   Fija arriba a la izquierda, haciendo pareja con el botón de idioma.
   Replica el .brand de /conocimiento/ y /rendimiento/ (esta página no
   carga styles.css, por eso el estilo va aquí). */
.brand-fab {
  position: fixed;
  top: 22px;
  left: 22px;
  z-index: 50;
  display: inline-flex;
  align-items: center;
  gap: 11px;
  padding: 7px 18px 7px 7px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(7, 10, 18, 0.72);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  text-decoration: none;
  color: var(--ink);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.50);
  transition: border-color .22s ease, background .22s ease,
              transform .22s ease, box-shadow .22s ease;
}
.brand-fab__logo {
  width: 40px;
  height: 40px;
  object-fit: contain;
  display: block;
  flex: 0 0 auto;
}
.brand-fab__text {
  font-family: Inter, system-ui, -apple-system, sans-serif;
  font-weight: 900;
  font-size: 18px;
  letter-spacing: 0.5px;
  line-height: 1;
  white-space: nowrap;
}
/* "100K" en fucsia de marca, igual que en el resto del sitio. */
.brand-fab__text span { color: #f21651; }

.brand-fab:hover,
.brand-fab:focus-visible {
  border-color: var(--cyan);
  background: rgba(7, 10, 18, 0.9);
  transform: translateY(-2px);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55),
              0 0 24px rgba(118, 209, 255, 0.35);
}
.brand-fab:focus-visible { outline: 2px solid #fff; outline-offset: 4px; }
.brand-fab:active { transform: translateY(0); }

@media (max-width: 640px) {
  .brand-fab {
    top: 14px;
    left: 14px;
    gap: 8px;
    padding: 6px 13px 6px 6px;
  }
  .brand-fab__logo { width: 32px; height: 32px; }
  .brand-fab__text { font-size: 14.5px; }
}
/* Muy estrecho: sólo el escudo, para no chocar con el botón de idioma.
   Sigue siendo un botón reconocible de vuelta al inicio. */
@media (max-width: 400px) {
  .brand-fab { padding: 6px; gap: 0; }
  .brand-fab__text { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .brand-fab { transition: none; }
  .brand-fab:hover, .brand-fab:focus-visible { transform: none; }
}


/* ===========================================================================
   BLOQUES SIN CAJA — actualización de agosto de 2026
   La página tenía 54 contenedores con borde y sombra, y nada distinguía una
   tarjeta de contenido de una nota al pie. Estos componentes sustituyen a los
   "ledger" de dos columnas y a las tarjetas anidadas de la sección Evidencia:
   misma información, sin marco.

   Nota: el hero, las estrellas, Qué es SPHERA, Una alianza… y Capacidades del
   software conservan su tratamiento original a propósito. Si tocas los tokens de
   arriba, revisa que esas zonas sigan viéndose igual.
   =========================================================================== */

/* Cuatro cifras en fila: la serie clínica del dossier (76 / 31 / 33 / volumen). */
.stat-row--4 { grid-template-columns: repeat(4, 1fr); }

/* ── .readout — un bloque de lectura, marcado con una regla, no con una caja ── */
.readout {
  margin-top: var(--sp-5);
  padding-left: clamp(16px, 2.2vw, 26px);
  border-left: 2px solid var(--purple-deep);
}
.readout--wide { margin-top: var(--sp-6); }
.readout__lead {
  margin: 0 0 var(--sp-3);
  color: #c4d4ea; line-height: 1.65; font-size: 0.98rem; text-wrap: pretty;
  max-width: 78ch;
}
.readout .ledger__list { margin-top: 0; }
.readout .card-cap { margin-top: 14px; }

/* Dos columnas de texto, sin marco ni fondo. */
.split-cols {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(24px, 4vw, 48px);
}

/* Rótulo de bloque dentro de un .readout. Un solo nivel, en la voz de los
   títulos, no otro rótulo en versalitas: ya hay bastantes. */
.block-title {
  margin: 0 0 12px;
  font-family: "Space Grotesk", sans-serif; font-weight: 700;
  font-size: 1.05rem; line-height: 1.2; color: #f3f8ff;
}

/* Lista numerada con la misma métrica que .ledger__list (ruta regulatoria). */
.ledger__list--ordered { counter-reset: step; }
.ledger__list--ordered li { padding-left: 30px; }
.ledger__list--ordered li::before {
  counter-increment: step; content: counter(step, decimal-leading-zero);
  font-size: 0.76rem; color: var(--cyan); top: 0.2em;
}
.ledger__list--check li::before { content: "\2713"; }

/* ── .docs-grid — manuscrito y congresos ────────────────────────────────────
   Antes cada uno era una .feat-card que CONTENÍA una <figure> completa con su
   placa blanca y su pie: caja dentro de caja dentro de caja. Ahora el texto va
   suelto y la única superficie es la placa de la figura, que sí es un objeto. */
.docs-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(28px, 4.5vw, 56px);
  margin-top: var(--sp-6);
}
.doc-block { display: flex; flex-direction: column; }
.doc-block h3 {
  margin: 0 0 10px;
  font-family: "Space Grotesk", sans-serif;
  font-size: clamp(1.05rem, 1.7vw, 1.28rem); line-height: 1.16; color: #f3f8ff;
}
.doc-block p { margin: 0; color: #c4d4ea; line-height: 1.66; font-size: 0.95rem; }
.doc-block figure { margin: var(--sp-3) 0 0; }

@media (max-width: 980px) {
  .stat-row--4 { grid-template-columns: 1fr 1fr; }
  .split-cols, .docs-grid { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .stat-row--4 { grid-template-columns: 1fr; }
  .readout { padding-left: 14px; }
}

/* ── .team-photo — retrato circular en las tarjetas de Equipo ────────────────
   Los archivos son recortes cuadrados centrados en la cara, generados a 176 px
   (2x) desde los originales de /assets/team/, que se conservan intactos. Al
   venir ya recortados no hace falta object-position: el círculo encuadra solo.
   NO reutilizar .team-card__img de nosotros.html: aquella hoja vive inline en
   esa página y su .team-card colisiona con la de aquí. */
.team-photo {
  display: block; width: 88px; height: 88px;
  margin: 0 0 16px; border-radius: var(--r-pill);
  object-fit: cover;
  border: 1px solid var(--line-soft);
  background: var(--surface-2);
  transition: transform var(--dur) cubic-bezier(0.16, 1, 0.3, 1);
}
.team-card:hover .team-photo { transform: scale(1.04); }

@media (prefers-reduced-motion: reduce) {
  .team-photo { transition: none; }
  .team-card:hover .team-photo { transform: none; }
}

/* ===========================================================================
   TRAYECTORIA DEL PROYECTO — sección #trayectoria de /sphera.html y /en/sphera.html

   Todo va prefijado con .tl-. Sin prefijo, .logo-halo pisaría el que ya existe
   más arriba en este archivo y rompería los logos con neón de #alianza. Aquí no
   se redeclara ni un token, ni html, ni body, ni :root: los colores, las
   tipografías, .section, .section-title, .section-copy, .shell, .head-center y
   .reveal se toman de lo ya definido arriba.

   Cero dependencias. La hélice se enciende con una sola variable CSS
   (--tl-progress, que escribe /js/trayectoria.js) y las entradas reusan el
   observador .reveal que la ficha ya tiene.

   La hélice está adaptada de /control-empresarial-ia/grupo-sanhueza-medical.html:
   peldaños en 3D con un animation-delay negativo escalonado por índice. Ese
   desfase es lo que la convierte en hélice y no en un montón de palitos girando.
   =========================================================================== */

.tl-track {
  --tl-dna-w: 74px;
  --tl-rose: #f21651;      /* citosina. sphera.css no tiene token de rosa */
  --tl-progress: 0;        /* la escribe trayectoria.js */

  /* El carril se sale del .shell (1120 px) para que los logos crezcan sin
     estrujar el texto ni pegarse a la hélice. left + translateX centra sin
     importar el ancho del padre. */
  position: relative;
  left: 50%;
  width: min(1240px, 94vw);
  transform: translateX(-50%);
  margin-top: clamp(18px, 3vw, 34px);
}

/* ===== HÉLICE =====
   Cada peldaño se posiciona en absoluto con su `top` en píxeles, no con flex y
   gap: un translateX de centrado pelearía con el rotateY de la animación. */

.tl-dna {
  position: absolute; top: 0; bottom: 0;
  left: 50%; margin-left: calc(var(--tl-dna-w) / -2);
  width: var(--tl-dna-w);
  z-index: 0; pointer-events: none;
}

.tl-dna__seg { position: absolute; left: 0; width: 100%; }

.tl-dna__rung {
  position: absolute; left: 0; width: 100%; height: 8px;
  display: flex; align-items: center; justify-content: space-between;
  transform-style: preserve-3d;

  /* Fuera de pantalla el peldaño no anima: queda quieto en el ángulo que le
     tocaría por su índice. 24° por paso y 3,2 s de vuelta obligan a un desfase
     de 24/360 × 3,2 = 0,21333 s; los dos valores viajan juntos. */
  transform: perspective(600px) rotateY(calc(var(--i) * 24deg));

  /* Se enciende al pasar el scroll, sin una sola línea de JS por peldaño:
     --tl-progress avanza de 0 a 1 y --p es la posición fija del peldaño. El
     piso en 0,07 lo deja apagado por delante del scroll, y el multiplicador 55
     estrecha la transición a unos 80 px: se ve un frente avanzando. */
  opacity: clamp(0.07, calc((var(--tl-progress) - var(--p)) * 55), 1);
}

/* La perspective va DENTRO del transform, no en el contenedor: sobre una
   columna de miles de píxeles un único punto de fuga deformaría los peldaños
   de los extremos. Como función, cada uno recibe el suyo. */
@keyframes tlDnaSpin {
  from { transform: perspective(600px) rotateY(0deg); }
  to   { transform: perspective(600px) rotateY(360deg); }
}

.tl-dna__seg.is-live .tl-dna__rung {
  animation: tlDnaSpin 3.2s linear infinite;
  animation-delay: calc(var(--i) * -0.21333s);
}

/* Los dos nucleótidos del par. Llevan colores DISTINTOS porque en el ADN las
   bases van emparejadas: adenina con timina, citosina con guanina. Que los dos
   extremos de un mismo peldaño sean de distinto color es lo que hace que se lea
   como ADN y no como una fila de puntos. trayectoria.js escribe --c1 y --c2. */
.tl-dna__rung::before,
.tl-dna__rung::after {
  content: ""; width: 10px; height: 10px; border-radius: 50%;
}
.tl-dna__rung::before { background: var(--c1); box-shadow: 0 0 14px var(--c1); }
.tl-dna__rung::after  { background: var(--c2); box-shadow: 0 0 14px var(--c2); }

/* La varilla va en degradado de una base a la otra: es el enlace del par. */
.tl-dna__rod {
  position: absolute; left: 0; top: 50%;
  width: 100%; height: 1.5px;
  transform: translateY(-50%);
  background: linear-gradient(90deg, var(--c1), var(--c2));
  opacity: 0.55;
}

/* Lo que todavía no ocurre: el peldaño conserva el color de sus bases pero va
   hueco, sólo contorno, y con la varilla punteada. La varilla mantiene el
   degradado y se puntea con máscara, no sustituyendo el fondo, para que el paso
   de una base a la otra se siga leyendo en el tramo futuro. */
.tl-dna__rung--future::before,
.tl-dna__rung--future::after {
  width: 11px; height: 11px;
  background: transparent;
}
.tl-dna__rung--future::before { border: 1.6px solid var(--c1); box-shadow: 0 0 9px var(--c1); }
.tl-dna__rung--future::after  { border: 1.6px solid var(--c2); box-shadow: 0 0 9px var(--c2); }

.tl-dna__rung--future .tl-dna__rod {
  -webkit-mask-image: repeating-linear-gradient(90deg, #000 0 4px, transparent 4px 9px);
  mask-image: repeating-linear-gradient(90deg, #000 0 4px, transparent 4px 9px);
  opacity: 0.5;
}

/* ===== MARCAS DE AÑO ===== */

.tl-year {
  position: relative; z-index: 1;
  display: flex; justify-content: center;
  padding-block: clamp(14px, 2.2vh, 30px);
}
.tl-year span {
  padding: 9px 24px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: rgba(7, 12, 26, 0.9);
  backdrop-filter: blur(8px);
  font-family: "Roboto Mono", monospace;
  font-weight: 700;
  font-size: clamp(1.35rem, 3vw, 1.9rem);
  letter-spacing: 0.06em;
  color: #f2f8ff;
  box-shadow: 0 0 30px rgba(118, 209, 255, 0.18);
}
.tl-year--future span {
  border-style: dashed;
  border-color: rgba(255, 154, 61, 0.6);
  color: var(--amber);
  box-shadow: 0 0 30px rgba(255, 154, 61, 0.16);
}

/* ===== HITOS =====
   Sin caja. El logo encabeza su columna y el texto se alinea hacia el eje: sin
   un marco que los contenga, esa alineación es lo único que mantiene la columna
   unida alrededor de la hélice.

   El logo va AL COSTADO, no encima. Apilado sumaba su alto a cada hito
   (~150 px × 12); al costado la altura del hito es el máximo de los dos. */

.tl-item {
  --tl-fig: clamp(120px, 12.5vw, 176px);
  position: relative; z-index: 1;
  display: grid;
  gap: 4px clamp(14px, 2.2vw, 28px);
  align-items: center;

  /* El segundo término reserva el hueco central: 74 px de hélice más 58 px de
     aire a cada lado. Sin él, entre 900 y 1050 px de ancho los hitos de un lado
     y del otro invadían la columna de la hélice y el texto quedaba debajo de
     los nucleótidos. */
  width: min(520px, calc((100% - 190px) / 2));
  margin-block: clamp(10px, 1.8vh, 22px);
}

.tl-item__figure {
  grid-row: 1 / span 3; align-self: center;
  width: 100%; margin: 0;

  /* Los logos no pueden salirse de su columna. Sin este tope, uno muy apaisado
     —Babson es 5:1— multiplica la altura fijada por su proporción y desborda el
     contenedor. El max-width de la imagen es circular mientras .tl-logo sea un
     inline-flex que se ajusta al contenido: hay que acotar también el envoltorio
     para romper esa circularidad. */
  max-width: 100%; min-width: 0;
}
.tl-logo, .tl-logos { max-width: 100%; }

/* El logo va PEGADO AL EJE y el texto fluye hacia afuera: la columna interior es
   la de la figura, no la del texto. Los doce logos quedan así en una columna
   apretada contra la hélice.

   La alineación del texto no cambia —izquierda a la derecha, derecha a la
   izquierda— y como ahora el texto ocupa la columna exterior, esa alineación es
   lo que lo mantiene pegado a su logo. */
.tl-item--left {
  grid-template-columns: minmax(0, 1fr) var(--tl-fig);
  margin-right: auto; text-align: right;
}
.tl-item--left .tl-item__figure { grid-column: 2; }
.tl-item--left .tl-meta  { grid-column: 1; grid-row: 1; justify-content: flex-end; }
.tl-item--left .tl-title { grid-column: 1; grid-row: 2; }
.tl-item--left .tl-desc  { grid-column: 1; grid-row: 3; }

.tl-item--right {
  grid-template-columns: var(--tl-fig) minmax(0, 1fr);
  margin-left: auto; text-align: left;
}
.tl-item--right .tl-item__figure { grid-column: 1; }
.tl-item--right .tl-meta  { grid-column: 2; grid-row: 1; justify-content: flex-start; }
.tl-item--right .tl-title { grid-column: 2; grid-row: 2; }
.tl-item--right .tl-desc  { grid-column: 2; grid-row: 3; }

.tl-meta {
  margin: 0 0 8px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 9px;
  font-family: "Roboto Mono", monospace;
  font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase;
}
.tl-meta__year { color: var(--cyan); font-weight: 700; font-size: 0.8rem; }
.tl-meta__kind { color: var(--muted); }
.tl-meta__kind::before { content: "· "; opacity: 0.6; }
.tl-meta__tag {
  padding: 4px 10px; border-radius: var(--r-pill);
  border: 1px solid rgba(180, 111, 182, 0.5);
  color: #e0c8e6; font-size: 0.6rem; letter-spacing: 0.1em;
}
.tl-item--future .tl-meta__year { color: var(--amber); }

.tl-title {
  margin: 0 0 8px;
  font-family: "Space Grotesk", sans-serif;
  font-size: clamp(1.18rem, 2vw, 1.5rem);
  line-height: 1.16;
  color: #f3f8ff;
  text-wrap: balance;
}

.tl-desc {
  margin: 0;
  font-size: 0.94rem; line-height: 1.62; color: #c4d4ea;
}

/* ===== LOGOS: HALO, NO PLACA =====
   Cuatro de estos logos son texto azul o negro sobre transparente y sobre el
   fondo casi negro quedarían apagados. El resplandor radial los despega sin
   dibujar el rectángulo blanco que se acaba de eliminar.

   Deliberadamente NO se llama .logo-halo: ese selector ya existe en sphera.css
   con otra geometría y lo usa la sección #alianza. */

/* ----- LA PLACA -----
   Antes cada logo se dimensionaba por altura con el ancho libre. Como las
   proporciones van de 1:1 (FALP, Altitud) a 5:1 (Babson), con la misma altura
   nominal uno ocupaba 20.700 px² y el otro 6.100: la columna salía descuadrada.

   Ahora los doce comparten EXACTAMENTE la misma caja y el logo se centra dentro
   con object-fit: contain. La columna queda alineada al píxel.

   La placa también sustituye al halo. Aquel eran tres degradados radiales de
   colores distintos, con border-radius: 50% sobre cajas de proporciones
   dispares —elipses larguísimas en los logos apaisados— y el frío casi opaco
   con 13 px de desenfoque: sobre el campo de estrellas leía como mancha. La
   placa resuelve la legibilidad de los cuatro logos de texto azul marino sin
   tocarle el color a ninguna marca. */

.tl-logo {
  display: flex; align-items: center; justify-content: center;
  width: var(--tl-fig);
  aspect-ratio: 8 / 5;
  max-width: 100%;
  margin: 0;
  padding: clamp(10px, 1.2vw, 16px);
  border-radius: 14px;
  background: #eef4fd;
  box-shadow: 0 10px 30px rgba(2, 6, 18, 0.5);
}

.tl-logo img {
  display: block;
  width: 100%; height: 100%;
  object-fit: contain;
}


/* ===== DISTINTIVOS, EN LÍNEA CON LOS METADATOS ===== */

.tl-stamp { display: inline-flex; width: 16px; height: 16px; flex: 0 0 auto; }
.tl-stamp svg { width: 100%; height: 100%; }
.tl-stamp svg path {
  fill: none; stroke: var(--cyan); stroke-width: 3;
  stroke-linecap: round; stroke-linejoin: round;
  /* Se dibuja solo al entrar, colgado del .reveal que ya tiene la ficha. */
  stroke-dasharray: 26; stroke-dashoffset: 26;
  transition: stroke-dashoffset 0.5s ease 0.25s;
}
.reveal.is-visible .tl-stamp svg path { stroke-dashoffset: 0; }

.tl-seal { display: inline-flex; width: 18px; height: 18px; flex: 0 0 auto; }
.tl-seal svg { width: 100%; height: 100%; }
.tl-seal__ring { fill: none; stroke: var(--amber); stroke-width: 2.2; }
.tl-seal__glyph {
  fill: var(--amber);
  font-family: "Roboto Mono", monospace; font-weight: 700; font-size: 15px;
}
.tl-seal__star { fill: var(--amber); }

/* ===== PICTOGRAMAS: ENCABEZAN EL HITO, EN EL LUGAR DEL LOGO ===== */

/* Los pictogramas de los hitos futuros NO llevan placa —son dibujos de línea
   pensados para fondo oscuro, y en un hito por ocurrir no hay logo que mostrar—
   pero sí ocupan exactamente la misma caja que ella, o la columna se descuadra
   otra vez en la mitad de abajo de la sección. */
.tl-hex {
  position: relative;
  display: grid; place-items: center;
  width: var(--tl-fig); aspect-ratio: 8 / 5;
  max-width: 100%;
  margin: 0;
  animation: tlSoonPulse 3.4s ease-in-out infinite;
}
.tl-hex svg { aspect-ratio: 1; width: auto; height: 100%; }
.tl-hex > * { grid-area: 1 / 1; }
.tl-hex polygon {
  fill: rgba(10, 16, 32, 0.85);
  stroke: var(--orange); stroke-width: 4;
  stroke-dasharray: 7 7; stroke-linejoin: round;
}
.tl-hex i {
  font-style: normal;
  font-family: "Roboto Mono", monospace; font-weight: 700;
  font-size: clamp(0.62rem, 1vw, 0.78rem);
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--amber);
}
@keyframes tlSoonPulse {
  0%, 100% { transform: scale(1);    filter: drop-shadow(0 0 8px rgba(255, 154, 61, 0.3)); }
  50%      { transform: scale(1.05); filter: drop-shadow(0 0 22px rgba(255, 154, 61, 0.6)); }
}

.tl-glyph {
  display: grid; place-items: center;
  width: var(--tl-fig); aspect-ratio: 8 / 5;
  max-width: 100%; margin: 0;
}
.tl-glyph svg { width: 88%; height: auto; display: block; }
.tl-glyph__stroke {
  fill: none; stroke: rgba(190, 220, 250, 0.55);
  stroke-width: 3; stroke-linecap: round; stroke-linejoin: round;
}
.tl-glyph__accent {
  fill: none; stroke: var(--amber);
  stroke-width: 3; stroke-linecap: round;
}

/* ===== TECLEO =====
   El escalonado lo resuelve el CSS con transition-delay: no hace falta GSAP ni
   un temporizador por carácter. trayectoria.js sólo parte el texto y pone --n. */

.tl-wd { display: inline-block; white-space: nowrap; }

.tl-ch {
  display: inline-block;
  opacity: 0;
  transform: translateY(24%);
  transition: opacity 0.3s ease, transform 0.3s ease;
  transition-delay: calc(var(--n) * 12ms);
}
.is-typed .tl-ch { opacity: 1; transform: none; }

/* ===== RESPONSIVE ===== */

@media (max-width: 900px) {
  /* La hélice pasa a correr DETRÁS del contenido, centrada y ancha.
     Arrinconada en 42 px a un costado, el giro de 24° por peldaño movía los
     nucleótidos apenas unos píxeles: no se apreciaba siquiera que estuviera
     animada. Centrada y a 280 px, la vuelta se lee entera y el contenido pasa
     por encima sin robarle ni un píxel de ancho al texto.

     No se toca .tl-dna: vuelve a la regla base, centrada con left: 50% y el
     margen negativo. La unidad es vw, no %: dentro de una variable el % se
     sustituye como texto y acabaría resolviéndose contra un contenedor que se
     dimensiona por su contenido. */
  .tl-track { --tl-dna-w: min(340px, 70vw); }

  /* El contenido va por delante y las placas son opacas, así que la hélice se
     ve pasar por detrás de ellas. */
  .tl-item { z-index: 2; }
  .tl-year { z-index: 2; }

  /* Separar un hito del siguiente. El problema no era que estuviera apretado,
     sino que el hueco ENTRE hitos (15 px) medía casi lo mismo que los huecos
     DENTRO de cada uno (8 a 10 px): con esa proporción el ojo no puede agrupar
     y todo se lee como una lista continua.

     Los espacios internos se dejan igual y sólo se abre el externo, así que la
     razón pasa de 1,7 a casi 5 a 1. No se añade ninguna línea ni separador: lo
     que aparece en el hueco es la propia hélice, que ya corre por detrás. Dos
     peldaños asoman entre hito e hito y hacen de bisagra sin pedir atención.

     Los márgenes verticales contiguos colapsan, así que este valor es la
     separación real, no el doble. */
  .tl-item { margin-block: clamp(46px, 7.4vh, 76px); }

  /* El marcador de año separa capítulos: respira algo más que un hito. */
  .tl-year { padding-block: clamp(26px, 4.5vh, 46px); }

  /* El texto sí cruza por encima de los nucleótidos. Una aureola oscura pegada
     a las letras lo mantiene legible sin dibujar ninguna caja; sobre el fondo
     liso no se nota que está. */
  .tl-meta, .tl-title, .tl-desc {
    text-shadow: 0 0 4px rgba(7, 10, 18, 0.95), 0 0 13px rgba(7, 10, 18, 0.92);
  }

  /* Centrado, una linea larga se lee mal y ademas tapa la helice de lado a
     lado. En movil no llega a activarse —ahi la columna ya mide unos 30ch— y
     en tablet recoge el texto hacia el centro. */
  .tl-title, .tl-desc { max-width: 42ch; }

  /* Sobre 280 px de ancho, los nucleótidos de 10 px se veían raquíticos. */
  .tl-dna__rung::before, .tl-dna__rung::after { width: 13px; height: 13px; }
  .tl-dna__rung--future::before,
  .tl-dna__rung--future::after { width: 14px; height: 14px; }
  .tl-dna__rod { height: 2px; }

  /* En una columna angosta el logo no cabe al costado: vuelve a encabezar. */
  .tl-item--left, .tl-item--right {
    width: 100%; margin-inline: 0;

    /* Longitud concreta, no un porcentaje. Dentro de una variable el 100% se
       sustituye como texto y acaba resolviendose contra .tl-item__figure, que
       en movil se dimensiona por su contenido: la referencia es circular y la
       placa se disparaba a 660 px dentro de un viewport de 768. */
    --tl-fig: 240px;
    grid-template-columns: minmax(0, 1fr);

    /* Centrado sobre el eje de la helice. Con la placa a un costado y el texto
       a todo el ancho, la composicion quedaba descolgada a la izquierda
       mientras el ADN corria por el centro. Centrado, la placa se apoya sobre
       la hebra como una estacion del recorrido. */
    text-align: center;
    justify-items: center;
  }
  .tl-item--left .tl-item__figure, .tl-item--right .tl-item__figure {
    grid-column: 1; grid-row: 1;
    width: var(--tl-fig); max-width: 100%;
    justify-self: center; margin-bottom: 10px;
  }
  .tl-item--left .tl-meta,  .tl-item--right .tl-meta  { grid-column: 1; grid-row: 2; justify-content: center; }
  .tl-item--left .tl-title, .tl-item--right .tl-title { grid-column: 1; grid-row: 3; }
  .tl-item--left .tl-desc,  .tl-item--right .tl-desc  { grid-column: 1; grid-row: 4; }
}

@media (max-width: 640px) {
  .tl-track { --tl-dna-w: min(290px, 76vw); }
  .tl-item--left, .tl-item--right { --tl-fig: 200px; }
}

/* ===== MOVIMIENTO REDUCIDO ===== */

@media (prefers-reduced-motion: reduce) {
  .tl-hex { animation: none; }

  /* La hélice queda quieta, cada peldaño en su ángulo, y toda visible. */
  .tl-dna__seg.is-live .tl-dna__rung { animation: none; }
  .tl-dna__rung { opacity: 0.7; }

  /* Nada queda a medio dibujar ni escondido. */
  .tl-stamp svg path { stroke-dashoffset: 0; transition: none; }
  .tl-ch { opacity: 1; transform: none; transition: none; }
}
