/* =====================================================================
   Airbnb en el Mundial — hoja de estilos unica
   Estructura: tokens -> reset -> tipografia -> layout -> componentes
   ===================================================================== */

/* ----------------------------------------------------------------------
   1. Tokens (variables CSS)
   ---------------------------------------------------------------------- */
:root {
  /* Paleta oficial Airbnb (nombres canonicos, intactos como tokens) */
  --c-rausch: #ff5a5f;
  --c-rausch-dark: #c8484d;
  --c-babu: #00a699;
  --c-babu-dark: #00857a;
  --c-arches: #fc642d;
  --c-hof: #484848;          /* ahora rol semantico: FONDO base */
  --c-hof-deep: #1f1f1f;     /* superficie mas oscura (metodologia, footer) */
  --c-foggy: #767676;        /* sobrevive como gris medio para overrides */
  --c-bone: #fafafa;         /* ahora rol semantico: TEXTO primario */
  --c-bone-dark: #efeeec;    /* sobrevive para casos puntuales en superficies claras */
  --c-error: #d93030;

  /* Sistema semantico nuevo: el resto del CSS consume estos tokens */
  --c-bg: #2C2D2D;                       /* fondo principal del tablero */
  --c-surface-1: #3a3a3a;                /* filtros, inputs, controles (un poco mas claro que el bg) */
  --c-surface-2: var(--c-hof-deep);      /* drawer, metodologia, footer (mas oscuro que el bg) */
  --c-text-primary: var(--c-bone);       /* #fafafa */
  --c-text-secondary: #c8c8c8;           /* WCAG AAA sobre #2C2D2D ~8.2:1 */
  --c-text-muted: #b8b8b8;                /* WCAG AAA sobre #2C2D2D ~7.0:1 */
  --c-border-subtle: #5a5a5a;
  --c-border-strong: #7a7a7a;

  /* Tokens de viz secundaria (recalibrados para fondo oscuro) */
  --grid-line: #5a5a5a;
  --axis-text: var(--c-text-muted);
  --axis-line: var(--c-border-subtle);
  --tooltip-bg: var(--c-hof-deep);
  --tooltip-text: var(--c-bone);
  --tooltip-border: var(--c-border-strong);

  /* Coropletico (5 cuantiles, Babu->Rausch via Arches) */
  --cuant-1: #b8e6e3;
  --cuant-2: #66c7c1;
  --cuant-3: #fcb698;
  --cuant-4: #fc8758;
  --cuant-5: #ff5a5f;
  --cuant-zero: transparent;             /* deja ver el tile dark de fondo */

  /* Tipografia */
  --font-display: "Figtree", system-ui, -apple-system, sans-serif;
  --font-body: "Roboto", system-ui, -apple-system, sans-serif;

  /* Escala tipografica desktop */
  --fs-display-xxl: 8rem;
  --fs-display-xl: 6rem;
  --fs-display-l: 4.5rem;
  --fs-display-m: 3.5rem;
  --fs-heading-l: 2rem;
  --fs-heading-m: 1.5rem;
  --fs-body-l: 1.25rem;
  --fs-body-m: 1rem;
  --fs-body-s: 0.875rem;
  --fs-caption: 0.8125rem;
  --fs-data-xl: clamp(3rem, 6vw, 6rem);
  --fs-data-l: clamp(2rem, 4vw, 3.5rem);

  /* Espaciado base 8px */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 1rem;
  --sp-4: 1.5rem;
  --sp-5: 2rem;
  --sp-6: 3rem;
  --sp-7: 4rem;
  --sp-8: 6rem;
  --sp-9: 8rem;

  /* Otros */
  --radius-s: 2px;
  --radius-m: 4px;
  /* Header en 2 filas compactas: brand centrado arriba, menú centrado abajo. */
  --header-h: 64px;
  --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
  --transition-base: 250ms cubic-bezier(0.4, 0, 0.2, 1);
  --shadow-sticky: 0 1px 0 rgba(0, 0, 0, 0.3);
  --max-w: 1440px;
}

@media (max-width: 640px) {
  :root {
    --fs-display-xxl: 3.5rem;
    --fs-display-xl: 3rem;
    --fs-display-l: 2.5rem;
    --fs-display-m: 2rem;
    --fs-heading-l: 1.625rem;
    --fs-heading-m: 1.25rem;
    --fs-body-l: 1.125rem;
    --fs-data-xl: 4rem;
    --fs-data-l: 2.5rem;
    /* En mobile el menú colapsa al hamburguesa, así que vuelve a 1 fila. */
    --header-h: 56px;
  }
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --transition-fast: 0ms;
    --transition-base: 0ms;
  }
  *, *::before, *::after {
    animation-duration: 0ms !important;
    transition-duration: 0ms !important;
  }
}

/* ----------------------------------------------------------------------
   2. Reset minimalista
   ---------------------------------------------------------------------- */
*, *::before, *::after {
  box-sizing: border-box;
}
html, body, h1, h2, h3, h4, h5, h6, p, figure, blockquote {
  margin: 0;
}
ul, ol {
  margin: 0;
  padding: 0;
  list-style: none;
}
img, svg, video {
  display: block;
  max-width: 100%;
}
button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
a {
  color: inherit;
  text-decoration: none;
}
input, button, textarea, select {
  font: inherit;
}

/* ----------------------------------------------------------------------
   3. Tipografia base
   ---------------------------------------------------------------------- */
html {
  font-size: 100%;
  text-size-adjust: 100%;
  /* Scrollbar simétrico: reserva el espacio del scrollbar a AMBOS
     lados del viewport, no sólo del derecho. Sin esto, el contenido
     centrado matemáticamente queda desplazado a la izquierda porque
     el navegador come ~15px del derecho con el scrollbar visible.
     `both-edges` garantiza que los márgenes L y R sean iguales para
     el ojo, sin importar si el scrollbar está visible o no. */
  scrollbar-gutter: stable both-edges;
  /* Vertical Scroll Section: cada section directa de <main> snapea al
     viewport. Usamos `proximity` (no `mandatory`) porque mandatory
     fuerza el snap al punto más cercano incluso con scrolls cortos —
     el efecto era que un click de rueda chico te regresaba al snap
     anterior en lugar de avanzar (el "rebote de dos clics"). Con
     proximity el snap se acomoda cuando el scroll está cerca de un
     section, sin pelearse con scrolls intermedios. */
  scroll-snap-type: y proximity;
  scroll-behavior: smooth;
  scroll-padding-top: var(--header-h);
}
main > section {
  min-height: 100vh;
  min-height: 100dvh;
  scroll-snap-align: start;
  /* `normal` (no `always`) deja que el scroll del usuario fluya
     naturalmente; el snap se acomoda al asentarse cerca de un punto,
     sin obligar parada en cada section. */
  scroll-snap-stop: normal;
  /* el min-height incluye el header sticky para que cada section
     ocupe pantalla completa real; scroll-padding-top compensa al
     hacer el snap. */
  box-sizing: border-box;
}
@media (max-width: 900px) {
  html {
    scroll-snap-type: y proximity;
  }
  main > section {
    min-height: auto;
  }
}
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-snap-type: none;
    scroll-behavior: auto;
  }
  main > section {
    min-height: auto;
  }
}
body {
  font-family: var(--font-body);
  font-size: var(--fs-body-m);
  line-height: 1.6;
  color: var(--c-text-primary);
  background: var(--c-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.skip-link {
  position: absolute;
  top: -100px; left: var(--sp-3);
  background: var(--c-bone);
  color: var(--c-bg);
  padding: var(--sp-2) var(--sp-3);
  z-index: 9999;
  font-weight: 700;
}
.skip-link:focus {
  top: var(--sp-3);
}

/* Foco visible global */
:focus-visible {
  outline: 2px solid var(--c-rausch);
  outline-offset: 2px;
}

/* ----------------------------------------------------------------------
   4. Header sticky
   - Layout: marca (izq) · nav de secciones (centro) · acciones (der)
   - Borde blanco abajo con sombra para destacar contra fondo oscuro
   - Barra de progreso de scroll sobre el borde (controlada por JS)
   ---------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 500;
  background: #000;
  border-bottom: 1px solid var(--c-bone);
  box-shadow:
    0 2px 8px rgba(0, 0, 0, 0.55),
    0 8px 24px rgba(0, 0, 0, 0.4);
  transition: box-shadow var(--transition-fast);
}
.site-header__wrap {
  display: flex;
  flex-direction: column;
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 4px var(--sp-4);
  height: var(--header-h);
  box-sizing: border-box;
  position: relative; /* anclaje para el pill Compartir posicionado absoluto */
  /* Por defecto el header arranca "encogido": solo el menú visible. JS
     agrega `is-expanded` en la <header> tras el primer scroll real
     (>24px) y entonces aparece la fila superior con brand + Compartir.
     La transición de altura/opacidad genera el efecto de reveal. */
  transition: height var(--transition-base);
}
/* Fila 1: grid 3 columnas, brand SIEMPRE en col 2 (centro absoluto),
   acciones SIEMPRE en col 3 (derecha). El toggle vive en col 1 solo
   en mobile (display:none en desktop no descuadra porque las celdas
   están asignadas por grid-column explícito). */
.site-header__top {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  height: 32px;
  overflow: hidden;
  transition: height var(--transition-base),
              opacity var(--transition-base),
              margin var(--transition-base);
}

/* ----------------------------------------------------------------------
   Estado "encogido" del header (default antes del primer scroll):
   - Fila superior colapsa: brand y botón Compartir se ocultan.
   - El alto total del header se reduce al de la fila inferior (menú).
   - La barra de progreso y el menú siguen visibles y funcionales.
   ---------------------------------------------------------------------- */
.site-header:not(.is-expanded) .site-header__wrap {
  /* Altura ajustada al menú (~28px) + paddings (4+4). El menú ya tiene
     height: 24px + margin-top: 2px; +2 de respiro abajo. */
  height: 34px;
}
.site-header:not(.is-expanded) .site-header__top {
  height: 0;
  opacity: 0;
  margin: 0;
  pointer-events: none;
}
.site-header:not(.is-expanded) .site-header__actions {
  /* El pill Compartir está absolute; lo apagamos aparte para que su
     halo blur no asome por debajo del header colapsado. */
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
  transition: opacity var(--transition-base),
              visibility 0s linear var(--transition-base);
}
.site-header.is-expanded .site-header__actions {
  transition: opacity var(--transition-base),
              visibility 0s linear 0s;
}
/* En mobile el header no se colapsa: la fila superior es necesaria
   para mostrar el botón hamburguesa que abre/cierra el menú. */
@media (max-width: 820px) {
  .site-header:not(.is-expanded) .site-header__wrap {
    height: var(--header-h);
  }
  .site-header:not(.is-expanded) .site-header__top {
    height: 100%;
    opacity: 1;
    margin: initial;
    pointer-events: auto;
  }
  .site-header:not(.is-expanded) .site-header__actions {
    opacity: 1;
    pointer-events: auto;
    visibility: visible;
  }
}
.site-header__top .site-header__toggle {
  grid-column: 1;
  justify-self: start;
}
.site-header__brand {
  grid-column: 2;
  justify-self: center;
  text-align: center;
}
.site-header__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.0625rem;
  letter-spacing: -0.01em;
  color: var(--c-text-primary);
  line-height: 1;
}
.site-header__actions {
  grid-column: 3;
  justify-self: end;
  /* Sacamos el pill Compartir del flujo de la grid para que pueda
     centrarse verticalmente contra el header completo (64px), no solo
     contra la fila superior de 32px. La grid mantiene 1fr auto 1fr;
     col 3 queda visualmente vacía pero el brand sigue centrado en col 2. */
  position: absolute;
  right: var(--sp-4);
  top: 50%;
  transform: translateY(-50%);
  z-index: 1;
}

/* Nav inferior: anchors centrados en la 2ª fila */
.site-header__sections {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
  flex-wrap: nowrap;
  height: 24px;
  margin-top: 2px;
}
.section-link {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--c-text-secondary);
  padding: 4px var(--sp-3);
  border-radius: var(--radius-s);
  white-space: nowrap;
  line-height: 1;
  transition: color var(--transition-fast);
  /* Subrayado-onda en Rausch — decisión editorial del nav. En reposo
     se posiciona fuera del elemento (bg-position-x: 390px); el
     keyframe `section-link-line` lo desliza a su posición final (0)
     al hacer hover o focus. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='390' height='50' viewBox='0 0 390 50'><path fill='none' stroke='%23ff5a5f' stroke-width='2.5' stroke-linecap='round' stroke-miterlimit='10' d='M0,47.585c0,0,97.5,0,130,0c13.75,0,28.74-38.778,46.168-19.416C192.669,46.5,243.603,47.585,260,47.585c31.821,0,130,0,130,0'/></svg>");
  background-repeat: no-repeat;
  /* SVG a tamaño nativo (390×50) anclado al pie del link. Como el link
     mide ~24px de alto, sólo se ve la banda inferior del SVG (donde
     vive la línea recta a y=47.585). El alto extra del SVG queda
     fuera del padding-box y se recorta. */
  background-position: 390px bottom;
  background-size: auto;
}
.section-link:hover {
  color: var(--c-text-primary);
  animation: section-link-line 0.4s linear forwards;
}
.section-link:focus-visible {
  color: var(--c-text-primary);
  background-color: rgba(255, 255, 255, 0.06);
  animation: section-link-line 0.4s linear forwards;
}
.section-link[aria-current="true"] {
  color: var(--c-rausch);
}
@keyframes section-link-line {
  from { background-position-x: 390px; }
  to   { background-position-x: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .section-link:hover,
  .section-link:focus-visible {
    animation: none;
    background-position-x: 0; /* línea estática, sin deslizamiento */
  }
}

/* Acciones (botón Compartir solo icono, derecha) */
.site-header__actions {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: var(--sp-1);
}
.header-btn {
  font-family: var(--font-body);
  font-size: var(--fs-body-s);
  font-weight: 500;
  color: var(--c-text-primary);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius-m);
  transition: background var(--transition-fast), color var(--transition-fast);
}
.header-btn:hover,
.header-btn:focus-visible {
  background: rgba(255, 255, 255, 0.08);
  color: var(--c-rausch);
}
/* Variante solo-icono: padding cuadrado, sin texto. */
.header-btn--icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
}
.header-btn--icon .icon {
  display: block;
}

/* ----------------------------------------------------------------------
   Botón Compartir con expansión pill + gradiente brand + halo difuso.
   Adapta el patrón YouTube de @ojomenos a la paleta del datero (Babu→
   Rausch en lugar del lime→cyan original). En reposo: 32×32 pill
   translúcido. En hover/focus: se expande a 142px, el ícono colapsa
   con delay y aparece la leyenda "Compartir" en uppercase. Un halo
   difuso sale por debajo gracias a ::after blur(12px).
   ---------------------------------------------------------------------- */
.header-btn--share {
  /* Botón sobrio sin gradientes Babu→Rausch (esos colores quedan
     reservados para dato). Fondo neutro que se vuelve Arches sólido
     en hover/focus, manteniendo la transición de ancho. */
  --share-w-collapsed: 32px;
  --share-w-expanded: 142px;
  position: relative;
  isolation: isolate;
  overflow: visible;
  width: var(--share-w-collapsed);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.08);
  /* line-height: 0 evita que el line-height heredado de body (1.6)
     empuje verticalmente el ícono dentro del flex de centrado. */
  line-height: 0;
  transition: width 0.5s, background 0.4s, color 0.4s;
}
.header-btn--share::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--c-rausch);
  opacity: 0;
  transition: opacity 0.5s;
  z-index: 0;
}
.header-btn--share .icon {
  position: relative;
  z-index: 1;
  transition: transform 0.5s 0.25s, color 0.4s;
}
.header-btn--share__title {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--c-bone);
  transform: scale(0);
  transition: transform 0.5s;
  pointer-events: none;
  white-space: nowrap;
  line-height: 1;
}
.header-btn--share:hover,
.header-btn--share:focus-visible {
  width: var(--share-w-expanded);
  background: transparent;
  color: var(--c-bone);
}
.header-btn--share:hover::before,
.header-btn--share:focus-visible::before {
  opacity: 1;
}
.header-btn--share:hover .icon,
.header-btn--share:focus-visible .icon {
  transform: scale(0);
  transition-delay: 0s;
}
.header-btn--share:hover .header-btn--share__title,
.header-btn--share:focus-visible .header-btn--share__title {
  transform: scale(1);
  transition-delay: 0.25s;
}
@media (prefers-reduced-motion: reduce) {
  .header-btn--share,
  .header-btn--share::before,
  .header-btn--share .icon,
  .header-btn--share__title {
    transition: none;
  }
  .header-btn--share:hover .icon,
  .header-btn--share:focus-visible .icon {
    transform: none;
  }
  .header-btn--share:hover .header-btn--share__title,
  .header-btn--share:focus-visible .header-btn--share__title {
    transform: scale(1);
  }
}

/* Hamburguesa solo en mobile */
.site-header__toggle {
  display: none;
  width: 40px; height: 40px;
  position: relative;
}
.site-header__toggle span {
  display: block;
  position: absolute;
  left: 8px;
  width: 24px;
  height: 2px;
  background: var(--c-text-primary);
  transition: transform var(--transition-fast);
}
.site-header__toggle span:nth-child(1) { top: 12px; }
.site-header__toggle span:nth-child(2) { top: 19px; }
.site-header__toggle span:nth-child(3) { top: 26px; }
.site-header__toggle[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.site-header__toggle[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
}
.site-header__toggle[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* Barra de progreso de scroll: corre sobre el borde inferior del header.
   --scroll-progress (0..1) lo actualiza JS en cada scroll. Color Babu
   por contraste contra negro (header) y Rausch (hero), y porque Rausch
   está reservado para datos Mundial — sería confuso si el progress
   también fuera Rausch. */
.site-header__progreso {
  position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 3px;
  background: var(--c-babu);
  transform: scaleX(var(--scroll-progress, 0));
  transform-origin: left center;
  pointer-events: none;
  will-change: transform;
}

/* Tablet: condensar el nav central */
@media (max-width: 1100px) {
  .section-link {
    padding: var(--sp-2) var(--sp-2);
    font-size: 11px;
  }
}

/* Mobile: brand centrado arriba, menú se vuelve dropdown bajo el header. */
@media (max-width: 820px) {
  .site-header__wrap {
    height: var(--header-h);
    padding: 0 var(--sp-3);
    flex-direction: row;
    align-items: center;
    gap: 0;
  }
  .site-header__top {
    flex: 1;
    height: 100%;
  }
  /* En mobile la wrap es flex-row con align-items: center; el pill ya
     queda vertical-centrado por el flow natural. Revertimos el absolute
     que aplicamos en desktop. */
  .site-header__actions {
    position: static;
    right: auto;
    top: auto;
    transform: none;
  }
  .site-header__sections {
    position: absolute;
    top: var(--header-h);
    left: 0; right: 0;
    background: var(--c-surface-2);
    flex-direction: column;
    align-items: stretch;
    padding: var(--sp-3);
    gap: 0;
    border-bottom: 1px solid var(--c-bone);
    box-shadow: 0 8px 24px rgba(0,0,0,0.5);
    transform: translateY(-10px);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--transition-fast), transform var(--transition-fast);
  }
  .site-header__sections.is-open {
    transform: translateY(0);
    opacity: 1;
    pointer-events: auto;
  }
  .section-link {
    text-align: left;
    padding: var(--sp-3) var(--sp-2);
    font-size: var(--fs-body-s);
    border-bottom: 1px solid var(--c-border-subtle);
  }
  .section-link:last-child {
    border-bottom: 0;
  }
  .site-header__toggle {
    display: block;
  }
}

/* ----------------------------------------------------------------------
   5a. Hero de orientación (intro)
   Tres niveles de jerarquía: titular XXL → subtítulo italic → intro
   con preguntas retóricas en color secundario para crear ritmo.
   ---------------------------------------------------------------------- */
/* Hero full-bleed cinematográfico (decisión editorial post-restructura).
   La ilustración risográfica ocupa toda la sección como capa de fondo;
   un gradiente vertical garantiza la legibilidad del texto anclado al
   pie. Parallax sutil vía scroll-driven animations (sin JS, degradación
   grácil en navegadores sin soporte). El fade inferior cierra contra
   #0D0E0E (mismo color del fondo de KPIs) para que el hero empalme sin
   costura con la siguiente sección. */
.hero {
  position: relative;
  background: var(--c-rausch); /* fallback mientras carga la imagen */
  padding: 0;
  display: flex;
  align-items: center;
  overflow: hidden;
  isolation: isolate;
  /* Override del `main > section { min-height: auto }` que aplica debajo
     de 900px: el hero cinematográfico siempre ocupa pantalla completa. */
  min-height: 100vh;
  min-height: 100dvh;
}
.hero__media {
  position: absolute;
  inset: 0;
  margin: 0;
  z-index: 0;
  overflow: hidden;
}
.hero__media img {
  width: 100%;
  height: 110%; /* margen para que el parallax no descubra fondo abajo */
  object-fit: cover;
  object-position: center 35%;
  display: block;
  will-change: transform;
}
.hero__overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  /* Gradiente diseñado para texto centrado verticalmente. Banda del
     texto (40-60%) más oscura para garantizar contraste AA del copy
     blanco sin depender de la luminosidad de la imagen. Cierre a
     #0D0E0E al pie para empalmar sin costura con la sección de KPIs. */
  background: linear-gradient(
    to bottom,
    rgba(13, 14, 14, 0)    0%,
    rgba(13, 14, 14, 0.30) 18%,
    rgba(13, 14, 14, 0.78) 42%,
    rgba(13, 14, 14, 0.88) 65%,
    rgba(13, 14, 14, 0.95) 88%,
    #0D0E0E               100%
  );
}
.hero__contenido {
  position: relative;
  z-index: 2;
  /* Padding asimétrico para centrar ÓPTICAMENTE el bloque. El flex
     padre centra matemáticamente (align-items: center), pero el
     gradient oscuro del overlay y el peso visual del titular XXL
     desplazan la percepción hacia abajo. Padding-bottom mayor que
     padding-top empuja el texto hacia arriba dentro del hero y
     compensa la ilusión, dejándolo sintiéndose centrado. */
  padding: var(--sp-3) var(--sp-5) var(--sp-6);
  max-width: 62ch;
  width: 100%;
  will-change: transform;
}
/* Parallax CSS-puro: la imagen sube despacio mientras el contenido baja
   un poco más rápido y se desvanece. Se desactiva con
   prefers-reduced-motion y queda inerte (estático) en navegadores sin
   soporte para scroll-driven animations. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll(root)) {
    .hero__media img {
      animation: hero-parallax-img linear both;
      animation-timeline: scroll(root);
      animation-range: 0 100vh;
    }
    .hero__contenido {
      animation: hero-parallax-text linear both;
      animation-timeline: scroll(root);
      animation-range: 0 100vh;
    }
  }
}
@keyframes hero-parallax-img {
  from { transform: translateY(0); }
  to   { transform: translateY(-10%); }
}
@keyframes hero-parallax-text {
  from { transform: translateY(0); opacity: 1; }
  to   { transform: translateY(28%); opacity: 0; }
}

.hero__meta {
  font-family: var(--font-body);
  /* -2 pt respecto a fs-caption (13px → 11px) */
  font-size: 0.6875rem;
  font-weight: 500;
  /* WCAG AA: texto sin transparencia sobre el overlay oscuro garantiza
     contraste ≥4.5:1 en cualquier banda del gradiente. */
  color: var(--c-bone);
  letter-spacing: 0.02em;
  margin: 0;
}
.hero__titulo {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(2.5rem, 5vw, 4.75rem);
  line-height: 0.95;
  letter-spacing: -0.03em;
  color: var(--c-bone);
  margin: var(--sp-1) 0 0;
  max-width: 18ch;
}
.hero__subtitulo {
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 400;
  font-size: var(--fs-body-l);
  line-height: 1.3;
  color: var(--c-bone);
  margin: var(--sp-2) 0 0;
  max-width: 40ch;
}
.hero__intro {
  font-family: var(--font-body);
  font-size: var(--fs-body-m);
  line-height: 1.35;
  color: var(--c-bone);
  max-width: 60ch;
  margin: var(--sp-3) 0 0;
  text-align: justify;
  hyphens: auto;
}
.hero__intro-preguntas {
  /* Sin opacidad: aseguramos contraste AA sobre el overlay del hero
     en todas las bandas del gradiente. */
  color: var(--c-bone);
}
.hero__creditos {
  font-family: var(--font-body);
  /* -1 pt respecto a fs-caption (13px → 12px) */
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--c-bone);
  margin: var(--sp-2) 0 0;
  letter-spacing: 0.01em;
  line-height: 1.55;
}
.hero__creditos a {
  /* Bone sobre el gradiente oscuro del hero full-bleed: contraste alto,
     subrayado sutil. */
  color: var(--c-bone);
  font-weight: 700;
  text-decoration: underline;
  text-decoration-color: rgba(250, 250, 250, 0.45);
  text-underline-offset: 3px;
  transition: text-decoration-color var(--transition-fast), color var(--transition-fast);
}
.hero__creditos a:hover,
.hero__creditos a:focus-visible {
  color: var(--c-rausch);
  text-decoration-color: currentColor;
}
@media (max-width: 900px) {
  .hero__media img {
    object-position: center 30%;
  }
  .hero__contenido {
    max-width: 100%;
    padding: var(--sp-4) var(--sp-4) var(--sp-5);
  }
}
@media (max-width: 640px) {
  .hero__media img {
    object-position: 70% 30%; /* prioriza el bloque del edificio */
  }
  .hero__overlay {
    /* Mobile: el texto centrado ocupa proporcionalmente más alto;
       subimos el oscurecido también en la mitad superior para asegurar
       legibilidad por encima del bloque de texto. */
    background: linear-gradient(
      to bottom,
      rgba(13, 14, 14, 0.10) 0%,
      rgba(13, 14, 14, 0.45) 25%,
      rgba(13, 14, 14, 0.78) 50%,
      rgba(13, 14, 14, 0.92) 75%,
      #0D0E0E               100%
    );
  }
  .hero__contenido {
    padding: var(--sp-4) var(--sp-3) var(--sp-4);
    gap: var(--sp-1);
  }
  .hero__intro {
    font-size: var(--fs-body-s);
    margin-top: var(--sp-2);
  }
  .hero__subtitulo {
    font-size: var(--fs-body-m);
  }
}

/* ----------------------------------------------------------------------
   5. Banda de KPIs (Componente 1)
   Grid uniforme 4×2: 8 tarjetas tipo card con sombra y bordes redondos.
   - Section con fondo #0D0E0E (más oscuro que el body) para que las
     cards se eleven visualmente.
   - Cada card en --c-bg (el mismo gris del body), border-top Rausch
     como acento editorial (decisión del bloque 6), box-shadow para
     profundidad.
   - La cifra +91 % conserva color Rausch (única excepción visual).
   ---------------------------------------------------------------------- */
/* Cards compactas centradas ÓPTICAMENTE contra el viewport (no
   solo contra la section visible). El header sticky tapa los
   primeros var(--header-h) del viewport: si el contenido se centra
   en la section a secas, queda desplazado +header_h hacia arriba.
   Padding-bottom = padding-top + header_h compensa esa asimetría:
   el centro óptico del contenido cae en el centro del viewport
   completo, no del área-visible-sin-header. */
.kpis {
  background: #0D0E0E;
  padding: var(--sp-6) var(--sp-4) calc(var(--sp-6) + var(--header-h));
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-6);
  width: 100%;
  box-sizing: border-box;
  height: calc(100vh - var(--header-h));
  height: calc(100dvh - var(--header-h));
  max-height: calc(100vh - var(--header-h));
  max-height: calc(100dvh - var(--header-h));
  min-height: calc(100vh - var(--header-h));
  min-height: calc(100dvh - var(--header-h));
  overflow: hidden;
}
.kpis > .kpis__fila {
  max-width: var(--max-w);
  width: 100%;
  margin: 0 auto;
}
.kpis__fila {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-4);
}
/* KPIs estáticas (cf. proyecto-maestro §12) con presencia visual:
   cifra centrada arriba sobre un divisor fino, etiqueta debajo. La
   card del Sobreprecio Mundial (.kpi--rausch) va completa en Rausch:
   fondo translúcido, borde, cifra, unidad y etiqueta. */
.kpi {
  position: relative;
  isolation: isolate;
  min-height: 170px;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.05) 0%,
    rgba(255, 255, 255, 0.02) 100%
  );
  border-radius: 14px;
  border: 1px solid var(--c-border-subtle);
  padding: var(--sp-4) var(--sp-3);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  min-width: 0;
  text-align: center;
  /* Accent vertical Rausch a la izquierda como guía cromática
     coherente con el resto del sitio. Sutil (3px) para no competir
     con la cifra. */
  border-left: 3px solid var(--c-rausch);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    0 2px 8px rgba(0, 0, 0, 0.35);
  transition: transform var(--transition-fast),
              border-color var(--transition-fast),
              box-shadow var(--transition-fast);
}
.kpi:hover,
.kpi:focus-within {
  transform: translateY(-2px);
  border-color: var(--c-border-strong);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 6px 18px rgba(0, 0, 0, 0.5);
}

/* Card del Sobreprecio Mundial: TODO el contenido en Rausch.
   Fondo translúcido del propio Rausch + borde Rausch grueso +
   cifra, unidad y etiqueta heredan el color via currentColor. */
.kpi--rausch {
  background: linear-gradient(
    180deg,
    rgba(255, 90, 95, 0.18) 0%,
    rgba(255, 90, 95, 0.08) 100%
  );
  border: 1px solid var(--c-rausch);
  border-left-width: 3px;
  color: var(--c-rausch);
}
.kpi--rausch:hover,
.kpi--rausch:focus-within {
  border-color: var(--c-rausch);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 6px 22px rgba(255, 90, 95, 0.25);
}

/* Cifra principal: tipografía grande, centrada, color bone por
   defecto. La unidad (USD, %) hereda el currentColor para que en la
   card Rausch toda la línea quede en el mismo tono. */
.kpi__cifra {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(2rem, 4vw, 3rem);
  line-height: 1.02;
  letter-spacing: -0.025em;
  color: var(--c-bone);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  margin: 0;
  text-align: center;
}
.kpi--rausch .kpi__cifra,
.kpi__cifra--rausch {
  color: var(--c-rausch);
}
.kpi__cifra--textual {
  font-weight: 800;
  font-variant-numeric: normal;
  letter-spacing: -0.02em;
}
.kpi__unidad {
  font-size: 0.5em;
  font-weight: 700;
  margin-left: 0.2em;
  letter-spacing: 0;
  /* Hereda el color del padre (.kpi__cifra) para que en la card
     Rausch la unidad también se vea en Rausch, no en muted. */
  color: inherit;
  opacity: 0.7;
}

/* Etiqueta debajo, siempre visible. */
.kpi__etiqueta {
  font-family: var(--font-body);
  font-size: var(--fs-body-s);
  font-weight: 500;
  line-height: 1.4;
  color: var(--c-text-secondary);
  margin: 0;
  max-width: 28ch;
  text-align: center;
}
/* En la card Rausch la etiqueta hereda Rausch directamente. */
.kpi--rausch .kpi__etiqueta {
  color: var(--c-rausch);
}

/* Cifra envuelta en link (KPI "alojamiento más caro" → airbnb.mx). */
.kpi__link {
  display: block;
  color: inherit;
  text-decoration: none;
}
.kpi__link:hover .kpi__cifra,
.kpi__link:focus-visible .kpi__cifra {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
  text-decoration-color: currentColor;
}

@media (max-width: 1200px) {
  .kpi__cifra {
    font-size: clamp(1.6rem, 3.6vw, 2.5rem);
  }
}
@media (max-width: 900px) {
  .kpis__fila {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: var(--sp-4);
  }
}
@media (max-width: 640px) {
  .kpis {
    padding: var(--sp-6) var(--sp-3);
    gap: var(--sp-4);
  }
  .kpis__fila {
    grid-template-columns: 1fr;
    row-gap: var(--sp-3);
  }
  .kpi {
    min-height: 140px;
  }
  .kpi__cifra {
    font-size: clamp(2.25rem, 9vw, 3rem);
  }
}

/* ----------------------------------------------------------------------
   6. Bloque mapa (Componente 2): pregunta arriba; layout 1fr 2fr con
   filtros a la izquierda (sidebar vertical) y mapa a la derecha
   (capas/leyenda arriba + mapa). Background oscuro #0D0E0E como en KPIs.
   Section fullscreen (min-height: 100vh viene de main > section).
   ---------------------------------------------------------------------- */
.bloque-mapa {
  background: #0D0E0E;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4);
  width: 100%;
  box-sizing: border-box;
  /* Fullscreen del area VISIBLE descontando el header sticky. */
  height: calc(100vh - var(--header-h));
  height: calc(100dvh - var(--header-h));
  max-height: calc(100vh - var(--header-h));
  max-height: calc(100dvh - var(--header-h));
  min-height: calc(100vh - var(--header-h));
  min-height: calc(100dvh - var(--header-h));
  overflow: hidden;
}
.bloque-mapa__layout {
  display: grid;
  grid-template-columns: minmax(260px, 1fr) 2fr;
  gap: var(--sp-3);
  max-width: var(--max-w);
  width: 100%;
  margin: 0 auto;
  flex: 1;
  min-height: 0;
}
.bloque-mapa__filtros {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-3);
  background: var(--c-surface-1);
  border-radius: 12px;
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--c-border-strong) transparent;
}
.bloque-mapa__filtros::-webkit-scrollbar { width: 6px; }
.bloque-mapa__filtros::-webkit-scrollbar-thumb {
  background: var(--c-border-strong);
  border-radius: 3px;
}
.bloque-mapa__mapa {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-width: 0;
  min-height: 0;
}

.mfilter {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  min-width: 0;
}
.mfilter__label {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--c-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 700;
}
.mfilter__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  width: 100%;
  background: var(--c-bg);
  color: var(--c-text-primary);
  border: 1px solid var(--c-border-subtle);
  border-radius: 8px;
  padding: 6px var(--sp-3);
  font-family: var(--font-body);
  font-size: var(--fs-body-s);
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: border-color var(--transition-fast), background var(--transition-fast);
  min-height: 34px;
}
.mfilter__trigger:hover {
  border-color: var(--c-border-strong);
}
.mfilter__trigger[aria-expanded="true"] {
  border-color: var(--c-rausch);
}
.mfilter__valor {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
}
.mfilter__chevron {
  flex-shrink: 0;
  color: var(--c-text-muted);
  transition: transform var(--transition-fast);
}
.mfilter__trigger[aria-expanded="true"] .mfilter__chevron {
  transform: rotate(180deg);
}

/* Filtro deshabilitado por la capa activa: queda visible pero gris,
   no clickeable, con cursor not-allowed. La etiqueta también se
   atenúa. Patrón usado p.ej. con "Periodo" cuando la capa Calor está
   activa (el heatmap no depende del periodo). */
.mfilter.is-disabled-por-capa {
  opacity: 0.55;
  pointer-events: none;
}
.mfilter.is-disabled-por-capa .mfilter__trigger {
  cursor: not-allowed;
  border-style: dashed;
}
.mfilter.is-disabled-por-capa .mfilter__label {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  text-decoration-color: rgba(255, 255, 255, 0.3);
}
.mfilter__panel {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  min-width: 220px;
  max-height: 300px;
  overflow-y: auto;
  background: var(--c-surface-2);
  border: 1px solid var(--c-border-strong);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  z-index: 800;
  padding: var(--sp-1);
}
.mfilter__panel[hidden] { display: none; }
.mfilter__opcion {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-body-s);
  color: var(--c-text-primary);
  cursor: pointer;
  border-radius: 6px;
  transition: background var(--transition-fast);
  user-select: none;
  line-height: 1.3;
}
.mfilter__opcion:hover,
.mfilter__opcion:focus-visible {
  background: rgba(255, 255, 255, 0.06);
  outline: none;
}
.mfilter__opcion[aria-selected="true"] {
  color: var(--c-text-primary);
  font-weight: 600;
}
/* Opción bloqueada por contexto (ej. Periodo restringido a sólo
   "México" y "España" cuando la subcapa Ocupación está activa). */
.mfilter__opcion.is-disabled-opcion {
  color: var(--c-text-muted);
  opacity: 0.5;
  cursor: not-allowed;
  text-decoration: line-through;
  text-decoration-color: rgba(255, 255, 255, 0.3);
}
.mfilter__opcion.is-disabled-opcion:hover,
.mfilter__opcion.is-disabled-opcion:focus-visible {
  background: transparent;
}
.mfilter__opcion-check {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  border: 1.5px solid var(--c-border-strong);
  border-radius: 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--c-bg);
  background: transparent;
  transition: background var(--transition-fast), border-color var(--transition-fast);
}
.mfilter__opcion[aria-selected="true"] .mfilter__opcion-check {
  background: var(--c-rausch);
  border-color: var(--c-rausch);
  color: var(--c-bone);
}
.mfilter__opcion-radio {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  border: 1.5px solid var(--c-border-strong);
  border-radius: 50%;
  position: relative;
  transition: border-color var(--transition-fast);
}
.mfilter__opcion[aria-selected="true"] .mfilter__opcion-radio {
  border-color: var(--c-rausch);
}
.mfilter__opcion[aria-selected="true"] .mfilter__opcion-radio::after {
  content: "";
  position: absolute;
  inset: 2px;
  background: var(--c-rausch);
  border-radius: 50%;
}

/* Slider doble (rango de precio): dos <input type=range> superpuestos
   sobre el mismo track. Los handlers de WebKit/Firefox se estilizan
   para tener un look coherente con el resto. */
.mfilter--rango {
  justify-content: end;
}
.mfilter__rango {
  position: relative;
  height: 32px;
  display: flex;
  align-items: center;
}
.mfilter__rango-track {
  position: absolute;
  left: 0; right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: 4px;
  background: var(--c-border-subtle);
  border-radius: 2px;
  pointer-events: none;
}
.mfilter__rango-fill {
  position: absolute;
  top: 0; bottom: 0;
  background: var(--c-rausch);
  border-radius: 2px;
}
.mfilter__rango input[type="range"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  background: transparent;
  appearance: none;
  -webkit-appearance: none;
  pointer-events: none;
  margin: 0;
  padding: 0;
}
.mfilter__rango input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  pointer-events: auto;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--c-bone);
  border: 2px solid var(--c-rausch);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  cursor: grab;
  margin-top: 0;
}
.mfilter__rango input[type="range"]::-webkit-slider-thumb:active {
  cursor: grabbing;
  transform: scale(1.1);
}
.mfilter__rango input[type="range"]::-moz-range-thumb {
  pointer-events: auto;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--c-bone);
  border: 2px solid var(--c-rausch);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  cursor: grab;
}
.mfilter__rango input[type="range"]::-webkit-slider-runnable-track,
.mfilter__rango input[type="range"]::-moz-range-track {
  background: transparent;
  border: 0;
}
.mfilter__rango input[type="range"]:focus-visible::-webkit-slider-thumb {
  outline: 2px solid var(--c-rausch);
  outline-offset: 2px;
}
.mfilter__rango input[type="range"]:focus-visible::-moz-range-thumb {
  outline: 2px solid var(--c-rausch);
  outline-offset: 2px;
}
/* En el slider doble, el segundo input (max) queda encima del track
   en el lado derecho. WebKit pinta el thumb del input "min" debajo si
   el cursor está en una zona compartida; usar z-index ayuda. */
.mfilter__rango input[type="range"]:nth-of-type(1) { z-index: 3; }
.mfilter__rango input[type="range"]:nth-of-type(2) { z-index: 4; }

.mfilter__hint {
  font-size: var(--fs-caption);
  color: var(--c-text-muted);
  font-variant-numeric: tabular-nums;
  margin: 0;
}

.mfilter__reset {
  background: transparent;
  color: var(--c-text-primary);
  border: 1px solid var(--c-border-strong);
  border-radius: 8px;
  padding: 6px var(--sp-3);
  font-size: var(--fs-body-s);
  font-weight: 500;
  transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
  min-height: 32px;
  margin-top: var(--sp-1);
}
.mfilter__reset:hover,
.mfilter__reset:focus-visible {
  background: var(--c-rausch);
  color: var(--c-bone);
  border-color: var(--c-rausch);
}

/* Tips de uso del tablero (chips con icono + texto). Viven al final
   del sidebar de filtros, después del botón Limpiar. */
.mfilter-tips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-3);
  align-items: center;
  justify-content: center;
  margin: var(--sp-2) 0 0;
  padding-top: var(--sp-2);
  border-top: 1px solid var(--c-border-subtle);
}
.mfilter-tips__chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--c-text-secondary);
  letter-spacing: 0;
}
.mfilter-tips__chip .icon {
  /* Iconos en Rausch para que la fila de tips marque acento de marca y
     se diferencie del texto descriptivo en gris. */
  color: var(--c-rausch);
  fill: currentColor;
  width: 14px;
  height: 14px;
}

/* Fila 3: barra con SOLO la leyenda (los toggles ya viven en sidebar).
   Centra el contenido respecto al ancho del mapa (2/3 del viewport). */
.mapa-capas-bar {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  background: var(--c-surface-1);
  border-radius: 12px;
  flex-wrap: wrap;
}
.mapa-capas-bar__leyenda {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  font-size: var(--fs-caption);
  color: var(--c-text-secondary);
  min-height: 24px;
  flex: 1;
  justify-content: center;
}
.leyenda-item {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
}
/* Item que ocupa la línea entera (p. ej. la oración explicativa de la
   leyenda Radios va sola arriba; los swatches viven en su propia fila). */
.leyenda-item--full {
  flex-basis: 100%;
  justify-content: center;
}
/* Contenedor de la rampa de color: una fila propia, centrada, con los
   5 swatches alineados entre sí. */
.leyenda-escala {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2) var(--sp-4);
  flex-basis: 100%;
}
.leyenda-swatch {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 3px;
}
.leyenda-swatch--dot {
  border-radius: 50%;
}
/* Swatch del patrón "Sin Airbnb": réplica visual del patrón SVG
   que usa el coroplético, para que la lectura sea idéntica. */
.leyenda-swatch--patron {
  background-color: #3a3a3a;
  background-image: repeating-linear-gradient(
    45deg,
    #5a5a5a 0,
    #5a5a5a 1.5px,
    transparent 1.5px,
    transparent 6px
  );
  border-color: #5a5a5a;
}

/* Botones toggle de la leyenda (capa Puntos): permiten filtrar
   disponibles/ocupados directamente desde la leyenda. La distinción
   entre activo y apagado es BIEN visible: activo tiene fondo coloreado
   del estado y un check visible; apagado queda con borde dashed,
   tachado y opacidad reducida. */
.leyenda-toggle {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 12px 4px 8px;
  border-radius: 999px;
  font-family: inherit;
  font-size: inherit;
  font-weight: 700;
  color: var(--c-bone);
  background: transparent;
  border: 1.5px solid var(--c-border-strong);
  cursor: pointer;
  position: relative;
  transition: background var(--transition-fast),
              border-color var(--transition-fast),
              color var(--transition-fast),
              opacity var(--transition-fast);
}
/* Indicador on/off al inicio del botón: círculo lleno (activo) o vacío
   con borde (apagado). Reemplaza el swatch heredado para que el estado
   se lea de un solo vistazo. */
.leyenda-toggle .leyenda-swatch {
  width: 12px;
  height: 12px;
  border: 1.5px solid currentColor;
  background: transparent !important;
  opacity: 1 !important;
  transition: background var(--transition-fast);
}
.leyenda-toggle.is-on .leyenda-swatch {
  background: currentColor !important;
}
/* Activo: borde y texto en el color del estado (cada toggle se ata a
   su color vía variables --tog-*). Fondo translúcido del color. */
.leyenda-toggle[data-toggle="disponibles"] {
  --tog-color: var(--c-babu);
}
.leyenda-toggle[data-toggle="ocupados"] {
  --tog-color: var(--c-rausch);
}
.leyenda-toggle.is-on {
  color: var(--tog-color);
  border-color: var(--tog-color);
  background: color-mix(in srgb, var(--tog-color) 18%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--tog-color) 35%, transparent);
}
.leyenda-toggle.is-off {
  color: var(--c-text-muted);
  border-color: var(--c-border-subtle);
  border-style: dashed;
  background: transparent;
  opacity: 0.7;
  text-decoration: line-through;
  text-decoration-thickness: 1.5px;
  text-decoration-color: rgba(255, 255, 255, 0.4);
}
.leyenda-toggle:hover,
.leyenda-toggle:focus-visible {
  border-style: solid;
  color: var(--c-bone);
}
.leyenda-toggle.is-on:hover,
.leyenda-toggle.is-on:focus-visible {
  color: var(--c-bone);
  border-color: var(--tog-color);
}

.drawer[hidden],
.drawer-backdrop[hidden] { display: none; }

/* Segmented (heredado) */
.segmented {
  display: inline-flex;
  border: 1px solid var(--c-border-strong);
  background: var(--c-bg);
  border-radius: 8px;
  overflow: hidden;
}
/* Variante full-width para el segmented dentro del sidebar de filtros:
   ocupa todo el ancho disponible y los botones se reparten equidistantes. */
.segmented--full {
  display: flex;
  width: 100%;
}
.segmented--full .segmented__btn {
  flex: 1;
  text-align: center;
  padding: var(--sp-2) var(--sp-1);
  font-size: var(--fs-caption);
}
.segmented--full.segmented--mini .segmented__btn {
  padding: 4px var(--sp-1);
}

/* ----------------------------------------------------------------------
   6c. Leaflet.markercluster — paleta del proyecto Airbnb-Mundial.
   El plugin trae estilos default verde/amarillo/rojo-naranja
   genéricos. Override por tamaño con la paleta base:
     small  (pocos listings)  → Babu   #00a699
     medium (densidad media)  → Arches #fc642d
     large  (saturado)        → Rausch #ff5a5f
   El gradiente Babu → Arches → Rausch es coherente con la escala
   cuantil del coroplético.
   ---------------------------------------------------------------------- */
.marker-cluster {
  color: var(--c-bone);
  font-family: var(--font-display);
  font-weight: 700;
  /* `background-clip: padding-box` mantiene el halo translúcido
     fuera del borde sólido. */
  background-clip: padding-box;
}
.marker-cluster div {
  color: var(--c-bone);
  width: 30px;
  height: 30px;
  margin-left: 5px;
  margin-top: 5px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.marker-cluster span {
  line-height: 1;
  font-size: 13px;
}

/* `!important` necesario porque el CSS de Leaflet.markercluster se
   carga dinámicamente (después de styles.css) y su orden gana por
   default. Sin esto los inner divs conservan los colores genéricos
   verde/amarillo/naranja del plugin. */

/* Small: Babu #00a699 (pocos listings). */
.marker-cluster-small {
  background-color: rgba(0, 166, 153, 0.30) !important;
  border: 2px solid var(--c-babu) !important;
}
.marker-cluster-small div {
  background-color: var(--c-babu) !important;
}

/* Medium: Arches #fc642d (densidad media). */
.marker-cluster-medium {
  background-color: rgba(252, 100, 45, 0.30) !important;
  border: 2px solid var(--c-arches) !important;
}
.marker-cluster-medium div {
  background-color: var(--c-arches) !important;
}

/* Large: Rausch #ff5a5f (zona saturada). */
.marker-cluster-large {
  background-color: rgba(255, 90, 95, 0.30) !important;
  border: 2px solid var(--c-rausch) !important;
}
.marker-cluster-large div {
  background-color: var(--c-rausch) !important;
}
.segmented__btn {
  font-family: var(--font-body);
  font-size: var(--fs-body-s);
  font-weight: 500;
  padding: 6px var(--sp-3);
  color: var(--c-text-primary);
  border-right: 1px solid var(--c-border-strong);
  transition: background var(--transition-fast), color var(--transition-fast);
}
.segmented__btn:last-child { border-right: 0; }
.segmented__btn[aria-checked="true"] {
  /* Estado activo de control: Arches. Rausch queda reservado para
     codificar datos del periodo Mundial, no para señalar selección. */
  background: var(--c-rausch);
  color: var(--c-bone);
}
.segmented__btn:hover:not([aria-checked="true"]):not(:disabled),
.segmented__btn:focus-visible:not([aria-checked="true"]):not(:disabled) {
  background: rgba(255, 255, 255, 0.06);
}
/* Estado deshabilitado: el bloque permanece visible para informar al
   usuario de la opcion, pero los botones quedan inertes. Anula el fondo
   Rausch del aria-checked para que "Cuantos" no engane como activo. */
.segmented__btn:disabled,
.segmented__btn:disabled[aria-checked="true"] {
  background: transparent;
  color: var(--c-text-muted);
  opacity: 0.45;
  cursor: not-allowed;
}
.mfilter--metrica.is-disabled .mfilter__label {
  opacity: 0.55;
}
.segmented--mini .segmented__btn {
  padding: 4px var(--sp-3);
  font-size: var(--fs-caption);
}

/* Mapa: ocupa todo el remanente del .bloque-mapa__mapa flex column.
   min-height bajo (260) para no desbordar en laptops chicos; en grande
   crece via flex:1 automaticamente. */
.mapa {
  flex: 1;
  width: 100%;
  height: 100%;
  min-height: 260px;
  background: var(--c-bg);
  border-radius: 12px;
  position: relative;
  z-index: 0;
  overflow: hidden;
}
.mapa:focus-visible {
  outline-offset: -2px;
}
/* Asegurar que el contenedor de Leaflet (que Leaflet escribe inline)
   herede los bordes redondos del padre. */
.leaflet-container { border-radius: 12px; }

/* ----------------------------------------------------------------------
   6b. Bloque #graficas (section): 4 mini-viz en grid 2×2 (dos pisos).
   Background oscuro #0D0E0E. Fullscreen exacto descontando header.
   Sincronizadas con los filtros y la colonia activa del mapa.
   ---------------------------------------------------------------------- */
.bloque-graficas {
  background: #0D0E0E;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  width: 100%;
  box-sizing: border-box;
  height: calc(100vh - var(--header-h));
  height: calc(100dvh - var(--header-h));
  max-height: calc(100vh - var(--header-h));
  max-height: calc(100dvh - var(--header-h));
  min-height: calc(100vh - var(--header-h));
  min-height: calc(100dvh - var(--header-h));
  overflow: hidden;
}
.bloque-graficas > .bloque-mapa__colonia-aviso {
  max-width: var(--max-w);
  width: 100%;
  margin: 0 auto;
}
.bloque-graficas__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3);
  max-width: var(--max-w);
  width: 100%;
  margin: 0 auto;
  flex: 1;
  min-height: 0;
}
.bloque-mapa__colonia-aviso {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  background: rgba(252, 100, 45, 0.12);
  border: 1px solid var(--c-rausch);
  border-radius: 8px;
  font-size: var(--fs-caption);
  color: var(--c-text-primary);
}
.bloque-mapa__colonia-aviso[hidden] { display: none; }
.bloque-mapa__colonia-txt strong {
  color: var(--c-rausch);
}
.bloque-mapa__colonia-quitar {
  background: transparent;
  color: var(--c-rausch);
  border: 1px solid var(--c-rausch);
  border-radius: 6px;
  padding: 2px var(--sp-2);
  font-size: var(--fs-caption);
  font-weight: 600;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
  flex-shrink: 0;
}
.bloque-mapa__colonia-quitar:hover,
.bloque-mapa__colonia-quitar:focus-visible {
  background: var(--c-rausch);
  color: var(--c-bone);
}

.mini-viz {
  background: var(--c-surface-1);
  border-radius: 12px;
  padding: var(--sp-2) var(--sp-3);
  overflow: hidden;
  min-height: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  margin: 0;
  gap: var(--sp-1);
}
.mini-viz__titulo {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--c-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 700;
  margin: 0;
  flex-shrink: 0;
  text-align: center;
}

/* Control opcional debajo del título de una mini-viz, alineado a la
   derecha. Hoy lo usa viz-distribucion para su dropdown de periodo. */
.mini-viz__control {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-2);
  flex-shrink: 0;
  margin-top: 2px;
}
.mini-viz__control-label {
  font-family: var(--font-body);
  /* Etiqueta discreta en altas y bajas: peso medio, 11px. */
  font-size: 0.6875rem;
  color: var(--c-text-muted);
  letter-spacing: 0.01em;
  font-weight: 500;
}
.mini-viz__select {
  font-family: var(--font-body);
  /* Filtro auxiliar: subordinado en jerarquía al título y la etiqueta. */
  font-size: 0.625rem;
  font-weight: 500;
  color: var(--c-text-primary);
  background: var(--c-bg);
  border: 1px solid var(--c-border-subtle);
  border-radius: 6px;
  padding: 2px 20px 2px 7px;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'><path d='M2 3.5l3 3 3-3' fill='none' stroke='%23b8b8b8' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 6px center;
  background-size: 10px;
  transition: border-color var(--transition-fast);
}
.mini-viz__select:hover { border-color: var(--c-border-strong); }
.mini-viz__select:focus-visible {
  border-color: var(--c-rausch);
  outline: 2px solid var(--c-rausch);
  outline-offset: 1px;
}
.mini-viz__select option {
  background: var(--c-surface-2);
  color: var(--c-text-primary);
}
.mini-viz__canvas {
  flex: 1;
  min-height: 0;
  min-width: 0;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: stretch;
}

/* Nube de palabras (viz-nube): contenedor con altura mínima generosa
   para que el algoritmo de d3-cloud tenga espacio para acomodar
   palabras en distintos tamaños y rotaciones. */
.viz__canvas--nube {
  min-height: 440px;
  background: var(--c-surface-1);
  border-radius: 12px;
  padding: var(--sp-3);
  display: flex;
  align-items: center;
  justify-content: center;
}
.viz__canvas--nube svg {
  width: 100%;
  height: 100%;
  max-height: 480px;
}
@media (max-width: 640px) {
  .viz__canvas--nube { min-height: 340px; }
}
.mini-viz__canvas svg {
  width: 100%;
  height: 100%;
  display: block;
}
.mini-viz__canvas .viz-empty {
  margin: auto;
  padding: var(--sp-3);
}


/* Responsive del bloque mapa y bloque gráficas */
@media (max-width: 1024px) {
  /* En tablet/mobile las 3 sections fullscreen (kpis, mapa, graficas)
     pierden la altura fija + overflow hidden. Si dejamos
     `height: calc(100vh - header)`, las 4 mini-viz apiladas (de
     240px c/u = ~960px) se cortan por `overflow: hidden` y la última
     gráfica desaparece. El contenido debe poder fluir verticalmente. */
  .kpis,
  .bloque-mapa,
  .bloque-graficas {
    height: auto;
    min-height: auto;
    max-height: none;
    overflow: visible;
  }
  .bloque-mapa__layout {
    grid-template-columns: 1fr;
    /* Mapa con altura mínima generosa en tablet: la auditoría
       documentó 406 px como insuficiente para lectura espacial.
       560 px + 65vh garantiza superficie de trabajo aún en
       pantallas de altura modesta. */
    grid-template-rows: auto minmax(560px, 65vh);
  }
  .bloque-mapa__filtros {
    overflow-y: visible;
  }
  .bloque-graficas__grid {
    grid-template-columns: 1fr;
    /* `auto` en lugar de `1fr`: cada fila toma la altura de su
       mini-viz, en lugar de repartirse un alto fijo que ya no
       existe (la section dejó de ser fullscreen). */
    grid-auto-rows: minmax(240px, auto);
    grid-template-rows: none;
  }
  .mini-viz {
    min-height: 240px;
  }
  /* KPIs en mobile: cada card su altura natural, padding razonable. */
  .kpis {
    padding: var(--sp-5) var(--sp-4);
  }
}
@media (max-width: 640px) {
  .bloque-mapa,
  .bloque-graficas {
    padding: var(--sp-3);
    gap: var(--sp-3);
  }
  .bloque-mapa__filtros {
    padding: var(--sp-3);
  }
  .bloque-mapa__layout {
    grid-template-rows: auto minmax(360px, 60vh);
  }
  .bloque-graficas__grid {
    grid-template-columns: 1fr;
    grid-auto-rows: minmax(220px, auto);
    grid-template-rows: none;
  }
  .mini-viz {
    min-height: 220px;
  }
  .segmented__btn {
    padding: var(--sp-2) var(--sp-3);
  }
  .kpis {
    padding: var(--sp-4) var(--sp-3);
    gap: var(--sp-4);
  }
}

/* ----------------------------------------------------------------------
   7. Bloques generales y vizes
   ---------------------------------------------------------------------- */
.bloque {
  max-width: var(--max-w);
  margin: 0 auto;
  padding: var(--sp-7) var(--sp-4);
  border-top: 1px solid var(--c-border-subtle);
}
.viz {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  margin: 0;
}
.viz__canvas {
  width: 100%;
  min-height: 320px;
  position: relative;
}
.viz--ancha .viz__canvas {
  min-height: 380px;
}
.viz__pie {
  font-size: var(--fs-body-s);
  color: var(--c-text-secondary);
  line-height: 1.5;
  max-width: 70ch;
}
.viz__caption-top {
  font-size: var(--fs-body-s);
  color: var(--c-text-secondary);
  line-height: 1.5;
  max-width: 70ch;
  margin: 0;
}
.viz__expandir {
  align-self: flex-start;
  font-size: var(--fs-body-s);
  font-weight: 500;
  color: var(--c-rausch);
  padding: var(--sp-1) 0;
  border-bottom: 1px solid currentColor;
}
.viz__expandir:hover,
.viz__expandir:focus-visible {
  color: var(--c-rausch-dark);
}

/* placeholder de carga */
.viz__canvas[data-loading="true"]::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    var(--c-surface-1) 0%,
    rgba(120, 120, 120, 0.20) 50%,
    var(--c-surface-1) 100%);
  background-size: 200% 100%;
  animation: shimmer 1.8s linear infinite;
}
@keyframes shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ----------------------------------------------------------------------
   8. D3 helpers (estilos compartidos)
   ---------------------------------------------------------------------- */
.viz svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}
.viz svg text {
  font-family: var(--font-body);
  fill: var(--axis-text);
}
.axis text {
  font-size: 11px;
  fill: var(--axis-text);
  font-variant-numeric: tabular-nums;
}
.axis line,
.axis path {
  stroke: var(--axis-line);
  shape-rendering: crispEdges;
}
.axis-title {
  font-size: 12px;
  font-weight: 500;
  fill: var(--c-text-primary);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.grid line {
  stroke: var(--grid-line);
  stroke-dasharray: 2 3;
  shape-rendering: crispEdges;
}
.ref-line {
  stroke: var(--c-bone);
  stroke-dasharray: 4 3;
  stroke-width: 1;
  opacity: 0.55;
}

/* Tooltip genérico para viz y mapa. Estilizado: fondo oscuro
   sólido con borde Rausch sutil (acento de marca), shadow para
   destacar sobre cualquier fondo, padding generoso, tipografía
   tabular-nums para cifras alineadas. */
.viz-tooltip {
  position: absolute;
  background: #1f1f1f;
  color: var(--c-bone);
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  line-height: 1.45;
  padding: 10px 14px;
  pointer-events: none;
  z-index: 1000;
  border: 1px solid var(--c-rausch);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.35);
  max-width: 260px;
  min-width: 160px;
  font-variant-numeric: tabular-nums;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity var(--transition-fast), transform var(--transition-fast);
}
.viz-tooltip.is-visible {
  opacity: 1;
  transform: translateY(0);
}
.viz-tooltip strong {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-body-s);
  color: var(--c-rausch);
  display: block;
  margin: 0 0 6px;
  letter-spacing: -0.01em;
}
.viz-tooltip .tooltip-row {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: 2px 0;
}
.viz-tooltip .tooltip-row span:first-child {
  color: var(--c-text-secondary);
}
.viz-tooltip .tooltip-row span:last-child {
  color: var(--c-bone);
  font-weight: 700;
}
.viz-tooltip .tooltip-nota {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  font-size: 11px;
  line-height: 1.4;
  color: rgba(248, 245, 240, 0.7);
  max-width: 22rem;
}

/* Tooltip de la capa Puntos del mapa: 5 líneas apiladas, una por piso.
   La primera es el nombre del alojamiento (titular); la última es un
   call-to-action en itálicas resaltado en Rausch. */
.viz-tooltip .tt-line {
  padding: 2px 0;
}
.viz-tooltip .tt-line--titulo {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-body-s);
  color: var(--c-bone);
  letter-spacing: -0.01em;
  margin-bottom: 4px;
  /* Limitar a 2 líneas con elipsis para títulos extremadamente largos. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.viz-tooltip .tt-line--cta {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  color: var(--c-rausch);
  font-weight: 700;
  font-size: 11px;
}
.viz-tooltip .tt-line--cta em {
  font-style: italic;
}

/* Boxplot */
.boxplot-rect {
  fill: var(--c-text-muted);
  fill-opacity: 0.30;
  stroke: var(--c-text-muted);
  stroke-width: 1.5;
  transition: fill-opacity var(--transition-fast);
}
.boxplot-rect.is-mundial {
  fill: var(--c-rausch);
  fill-opacity: 0.40;
  stroke: var(--c-rausch);
}
.boxplot-rect.is-active,
.boxplot-row:hover .boxplot-rect {
  fill-opacity: 0.60;
}
.boxplot-row {
  cursor: pointer;
}
.boxplot-median {
  stroke: var(--c-bone);
  stroke-width: 2.5;
}
.boxplot-whisker {
  stroke: var(--c-text-secondary);
  stroke-width: 1;
}
.boxplot-whisker.is-mundial { stroke: var(--c-rausch); }

/* Serie temporal */
.serie-banda {
  fill: var(--c-text-muted);
  fill-opacity: 0.20;
}
.serie-linea {
  fill: none;
  stroke: var(--c-bone);
  stroke-width: 2;
}
.serie-punto {
  fill: var(--c-bg);
  stroke: var(--c-bone);
  stroke-width: 2;
  cursor: pointer;
  transition: r var(--transition-fast);
}
.serie-punto.is-mundial {
  fill: var(--c-rausch);
  stroke: var(--c-rausch-dark);
}
.serie-punto:hover {
  r: 8;
}
.serie-etiqueta {
  font-size: 11px;
  font-weight: 700;
  fill: var(--c-rausch);
  font-family: var(--font-display);
}

/* Heatmap saturacion */
.heatmap-cell {
  cursor: pointer;
  transition: stroke var(--transition-fast);
  stroke: var(--c-bg);
  stroke-width: 2;
}
.heatmap-cell:hover {
  stroke: var(--c-bone);
  stroke-width: 2;
}
.heatmap-label {
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  font-family: var(--font-display);
}

/* Top colonias */
.colonia-row {
  cursor: pointer;
}
.colonia-row:hover .colonia-bar {
  fill: var(--c-rausch);
}
.colonia-bar {
  fill: var(--c-text-secondary);
  transition: fill var(--transition-fast);
}
.colonia-bar.is-active {
  fill: var(--c-rausch);
}
.colonia-label,
.colonia-conteo {
  font-size: 12px;
  fill: var(--c-text-primary);
  font-variant-numeric: tabular-nums;
}
.colonia-label {
  font-weight: 500;
}
.colonia-conteo {
  font-weight: 700;
  text-anchor: end;
}
.colonia-spark {
  fill: none;
  stroke: var(--c-rausch);
  stroke-width: 1.5;
}
.colonia-spark-baseline {
  stroke: var(--c-border-subtle);
  stroke-dasharray: 2 2;
}

/* Menciones (Mundial + Estadio). Vive en una mini-viz dentro del grid
   2×2 de gráficas: 5 filas + sección de ejemplos breves, todo cabe. */
.mencion-row {
  display: grid;
  grid-template-columns: 100px 1fr 44px;
  gap: var(--sp-2);
  align-items: center;
  padding: 6px 0;
  cursor: pointer;
  transition: background var(--transition-fast);
}
.mencion-row:hover {
  background: rgba(255, 255, 255, 0.05);
}
.mencion-row.is-active {
  background: rgba(255, 255, 255, 0.05);
}
.mencion-termino {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-body-s);
  color: var(--c-text-primary);
}
.mencion-bar {
  height: 12px;
  background: rgba(255, 255, 255, 0.06);
  position: relative;
  overflow: hidden;
  border-radius: 2px;
}
.mencion-bar__fill {
  position: absolute;
  inset: 0;
  background: var(--c-rausch);
  transform-origin: left;
  transition: transform var(--transition-base), background var(--transition-fast);
}
.mencion-conteo {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-body-s);
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--c-text-primary);
}
.mencion-ejemplos {
  margin-top: var(--sp-2);
  padding-top: var(--sp-2);
  border-top: 1px solid var(--c-border-subtle);
}
.mencion-ejemplo {
  font-size: var(--fs-caption);
  color: var(--c-text-secondary);
  padding: 1px 0;
  line-height: 1.35;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mencion-ejemplo::before {
  content: "· ";
  color: var(--c-text-muted);
  margin-right: var(--sp-1);
}
.mencion-resaltado {
  background: var(--c-rausch);
  color: var(--c-bone);
  padding: 0 4px;
  border-radius: 2px;
  font-weight: 700;
}

/* Scatter calidad-precio */
.scatter-canvas-wrap {
  position: relative;
}
.scatter-canvas {
  display: block;
  background: var(--c-bg);
  border: 1px solid var(--c-border-subtle);
  cursor: crosshair;
}
.scatter-axes {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* ----------------------------------------------------------------------
   9. Drawer del listing (Componente 3) — sistema "ficha" rediseñado
   ---------------------------------------------------------------------- */
.drawer {
  position: fixed;
  top: 0; right: 0;
  width: 440px;
  max-width: 100vw;
  height: 100dvh;
  /* Fondo del drawer: gradiente vertical sutil que añade profundidad
     sin interferir con la legibilidad. */
  background:
    radial-gradient(120% 60% at 100% 0%, rgba(255, 90, 95, 0.10), transparent 60%),
    var(--c-surface-2);
  border-left: 1px solid var(--c-border-strong);
  box-shadow: -16px 0 40px rgba(0, 0, 0, 0.45);
  z-index: 1500;
  overflow-y: auto;
  transform: translateX(100%);
  transition: transform var(--transition-base);
  display: flex;
  flex-direction: column;
  color: var(--c-text-primary);
}
.drawer.is-open {
  transform: translateX(0);
}
.drawer__close {
  position: sticky;
  top: var(--sp-2);
  align-self: flex-end;
  margin-right: var(--sp-3);
  width: 40px; height: 40px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--c-text-primary);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--c-border-subtle);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  z-index: 2;
  transition: background var(--transition-fast),
              color var(--transition-fast),
              transform var(--transition-fast);
}
.drawer__close:hover,
.drawer__close:focus-visible {
  background: var(--c-rausch);
  color: var(--c-bone);
  border-color: var(--c-rausch);
  transform: rotate(90deg);
}
.drawer__close .icon path {
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  fill: none;
}
.drawer__contenido {
  padding: 0 var(--sp-5) var(--sp-6);
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}

/* Cabecera de la ficha: titular, ubicación, rating en pill. */
.ficha-cab {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding-top: var(--sp-2);
  padding-bottom: var(--sp-4);
  border-bottom: 1px solid var(--c-border-subtle);
}
.ficha-cab__titulo {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(1.4rem, 3vw, 1.75rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--c-bone);
  margin: 0;
  text-wrap: balance;
}
.ficha-cab__ubic {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  font-size: var(--fs-body-s);
  color: var(--c-text-secondary);
  margin: 0;
  line-height: 1.35;
}
.ficha-cab__icono {
  flex-shrink: 0;
  margin-top: 2px;
  color: var(--c-rausch);
}
.ficha-cab__ubic strong {
  color: var(--c-bone);
  font-weight: 700;
}
.ficha-cab__rating {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: 2px;
}
/* Contexto del barrio: micro-pie debajo del rating con N de
   alojamientos en la colonia y mediana del sobreprecio. Conecta el
   listing individual con su entorno (datificación testimonial). */
.ficha-cab__contexto {
  margin: var(--sp-2) 0 0;
  font-family: var(--font-body);
  font-size: var(--fs-body-s);
  line-height: 1.5;
  color: var(--c-text-secondary);
  padding-top: var(--sp-2);
  border-top: 1px solid var(--c-border-subtle);
}
.ficha-cab__contexto strong {
  color: var(--c-text-primary);
  font-weight: 600;
}
.ficha-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  border-radius: 999px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-body-s);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.ficha-pill--rating {
  background: rgba(252, 100, 45, 0.15);
  color: var(--c-rausch);
  border: 1px solid rgba(252, 100, 45, 0.4);
}
.ficha-cab__reviews {
  font-size: var(--fs-caption);
  color: var(--c-text-muted);
}

/* Stats de sobreprecio (una o dos cards lado a lado). */
.ficha-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-3);
}
.ficha-stats:has(.ficha-stat:only-child) {
  grid-template-columns: 1fr;
}
.ficha-stat {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: var(--sp-3);
  border-radius: 12px;
  /* Fondo neutro: la marca cromática queda en la cifra (no en el
     contenedor). Sin gradientes decorativos Rausch+Babu. */
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--c-border-subtle);
  position: relative;
  overflow: hidden;
}
.ficha-stat__cifra {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(1.75rem, 5vw, 2.5rem);
  line-height: 1;
  letter-spacing: -0.02em;
  /* Rausch sí aquí: la cifra ES el dato Mundial (sobreprecio del
     periodo). El fondo contenedor queda neutro para que el color
     codifique sólo el contenido. */
  color: var(--c-rausch);
  font-variant-numeric: tabular-nums;
}
.ficha-stat__et {
  font-size: var(--fs-caption);
  font-weight: 500;
  color: var(--c-text-secondary);
  line-height: 1.3;
}

/* Bloque de precios: tabla limpia de 9 ventanas. */
.ficha-precios {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.ficha-precios__tit {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-body-m);
  color: var(--c-bone);
  margin: 0;
  letter-spacing: -0.01em;
}
.ficha-precios__unidad {
  font-size: var(--fs-caption);
  color: var(--c-text-muted);
  margin: 0;
}
.ficha-precios__grid {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: var(--sp-2);
}
.ficha-precios__fila {
  display: grid;
  grid-template-columns: 4px 1fr auto;
  align-items: center;
  gap: var(--sp-2);
  padding: 8px var(--sp-2) 8px 0;
  border-bottom: 1px solid var(--c-border-subtle);
}
.ficha-precios__fila::before {
  content: "";
  display: block;
  width: 4px;
  height: 16px;
  border-radius: 2px;
  background: transparent;
}
.ficha-precios__fila.is-mundial::before {
  background: var(--c-rausch);
}
.ficha-precios__fila.is-mundial {
  background: rgba(255, 90, 95, 0.08);
}
.ficha-precios__et {
  font-size: var(--fs-body-s);
  color: var(--c-text-secondary);
}
.ficha-precios__fila.is-mundial .ficha-precios__et {
  color: var(--c-bone);
  font-weight: 600;
}
.ficha-precios__val {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-body-m);
  font-variant-numeric: tabular-nums;
  color: var(--c-bone);
}
.ficha-precios__fila.is-mundial .ficha-precios__val {
  color: var(--c-rausch);
  font-weight: 800;
}

/* CTA "Ver en Airbnb": pill grande con micro-degradé al hover. */
.ficha-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  margin-top: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border-radius: 999px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-body-m);
  letter-spacing: 0.01em;
  color: var(--c-bg);
  background: var(--c-bone);
  border: 2px solid var(--c-bone);
  text-decoration: none;
  transition: background var(--transition-base),
              color var(--transition-base),
              border-color var(--transition-base),
              transform var(--transition-fast);
}
.ficha-cta:hover,
.ficha-cta:focus-visible {
  background: linear-gradient(90deg, var(--c-babu), var(--c-rausch));
  color: var(--c-bone);
  border-color: var(--c-rausch);
}
.ficha-cta:active {
  transform: translateY(1px);
}
.ficha-cta__icono {
  transition: transform var(--transition-fast);
}
.ficha-cta:hover .ficha-cta__icono,
.ficha-cta:focus-visible .ficha-cta__icono {
  transform: translate(2px, -2px);
}

.drawer-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  z-index: 1400;
  opacity: 0;
  transition: opacity var(--transition-base);
}
.drawer-backdrop.is-visible {
  opacity: 1;
}

@media (max-width: 640px) {
  .drawer {
    width: 100%;
    height: 80dvh;
    top: auto;
    bottom: 0;
    transform: translateY(100%);
    border-left: 0;
    border-top: 1px solid var(--c-border-strong);
  }
  .drawer.is-open {
    transform: translateY(0);
  }
}

/* ----------------------------------------------------------------------
   10. Página de Metodología (independiente, long-form editorial)
   Una columna ancha (60-65ch), tipografía protagonista. Sin cards.
   Drop caps en primer párrafo, pull-quotes con cifras clave,
   secciones numeradas 01 · 02 · etc., separadores tipográficos.
   ---------------------------------------------------------------------- */
.metodologia-page {
  background: var(--c-bg);
  /* Padding superior considera la altura del header sticky para que
     el hero no quede pegado debajo del menú. */
  padding: calc(var(--header-h) + var(--sp-7)) var(--sp-4) var(--sp-9);
}
.metodologia-page__wrap {
  /* Columna editorial ancha: 1040 px deja espacio cómodo a la
     tabla del diccionario y a las listas con bullets, sin pasarse
     a ancho de dashboard. `margin-inline: auto` centra dentro del
     padding lateral de `.metodologia-page`. */
  max-width: 1040px;
  margin-left: auto;
  margin-right: auto;
  display: grid;
  gap: var(--sp-7);
}

/* Hero editorial sobrio: titular contenido (no XXL), sin desborde
   asimétrico, subtítulo en redonda. La sobriedad se logra
   reservando la fuerza tipográfica para los datos. */
.metodologia-hero {
  display: grid;
  gap: var(--sp-3);
  padding-bottom: var(--sp-5);
}
.metodologia-hero__breadcrumb {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 500;
  color: var(--c-text-muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.metodologia-hero__breadcrumb a {
  color: var(--c-text-muted);
  transition: color var(--transition-fast);
}
.metodologia-hero__breadcrumb a:hover,
.metodologia-hero__breadcrumb a:focus-visible {
  color: var(--c-text-primary);
}
.metodologia-hero__titulo {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.75rem, 6vw, var(--fs-display-m));
  line-height: 1.02;
  letter-spacing: -0.03em;
  color: var(--c-text-primary);
  margin: 0;
}
.metodologia-hero__sub {
  font-family: var(--font-body);
  font-style: normal;
  font-weight: 400;
  font-size: var(--fs-body-l);
  line-height: 1.45;
  color: var(--c-text-secondary);
  max-width: 56ch;
  margin: var(--sp-3) 0 0;
}

/* Índice (table of contents) del hero: lista ordenada compacta con
   números visibles. Función de navegación interna a las 6 secciones. */
.metodologia-toc {
  margin: var(--sp-4) 0 0;
  padding: var(--sp-3) 0;
  border-top: 1px solid var(--c-border-subtle);
  border-bottom: 1px solid var(--c-border-subtle);
}
.metodologia-toc ol {
  list-style: none;
  counter-reset: toc;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--sp-2) var(--sp-4);
}
.metodologia-toc li {
  counter-increment: toc;
  font-family: var(--font-body);
  font-size: var(--fs-body-m);
  line-height: 1.4;
}
.metodologia-toc li::before {
  content: counter(toc, decimal-leading-zero) " · ";
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--c-text-muted);
  letter-spacing: 0.02em;
}
.metodologia-toc a {
  color: var(--c-text-primary);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color var(--transition-fast);
}
.metodologia-toc a:hover,
.metodologia-toc a:focus-visible {
  border-bottom-color: var(--c-rausch);
}

/* Tabla del diccionario de datos. Tres columnas: campo / tipo /
   significado. Tipografía monoespaciada en la columna del campo.
   Borde sutil entre filas para que la tabla "respire". */
.metodologia-tabla-wrap {
  margin: var(--sp-3) 0;
  overflow-x: auto;
  border: 1px solid var(--c-border-subtle);
  border-radius: var(--radius-m);
}
.metodologia-tabla {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-body);
  font-size: var(--fs-body-s);
  line-height: 1.5;
}
.metodologia-tabla thead th {
  text-align: left;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-caption);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--c-text-muted);
  padding: var(--sp-3);
  background: rgba(255, 255, 255, 0.03);
  border-bottom: 1px solid var(--c-border-strong);
}
.metodologia-tabla tbody td {
  padding: var(--sp-3);
  vertical-align: top;
  border-bottom: 1px solid var(--c-border-subtle);
  color: var(--c-text-primary);
}
.metodologia-tabla tbody tr:last-child td {
  border-bottom: 0;
}
.metodologia-tabla tbody td:first-child {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.88rem;
  color: var(--c-text-primary);
  white-space: nowrap;
}
.metodologia-tabla tbody td:nth-child(2) {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.82rem;
  color: var(--c-text-muted);
  white-space: nowrap;
}
.metodologia-tabla code {
  background: rgba(255, 255, 255, 0.06);
  padding: 1px 5px;
  border-radius: var(--radius-s);
}

/* Cada sección: número grande a la izquierda + título */
.metodologia-seccion {
  display: grid;
  gap: var(--sp-4);
}
.metodologia-seccion__head {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  flex-wrap: wrap;
}
.metodologia-seccion__num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-heading-m);
  color: var(--c-text-muted);
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}
.metodologia-seccion__num::after {
  content: " ·";
  color: var(--c-border-subtle);
  margin-left: 2px;
}
.metodologia-seccion__titulo {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-heading-l);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--c-text-primary);
  margin: 0;
  max-width: 28ch;
}

/* Cuerpo en una columna ancha (~62ch). Roboto 1.25rem, line-height 1.7 */
.metodologia-prosa {
  display: grid;
  gap: var(--sp-4);
}
.metodologia-prosa p {
  font-family: var(--font-body);
  font-size: var(--fs-body-l);
  line-height: 1.7;
  color: var(--c-text-primary);
  margin: 0;
}
.metodologia-prosa code {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.88em;
  background: rgba(255, 255, 255, 0.06);
  padding: 2px 6px;
  border-radius: var(--radius-s);
  color: var(--c-text-primary);
}
.metodologia-prosa strong {
  color: var(--c-text-primary);
  font-weight: 700;
}
.metodologia-prosa em {
  color: var(--c-text-secondary);
  font-style: italic;
}

/* Subtítulos h3 dentro de la prosa (sección Sesgos): tipografía
   display moderada, peso 700, color primario, espacio de respiro
   antes del párrafo siguiente. */
.metodologia-subtitulo {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-heading-m);
  line-height: 1.2;
  letter-spacing: -0.015em;
  color: var(--c-text-primary);
  margin: var(--sp-3) 0 0;
}

/* Listas dentro de las secciones de detalle: indentación pareja con
   la prosa y separación visual ligera entre items para legibilidad
   sin volverse "ficha técnica". */
.metodologia-prosa ul,
.metodologia-prosa ol {
  margin: 0;
  padding-left: 1.25em;
  display: grid;
  gap: var(--sp-2);
}
.metodologia-prosa li {
  font-family: var(--font-body);
  font-size: var(--fs-body-l);
  line-height: 1.65;
  color: var(--c-text-primary);
}

/* <details> de outliers excluidos: tipografía pareja con la prosa,
   indicador sutil. Sin acento de color. */
.metodologia-prosa details {
  border-top: 1px solid var(--c-border-subtle);
  border-bottom: 1px solid var(--c-border-subtle);
  padding: var(--sp-3) 0;
}
.metodologia-prosa details summary {
  font-family: var(--font-body);
  font-size: var(--fs-body-m);
  font-weight: 600;
  color: var(--c-text-secondary);
  cursor: pointer;
  letter-spacing: 0.01em;
}
.metodologia-prosa details summary:hover,
.metodologia-prosa details summary:focus-visible {
  color: var(--c-text-primary);
}
.metodologia-prosa details[open] summary {
  margin-bottom: var(--sp-3);
}
.metodologia-prosa details ul {
  font-size: var(--fs-body-m);
}
.metodologia-prosa details li {
  font-size: var(--fs-body-m);
  line-height: 1.55;
}

/* Pull-quote: cifras clave como cartel tipográfico, alineado a la
   columna (sin desborde asimétrico) y monocromo: la fuerza viene
   del tamaño y del peso, no del color. */
.metodologia-pullquote {
  display: grid;
  gap: var(--sp-3);
  padding: var(--sp-5) 0;
  border-top: 1px solid var(--c-border-subtle);
  border-bottom: 1px solid var(--c-border-subtle);
}
.metodologia-pullquote__cifra {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.25rem, 5vw, 3rem);
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--c-text-primary);
  font-variant-numeric: tabular-nums;
  margin: 0;
}
.metodologia-pullquote__cifra .accent,
.metodologia-pullquote__cifra .accent {
  /* Las cifras protagonistas se distinguen por peso/tamaño, no por
     color; mantenemos consistencia tipográfica monocroma para que
     la página se lea como documento metodológico, no como hero. */
  color: var(--c-text-primary);
}
.metodologia-pullquote__label {
  font-family: var(--font-body);
  font-size: var(--fs-body-s);
  font-weight: 500;
  color: var(--c-text-muted);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  max-width: 50ch;
  line-height: 1.5;
}

/* Separadores entre secciones: línea horizontal sutil de ancho completo,
   sin truncamiento. Marca la transición con sobriedad. */
.metodologia-page hr {
  border: 0;
  border-top: 1px solid var(--c-border-subtle);
  height: 0;
  margin: var(--sp-2) 0;
}

/* Bloque CTA de descarga: rompe la columna y ocupa todo el ancho.
   Sin acentos cromáticos: borde sutil y kicker en gris. La sobriedad
   del documento metodológico no admite "cartel publicitario". */
.metodologia-cta {
  background: var(--c-surface-2);
  border: 1px solid var(--c-border-subtle);
  padding: var(--sp-6) var(--sp-5);
  display: grid;
  gap: var(--sp-4);
  margin: var(--sp-3) 0;
}
.metodologia-cta__head {
  display: grid;
  gap: var(--sp-2);
}
.metodologia-cta__kicker {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--c-text-muted);
}
.metodologia-cta__titulo {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-heading-l);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--c-text-primary);
  margin: 0;
  max-width: 26ch;
}
.metodologia-cta__desc {
  font-family: var(--font-body);
  font-size: var(--fs-body-m);
  line-height: 1.55;
  color: var(--c-text-secondary);
  max-width: 60ch;
  margin: 0;
}
.metodologia-cta__botones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}
.metodologia-cta__pie {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--c-text-muted);
  line-height: 1.5;
  border-top: 1px solid var(--c-border-subtle);
  padding-top: var(--sp-3);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  align-items: baseline;
}
.metodologia-cta__pie a {
  color: var(--c-text-primary);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: var(--c-border-strong);
  text-underline-offset: 3px;
  transition: text-decoration-color var(--transition-fast);
}
.metodologia-cta__pie a:hover,
.metodologia-cta__pie a:focus-visible {
  text-decoration-color: var(--c-text-primary);
}

/* Botones (reutilizados del bloque CTA) */
.boton {
  display: inline-flex;
  flex-direction: column;
  padding: var(--sp-3) var(--sp-4);
  font-weight: 500;
  font-size: var(--fs-body-m);
  border: 1px solid currentColor;
  transition: background var(--transition-fast), color var(--transition-fast),
              border-color var(--transition-fast);
}
.boton--primario {
  background: var(--c-rausch);
  color: var(--c-bone);
  border-color: var(--c-rausch);
}
.boton--primario:hover,
.boton--primario:focus-visible {
  background: var(--c-rausch);
  border-color: var(--c-rausch);
}
.boton__titulo {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
}
.boton__meta {
  display: block;
  font-size: var(--fs-caption);
  font-weight: 400;
  opacity: 0.75;
  margin-top: 2px;
}

@media (max-width: 640px) {
  .metodologia-page {
    padding: var(--sp-6) var(--sp-3) var(--sp-7);
  }
  .metodologia-page__wrap {
    gap: var(--sp-6);
  }
  .metodologia-cta {
    padding: var(--sp-4) var(--sp-3);
  }
  .metodologia-cta__botones .boton {
    width: 100%;
  }
}

/* ----------------------------------------------------------------------
   11. Footer
   Fondo Babu #00a699. Texto en Hof-deep para contraste alto (~6.2:1
   AA OK). El acento de marca cierra el documento con identidad
   cromática Airbnb sin saturar.
   ---------------------------------------------------------------------- */
.site-footer {
  background: var(--c-babu);
  color: var(--c-hof-deep);
  padding: var(--sp-6) var(--sp-4) var(--sp-5);
  border-top: 4px solid var(--c-hof-deep);
}
.site-footer__wrap {
  max-width: var(--max-w);
  margin: 0 auto;
  display: grid;
  /* Tres columnas iguales: izq metodología, centro autor, der licencia.
     Con `1fr 1fr 1fr` el autor queda centrado respecto al wrap. */
  grid-template-columns: 1fr 1fr 1fr;
  align-items: center;
  gap: var(--sp-4);
}

/* Bloque autor (ahora vive en columna central) */
.site-footer__autor {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 2px;
  line-height: 1.25;
}
.site-footer__nombre {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--fs-heading-m);
  color: var(--c-hof-deep);
  letter-spacing: -0.01em;
  margin: 0;
}
/* Botones sociales: círculo Bone con borde Hof-deep. Al hover sube un
   overlay coloreado desde abajo (::before de top:100% a top:0) mientras
   el ícono rota 360° y cambia a Bone. Adapta el patrón YouTube de
   @QaSLBMqPb2U a la paleta del datero (X→negro, mail→Arches,
   web→Rausch). */
.site-footer__social {
  list-style: none;
  display: flex;
  gap: var(--sp-2);
  margin: var(--sp-2) 0 0;
  padding: 0;
}
.site-footer__social li {
  list-style: none;
}
.site-footer__social-btn {
  --btn-size: 44px;
  --btn-hover-bg: var(--c-hof-deep);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--btn-size);
  height: var(--btn-size);
  border-radius: 50%;
  background: var(--c-bone);
  border: 2px solid var(--c-hof-deep);
  color: var(--c-hof-deep);
  text-decoration: none;
  transition: color 0.5s;
}
.site-footer__social-btn::before {
  content: "";
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  height: 100%;
  background: var(--btn-hover-bg);
  transition: top 0.5s;
  z-index: 1;
}
.site-footer__social-btn:hover::before,
.site-footer__social-btn:focus-visible::before {
  top: 0;
}
.site-footer__social-btn .icon {
  position: relative;
  z-index: 2;
  transition: color 0.5s, transform 0.5s;
}
.site-footer__social-btn:hover .icon,
.site-footer__social-btn:focus-visible .icon {
  color: var(--c-bone);
  transform: rotateY(360deg);
}
/* Color del overlay por red social. Restaurado al diseño original. */
.site-footer__social-btn[data-net="x"] {
  --btn-hover-bg: #0a0a0a;
}
.site-footer__social-btn[data-net="mail"] {
  --btn-hover-bg: var(--c-arches);
}
.site-footer__social-btn[data-net="web"] {
  --btn-hover-bg: var(--c-rausch);
}
@media (prefers-reduced-motion: reduce) {
  .site-footer__social-btn,
  .site-footer__social-btn::before,
  .site-footer__social-btn .icon {
    transition: none;
  }
  .site-footer__social-btn:hover .icon,
  .site-footer__social-btn:focus-visible .icon {
    transform: none;
  }
}

/* CTA Metodología (izquierda) */
.site-footer__nav {
  display: flex;
  justify-content: flex-start;
}
.site-footer__link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-body-s);
  letter-spacing: 0;
  color: var(--c-hof-deep);
  padding: var(--sp-2) var(--sp-3);
  background: transparent;
  border: 1.5px solid var(--c-hof-deep);
  border-radius: 999px;
  transition: background var(--transition-fast), color var(--transition-fast);
}
.site-footer__link:hover,
.site-footer__link:focus-visible {
  background: var(--c-hof-deep);
  color: var(--c-babu);
}

/* Licencia (der). Texto Hof-deep para contraste alto sobre Babu. */
.site-footer__licencia {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--c-hof-deep);
  line-height: 1.3;
  margin: 0;
  text-align: right;
}
.site-footer__cc {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--fs-body-l);
  letter-spacing: 0.02em;
  padding: 2px var(--sp-2);
  background: var(--c-hof-deep);
  color: var(--c-babu);
  border-radius: 4px;
}

@media (max-width: 900px) {
  .site-footer__wrap {
    grid-template-columns: 1fr;
    text-align: center;
    gap: var(--sp-4);
  }
  .site-footer__nav {
    justify-content: center;
  }
  .site-footer__autor {
    align-items: center;
  }
  .site-footer__licencia {
    align-items: center;
    text-align: center;
  }
}

/* ----------------------------------------------------------------------
   12. Estados de carga y toast
   ---------------------------------------------------------------------- */
.estado-carga {
  position: fixed;
  inset: 0;
  background: var(--c-bg);
  z-index: 2000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-5);
  font-family: var(--font-display);
  font-size: var(--fs-heading-m);
  color: var(--c-text-secondary);
  transition: opacity var(--transition-base);
}
.estado-carga.is-hidden {
  opacity: 0;
  pointer-events: none;
}

/* Loader de pilares con bolita rebotando. Pilares en gris claro
   (legible sobre el tile dark del estado de carga) y bolita en
   Rausch — refuerza la identidad cromática del proyecto. */
.loader {
  position: relative;
  width: 75px;
  height: 100px;
  background-repeat: no-repeat;
  background-image:
    linear-gradient(#ddd 50px, transparent 0),
    linear-gradient(#ddd 50px, transparent 0),
    linear-gradient(#ddd 50px, transparent 0),
    linear-gradient(#ddd 50px, transparent 0),
    linear-gradient(#ddd 50px, transparent 0);
  background-size: 8px 100%;
  background-position: 0 90px, 15px 78px, 30px 66px, 45px 58px, 60px 50px;
  animation: pillerPushUp 4s linear infinite;
}
.loader::after {
  content: "";
  position: absolute;
  bottom: 10px;
  left: 0;
  width: 10px;
  height: 10px;
  background: var(--c-rausch);
  border-radius: 50%;
  animation: ballStepUp 4s linear infinite;
}
@keyframes pillerPushUp {
  0%, 40%, 100% { background-position: 0 90px, 15px 78px, 30px 66px, 45px 58px, 60px 50px; }
  50%, 90%     { background-position: 0 50px, 15px 58px, 30px 66px, 45px 78px, 60px 90px; }
}
@keyframes ballStepUp {
  0%   { transform: translate(0, 0); }
  5%   { transform: translate(8px, -14px); }
  10%  { transform: translate(15px, -10px); }
  17%  { transform: translate(23px, -24px); }
  20%  { transform: translate(30px, -20px); }
  27%  { transform: translate(38px, -34px); }
  30%  { transform: translate(45px, -30px); }
  37%  { transform: translate(53px, -44px); }
  40%  { transform: translate(60px, -40px); }
  50%  { transform: translate(60px, 0); }
  57%  { transform: translate(53px, -14px); }
  60%  { transform: translate(45px, -10px); }
  67%  { transform: translate(37px, -24px); }
  70%  { transform: translate(30px, -20px); }
  77%  { transform: translate(22px, -34px); }
  80%  { transform: translate(15px, -30px); }
  87%  { transform: translate(7px, -44px); }
  90%  { transform: translate(0, -40px); }
  100% { transform: translate(0, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .loader,
  .loader::after { animation: none; }
}
.toast {
  position: fixed;
  bottom: var(--sp-4);
  left: 50%;
  transform: translateX(-50%) translateY(120%);
  background: var(--c-hof-deep);
  color: var(--c-bone);
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-body-s);
  border: 1px solid var(--c-border-strong);
  z-index: 3000;
  transition: transform var(--transition-base), visibility 0s linear var(--transition-base);
  pointer-events: none;
  /* Mientras no hay mensaje, el toast no existe visualmente — evita
     el "rectángulo fantasma" abajo centro. */
  visibility: hidden;
}
.toast.is-visible {
  transform: translateX(-50%) translateY(0);
  visibility: visible;
  transition: transform var(--transition-base), visibility 0s linear 0s;
}

/* Scroll-down indicator: flecha en círculo, centrada abajo, con
   animación bounce sutil. Aparece en todas las sections excepto en
   la última (clase .is-hidden controlada por JS). */
.scroll-next {
  position: fixed;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: var(--c-bone);
  border: 1px solid rgba(255, 255, 255, 0.25);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 700;
  animation: scroll-bounce 1.6s ease-in-out infinite;
  transition: opacity var(--transition-base), visibility 0s linear 0s;
}
.scroll-next:hover,
.scroll-next:focus-visible {
  /* Estado activo de control: Arches (Rausch reservado a dato). */
  background: var(--c-rausch);
  color: var(--c-bone);
  border-color: var(--c-rausch);
  animation-play-state: paused;
}
.scroll-next.is-hidden {
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--transition-base), visibility 0s linear var(--transition-base);
}
@keyframes scroll-bounce {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50%      { transform: translateX(-50%) translateY(6px); }
}
@media (prefers-reduced-motion: reduce) {
  .scroll-next { animation: none; }
}
/* Mobile: subir el bottom para no taparle la cara a la card +91% del
   KPI Sobreprecio cuando el lector está en el fold de KPIs. */
@media (max-width: 640px) {
  .scroll-next {
    bottom: 60px;
  }
}

/* noscript */
.noscript {
  position: fixed;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  padding: var(--sp-5);
  background: var(--c-surface-1);
  color: var(--c-text-primary);
  border: 2px solid var(--c-rausch);
  font-size: var(--fs-body-m);
  max-width: 90%;
  text-align: center;
}
.noscript a {
  color: var(--c-rausch);
  text-decoration: underline;
}

/* ----------------------------------------------------------------------
   13. Leaflet overrides minimos
   ---------------------------------------------------------------------- */
.leaflet-container {
  font-family: var(--font-body);
  background: var(--c-bg);
}
.leaflet-control-attribution {
  font-size: 10px !important;
  background: rgba(31, 31, 31, 0.85) !important;
  color: var(--c-text-muted) !important;
}
.leaflet-control-attribution a {
  color: var(--c-rausch) !important;
}
.leaflet-tooltip.airbnb-tooltip {
  background: var(--tooltip-bg);
  color: var(--tooltip-text);
  border: 1px solid var(--tooltip-border);
  font-size: var(--fs-caption);
  line-height: 1.4;
  padding: var(--sp-2) var(--sp-3);
  box-shadow: none;
  font-variant-numeric: tabular-nums;
}
.leaflet-tooltip.airbnb-tooltip::before {
  display: none;
}
.leaflet-tooltip.airbnb-tooltip strong {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  margin-bottom: 2px;
}

/* Colonia destacada al click */
.path-colonia-activa {
  stroke: var(--c-bone) !important;
  stroke-width: 2.5 !important;
}

/* ----------------------------------------------------------------------
   Capa Radios: anillos concéntricos desde el Estadio Akron.
   ---------------------------------------------------------------------- */
.radios-anillo {
  transition: fill-opacity 160ms ease, stroke-opacity 160ms ease;
}
.radios-anillo:hover {
  fill-opacity: 0.85 !important;
  stroke-opacity: 1 !important;
}
.radios-anillo--gris {
  pointer-events: all;
}
.radios-anillo-label {
  background: transparent;
  border: 0;
  text-align: center;
  pointer-events: none;
  font-family: var(--font-display);
  color: var(--c-bone);
  text-shadow:
    0 0 4px rgba(0, 0, 0, 0.95),
    0 0 2px rgba(0, 0, 0, 0.95),
    0 1px 0 rgba(0, 0, 0, 0.95);
  line-height: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
}
.radios-anillo-label span {
  font-weight: 700;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.radios-anillo-label small {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 9px;
  opacity: 0.85;
  letter-spacing: 0.02em;
}
/* Marcador del Estadio Akron como centro */
.radios-centro {
  display: flex !important;
  align-items: center;
  justify-content: center;
  background: var(--c-rausch);
  border: 2px solid var(--c-bone);
  border-radius: 50%;
  font-size: 13px;
  line-height: 1;
  color: var(--c-bone);
  box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.45), 0 2px 6px rgba(0, 0, 0, 0.5);
}

/* ----------------------------------------------------------------------
   14. Empty states, badge, overlay mapa, controles scatter
   ---------------------------------------------------------------------- */
.mapa-empty {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: var(--c-surface-2);
  border: 1px solid var(--c-border-strong);
  padding: var(--sp-3) var(--sp-4);
  z-index: 700;
  text-align: center;
  max-width: 320px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
}
.mapa-empty__titulo {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-body-l);
  color: var(--c-text-primary);
  margin-bottom: var(--sp-1);
}
.mapa-empty__desc {
  font-size: var(--fs-body-s);
  color: var(--c-text-secondary);
  margin-bottom: var(--sp-2);
}
.mapa-empty__cta {
  background: var(--c-rausch);
  color: var(--c-bone);
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-body-s);
  font-weight: 500;
  border: 1px solid var(--c-rausch);
  transition: background var(--transition-fast);
}
.mapa-empty__cta:hover,
.mapa-empty__cta:focus-visible {
  background: var(--c-rausch);
  border-color: var(--c-rausch);
}

/* Empty state genérico para vizes secundarias */
.viz-empty {
  font-size: var(--fs-body-s);
  color: var(--c-text-secondary);
  padding: var(--sp-5) var(--sp-3);
  text-align: center;
  background: var(--c-surface-1);
  border: 1px dashed var(--c-border-subtle);
  line-height: 1.5;
}
.viz-empty__link {
  background: none;
  border: 0;
  padding: 0;
  color: var(--c-rausch);
  font-weight: 700;
  text-decoration: underline;
  cursor: pointer;
}
.viz-empty__link:hover,
.viz-empty__link:focus-visible {
  color: var(--c-rausch);
}

/* Scatter: selector de color (B2) + leyenda */
.scatter-controles {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
  font-size: var(--fs-body-s);
}
.scatter-controles__label {
  font-family: var(--font-body);
  font-weight: 700;
  color: var(--c-text-secondary);
  font-size: var(--fs-caption);
}
.scatter-controles__btn {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 500;
  color: var(--c-text-primary);
  padding: 3px var(--sp-2);
  border: 1px solid var(--c-border-subtle);
  background: var(--c-surface-1);
  transition: background var(--transition-fast), border-color var(--transition-fast);
}
.scatter-controles__btn[aria-checked="true"] {
  background: var(--c-bone);
  color: var(--c-bg);
  border-color: var(--c-bone);
}
.scatter-controles__btn:hover:not([aria-checked="true"]),
.scatter-controles__btn:focus-visible:not([aria-checked="true"]) {
  border-color: var(--c-bone);
}
.scatter-leyenda {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-3);
  margin-top: var(--sp-2);
  font-size: var(--fs-caption);
  color: var(--c-text-secondary);
}

/* ----------------------------------------------------------------------
   15. Subgrupo "Mundial" dentro de la banda de KPIs (B1)
   Bloque conservado por compatibilidad de overrides anteriores.
   La diferenciación visual de tarjetas Mundial vive en la sección 5
   (border-top Rausch + padding-left).
   ---------------------------------------------------------------------- */

/* ----------------------------------------------------------------------
   16. Top colonias: agrupaciones (B3)
   ---------------------------------------------------------------------- */
.colonia-grupo-label {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  fill: var(--c-text-muted);
}
.colonia-grupo-divider {
  stroke: var(--c-border-subtle);
  stroke-width: 1;
  shape-rendering: crispEdges;
}
.colonia-spark {
  stroke-width: 2;
}

.axis-title {
  text-transform: none;
  letter-spacing: 0;
}

/* ----------------------------------------------------------------------
   19. Iconos SVG inline (C1)
   ---------------------------------------------------------------------- */
.icon {
  display: inline-block;
  width: 16px;
  height: 16px;
  vertical-align: -3px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}
.icon--lg { width: 20px; height: 20px; }
.icon--inline { vertical-align: -2px; }

/* ----------------------------------------------------------------------
   21. Export SVG por viz (C7)
   ---------------------------------------------------------------------- */
.viz__pie {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-3);
  justify-content: space-between;
}
.viz__pie-texto {
  flex: 1;
  min-width: 200px;
}
.viz__export {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  color: var(--c-rausch);
  padding: 2px var(--sp-2);
  border: 1px solid currentColor;
  font-weight: 500;
  flex-shrink: 0;
  transition: background var(--transition-fast), color var(--transition-fast);
}
.viz__export:hover,
.viz__export:focus-visible {
  background: var(--c-rausch);
  color: var(--c-bone);
}
.viz__caveat {
  display: block;
  margin-top: var(--sp-1);
  font-style: italic;
  font-size: var(--fs-caption);
  color: var(--c-text-muted);
  opacity: 0.85;
}

/* ----------------------------------------------------------------------
   View Transitions
   ---------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: 250ms;
    animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  }
}
