/* Pantallas con visor: el splat suelto (pantallas/splat.js), que es el visor limpio con sus
   controles flotando encima, y el proyecto (pantallas/proyecto.js), que suma una barra
   arriba, la jerarquía a la izquierda y los comentarios a la derecha. Ninguna lleva el marco
   de la app: ocupan la ventana. */

.vista {
  height: 100%;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
}

.vista.pantalla-completa {
  height: 100vh;
  height: 100dvh;
}

/* ---------- El visor limpio (pantallas/splat.js) ----------
   Solo el splat. Lo demás son capas sueltas sobre la escena: volver arriba a la izquierda,
   foto, PDF, calidad y compartir arriba a la derecha, el nombre abajo a la izquierda, el
   switch de los modos abajo al medio y la guía abajo a la derecha (el switch y la guía viven
   adentro de la escena: ver "Guía del visor"). */

.vista-limpia {
  position: relative;
  grid-template-rows: minmax(0, 1fr);
  background: #000;
}

.vista-limpia,
.vista-escena {
  --borde-visor: clamp(12px, 2vw, 22px);
}

.capa {
  position: absolute;
  z-index: 7;
}

.capa-atras {
  top: var(--borde-visor);
  left: var(--borde-visor);
}

.capa-controles {
  top: var(--borde-visor);
  right: var(--borde-visor);
  display: flex;
  align-items: center;
  gap: var(--esp-2);
}

/* El botón redondo de lo que flota sobre un splat. La escena de abajo puede ser clara u
   oscura: lleva un velo casi opaco y un borde claro. Sin `backdrop-filter`: desenfocar un
   lienzo que se redibuja en cada cuadro sale caro. */
.boton-vidrio {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  background: var(--velo);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
  color: var(--texto);
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--transicion), border-color var(--transicion), transform var(--transicion);
}

.boton-vidrio:hover,
.boton-vidrio[aria-expanded="true"] {
  border-color: var(--celeste);
  background: var(--velo-fuerte);
}

.boton-vidrio:active {
  transform: scale(0.94);
}

/* Las capas, hasta que el splat tiene un viaje. */
.boton-vidrio[hidden] {
  display: none;
}

.boton-vidrio .icono {
  width: 21px;
  height: 21px;
  stroke-width: 2;
}

/* El engranaje gira un poco al acercarse: dice que ahí se ajusta algo. */
.capa-controles .menu-boton .icono {
  transition: transform 300ms ease;
}

.capa-controles [data-menu-calidad] .menu-boton:hover .icono,
.capa-controles [data-menu-calidad] .menu-boton[aria-expanded="true"] .icono {
  transform: rotate(60deg);
}

/* Los PDF del splat (componentes/documentos.js): el botón lleva la cuenta en una insignia y la
   lista se despliega debajo, con el mismo aspecto que el menú de calidad. */
.documentos-splat .menu-boton {
  position: relative;
}

.documentos-cuenta {
  position: absolute;
  top: -3px;
  right: -3px;
  min-width: 19px;
  height: 19px;
  padding: 0 5px;
  display: grid;
  place-items: center;
  border-radius: var(--r-pastilla);
  background: var(--acento);
  color: #fff;
  font-size: 0.68rem;
  font-weight: var(--peso-semibold);
  line-height: 1;
}

.documentos-lista {
  width: min(320px, calc(100vw - 2 * var(--borde-visor)));
  display: grid;
  gap: 2px;
}

/* En un teléfono parado los menús de arriba a la derecha (los PDF, el engranaje, compartir)
   salían por la izquierda: cada uno cuelga de su botón y los botones no están en la punta
   (OT-215). Ahí ocupan el ancho, debajo de la fila de botones, y se corren si son largos. */
@media (max-width: 600px) {
  .capa-controles .menu-lista {
    position: fixed;
    top: calc(var(--borde-visor) + 46px + var(--esp-2));
    left: var(--borde-visor);
    right: var(--borde-visor);
    width: auto;
    max-height: calc(100dvh - 2 * var(--borde-visor) - 46px - 2 * var(--esp-2));
    overflow-y: auto;
  }
}

/* ---------- El visor de un splat en el teléfono (OT-249) ----------
   Con el dedo, arriba a la derecha quedan el engranaje (solo la Cámara: la calidad va arriba del
   menú) y las tres rayas, en la punta; la foto, los PDF, las capas y compartir van adentro del
   menú (dialogos.js: verOpciones). La realidad aumentada va abajo, en la punta derecha de la fila
   del switch. Con mouse, todo como estaba: las tres rayas no aparecen. */
.capa-controles .capa-opciones {
  display: none;
}

.capa-ar {
  right: var(--borde-visor);
  bottom: calc(var(--borde-visor) + 1px + env(safe-area-inset-bottom, 0px));
}

/* Mientras un cartel tapa la escena (cargando, procesando) no hay nada que poner en el espacio. */
.vista-limpia:has(.vista-aviso:not(.oculto)) .capa-ar {
  display: none;
}

/* Lo que se ve encima de la realidad aumentada (la capa del DOM de WebXR): transparente, para que
   se vea la cámara, y a toda la pantalla, porque ahí se pellizca. Solo el engranaje de la calidad,
   arriba a la derecha. Afuera de esa vista está escondida. */
.capa-ar-vista {
  position: fixed;
  inset: 0;
  z-index: 30;
  background: transparent;
  touch-action: none;
}

.capa-ar-vista[hidden] {
  display: none;
}

.capa-ar-calidad {
  position: absolute;
  top: calc(var(--borde-visor) + env(safe-area-inset-top, 0px));
  right: var(--borde-visor);
}

@media (pointer: coarse) {
  .capa-controles .capa-opciones {
    display: grid;
  }

  .con-opciones .capa-controles > :is([data-capas], [data-foto], [data-documentos], [data-acciones]) {
    display: none;
  }

  .con-opciones .capa-controles :is([data-seccion="renderizado"], [data-seccion="ayuda"]) {
    display: none;
  }

  .con-opciones .capa-controles [data-seccion="camara"] {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
  }
}

/* ---------- El menú de tres rayas (dialogos.js: verOpciones) ----------
   Va en la hoja que sube desde abajo (`.dialogo-hoja`, css/componentes.css): arriba el
   renderizado y debajo una fila por cosa, con su símbolo a la derecha. */
.config-suelto {
  padding: var(--esp-3) var(--esp-4);
  border: 1px solid var(--borde);
  border-radius: var(--r-boton);
  background: rgba(255, 255, 255, 0.03);
}

.opciones-lista {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--esp-2);
}

/* Una fila: el nombre a la izquierda y su símbolo, redondo como los del visor, a la derecha. La
   fila entera es el botón (salvo la de los PDF, que tiene dos: subir y ver la lista). */
.opciones-fila {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
  width: 100%;
  min-height: 60px;
  padding: var(--esp-2) var(--esp-2) var(--esp-2) var(--esp-4);
  border: 1px solid var(--borde);
  border-radius: var(--r-boton);
  background: rgba(255, 255, 255, 0.03);
  color: var(--texto);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color var(--transicion), border-color var(--transicion);
}

button.opciones-fila:active {
  border-color: var(--celeste);
  background: var(--panel-activo);
}

.opciones-nombre {
  flex: 1;
  min-width: 0;
  font-weight: var(--peso-semibold);
}

.opciones-boton {
  flex: none;
  width: 44px;
  height: 44px;
  box-shadow: none;
}

.opciones-ayuda h3 {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
}

.opciones-ayuda h3 .icono {
  width: 16px;
  height: 16px;
}

.opciones-ayuda ul {
  margin: 0;
  padding-left: 1.2em;
  display: grid;
  gap: var(--esp-1);
  color: var(--texto-2);
  font-size: 0.92rem;
}

.opciones-documento {
  display: flex;
  align-items: center;
  gap: var(--esp-1);
}

.opciones-documento .opcion-galeria {
  flex: 1;
  min-width: 0;
  text-decoration: none;
}

.opciones-subir {
  justify-self: start;
  cursor: pointer;
}

.opciones-nota {
  max-width: none;
  margin-bottom: var(--esp-1);
}

.documentos-rotulo {
  padding: var(--esp-1) var(--esp-3) var(--esp-2);
  color: var(--texto-3);
  font-family: var(--fuente-marca);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.documentos-lista ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 2px;
}

.documentos-lista li {
  display: flex;
  align-items: center;
  gap: 2px;
}

.documentos-lista li .menu-item {
  flex: 1;
  min-width: 0;
}

.documentos-lista li .menu-item span {
  overflow: hidden;
  text-overflow: ellipsis;
}

.documentos-vacio,
.documentos-subiendo {
  padding: var(--esp-2) var(--esp-3);
}

.documentos-subir {
  margin-top: var(--esp-1);
  border-top: 1px solid var(--borde);
  border-radius: 0 0 var(--r-tag) var(--r-tag);
  color: var(--celeste);
  cursor: pointer;
}

/* El nombre del splat: texto suelto sobre la escena, sin tarjeta detrás. La sombra es lo que
   lo deja leerse sobre cualquier cosa, clara u oscura. No recibe el puntero: lo que hay
   debajo se sigue pudiendo arrastrar. */
.capa-titulo {
  left: calc(var(--borde-visor) + 4px);
  bottom: calc(var(--borde-visor) + env(safe-area-inset-bottom, 0px));
  /* Hasta el switch de los modos, que va abajo al medio. */
  max-width: min(calc(50% - 150px), 760px);
  display: grid;
  gap: 2px;
  pointer-events: none;
  color: #fff;
  text-shadow:
    0 1px 2px rgba(0, 0, 0, 0.95),
    0 0 12px rgba(0, 0, 0, 0.75),
    0 0 32px rgba(0, 0, 0, 0.55);
}

.capa-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.5em;
  font-family: var(--fuente-marca);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.86);
}

.capa-meta-sep {
  opacity: 0.6;
}

.capa-meta time {
  font-variant-numeric: tabular-nums;
}

.capa-titulo h1 {
  font-size: clamp(1.5rem, 3vw, 2.5rem);
  /* El renglón es un poco más alto que la letra para que el recorte de abajo no se coma las
     que bajan (g, p, y). */
  line-height: 1.12;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
  /* Un nombre largo no pasa de tres renglones: el resto se corta con puntos suspensivos. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}

/* Mientras la escena muestra un estado (procesando, subida a medias, un error) el nombre se
   queda en un renglón, abajo del todo, y el cartel se centra en lo que queda arriba: un nombre
   largo no lo pisa. */
.vista-limpia:has(.vista-aviso:not(.oculto)) .capa-titulo {
  bottom: calc(var(--borde-visor) + env(safe-area-inset-bottom, 0px));
  max-width: calc(100% - 2 * var(--borde-visor) - 8px);
}

.vista-limpia:has(.vista-aviso:not(.oculto)) .capa-titulo h1 {
  -webkit-line-clamp: 1;
  line-clamp: 1;
}

.vista-limpia .vista-aviso {
  padding-bottom: calc(var(--borde-visor) + 5.5rem + env(safe-area-inset-bottom, 0px));
  overflow-y: auto;
}

/* En el visor limpio el editor de prueba baja: arriba a la derecha están los botones. */
.vista-limpia .vista-editor {
  top: calc(var(--borde-visor) + 58px);
  right: var(--borde-visor);
  max-height: calc(100% - var(--borde-visor) * 2 - 130px);
}

/* Con el dedo, abajo va la fila del switch de los modos: el nombre va encima de ella. */
@media (pointer: coarse) {
  .capa-titulo {
    bottom: calc(var(--borde-visor) + 48px + var(--esp-3) + env(safe-area-inset-bottom, 0px));
    max-width: calc(100% - 2 * var(--borde-visor));
  }
}

/* ---------- Guía del visor (componentes/guia.js) ----------
   El botón de pregunta, abajo a la derecha de la escena, y el panel que despliega a su
   izquierda: tres dibujos que entran con un fundido, uno detrás del otro. Las animaciones
   están en pausa hasta que el panel se ve. */

.guia {
  position: absolute;
  right: var(--borde-visor);
  bottom: calc(var(--borde-visor) + env(safe-area-inset-bottom, 0px));
  z-index: 6;
  display: flex;
  align-items: flex-end;
}

/* Mientras un cartel tapa la escena (cargando, procesando) no hay por dónde moverse. */
.vista-aviso:not(.oculto) ~ .guia,
.vista-aviso:not(.oculto) ~ .modos {
  display: none;
}

/* El switch de los modos, abajo al medio: una pastilla con las tres opciones y la elegida
   resaltada en el acento. */
.modos {
  position: absolute;
  left: 50%;
  bottom: calc(var(--borde-visor) + env(safe-area-inset-bottom, 0px));
  z-index: 6;
  display: flex;
  gap: 4px;
  padding: 4px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: var(--r-pastilla);
  background: var(--velo);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
  transform: translateX(-50%);
}

.modo {
  display: inline-flex;
  align-items: center;
  gap: var(--esp-2);
  height: 38px;
  padding: 0 var(--esp-4) 0 var(--esp-3);
  border: 0;
  border-radius: var(--r-pastilla);
  background: none;
  color: var(--texto-2);
  font: inherit;
  font-family: var(--fuente-marca);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color var(--transicion), color var(--transicion);
}

/* Los modos que el splat no ofrece (un objeto no camina, una sala no orbita). */
.modo[hidden] {
  display: none;
}

/* La casita: vuelve la cámara al inicio, como R. Arriba a la izquierda, debajo de volver (en el
   proyecto, arriba a la izquierda de la escena: el medio es del tirador del panel). La R va
   escrita en una esquina, como una tecla; al pasarle el cursor se despliega "Volver al inicio". */
.visor-inicio {
  position: absolute;
  z-index: 6;
  top: calc(var(--borde-visor, var(--esp-3)) + 46px + var(--esp-2));
  left: var(--borde-visor, var(--esp-3));
  overflow: visible;
}

.vista-aviso:not(.oculto) ~ .visor-inicio {
  display: none;
}

.visor-inicio-tecla {
  position: absolute;
  right: -5px;
  bottom: -5px;
  min-width: 18px;
  padding: 0 4px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-bottom-width: 2px;
  border-radius: 5px;
  background: var(--velo-fuerte);
  color: var(--texto);
  font-family: var(--fuente-marca);
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 15px;
  text-align: center;
}

.visor-inicio-texto {
  position: absolute;
  left: calc(100% + var(--esp-2));
  top: 50%;
  padding: 4px 10px;
  border-radius: var(--r-pastilla);
  background: var(--velo-fuerte);
  color: var(--texto);
  font-size: 0.8rem;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translate(-4px, -50%);
  transition: opacity var(--transicion), transform var(--transicion);
}

.visor-inicio:hover .visor-inicio-texto,
.visor-inicio:focus-visible .visor-inicio-texto {
  opacity: 1;
  transform: translate(0, -50%);
}

/* Con el dedo no hay tecla ni cursor: queda la casita sola. */
@media (pointer: coarse) {
  .visor-inicio-tecla,
  .visor-inicio-texto {
    display: none;
  }
}

.modo .icono {
  width: 19px;
  height: 19px;
  stroke-width: 1.9;
}

.modo:hover {
  color: var(--texto);
}

.modo[aria-checked="true"] {
  background: var(--acento);
  color: #fff;
  box-shadow: 0 4px 12px rgba(30, 111, 224, 0.4);
}

/* El modo dron: el punto del centro es a dónde vuela el clic. */
.visor-mira {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 3;
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  pointer-events: none;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.55);
}

.vista-aviso:not(.oculto) ~ .visor-mira {
  display: none;
}

.guia-pie kbd {
  display: inline-block;
  min-width: 1.6em;
  padding: 1px 6px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-bottom-width: 2px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.08);
  font-family: var(--fuente-marca);
  font-size: 0.72rem;
  font-weight: 700;
  text-align: center;
}

.guia-panel {
  position: absolute;
  right: calc(100% + var(--esp-3));
  bottom: 0;
  padding: var(--esp-2);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 20px;
  background: var(--velo-fuerte);
  box-shadow: var(--sombra-flotante);
  opacity: 0;
  visibility: hidden;
  transform: translateX(10px);
  pointer-events: none;
  transition: opacity 240ms ease, transform 240ms ease, visibility 0s linear 240ms;
}

/* Solo los gestos del modo elegido en el switch. */
.guia[data-modo="orbitar"] [data-de]:not([data-de="orbitar"]),
.guia[data-modo="dron"] [data-de]:not([data-de="dron"]),
.guia[data-modo="caminar"] [data-de]:not([data-de="caminar"]) {
  display: none;
}

.guia-gestos {
  display: flex;
  gap: var(--esp-2);
}

.guia-pie {
  padding: var(--esp-2) 6px 2px;
  color: var(--texto-2);
  font-size: 0.72rem;
}

.guia:hover .guia-panel,
.guia:focus-within .guia-panel {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: 0s;
}

.guia-gesto {
  width: 138px;
  margin: 0;
  display: grid;
  align-content: start;
  gap: var(--esp-2);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 320ms ease, transform 320ms ease;
}

/* Los tres entran en fila: cada uno un poco después que el anterior. */
.guia:hover .guia-gesto,
.guia:focus-within .guia-gesto {
  opacity: 1;
  transform: none;
  transition-delay: calc(120ms + var(--i) * 110ms);
}

.guia-dibujo {
  position: relative;
  height: 96px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  overflow: hidden;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.07);
}

.guia-gesto figcaption {
  display: grid;
  gap: 1px;
  padding: 0 4px 4px;
  font-size: 0.72rem;
  line-height: 1.35;
  color: var(--texto-2);
}

.guia-gesto figcaption strong {
  color: var(--texto);
  font-family: var(--fuente-marca);
  font-size: 0.78rem;
}

/* El mouse: claro, con lo que se aprieta en oscuro. */
.guia-mouse {
  display: block;
  width: 30px;
  height: auto;
  fill: none;
  stroke: var(--noche);
  stroke-width: 2;
  stroke-linejoin: round;
}

.guia-mouse-cuerpo {
  fill: #f1f6fc;
}

.guia-mouse .apretado {
  fill: var(--noche);
}

.guia-mueve {
  display: block;
  animation: var(--guia-anima, none) 1.9s ease-in-out infinite;
  animation-play-state: paused;
}

.guia-flechas {
  position: absolute;
  fill: none;
  stroke: var(--celeste);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  animation: guia-late 1.9s ease-in-out infinite;
  animation-play-state: paused;
}

.guia:hover .guia-mueve,
.guia:focus-within .guia-mueve,
.guia:hover .guia-orbe-icono,
.guia:focus-within .guia-orbe-icono,
.guia:hover .guia-flechas,
.guia:focus-within .guia-flechas,
.guia:hover .guia-aro,
.guia:focus-within .guia-aro,
.guia:hover .guia-teclado kbd,
.guia:focus-within .guia-teclado kbd,
.guia:hover .guia-mouse .apretado,
.guia:focus-within .guia-mouse .apretado {
  animation-play-state: running;
}

/* Elegir un punto, volar o caminar hasta él: el aro de destino late y el mouse aprieta. */
.guia-aro {
  position: absolute;
  left: 50%;
  bottom: 12px;
  width: 44px;
  margin-left: -22px;
  fill: none;
  stroke: var(--celeste);
  stroke-width: 2.5;
  animation: guia-aro 1.9s ease-out infinite;
  animation-play-state: paused;
}

.guia-elegir .guia-mueve,
.guia-volar .guia-mueve,
.guia-caminar .guia-mueve {
  --guia-anima: guia-toca;
  margin-top: -22px;
}

/* Doble clic: el botón izquierdo se aprieta dos veces seguidas. */
.guia-doble .guia-mouse .apretado {
  animation: guia-doble 1.9s ease-in-out infinite;
  animation-play-state: paused;
}

/* Girar sobre sí mismo (dron): el mouse va de un lado al otro con el izquierdo apretado. */
.guia-mirar .guia-mueve {
  --guia-anima: guia-costado;
  margin-top: -14px;
}

/* WASD: las cuatro teclas en su lugar, y se iluminan de a una. Se llama "teclado" y no
   "teclas": `guia-teclas` es la clase del gesto entero (`guia-${id}`), y con el mismo nombre la
   caja del gesto se volvía esta grilla de 26 px ("W A S D" en dos renglones, OT-217). */
.guia-teclado {
  display: grid;
  grid-template-columns: repeat(3, 26px);
  grid-template-areas: ". w ." "a s d";
  gap: 4px;
}

.guia-teclado kbd {
  display: grid;
  place-items: center;
  height: 26px;
  border: 1px solid rgba(255, 255, 255, 0.4);
  border-bottom-width: 3px;
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.08);
  color: var(--texto);
  font-family: var(--fuente-marca);
  font-size: 0.72rem;
  font-weight: 700;
  animation: guia-tecla 2.4s ease-in-out infinite;
  animation-play-state: paused;
}

.guia-tecla-w {
  grid-area: w;
}

.guia-tecla-a {
  grid-area: a;
  animation-delay: 0.6s !important;
}

.guia-tecla-s {
  grid-area: s;
  animation-delay: 1.2s !important;
}

.guia-tecla-d {
  grid-area: d;
  animation-delay: 1.8s !important;
}

@keyframes guia-aro {
  0% {
    opacity: 0;
    transform: scale(0.6);
  }
  35% {
    opacity: 1;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(1.25);
  }
}

@keyframes guia-toca {
  0%,
  30%,
  100% {
    transform: none;
  }
  40% {
    transform: translateY(2px) scale(0.95);
  }
  55% {
    transform: none;
  }
}

@keyframes guia-doble {
  0%,
  20%,
  34%,
  48%,
  100% {
    fill: #f1f6fc;
  }
  27%,
  41% {
    fill: var(--noche);
  }
}

@keyframes guia-tecla {
  0%,
  30%,
  100% {
    border-color: rgba(255, 255, 255, 0.4);
    background: rgba(255, 255, 255, 0.08);
  }
  10%,
  20% {
    border-color: var(--celeste);
    background: var(--acento);
  }
}

/* 1 · Desplazar: el mouse va de un lado al otro con el botón derecho apretado. */
.guia-desplazar .guia-mueve {
  --guia-anima: guia-costado;
  margin-top: -14px;
}

.guia-flechas-costado {
  bottom: 10px;
  left: 50%;
  width: 52px;
  margin-left: -26px;
}

/* 2 · Orbitar: el orbe a la izquierda y el mouse, con el izquierdo apretado, dando la vuelta. */
.guia-orbe {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 2px solid rgba(255, 255, 255, 0.75);
  border-radius: 50%;
  box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.1);
  color: #fff;
}

.guia-orbe-icono {
  width: 24px;
  height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.25;
  stroke-linecap: round;
  stroke-linejoin: round;
  animation: guia-gira 3.8s linear infinite;
  animation-play-state: paused;
}

.guia-orbitar .guia-mueve {
  --guia-anima: guia-arco;
}

/* 3 · Acercar: el mouse va adelante y atrás, con la rueda marcada. */
.guia-acercar .guia-mueve {
  --guia-anima: guia-frente;
}

.guia-flechas-frente {
  left: 26px;
  top: 50%;
  height: 52px;
  margin-top: -26px;
}

@keyframes guia-costado {
  0%,
  100% {
    transform: translateX(-20px);
  }
  50% {
    transform: translateX(20px);
  }
}

@keyframes guia-frente {
  0%,
  100% {
    transform: translateY(-10px) scale(0.94);
  }
  50% {
    transform: translateY(10px) scale(1.04);
  }
}

@keyframes guia-arco {
  0%,
  100% {
    transform: translate(-5px, 9px) rotate(-8deg);
  }
  50% {
    transform: translate(7px, -9px) rotate(8deg);
  }
}

@keyframes guia-gira {
  to {
    transform: rotate(360deg);
  }
}

@keyframes guia-late {
  0%,
  100% {
    opacity: 0.45;
  }
  50% {
    opacity: 1;
  }
}

/* Con el dedo no hay mouse: no va la guía (cómo moverse en cada modo lo dice el cartel). El
   switch sí, con los íconos solos. */
@media (pointer: coarse) {
  .guia {
    display: none;
  }

  .modo {
    padding: 0 var(--esp-3);
  }

  .modo span {
    display: none;
  }
}

/* En una ventana angosta los cuatro no entran de costado: se apilan hacia arriba. */
@media (max-width: 1000px) {
  .guia-panel {
    right: 0;
    bottom: calc(100% + var(--esp-2));
  }

  .guia-gestos {
    flex-direction: column;
  }

  .guia-gesto {
    width: 200px;
    grid-template-columns: 76px minmax(0, 1fr);
    align-items: center;
  }

  .guia-dibujo {
    height: 72px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .guia-mueve,
  .guia-orbe-icono,
  .guia-flechas,
  .guia-aro,
  .guia-teclado kbd,
  .guia-doble .guia-mouse .apretado {
    animation: none;
  }

  .guia-panel,
  .guia-gesto {
    transition: none;
  }
}

.vista-barra {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
  padding: var(--esp-3) var(--esp-5);
  background: var(--panel-solido);
  border-bottom: 1px solid var(--borde);
}

.vista-titulo {
  min-width: 0;
  display: grid;
  margin-right: var(--esp-2);
}

.vista-titulo h1 {
  font-size: 1.15rem;
  font-weight: var(--peso-semibold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.vista-acciones {
  margin-left: auto;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--esp-2);
}

.vista-acciones [data-acciones] {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--esp-2);
}

.vista-acciones .boton {
  padding: 8px 14px;
  font-size: var(--t-chico);
}

.vista-cuerpo {
  position: relative;
  display: grid;
  grid-template-columns: var(--ancho-jerarquia, 230px) minmax(0, 1fr) var(--ancho-info, 340px);
  min-height: 0;
}

/* ---------- Paneles plegables (componentes/paneles.js) ---------- */

.vista-cuerpo.jerarquia-cerrada {
  --ancho-jerarquia: 0px;
}

.vista-cuerpo.info-cerrada {
  --ancho-info: 0px;
}

.jerarquia-cerrada .panel-jerarquia,
.info-cerrada .panel-info {
  padding-left: 0;
  padding-right: 0;
  border: 0;
  overflow: hidden;
}

/* El botón del canto de cada panel: una flecha redonda, en el acento. Un toque contrae el
   panel y otro lo extiende. */
.panel-tirador {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 6;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--acento);
  color: var(--texto);
  box-shadow: var(--sombra-boton);
  cursor: pointer;
  transition: filter var(--transicion);
}

.panel-tirador:hover {
  filter: brightness(1.2);
}

.panel-tirador .icono {
  width: 18px;
  height: 18px;
  transition: transform 200ms ease;
}

/* Abierto, el botón va montado sobre el borde del panel; cerrado, entero contra el costado. */
.tirador-izq {
  left: var(--ancho-jerarquia, 230px);
  margin-left: -16px;
}

.tirador-der {
  right: var(--ancho-info, 340px);
  margin-right: -16px;
}

.jerarquia-cerrada .tirador-izq {
  margin-left: 0;
}

.info-cerrada .tirador-der {
  margin-right: 0;
}

/* La flecha apunta hacia donde se va a mover el panel. */
.tirador-izq[aria-expanded="false"] .icono,
.tirador-der[aria-expanded="true"] .icono {
  transform: rotate(180deg);
}

/* ---------- Jerarquía (izquierda) ---------- */

.panel-jerarquia {
  background: var(--panel-solido);
  border-right: 1px solid var(--borde);
  overflow-y: auto;
  padding: var(--esp-4) var(--esp-3);
  display: flex;
  flex-direction: column;
  gap: var(--esp-4);
}

/* La documentación técnica queda al pie del panel. */
.panel-jerarquia > [data-documentos] {
  margin-top: auto;
  padding-top: var(--esp-4);
  border-top: 1px solid var(--borde);
}

.panel-documentos {
  display: grid;
  gap: var(--esp-2);
}

.panel-documentos h2 {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--texto-3);
  padding: 0 var(--esp-2);
}

.panel-documentos .icono {
  width: 14px;
  height: 14px;
}

.panel-documentos > p {
  padding: 0 var(--esp-2);
}

.lista-documentos {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 2px;
}

.lista-documentos li {
  display: flex;
  align-items: center;
  gap: var(--esp-1);
}

.documento {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--esp-2);
  padding: 7px var(--esp-2);
  border: 0;
  border-radius: var(--r-boton);
  background: none;
  color: var(--texto-2);
  text-align: left;
  cursor: pointer;
}

.documento:hover {
  background: rgba(255, 255, 255, 0.04);
  color: var(--texto);
}

.documento .icono {
  width: 16px;
  height: 16px;
}

.documento-nombre {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.panel-jerarquia-cuerpo {
  display: grid;
  gap: var(--esp-3);
  align-content: start;
}

.panel-jerarquia h2 {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--texto-3);
  padding: 0 var(--esp-2);
}

.arbol,
.rama {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 2px;
}

.rama {
  margin: 2px 0 var(--esp-3) var(--esp-4);
  padding-left: var(--esp-3);
  border-left: 1px solid var(--borde);
}

.nodo-fila {
  display: flex;
  align-items: center;
  gap: var(--esp-1);
}

.nodo {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--esp-2);
  padding: 7px var(--esp-2);
  border: 0;
  border-radius: var(--r-boton);
  background: none;
  color: var(--texto-2);
  text-align: left;
  cursor: pointer;
}

.nodo:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.04);
  color: var(--texto);
}

.nodo.activo {
  background: var(--panel-activo);
  color: var(--texto);
}

.nodo:disabled {
  cursor: default;
  opacity: 0.75;
}

.nodo-nombre {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nodo-agregar {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
  width: 100%;
  padding: 7px var(--esp-2);
  border: 1px dashed rgba(255, 255, 255, 0.16);
  border-radius: var(--r-boton);
  background: none;
  color: var(--texto-3);
  font-size: var(--t-chico);
  text-align: left;
  cursor: pointer;
}

.nodo-agregar:hover {
  border-color: var(--acento);
  color: var(--texto);
}

/* ---------- Escena (centro) ---------- */

.vista-escena {
  position: relative;
  min-height: 0;
  background: #000;
  overflow: hidden;
}

.visor-canvas {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;
}

.vista-aviso {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--esp-5);
  text-align: center;
  color: var(--texto-2);
  background: rgba(10, 21, 34, 0.88);
}

.vista-estado {
  display: grid;
  gap: var(--esp-5);
  width: min(760px, 100%);
}

/* El botón de retomar una subida: del ancho de su texto, no de la grilla. */
.vista-estado > .boton {
  justify-self: center;
}

.vista-ayuda {
  position: absolute;
  left: 50%;
  bottom: var(--esp-4);
  transform: translateX(-50%);
  margin: 0;
  padding: var(--esp-2) var(--esp-4);
  border-radius: var(--r-pastilla);
  background: rgba(10, 21, 34, 0.8);
  color: var(--texto);
  font-size: var(--t-chico);
  text-align: center;
  width: max-content;
  max-width: calc(100% - 2 * var(--esp-4));
  pointer-events: none;
  transition: opacity 400ms ease;
}

.vista-ayuda.oculta {
  opacity: 0;
}

/* Con el dedo, abajo están el switch de los modos y el nombre: el cartel va arriba, debajo de
   la fila de botones y sin tapar la casita. */
@media (pointer: coarse) {
  .vista-ayuda {
    top: calc(var(--borde-visor) + 46px + var(--esp-3) + env(safe-area-inset-top, 0px));
    bottom: auto;
    max-width: calc(100% - 2 * (var(--borde-visor) + 46px + var(--esp-2)));
  }
}

/* ---------- Editor de prueba (componentes/editor-escena.js) ----------
   Temporal: se saca junto con el módulo cuando el pipeline acomode las escenas solo. */

.vista-editor {
  position: absolute;
  z-index: 5;
  top: var(--esp-3);
  right: var(--esp-3);
  max-height: calc(100% - 2 * var(--esp-3));
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--esp-2);
  pointer-events: none;
}

/* El hueco que monta escena.js ([data-editor]) y el envoltorio del módulo no arman caja: así
   el panel es hijo directo del flex y se achica con scroll al alto disponible, en vez de
   estirar un div intermedio que no tiene tope. */
.vista-editor > div,
.editor {
  display: contents;
}

.editor-toggle,
.editor-panel {
  pointer-events: auto;
}

.editor-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--esp-2);
  padding: 6px 12px;
  border: 1px solid var(--borde);
  border-radius: var(--r-boton);
  background: rgba(10, 21, 34, 0.85);
  color: var(--texto-2);
  font-size: var(--t-chico);
  cursor: pointer;
}

.editor-toggle:hover {
  color: var(--texto);
  border-color: rgba(255, 255, 255, 0.24);
}

.editor-panel {
  width: 280px;
  min-height: 0;
  flex: 0 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: grid;
  gap: var(--esp-4);
  padding: var(--esp-4);
  border: 1px solid var(--borde);
  border-radius: var(--r-card);
  background: rgba(10, 21, 34, 0.94);
  box-shadow: var(--sombra-boton);
}

.editor-bloque {
  display: grid;
  gap: var(--esp-2);
}

.editor-bloque h3 {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--texto-3);
}

.editor-datos {
  margin: 0;
  padding: var(--esp-2);
  border-radius: var(--r-tag);
  background: var(--fondo);
  color: var(--texto);
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: 0.72rem;
  line-height: 1.5;
  white-space: pre;
}

.editor-botones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--esp-2);
}

.editor-grilla {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--esp-2);
}

.editor-campo {
  display: grid;
  gap: 2px;
}

.editor-campo span {
  font-size: 0.7rem;
  color: var(--texto-3);
}

.editor-campo input,
.editor-campo select {
  width: 100%;
  padding: 4px 6px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--r-tag);
  background: var(--fondo);
  color: var(--texto);
  font-size: var(--t-chico);
}

/* La lista de cajas de colisión: una fila por caja, la elegida marcada. La caja elegida es
   la que muestran los campos de abajo y la que va en blanco adentro de la escena. */
.editor-lista {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 2px;
  max-height: 160px;
  overflow-y: auto;
}

.editor-item {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
  border-radius: var(--r-tag);
}

.editor-item.activo {
  background: var(--acento-suave);
}

.editor-item-nombre {
  flex: 1;
  display: flex;
  align-items: baseline;
  gap: var(--esp-2);
  padding: 4px 6px;
  border: 0;
  border-radius: var(--r-tag);
  background: none;
  color: var(--texto-2);
  font: inherit;
  font-size: var(--t-chico);
  text-align: left;
  cursor: pointer;
}

.editor-item.activo .editor-item-nombre {
  color: var(--texto);
}

.editor-check {
  display: flex;
  align-items: flex-start;
  gap: var(--esp-2);
  font-size: var(--t-chico);
  color: var(--texto-2);
}

/* TEMPORAL (OT-118): mientras la órbita para grabar gira con la interfaz escondida, sobre el
   splat no queda nada: ni botones, ni título, ni el panel, ni el cursor. Escape la devuelve. */
.vista.grabando .capa,
.vista.grabando .guia,
.vista.grabando .modos,
.vista.grabando .vista-editor,
.vista.grabando .vista-ayuda,
.vista.grabando .visor-orbe {
  display: none;
}

.vista.grabando .visor-canvas {
  cursor: none;
}

/* ---------- Descripción y comentarios (derecha) ---------- */

.panel-info {
  background: var(--panel-solido);
  border-left: 1px solid var(--borde);
  overflow-y: auto;
  padding: var(--esp-5);
  display: grid;
  align-content: start;
  gap: var(--esp-5);
}

.panel-seccion {
  display: grid;
  gap: var(--esp-3);
  align-content: start;
}

.panel-seccion h2 {
  font-size: 0.95rem;
}

.panel-titulo {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
}

.panel-titulo h2 {
  min-width: 0;
  overflow-wrap: anywhere;
}

.panel-titulo .boton-icono {
  margin-left: auto;
}

.panel-seccion .tag {
  justify-self: start;
}

/* Las descripciones técnicas vienen con viñetas y saltos de línea. */
.descripcion {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.panel-escena {
  border-top: 1px solid var(--borde);
  padding-top: var(--esp-4);
}

.panel-escena h3 {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
  color: var(--texto);
}

.panel-escena h3 .icono {
  width: 16px;
  height: 16px;
  color: var(--texto-3);
}

.comentarios {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--esp-4);
}

.comentario {
  display: grid;
  gap: var(--esp-2);
}

.comentario-cabeza {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
}

.comentario-cabeza strong {
  color: var(--texto);
  font-size: 0.85rem;
  font-weight: var(--peso-semibold);
}

.comentario-texto {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.adjuntos {
  display: flex;
  flex-wrap: wrap;
  gap: var(--esp-2);
}

.adjunto-imagen img {
  width: 96px;
  height: 72px;
  object-fit: cover;
  border-radius: var(--r-tag);
}

.adjunto-doc {
  display: inline-flex;
  align-items: center;
  gap: var(--esp-2);
  max-width: 100%;
  padding: var(--esp-2) var(--esp-3);
  border: 1px solid var(--borde);
  border-radius: var(--r-boton);
  color: var(--texto-2);
  text-decoration: none;
  font-size: var(--t-chico);
}

.adjunto-doc:hover {
  color: var(--texto);
  border-color: rgba(255, 255, 255, 0.24);
}

.adjunto-doc span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.comentario-nuevo {
  display: grid;
  gap: var(--esp-2);
  border-top: 1px solid var(--borde);
  padding-top: var(--esp-4);
}

.comentario-acciones {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
}

.comentario-acciones button[type="submit"] {
  margin-left: auto;
}

/* ---------- Embebido (iframe en otro sitio) ---------- */

.vista.embebido .panel-jerarquia,
.vista.embebido .panel-info,
.vista.embebido .vista-acciones [data-acciones],
.vista.embebido .capa-controles [data-acciones],
.vista.embebido .capa-atras,
.vista.embebido .boton-icono {
  display: none;
}

.vista.embebido .vista-cuerpo {
  grid-template-columns: 1fr;
}

/* ---------- Celular ---------- */

/* Tablet: los paneles se apilan bajo el visor. En teléfono no se apila nada —los paneles
   son capas que se deslizan (css/movil.css)—, así que este rango también arranca en 768. */
@media (min-width: 768px) and (max-width: 1000px) {
  /* El visor de un splat no tiene paneles que apilar: sigue ocupando la ventana. */
  .vista:not(.vista-limpia),
  .vista.pantalla-completa:not(.vista-limpia) {
    height: auto;
    min-height: 100vh;
  }

  .vista-cuerpo {
    grid-template-columns: 1fr;
  }

  /* Apilados no hay canto que tocar: los paneles van siempre abiertos. */
  .panel-tirador {
    display: none;
  }

  .jerarquia-cerrada .panel-jerarquia,
  .info-cerrada .panel-info {
    padding: var(--esp-4) var(--esp-3);
    overflow: visible;
  }

  .editor-panel {
    width: min(280px, calc(100vw - 2 * var(--esp-4)));
  }

  .vista:not(.vista-limpia) .vista-escena {
    height: 60vh;
  }

  .panel-jerarquia {
    border-right: 0;
    border-bottom: 1px solid var(--borde);
  }

  .panel-info {
    border-left: 0;
    border-top: 1px solid var(--borde);
  }

  .vista-barra {
    flex-wrap: wrap;
  }

  .vista-acciones {
    margin-left: 0;
    width: 100%;
  }
}

/* El símbolo de orbitar que se apoya sobre el punto elegido del visor. Va en el DOM y no en
   la escena para verse del mismo tamaño esté el punto cerca o lejos: es un cartel, no un
   objeto. Lo ubica el bucle del visor con un transform; acá solo vive cómo se ve. El aro de
   abajo titila desde componentes/visor.js, que es lo que dice que se puede agarrar. */
.visor-orbe {
  position: absolute;
  top: 0;
  left: 0;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  pointer-events: none;
  color: var(--texto);
  opacity: 0.55;
}

.visor-orbe-icono {
  width: 30px;
  height: 30px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.25; /* el del trazo original de lucide */
  stroke-linecap: round;
  stroke-linejoin: round;
  /* La escena de abajo puede ser clara u oscura: la sombra lo despega de las dos. */
  filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.85));
}

/* Diagnóstico del visor (`?diag=1`, componentes/visor.js): para medir en un teléfono real. */
.visor-diag {
  position: absolute;
  top: var(--esp-2);
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  margin: 0;
  padding: var(--esp-1) var(--esp-2);
  border-radius: var(--r-tag);
  background: var(--panel-solido);
  color: var(--texto);
  font: var(--t-chico) / 1.35 ui-monospace, monospace;
  white-space: pre;
  pointer-events: none;
}

/* ---------- Burbujas y modo editor (componentes/capa-de-burbujas.js) ----------
   Cada burbuja está parada en su punto (el div mide cero y se traslada ahí en cada cuadro) y
   crece hacia arriba y a la derecha. La forma es una "P" de una pieza: el bucle redondo con el
   círculo del número y la imagen, y el canto izquierdo recto que baja hasta el punto. De lejos,
   el nombre al costado con sombra; abierta, la tarjeta en su lugar. */

.burbujas {
  position: absolute;
  inset: 0;
  z-index: 4;
  overflow: hidden;
  pointer-events: none;
}

.vista-aviso:not(.oculto) ~ .burbujas,
.vista-aviso:not(.oculto) ~ .editor-modo {
  display: none;
}

.burbuja {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  transition: opacity 200ms ease;
}

.burbuja.tapada {
  opacity: 0.35;
}

/* La que despliega su tarjeta va encima de las demás: que ninguna tape lo que se lee. */
.burbuja.abierta {
  z-index: 1;
}

/* Con la cámara pegada se va entera, para ver lo que tiene detrás. */
.burbuja.pegada {
  opacity: 0;
  visibility: hidden;
  transition: opacity 200ms ease, visibility 0s linear 200ms;
}

.burbuja-globo {
  position: absolute;
  left: -3px;
  bottom: 0;
  width: 46px;
  height: 62px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  pointer-events: auto;
  filter: drop-shadow(0 5px 10px rgba(0, 0, 0, 0.5));
  transition: transform var(--transicion);
  transform-origin: 3px 100%;
}

.burbuja-globo:hover,
.burbuja.abierta .burbuja-globo {
  transform: scale(1.08);
}

/* El bucle: canto izquierdo recto, el resto redondo. */
.burbuja-globo::before {
  content: "";
  position: absolute;
  inset: 0 0 16px 0;
  border-radius: 4px 23px 23px 4px;
  background: var(--acento);
}

/* El palo de la P, que baja hasta el punto. */
.burbuja-globo::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 8px;
  height: 20px;
  border-radius: 0 0 2px 4px;
  background: var(--acento);
}

.burbuja-ojo {
  position: absolute;
  left: 6px;
  top: 6px;
  z-index: 1;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: 50%;
  background: var(--texto);
  color: var(--acento-fuerte);
}

.burbuja-numero {
  font-family: var(--fuente-marca);
  font-size: 0.95rem;
  font-weight: 800;
}

.burbuja-foto {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
}

/* Con imagen, el círculo pasa del número a la imagen y vuelve, cada 4 s, como un pulso. */
.con-foto .burbuja-numero {
  animation: burbuja-numero 8s ease-in-out infinite;
}

.con-foto .burbuja-foto {
  animation: burbuja-foto 8s ease-in-out infinite;
}

@keyframes burbuja-numero {
  0%, 44%, 100% { opacity: 1; transform: scale(1); }
  50%, 94% { opacity: 0; transform: scale(0.6); }
}

@keyframes burbuja-foto {
  0%, 44%, 100% { opacity: 0; transform: scale(1.15); }
  50%, 94% { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .con-foto .burbuja-numero,
  .con-foto .burbuja-foto {
    animation: none;
  }
  .con-foto .burbuja-numero {
    opacity: 0;
  }
  .con-foto .burbuja-foto {
    opacity: 1;
  }
}

.burbuja-nombre {
  position: absolute;
  left: 50px;
  bottom: 39px;
  transform: translateY(50%);
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: #fff;
  font-family: var(--fuente-marca);
  font-size: 0.9rem;
  font-weight: 700;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9), 0 0 10px rgba(0, 0, 0, 0.6);
  pointer-events: none;
  transition: opacity var(--transicion);
}

.burbuja-tarjeta {
  position: absolute;
  left: 52px;
  bottom: 16px;
  width: min(250px, 60vw);
  display: grid;
  gap: var(--esp-2);
  justify-items: start;
  padding: var(--esp-3);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 16px;
  background: var(--velo-fuerte);
  box-shadow: var(--sombra-flotante);
  color: var(--texto-2);
  opacity: 0;
  visibility: hidden;
  transform: translateX(-8px) scale(0.96);
  transform-origin: 0 100%;
  transition: opacity 200ms ease, transform 200ms ease, visibility 0s linear 200ms;
}

.burbuja.abierta:not(.tapada) .burbuja-tarjeta {
  opacity: 1;
  visibility: visible;
  transform: none;
  pointer-events: auto;
  transition-delay: 0s;
}

.burbuja.abierta:not(.tapada) .burbuja-nombre {
  opacity: 0;
}

/* Con el dedo la tarjeta va encima del punto (70 px: el globo y un poco de aire), centrada y
   corrida lo justo para entrar en la pantalla: `--tarjeta-x` la calcula capa-de-burbujas.js
   (`acomodarTarjeta`). Si arriba no entra, va debajo del punto. */
@media (pointer: coarse) {
  .burbuja-tarjeta {
    left: var(--tarjeta-x, -125px);
    bottom: 70px;
    width: min(250px, calc(100vw - 24px));
    transform: translateY(8px) scale(0.96);
    transform-origin: 50% 100%;
  }

  .burbuja.tarjeta-abajo .burbuja-tarjeta {
    top: 12px;
    bottom: auto;
    transform: translateY(-8px) scale(0.96);
    transform-origin: 50% 0;
  }
}

/* La cruz de la tarjeta, arriba a la derecha, y a su izquierda el tacho (solo el dueño): símbolos
   sin caja de botón. */
.burbuja-simbolo {
  position: absolute;
  top: 6px;
  right: 6px;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--texto-2);
  cursor: pointer;
  transition: background-color var(--transicion), color var(--transicion);
}

.burbuja-quitar {
  right: 32px;
}

.burbuja-simbolo:hover {
  background: rgba(255, 255, 255, 0.12);
  color: var(--texto);
}

.burbuja-simbolo:focus-visible {
  outline: 2px solid var(--celeste);
  outline-offset: 1px;
}

.burbuja-simbolo .icono {
  width: 14px;
  height: 14px;
}

.burbuja-tipo {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: var(--r-pastilla);
  background: var(--acento-suave);
  color: var(--celeste);
  font-family: var(--fuente-marca);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.burbuja-tipo .icono {
  width: 13px;
  height: 13px;
}

.burbuja-titulo {
  color: var(--texto);
  font-family: var(--fuente-marca);
  font-size: 0.95rem;
  overflow-wrap: anywhere;
}

.burbuja-descripcion {
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 0.8rem;
  line-height: 1.4;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* En Editar, el puntero dice que se puede clavar algo. */
.vista-escena.editando .visor-canvas {
  cursor: crosshair;
}

/* El switch Visor / Editar: vertical, a la izquierda, con el estilo del de los modos. */
.editor-modo {
  position: absolute;
  left: var(--borde-visor);
  top: 50%;
  z-index: 6;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--esp-2);
  transform: translateY(-50%);
}

.editor-switch {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 4px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: var(--r-pastilla);
  background: var(--velo);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
}

.editor-switch .modo {
  width: 42px;
  height: 42px;
  padding: 0;
  justify-content: center;
}

.editor-opcion {
  position: relative;
}

/* Lo que hace cada lado: entra con un fundido al pasarle el cursor. */
.editor-ayuda {
  position: absolute;
  z-index: 2; /* encima de "Guardar cambios", que viene después */
  left: calc(100% + var(--esp-3));
  top: 50%;
  width: 200px;
  display: grid;
  justify-items: center;
  gap: 2px;
  padding: var(--esp-2) var(--esp-2) var(--esp-3);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 20px;
  background: var(--velo-fuerte);
  box-shadow: var(--sombra-flotante);
  color: var(--texto-2);
  font-size: 0.74rem;
  text-align: center;
  opacity: 0;
  visibility: hidden;
  transform: translate(-8px, -50%);
  pointer-events: none;
  transition: opacity 240ms ease, transform 240ms ease, visibility 0s linear 240ms;
}

.editor-ayuda strong {
  color: var(--texto);
  font-family: var(--fuente-marca);
  font-size: 0.82rem;
}

.editor-opcion:hover .editor-ayuda,
.editor-opcion:focus-within .editor-ayuda {
  opacity: 1;
  visibility: visible;
  transform: translate(0, -50%);
  transition-delay: 0s;
}

/* El dibujo es uno del tutorial (tutorial.js, `DIBUJOS`): solo se anima mientras se ve. */
.editor-ayuda-dibujo {
  margin-bottom: var(--esp-1);
}

.editor-ayuda-dibujo * {
  animation-play-state: paused;
}

.editor-opcion:hover .editor-ayuda-dibujo *,
.editor-opcion:focus-within .editor-ayuda-dibujo * {
  animation-play-state: running;
}

.editor-guardar-fila {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
}

.editor-guardar {
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
}

/* Mientras hay cambios sin guardar, una flecha blanca señala el botón: va y viene despacio y
   late, para que se note sin gritar. */
.editor-flecha {
  width: 30px;
  height: 16px;
  fill: none;
  stroke: #fff;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.8));
  opacity: 0;
  visibility: hidden;
  transition: opacity 240ms ease, visibility 0s linear 240ms;
}

.editor-modo[data-sin-guardar] .editor-flecha {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
  animation: editor-flecha 1.6s ease-in-out infinite;
}

@keyframes editor-flecha {
  0%,
  100% {
    transform: translateX(8px) scale(1);
    opacity: 0.55;
  }
  50% {
    transform: translateX(0) scale(1.12);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .editor-modo[data-sin-guardar] .editor-flecha {
    animation: none;
  }
}

.editor-pista {
  max-width: 150px;
  color: #fff;
  font-size: 0.74rem;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
}

.editor-modo:not([data-modo="editar"]) .editor-guardar-fila,
.editor-modo:not([data-modo="editar"]) .editor-pista {
  display: none;
}

/* Con el dedo no hay clic derecho ni cursor: se ven las burbujas, pero no se edita. */
@media (pointer: coarse) {
  .editor-modo {
    display: none;
  }
}

/* Volver de un viaje: el botón dice a dónde. */
.capa-atras-viaje {
  width: auto;
  display: inline-flex;
  gap: var(--esp-1);
  padding: 0 var(--esp-4) 0 var(--esp-2);
  border-radius: var(--r-pastilla);
}

.capa-atras-texto {
  max-width: min(42vw, 280px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--fuente-marca);
  font-size: 0.85rem;
  font-weight: 700;
}

/* La ventana de una burbuja (dialogos.js: editarBurbuja): lo de cada tipo se despliega al
   elegirlo. */
.burbuja-formulario[data-tipo="hito"] [data-de="splat"],
.burbuja-formulario[data-tipo="splat"] [data-de="hito"] {
  display: none;
}

.burbuja-extra {
  animation: burbuja-extiende 220ms ease;
}

@keyframes burbuja-extiende {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }
}

.burbuja-imagen {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 120px;
  overflow: hidden;
  border: 1px dashed var(--borde-fuerte);
  border-radius: var(--r-boton);
  color: var(--texto-2);
  cursor: pointer;
  transition: border-color var(--transicion), background-color var(--transicion);
}

.burbuja-imagen:hover,
.burbuja-imagen.encima {
  border-color: var(--celeste);
  background: var(--panel-activo);
}

.burbuja-imagen img {
  width: 100%;
  max-height: 200px;
  object-fit: cover;
}

.burbuja-imagen-texto {
  display: inline-flex;
  align-items: center;
  gap: var(--esp-2);
  padding: var(--esp-3);
  font-size: 0.85rem;
}

.burbuja-imagen img:not([hidden]) + .burbuja-imagen-texto {
  position: absolute;
  bottom: var(--esp-2);
  padding: 4px 10px;
  border-radius: var(--r-pastilla);
  background: var(--velo-fuerte);
  font-size: 0.75rem;
}

.burbuja-splats {
  max-height: 240px;
  margin-top: var(--esp-2);
  overflow-y: auto;
}

.burbuja-splat {
  justify-content: space-between;
}

.burbuja-splat[aria-pressed="true"],
.capa-nodo[aria-current="true"] {
  border-color: var(--acento);
  background: var(--panel-activo);
  color: var(--texto);
}

.burbuja-splat-imagen {
  flex: none;
  width: 64px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: var(--panel);
  object-fit: cover;
}

.burbuja-borrar {
  margin-right: auto;
  color: var(--error);
}

.dialogo-hito {
  max-width: min(900px, 95vw);
}

.hito-imagen {
  width: 100%;
  max-height: 52vh;
  object-fit: contain;
  border-radius: var(--r-boton);
  background: #000;
}

.capa-numero {
  flex: none;
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--acento);
  color: #fff;
  font-family: var(--fuente-marca);
  font-size: 0.72rem;
  font-weight: 800;
}
