/* =============================================================================
 * showroom-v2.css — LA PIEL DEL SHOWROOM. Hoja única. Julio 2026.
 * -----------------------------------------------------------------------------
 * QUÉ ESPERA
 *   · Nada. Es la única hoja de estilo del recorrido: trae su propio reset y no
 *     da por hecho box-sizing, márgenes en cero ni tipografía. No hay base.css
 *     debajo (app.showroom_pelado) y no debe volver a haberlo: si base.css
 *     vuelve, su `line-height:1.55` global engorda cada pastilla 3-5 px y esta
 *     hoja se ve «casi igual» otra vez.
 *   · PELADA: es la ÚNICA hoja propia. Ni base.css ni showroom.css ni
 *     animaciones.css. Lo que se usaba de animaciones.css está absorbido acá
 *     (§1.bis): los `.anim-*` de los hotspots y el posicionamiento de
 *     `.s-portada`. La única hoja de terceros que sigue debajo es la de Photo
 *     Sphere Viewer, porque es parte de la librería que dibuja la esfera.
 *         'hojas' => ['css/showroom-v2.css'],
 *   · Colores del cliente, ya validados en PHP (DISENO §2.2), inyectados como
 *     estilo en línea sobre `.sr`:
 *       --showroom-primary · --showroom-primary-text
 *       --showroom-foreground · --showroom-foreground-text
 *     Si no llegan, los valores de reserva de :root mantienen el contraste.
 *
 * QUÉ GANCHOS CONSERVA (no toca ninguno, sólo los viste)
 *   #sr-boot · #sr-visor · #sr-html · .s-carga[data-carga] y sus partes ·
 *   [data-menu] · data-sr="entrar|hotspot|canal|unidad" + data-canal /
 *   data-codigo / data-hotspot · .sr[data-slug][data-escena] · el formulario de
 *   lead completo · los <script> en línea.
 *
 * QUÉ MOVÍ Y POR QUÉ
 *   · NINGUNA POSICIÓN de control gobernado por el layout se escribe acá.
 *     ui.js aplica ancla+dx+dy+escala como estilo EN LÍNEA y le gana a esta
 *     hoja. Lo que esta hoja define de esos controles es sólo forma, color,
 *     tamaño y tipografía. Las posiciones que el diseño necesita van en
 *     LEEME-LAYOUT.md para guardarlas en projects.layout.
 *   · Sí se posicionan los cinco controles que NO son elemento del layout y que
 *     ui.js/gestos.js fijan por su cuenta: `.s-btn--full`, `.s-btn--volver`,
 *     `.s-flecha`, `.s-pasos-piso` y `.s-btn--filtros`. Están marcados abajo.
 *   · Sin sombras sobre la foto salvo en las placas BLANCAS: sobre render una
 *     tarjeta blanca sin sombra flota sin borde y se lee peor. Los controles
 *     oscuros usan velo + desenfoque + borde de 1 px (DISENO §2.3).
 *   · Área táctil 44×44 en todo control con `::after`, aunque el disco se dibuje
 *     de 34, 38 o 40 px. Nunca se agranda el botón para conseguirla.
 *   · No existe una regla `.sw a { color: X }`. Cada componente declara su
 *     propio color con su propia especificidad, para que ningún enlace genérico
 *     vuelva a pintar el rótulo de un botón del color de su fondo.
 *
 * QUÉ NO SE PUDO DISEÑAR SIN UN DATO QUE NO EXISTE
 *   · La barra 4D y el conmutador vuelo/dentro: hay hueco reservado en la
 *     columna derecha (`.s-futuro`), pero no se dibuja nada.
 *   · El contador de unidades por vista (`.s-piso__cuenta`) sólo aparece si
 *     unidades.js emitió `unidades:pisos`. Sin el módulo, el chip va sin cifra.
 * ========================================================================== */

/* =============================================================================
 * 0. RESET PROPIO
 * ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
}

/* EL RESET VA EN `:where(…)`, Y NO ES UN ADORNO.
   `:where()` pone en CERO la especificidad de lo que envuelve. Sin él,
   `.sr button` y `.sr input` son (0,1,1) —clase + ELEMENTO— y le ganaban a los
   componentes de esta misma hoja, que son (0,1,0): el `background: none;
   border: 0` del reset se imponía sobre el `background: var(--p)` de
   `.s-lead__enviar`, el `#fff` de `.s-btn--primario` y el `border: 1px solid
   var(--fg-borde)` de `.s-input`. En pantalla: campos sin borde ni fondo y
   botones primarios sin color de marca.
   Con `:where()` el reset sigue barriendo el estilo del navegador y cualquier
   componente de la hoja le gana sin un solo `!important`. */
:where(
.sr,
.sr *,
.s-capa-ui,
.s-capa-ui *,
.s-portada,
.s-portada *,
.s-carga,
.s-carga *) {
  margin: 0;
  padding: 0;
  border: 0;
  font: inherit;
  line-height: normal;
  color: inherit;
  background: none;
  -webkit-tap-highlight-color: transparent;
}

:where(
.sr button,
.sr input,
.sr select,
.sr textarea,
.s-capa-ui button,
.s-capa-ui input,
.s-capa-ui select,
.s-capa-ui textarea,
.s-carga button) {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
}

:where(
.sr img,
.s-capa-ui img,
.s-carga img) {
  display: block;
  max-width: 100%;
}

:where(
.sr ul,
.sr ol,
.s-capa-ui ul,
.s-capa-ui ol) {
  list-style: none;
}

/* EL ENLACE «SALTAR AL CONTENIDO» LO DEFINÍA base.css, Y base.css YA NO ESTÁ.
 * Sin esta regla se pinta como texto suelto arriba de todo, encima de la portada
 * y sin velo: es la primera cosa que ve el visitante. Va acá porque la página va
 * pelada y esta hoja es la única que queda. */
.saltar-al-contenido {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 12px 18px;
  border-radius: 0 0 var(--r-md) 0;
  background: var(--p, #14487F);
  color: var(--p-txt, #fff);
  font: 650 14px/1 var(--f);
  text-decoration: none;
}
.saltar-al-contenido:focus,
.saltar-al-contenido:focus-visible { left: 0; }

/* El cuerpo del recorrido: también lo vestía base.css. Sin fondo propio, entre
 * que carga la hoja y monta el visor se ve el blanco del navegador. */
html.s-showroom,
body.cuerpo-showroom {
  margin: 0;
  min-height: 100dvh;
  background: #0B1017;
  overflow-x: hidden;
  font-family: var(--f);
}

.oculto-visual {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* =============================================================================
 * 1. TOKENS
 * ========================================================================== */

:root {
  /* Los cuatro del cliente, con reserva legible si no llegan. */
  --showroom-primary: #14487F;
  --showroom-primary-text: #FFFFFF;
  --showroom-foreground: #FFFFFF;
  --showroom-foreground-text: #12181F;
}

.sr {
  --p:      var(--showroom-primary);
  --p-txt:  var(--showroom-primary-text);
  --fg:     var(--showroom-foreground);
  --fg-txt: var(--showroom-foreground-text);

  --p-hover:  color-mix(in oklab, var(--p) 88%, black);
  --p-press:  color-mix(in oklab, var(--p) 76%, black);
  --p-suave:  color-mix(in oklab, var(--p) 10%, transparent);
  --p-borde:  color-mix(in oklab, var(--p) 38%, transparent);

  --fg-2:      color-mix(in oklab, var(--fg) 96%, var(--fg-txt));
  --fg-3:      color-mix(in oklab, var(--fg) 92%, var(--fg-txt));
  --fg-borde:  color-mix(in oklab, var(--fg) 86%, var(--fg-txt));
  --fg-txt-2:  color-mix(in oklab, var(--fg-txt) 66%, var(--fg));
  --fg-txt-3:  color-mix(in oklab, var(--fg-txt) 44%, var(--fg));

  /* Placa oscura sobre foto. El fallback sube la opacidad cuando no hay blur. */
  --placa:        rgb(12 17 24 / .64);
  --placa-fuerte: rgb(12 17 24 / .72);
  --placa-borde:  rgb(255 255 255 / .17);
  --placa-blur:   saturate(1.45) blur(20px);

  /* La tarjeta del diseño. SE DERIVA DEL FONDO DEL CLIENTE, no es blanco fijo:
   * encima se pinta con `color: var(--fg-txt)`, que es el texto del cliente. Con
   * un proyecto de tema oscuro (fondo #101216, texto #F2F4F7 — el de
   * altos-de-cavancha-3) un blanco fijo daba texto casi blanco sobre tarjeta
   * blanca, y la ficha de escena y el riel de pisos se veían como dos
   * rectángulos vacíos. Derivarla deja el caso claro EXACTAMENTE como estaba
   * (fondo blanco → tarjeta blanca) y arregla el oscuro. */
  --tarjeta:        color-mix(in srgb, var(--fg) 94%, transparent);
  --tarjeta-sombra: 0 12px 34px rgb(6 11 18 / .26);
  --panel-sombra:   0 30px 70px rgb(6 11 18 / .40);

  --velo-abajo: linear-gradient(to top, rgb(0 0 0 / .48) 0%, rgb(0 0 0 / .22) 18%, transparent 34%);
  --velo-arriba: linear-gradient(to bottom, rgb(0 0 0 / .42) 0%, transparent 26%);

  --ok:    #1E8E4C;
  --ok-bg: #E8F5EC;
  --ok-tx: #186B3A;
  --aviso:    #A96A08;
  --aviso-bg: #FCF3E3;
  --error:    #C0392F;
  --error-bg: #FFF3F1;
  --error-tx: #A32A21;

  --f:     ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --f-num: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;

  --e-1: 4px;  --e-2: 8px;  --e-3: 12px; --e-4: 16px;
  --e-5: 24px; --e-6: 32px; --e-7: 48px; --e-8: 64px;

  --r-sm: 8px; --r-md: 12px; --r-lg: 16px; --r-xl: 20px; --r-full: 9999px;

  --ms-inst: 80ms; --ms-rap: 160ms; --ms-nor: 240ms;
  --ease: cubic-bezier(.32, .72, 0, 1);

  /* Margen del borde de la capa. Lo pisa el tramo compacto. */
  --margen: 16px;
  /* Filas apiladas arriba a la izquierda: las escribe ui.js (76/130/184). */
  --s-fila-1: 76px; --s-fila-2: 130px; --s-fila-3: 184px;

  font-family: var(--f);
  color: var(--fg-txt);
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .sr {
    --placa: rgb(12 17 24 / .86);
    --placa-fuerte: rgb(12 17 24 / .9);
    --tarjeta: var(--fg);
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* =============================================================================
 * 1.bis  LO QUE ANTES PONÍA animaciones.css
 * -----------------------------------------------------------------------------
 * Se copia acá para que la página pueda ir pelada. Son las dos únicas cosas de
 * esa hoja que el recorrido necesitaba: la portada tapando el visor, y los
 * estilos de pulso del hotspot que el cliente elige en el panel
 * (animaciones.js escribe `.anim-hot-*` en la raíz).
 * ========================================================================== */

.s-portada,
.s-trans,
.s-error {
  position: absolute;
  inset: 0;
}
.s-portada {
  z-index: 58;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
}

/* =============================================================================
 * 2. CONTENEDOR DEL RECORRIDO
 * ========================================================================== */

.sr {
  position: relative;
  min-height: 100dvh;
  background: #0B1017;
  overflow-x: hidden;
}

#sr-visor,
.s-visor {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: #0B1017;
}

.s-capa-ui {
  position: absolute;
  inset: 0;
  z-index: 40;
  pointer-events: none;
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
  font-family: var(--f);
}

/* Velos permanentes: ningún texto del recorrido se apoya en la foto pelada. */
.s-capa-ui::before,
.s-capa-ui::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  pointer-events: none;
  z-index: -1;
}
.s-capa-ui::before { top: 0; height: 190px; background: var(--velo-arriba); }
.s-capa-ui::after  { bottom: 0; height: 210px; background: var(--velo-abajo); }

/* Con la portada puesta, arriba sólo viven menú, QR y pantalla completa. */
.s-capa-ui[data-portada="1"] { z-index: 59; }
.s-capa-ui[data-portada="1"]::before,
.s-capa-ui[data-portada="1"]::after { display: none; }
.s-capa-ui[data-portada="1"] > *:not(.s-btn--menu):not(.s-btn--qr):not(.s-btn--full):not(.s-menu):not(.s-qr):not(.s-lead):not(.s-avisos) {
  display: none !important;
}

/* Zoom y minimapa: los apaga la marca de la raíz, no el JS (ui.js §gobernarZoom). */
[data-s-zoom="0"] .s-zoom,
[data-s-zoom="0"] .s-minimapa { display: none !important; }

/* =============================================================================
 * 3. FOCO
 * ========================================================================== */

.sr :focus-visible {
  outline: 2px solid var(--p);
  outline-offset: 2px;
  border-radius: inherit;
}
/* Sobre imagen el color del cliente puede desaparecer: doble anillo. */
.s-capa-ui :focus-visible,
.s-portada :focus-visible,
.s-carga :focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
  box-shadow: 0 0 0 5px rgb(0 0 0 / .55);
}

/* =============================================================================
 * 4. BOTONES
 * ========================================================================== */

.s-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  border-radius: var(--r-full);
  font: 650 13px/1 var(--f);
  letter-spacing: .002em;
  cursor: pointer;
  text-decoration: none;
  transition: background var(--ms-inst) var(--ease), transform var(--ms-inst) var(--ease), opacity var(--ms-inst);
  pointer-events: auto;
}

/* Área táctil de 44×44 sin agrandar el dibujo (DISENO §4.2). */
.s-btn::after,
.s-thumb::after,
.s-migas__enlace::after,
.s-dianoche__btn::after,
.s-piso::after,
.s-paso-piso::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  min-width: 44px; min-height: 44px;
  width: 100%; height: 100%;
  transform: translate(-50%, -50%);
  border-radius: inherit;
}

.s-btn:disabled,
.s-btn[aria-disabled="true"] { opacity: .42; cursor: not-allowed; }

.s-btn__texto { white-space: nowrap; }

/* --- flotante: la pastilla oscura sobre la foto ---------------------------- */
.s-btn--flotante {
  min-height: 44px;
  padding: 0 17px;
  color: #fff;
  background: var(--placa);
  border: 1px solid var(--placa-borde);
  -webkit-backdrop-filter: var(--placa-blur);
  backdrop-filter: var(--placa-blur);
}
.s-btn--flotante:hover  { background: var(--placa-fuerte); }
.s-btn--flotante:active { transform: scale(.97); }

/* Sólo icono: círculo de 44. El padding se anula para que no se ovale. */
.s-btn--qr,
.s-btn--full,
.s-btn--volver,
.s-btn--compartir,
.s-btn--filtros {
  width: 44px;
  padding: 0;
}
.s-btn--filtros { width: 48px; min-height: 48px; background: var(--placa-fuerte); }
/* El FAB de filtros va AL LADO del contacto, no encima: encima choca con la
 * barra de vistas, que vive en ese mismo rincón (bottom 78, right 16). Ver el
 * punto 6 de LEEME-LAYOUT.md: es un cambio de una línea en colocarFiltros(). */

/* Los tres que NO son elemento del layout: acá sí se posicionan. */
.s-btn--full   { position: absolute; top: var(--margen); right: var(--margen); z-index: 44; }
.s-btn--volver { position: absolute; top: var(--margen); z-index: 44; }

/* --- primario / secundario ------------------------------------------------- */
.s-btn--primario {
  min-height: 48px;
  padding: 0 26px;
  border-radius: 14px;
  background: #fff;
  color: #12181F;
  font: 700 15px/1 var(--f);
  box-shadow: 0 16px 40px rgb(0 0 0 / .34);
}
.s-btn--primario:hover  { background: #F2F5F8; }
.s-btn--primario:active { transform: translateY(1px); }

.s-btn--secundario {
  min-height: 48px;
  padding: 0 22px;
  border-radius: 14px;
  background: rgb(255 255 255 / .12);
  border: 1px solid rgb(255 255 255 / .32);
  color: #fff;
  font: 650 14.5px/1 var(--f);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}
.s-btn--secundario:hover { background: rgb(255 255 255 / .2); }

/* --- canal de contacto: el círculo verde del diseño ------------------------ */
.s-btn--canal {
  width: 52px; height: 52px;
  min-height: 52px;
  padding: 0;
  background: var(--ok);
  border: 0;
  color: #fff;
  box-shadow: 0 10px 26px rgb(9 80 42 / .42);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.s-btn--canal:hover { background: color-mix(in oklab, var(--ok) 88%, black); }
/* Cuando el canal no es WhatsApp, el disco toma el color de marca. */
.s-btn--canal[aria-label*="mail" i],
.s-btn--canal[href^="mailto"],
.s-btn--canal[href^="tel"] { background: var(--p); color: var(--p-txt); box-shadow: 0 10px 26px rgb(6 11 18 / .34); }

/* El formulario, cuando no hay ningún canal configurado. */
.s-btn--contacto {
  min-height: 52px;
  padding: 0 22px;
  background: var(--p);
  color: var(--p-txt);
  border: 0;
  box-shadow: 0 10px 26px rgb(6 11 18 / .34);
  font: 650 14px/1 var(--f);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

.s-btn--avance { min-height: 44px; padding: 0 16px; font: 650 12.5px/1 var(--f); }

.s-btn--menu { padding: 0 17px; }

/* =============================================================================
 * 5. LOGO DEL CLIENTE EN EL RECORRIDO
 * ========================================================================== */

.s-logo-caja { pointer-events: none; }
.s-logo {
  height: 34px;
  width: auto;
  max-width: 180px;
  object-fit: contain;
  filter: drop-shadow(0 2px 8px rgb(0 0 0 / .45));
}

/* =============================================================================
 * 6. MIGAS
 * ========================================================================== */

.s-migas { pointer-events: auto; }
.s-migas__lista {
  height: 32px;
  padding: 0 14px;
  border-radius: var(--r-full);
  background: var(--placa);
  border: 1px solid var(--placa-borde);
  -webkit-backdrop-filter: var(--placa-blur);
  backdrop-filter: var(--placa-blur);
}
.s-migas__enlace {
  position: relative;
  color: rgb(255 255 255 / .72);
  font: 500 12px/1 var(--f);
  cursor: pointer;
}
.s-migas__enlace:hover { color: #fff; }
.s-migas__sep    { color: rgb(255 255 255 / .42); font: 400 12px/1 var(--f); }
.s-migas__actual { color: #fff; font: 600 12px/1 var(--f); }

/* =============================================================================
 * 7. CONMUTADOR DÍA / NOCHE
 * ========================================================================== */

.s-dianoche {
  height: 44px;
  padding: 5px;
  gap: 2px;
  border-radius: var(--r-full);
  background: rgb(255 255 255 / .9);
  border: 1px solid rgb(255 255 255 / .7);
  box-shadow: 0 6px 20px rgb(6 11 18 / .22);
  -webkit-backdrop-filter: saturate(1.4) blur(20px);
  backdrop-filter: saturate(1.4) blur(20px);
}
.s-dianoche__btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 34px;
  padding: 0 13px;
  border-radius: var(--r-full);
  color: #6B7787;
  font: 500 13px/1 var(--f);
  cursor: pointer;
}
.s-dianoche__btn[aria-pressed="true"] {
  background: #fff;
  color: #12181F;
  font-weight: 600;
  box-shadow: 0 1px 3px rgb(10 16 24 / .18);
}
/* Sin foto nocturna real, el modo noche es un filtro sobre la diurna.
   EL SELECTOR DEL 360 ERA INALCANZABLE y por eso la panorámica nunca se veía de
   noche: `.s-showroom` es la clase del elemento <html>, el mismo que lleva
   `[data-modo-escena]`, así que pedirla como DESCENDIENTE no puede casar jamás
   (medido en vivo: un único `.s-showroom` en todo el documento, y es el <html>).
   Se apunta a la capa del panorama, que es el equivalente exacto de `.s-flat`
   del lado plano y es donde pano.js escribe la misma marca `data-noche="1"`. */
[data-modo-escena="noche"] .s-capa-pano:not([data-noche="1"]) .psv-canvas-container,
[data-modo-escena="noche"] .s-flat:not([data-noche="1"]) {
  filter: brightness(.52) saturate(.78) hue-rotate(-12deg);
}

/* =============================================================================
 * 8. FICHA DE ESCENA
 * ========================================================================== */

.s-info { pointer-events: auto; }

.s-info__caja {
  width: 212px;
  padding: 13px 14px 14px;
  border-radius: var(--r-lg);
  background: var(--tarjeta);
  box-shadow: var(--tarjeta-sombra);
  -webkit-backdrop-filter: saturate(1.4) blur(18px);
  backdrop-filter: saturate(1.4) blur(18px);
  color: var(--fg-txt);
}
.s-info__etiqueta {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 6px;
  font: 600 11px/1 var(--f);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--fg-txt-2);
}
/* Forma además de color: redondo = 360, cuadrado = plana (daltonismo). */
.s-info__punto {
  width: 8px; height: 8px;
  border-radius: 2px;
  background: var(--p);
}
.s-info__punto--360 { border-radius: var(--r-full); }
/* `titulo` sale del nombre del archivo que subió el cliente: puede ser
 * «WhatsApp Image 2026 07 28 at 19.08.22». Se muestra tal cual —corregirlo sería
 * inventar dato— pero se recorta a dos líneas y se parte por donde haga falta,
 * para que no estire la tarjeta ni se salga de la caja. */
.s-info__titulo {
  font: 700 15px/1.25 var(--f);
  color: var(--fg-txt);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}
.s-info__texto  { margin-top: 6px; font: 400 13px/1.45 var(--f); color: var(--fg-txt-2); text-wrap: pretty; }
/* `descripcion` viene vacía en casi todas las escenas: sin esto queda un hueco
 * de 6 px que hace que la tarjeta parezca mal alineada. */
.s-info__texto:empty { display: none; }
/* Título vacío: se dice «Vista sin título» y se dice en gris, para que se lea
 * como lo que es —un dato que falta— y no como el nombre del proyecto. */
.s-info__titulo--sin-titulo,
.s-menu__item--sin-titulo .s-menu__texto,
.sw-escena__enlace--sin-titulo { color: var(--fg-txt-3); font-style: italic; }

/* Tramo compacto: franja de lado a lado en el pie. */
.s-info[data-pres="pie"] { left: var(--margen) !important; right: var(--margen) !important; }
.s-info[data-pres="pie"] .s-info__caja { width: 100%; }
.s-info[data-pres="pie"] .s-info__texto { display: none; }

/* =============================================================================
 * 9. RIEL DE VISTAS / PISOS
 * ========================================================================== */

.s-pisos {
  flex-direction: column;
  gap: 2px;
  padding: 6px;
  width: 212px;
  border-radius: var(--r-lg);
  background: var(--tarjeta);
  box-shadow: var(--tarjeta-sombra);
  -webkit-backdrop-filter: saturate(1.4) blur(18px);
  backdrop-filter: saturate(1.4) blur(18px);
  overflow-y: auto;
}
.s-pisos__titulo {
  margin: 2px 6px 4px;
  font: 600 10.5px/1 var(--f);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--fg-txt-3);
}
.s-piso {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 38px;
  margin-bottom: 2px;
  padding: 8px 10px;
  border-radius: 11px;
  color: var(--fg-txt-2);
  font: 500 13px/1.25 var(--f);
  text-align: left;
  cursor: pointer;
}
.s-piso:hover { background: var(--fg-3); }
.s-piso--activo { background: var(--p-suave); color: var(--fg-txt); font-weight: 650; }
.s-piso__texto  { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* El riel dice el TIPO de cada vista, no un contador: el payload del recorrido
 * no trae recuentos de unidades y no se inventa uno. */
.s-piso__tipo {
  flex: 0 0 auto;
  font: 500 10px/1 var(--f);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--fg-txt-3);
}
.s-piso__cuenta {
  flex: 0 0 auto;
  min-width: 20px; height: 18px;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0 6px;
  border-radius: var(--r-full);
  background: var(--ok-bg);
  color: var(--ok-tx);
  font: 700 11px/1 var(--f-num);
}
.s-piso__cuenta[data-cero="1"] { background: var(--fg-3); color: var(--fg-txt-3); }

/* Móvil y compacto: el riel se acuesta y vive en el pie (dentro del dock, §21). */
@media (max-width: 767px) {
  .s-pisos {
    flex-direction: row;
    width: auto;
    max-width: 100%;
    gap: 6px;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
  }
  .s-pisos::-webkit-scrollbar { display: none; }
  .s-pisos__titulo { display: none; }
  .s-piso { margin-bottom: 0; flex: 0 0 auto; min-height: 34px; }
}

/* FLECHAS ▲▼ DE PISO: RETIRADAS DEL RENDER (29-jul-2026, orden del dueño).
 *
 * Vivían a media altura del borde izquierdo, que es EXACTAMENTE donde ahora van
 * las flechas ‹ › de recorrido (§10). Dos pares de discos con flechas en el
 * mismo sitio, uno encima del otro y con significados distintos —uno cambia de
 * vista, el otro de planta— es el desorden que se pidió arreglar, y es lo que se
 * ve en la captura del dueño.
 *
 * Lo que hacían NO se pierde: el riel de plantas (arriba de este bloque) lista
 * todas las plantas con su nombre a un toque, y las teclas ↑ ↓ siguen subiendo y
 * bajando (ui.js alTeclaPiso mira `pasosPiso.hidden`, que sigue en false, no el
 * display, así que el atajo de teclado sigue vivo).
 *
 * `!important` porque ui.js escribe `display:flex` en línea al mostrarlas.
 * Volver atrás es borrar esta regla y devolverles su posición. */
.s-pasos-piso { display: none !important; }
.s-paso-piso {
  position: relative;
  width: 40px; height: 40px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-full);
  background: var(--placa);
  border: 1px solid var(--placa-borde);
  color: #fff;
  cursor: pointer;
  -webkit-backdrop-filter: var(--placa-blur);
  backdrop-filter: var(--placa-blur);
}
.s-paso-piso:disabled { opacity: .35; cursor: not-allowed; }

/* =============================================================================
 * 10. BARRA DE VISTAS (MINIATURAS) + FLECHAS ‹ ›
 * ========================================================================== */

.s-thumbs-caja {
  flex-direction: row-reverse;   /* el plegable queda pegado al borde derecho */
  gap: 4px;
  padding: 6px;
  /* 250 = columna de zoom + el enlace de avance de la esquina izquierda. */
  max-width: calc(100% - 250px);
  border-radius: var(--r-lg);
  background: var(--placa);
  border: 1px solid var(--placa-borde);
  -webkit-backdrop-filter: var(--placa-blur);
  backdrop-filter: var(--placa-blur);
}
.s-btn--thumbs {
  width: 34px; height: 34px;
  min-height: 34px;
  min-width: 34px;
  padding: 0;
  border: 0;
  background: rgb(255 255 255 / .12);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.s-thumbs { scrollbar-width: none; }
.s-thumbs::-webkit-scrollbar { display: none; }

.s-thumb {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 34px;
  padding: 0 13px 0 4px;
  border-radius: var(--r-full);
  background: rgb(255 255 255 / .1);
  color: #fff;
  font: 500 12.5px/1 var(--f);
  white-space: nowrap;
  cursor: pointer;
}
.s-thumb:hover { background: rgb(255 255 255 / .18); }
.s-thumb--activo { background: #fff; color: #141A21; font-weight: 650; }
.s-thumb img {
  width: 26px; height: 26px;
  border-radius: var(--r-full);
  object-fit: cover;
  display: block;
  background: rgb(255 255 255 / .22);
}
.s-thumb__spinner {
  position: absolute;
  left: 4px; top: 50%;
  width: 26px; height: 26px;
  margin-top: -13px;
  border-radius: var(--r-full);
  background: rgb(255 255 255 / .18);
}
.s-thumb[data-estado="listo"] .s-thumb__spinner { display: none; }
.s-thumb[data-estado="error"] img { display: none; }
.s-thumb__titulo { display: inline; }

/* LAS DOS FLECHAS DE RECORRIDO. Hasta ahora no tenían ni una regla y por eso
 * medían 0x0: se servían y no se veían. Van SIEMPRE, a media altura y pegadas a
 * los bordes; no son elemento del layout, así que la posición sí va acá. */
.s-flecha {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 43;
  width: 44px; height: 44px;
  min-width: 44px; min-height: 44px;
  padding: 0;
  border: 1px solid var(--placa-borde);
  border-radius: var(--r-full);
  background: var(--placa);
  color: #fff;
  box-shadow: 0 10px 30px rgb(4 8 14 / .32);
  transition: background var(--ms-rap) var(--ease), transform var(--ms-rap) var(--ease), opacity var(--ms-rap);
  -webkit-backdrop-filter: var(--placa-blur);
  backdrop-filter: var(--placa-blur);
}
.s-flecha--previa    { left: var(--margen); right: auto; }
.s-flecha--siguiente { right: var(--margen); left: auto; }
.s-flecha:hover      { background: var(--placa-fuerte); transform: translateY(-50%) scale(1.06); }
.s-flecha:active     { transform: translateY(-50%) scale(.96); }
.s-flecha:disabled   { opacity: .3; cursor: not-allowed; }

/* AQUÍ VIVÍA `.s-thumbs-caja .s-flecha`, que las convertía en dos chips de 34 px
 * DENTRO de la barra de vistas, porque ui.js las insertaba ahí. Se retiró junto
 * con esas dos líneas de ui.js (montar(): ahora cuelgan de la capa): dentro de la
 * barra no se podían sacar a los lados desde la hoja, porque la barra lleva
 * `backdrop-filter` y eso la convierte en el bloque contenedor de cualquier hija
 * posicionada. Colgadas de la capa, las dos reglas de arriba bastan.
 *
 * De 768 arriba el disco crece: en escritorio son el único control en el centro
 * de la pantalla y a 44 px se leen como un adorno. */
@media (min-width: 768px) {
  .s-flecha { width: 48px; height: 48px; min-width: 48px; min-height: 48px; }
}

/* LA COLUMNA DERECHA NO PUEDE PISAR LA BANDA DE LA FLECHA ›, y al revés tampoco.
 * Las dos cosas se resuelven MIDIENDO en ui.js, que es donde están las medidas:
 * apilarDerecha() corta el riel de plantas antes del centro y apartarFlechas()
 * corre la flecha hacia dentro si aún así queda algo debajo. Acá no hay número
 * que sirva: el `top` del riel depende del alto de la ficha, que depende del
 * título que escribió el cliente. */

/* =============================================================================
 * 10.bis  IMÁGENES 16:9 — NUNCA SE RECORTAN A LOS LADOS
 * -----------------------------------------------------------------------------
 * Casi todos los renders del cliente son 16:9 y la pantalla casi nunca lo es.
 * `cover` recorta: en un teléfono vertical se come media torre por cada lado.
 * La regla es `100% auto`: el ANCHO siempre entra completo y lo que sobra o
 * falta se resuelve en vertical, con el fondo profundo del recorrido de relleno.
 * Vale para la escena plana, la portada, el hero servido y las fotos servidas.
 * (La panorámica 360 no entra acá: la proyecta Photo Sphere Viewer en su lienzo
 * y ahí no hay recorte que valga.)
 * ========================================================================== */

.s-flat,
.s-portada__fondo,
.sw-hero__fondo,
.s-trans__poster {
  background-size: 100% auto;
  background-position: center center;
  background-repeat: no-repeat;
  background-color: #0B1017;
}
/* El desenfoque de arranque sí llena la caja: es el relleno de las bandas. */
.s-blur { background-size: cover; }

.s-flat img,
.s-trans img,
.s-trans video,
.sw-escena__img,
.sw-escena-card img {
  width: 100%;
  height: auto;
  max-height: 100%;
  object-fit: contain;
  background: #0B1017;
}

/* Con la imagen acostada al centro, los velos de la capa de UI son lo único
 * que separa el texto de la banda oscura: se refuerzan un punto. */
@media (max-aspect-ratio: 16/9) {
  .s-capa-ui::before { height: 210px; }
  .s-capa-ui::after  { height: 230px; }
}

/* =============================================================================
 * 11. HOTSPOTS
 * ========================================================================== */

.s-hot,
.s-hot-360-punto {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 34px;
  padding: 0 15px 0 11px;
  border-radius: var(--r-full);
  background: #fff;
  color: #141A21;
  font: 600 13.5px/1 var(--f);
  white-space: nowrap;
  box-shadow: 0 8px 22px rgb(6 11 18 / .34);
  cursor: pointer;
  transition: transform var(--ms-rap) var(--ease), box-shadow var(--ms-rap) var(--ease);
}
.s-hot::after,
.s-hot-360-punto::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  min-width: 44px; min-height: 44px;
  width: 100%; height: 100%;
  transform: translate(-50%, -50%);
}
.s-hot:hover,
.s-hot-360-punto:hover { transform: scale(1.04); box-shadow: 0 12px 28px rgb(6 11 18 / .42); }

.s-hot__punto,
.s-hot-360-punto > .s-hot__punto {
  position: relative;
  flex: 0 0 auto;
  width: 12px; height: 12px;
  border-radius: var(--r-full);
  background: var(--p);
  border: 2px solid #fff;
}
.s-hot__punto::before {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: var(--r-full);
  background: var(--p);
  opacity: .5;
  animation: s-pulso 2.4s ease-out infinite;
}
@keyframes s-pulso {
  0%   { transform: scale(1);   opacity: .5; }
  70%  { transform: scale(2.6); opacity: 0; }
  100% { transform: scale(2.6); opacity: 0; }
}
/* Estilos que el cliente elige en el panel (animaciones.js escribe .anim-hot-*) */
.anim-hot-fijo   .s-hot__punto::before { animation: none; opacity: 0; }
.anim-hot-latido .s-hot__punto::before { animation: none; opacity: 0; }
.anim-hot-latido .s-hot__punto { animation: s-latido 2.2s ease-in-out infinite; }
@keyframes s-latido { 0%,100% { transform: scale(1); } 50% { transform: scale(1.14); } }

/* `etiqueta` vacía es normal en el payload: entonces el hotspot es sólo el punto
 * (44 de área táctil por el ::after) y el nombre lo da el aria-label. */
.s-hot:not(:has(.s-hot__texto)),
.s-hot-360-punto:not(:has(.s-hot__texto)),
.s-hot--sin-texto {
  width: 34px;
  padding: 0;
  justify-content: center;
}

/* En móvil la etiqueta aparece al primer toque; el segundo navega. */
@media (max-width: 767px) {
  .s-hot__texto,
  .s-hot-360-punto .s-hot__texto { display: none; }
  .s-hot[aria-expanded="true"] .s-hot__texto,
  .s-hot-360-punto[aria-expanded="true"] .s-hot__texto { display: inline; }
  .s-hot:not([aria-expanded="true"]),
  .s-hot-360-punto:not([aria-expanded="true"]) { padding: 0; width: 34px; justify-content: center; }
}

/* =============================================================================
 * 12. ZOOM
 * ========================================================================== */

.s-zoom {
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: auto;
}
.s-zoom button {
  position: relative;
  width: 44px; height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-full);
  background: var(--placa);
  border: 1px solid var(--placa-borde);
  color: #fff;
  cursor: pointer;
  -webkit-backdrop-filter: var(--placa-blur);
  backdrop-filter: var(--placa-blur);
}
.s-zoom button:hover { background: var(--placa-fuerte); }
.s-minimapa {
  border-radius: var(--r-md);
  overflow: hidden;
  border: 1px solid var(--placa-borde);
  box-shadow: 0 8px 22px rgb(6 11 18 / .3);
}

/* =============================================================================
 * 13. MENÚ
 * ========================================================================== */

.s-menu {
  display: flex;
  flex-direction: column;
  width: min(340px, calc(100% - 24px));
  top: 12px; left: 12px; bottom: 12px;
  border-radius: var(--r-xl);
  background: var(--fg);
  color: var(--fg-txt);
  box-shadow: var(--panel-sombra);
  overflow: hidden;
}
.s-menu[data-presentacion="pantalla"] {
  top: 0; left: 0; right: 0; bottom: 0;
  width: 100%;
  border-radius: 0;
  padding-bottom: env(safe-area-inset-bottom);
}
/* El velo detrás del panel. */
.s-menu::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: rgb(9 14 20 / .34);
  -webkit-backdrop-filter: blur(7px);
  backdrop-filter: blur(7px);
}

.s-menu__cabecera {
  position: relative;
  flex: 0 0 auto;
  padding: 26px 22px 16px;
}
.s-menu__cabecera .s-btn--flotante {
  position: absolute;
  top: 18px; right: 18px;
  width: 38px; min-height: 38px;
  padding: 0;
  background: var(--fg);
  border: 1px solid var(--fg-borde);
  color: var(--fg-txt-2);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.s-menu__cabecera .s-btn--flotante:hover { background: var(--fg-3); }

.s-menu__marca { display: block; }
.s-menu__logo {
  height: 52px;
  width: auto;
  max-width: 190px;
  object-fit: contain;
  margin-bottom: 22px;
}
.s-menu__titulo { font: 700 14px/1.3 var(--f); color: var(--fg-txt); margin-bottom: 4px; }
.s-menu__direccion {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  font: 400 11.5px/1.4 var(--f);
  color: var(--fg-txt-2);
}
.s-menu__direccion svg { flex: 0 0 auto; margin-top: 1px; }

.s-menu__lista {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 6px 12px 12px;
}
.s-menu__rama .s-menu__rama { margin: 0; }
.s-menu__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 44px;
  padding: 8px 12px;
  border-radius: 10px;
  color: color-mix(in oklab, var(--fg-txt) 88%, var(--fg));
  font: 500 15px/1.3 var(--f);
  text-align: left;
  cursor: pointer;
}
.s-menu__item:hover { background: var(--fg-3); }
.s-menu__item--activo { background: var(--p-suave); color: var(--fg-txt); font-weight: 650; }
.s-menu__item--activo::before {
  content: "";
  position: absolute;
  left: 0; top: 9px; bottom: 9px;
  width: 3px;
  border-radius: var(--r-full);
  background: var(--p);
}
.s-menu__texto { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.s-menu__tipo {
  flex: 0 0 auto;
  font: 500 10px/1 var(--f);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--fg-txt-3);
}
/* Punto redondo (360) o cuadrado (plana): forma además de color. */
.s-menu__item[data-tipo]::after {
  content: "";
  position: absolute;
  left: 4px; top: 50%;
  width: 5px; height: 5px;
  margin-top: -2.5px;
  border-radius: 1px;
  background: var(--fg-txt-3);
  opacity: 0;
}
.s-menu__item[data-tipo="360"]::after { border-radius: var(--r-full); }

.s-menu__extra { flex: 0 0 auto; padding: 0 12px 12px; }
.s-menu__extra .s-info__caja { width: 100%; box-shadow: none; background: var(--fg-2); }

.s-menu__pie {
  flex: 0 0 auto;
  display: flex;
  gap: 8px;
  padding: 12px;
  border-top: 1px solid var(--fg-3);
  background: var(--fg-2);
}
.s-menu__accion {
  flex: 1 1 120px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-md);
  border: 1px solid var(--fg-borde);
  background: var(--fg);
  color: var(--fg-txt);
  font: 650 13.5px/1 var(--f);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}
.s-menu__accion:hover { background: var(--fg-3); }
.s-menu__accion--primaria {
  background: var(--p);
  border-color: transparent;
  color: var(--p-txt);
}
.s-menu__accion--primaria:hover { background: var(--p-hover); }

/* =============================================================================
 * 14. QR
 * ========================================================================== */

.s-qr { background: rgb(9 14 20 / .5); -webkit-backdrop-filter: blur(7px); backdrop-filter: blur(7px); }
.s-qr__caja {
  position: relative;
  width: min(420px, calc(100% - 32px));
  padding: 24px;
  border-radius: var(--r-xl);
  background: var(--fg);
  color: var(--fg-txt);
  box-shadow: 0 30px 80px rgb(6 11 18 / .45);
  text-align: left;
}
.s-qr__caja .s-btn--flotante {
  position: absolute;
  top: 18px; right: 18px;
  width: 40px; min-height: 40px;
  padding: 0;
  background: var(--fg-3);
  border: 0;
  color: var(--fg-txt-2);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.s-qr__titulo { font: 700 16px/1.3 var(--f); margin-bottom: 4px; padding-right: 52px; }
.s-qr__ayuda  { font: 400 13px/1.5 var(--f); color: var(--fg-txt-2); margin-bottom: 16px; }
.s-qr__caja canvas {
  display: block;
  margin: 0 auto;
  padding: 18px;
  border-radius: 14px;
  background: var(--fg-2);
}
.s-qr__url {
  margin: 14px 0 10px;
  font: 500 12px/1.4 var(--f-num);
  color: var(--fg-txt-2);
  word-break: break-all;
}
.s-qr__copiar {
  width: 100%;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border-radius: var(--r-md);
  border: 1px solid var(--fg-borde);
  background: var(--fg);
  color: var(--fg-txt);
  font: 650 13.5px/1 var(--f);
  cursor: pointer;
}
.s-qr__copiar:hover { background: var(--fg-3); }
.s-qr__error { font: 500 13.5px/1.5 var(--f); color: var(--error-tx); }

/* =============================================================================
 * 15. FORMULARIO DE CONTACTO (lead.js) Y SERVIDO (sw-lead)
 * ========================================================================== */

.s-lead {
  display: flex;
  flex-direction: column;
  width: min(420px, calc(100% - 24px));
  border-radius: var(--r-xl);
  background: var(--fg);
  color: var(--fg-txt);
  box-shadow: var(--panel-sombra);
  overflow: hidden;
}
.s-lead__cabecera {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 22px 22px 14px;
}
.s-lead__titulo { font: 700 19px/1.25 var(--f); }
.s-lead__etiqueta {
  font: 600 10.5px/1 var(--f);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--fg-txt-3);
  margin-bottom: 5px;
}
.s-lead__cuerpo {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 0 22px 22px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.s-lead__pie {
  flex: 0 0 auto;
  display: flex;
  gap: 8px;
  padding: 14px 22px calc(14px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--fg-3);
  background: var(--fg-2);
}

/* Campos: la etiqueta SIEMPRE arriba y visible (DISENO §4.6). */
.s-campo, .sw-campo { display: flex; flex-direction: column; gap: 6px; }
.s-label, .sw-label { font: 600 12.5px/1 var(--f); color: color-mix(in oklab, var(--fg-txt) 82%, var(--fg)); }
.s-input, .sw-input {
  min-height: 44px;
  padding: 0 12px;
  border: 1px solid var(--fg-borde);
  border-radius: var(--r-sm);
  background: var(--fg);
  color: var(--fg-txt);
  font: 400 14px/1.4 var(--f);
}
.s-area, .sw-area { padding: 10px 12px; min-height: 88px; resize: vertical; line-height: 1.5; }
.s-input:focus-visible, .sw-input:focus-visible { border-color: var(--p); }
.s-input[aria-invalid="true"], .sw-input[aria-invalid="true"] { border-color: var(--error); background: var(--error-bg); }
.s-ayuda, .sw-ayuda { font: 400 12px/1.4 var(--f); color: var(--fg-txt-2); }
.s-error-campo, .sw-error-campo {
  display: flex; align-items: center; gap: 6px;
  font: 500 12px/1.4 var(--f);
  color: var(--error-tx);
}
.s-consentimiento, .sw-consentimiento {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px;
  border-radius: 10px;
  background: var(--fg-2);
  font: 400 12.5px/1.5 var(--f);
  color: var(--fg-txt-2);
}
.s-consentimiento input, .sw-consentimiento input { flex: 0 0 auto; width: 18px; height: 18px; margin-top: 1px; accent-color: var(--p); }

/* El campo trampa. No se puede quitar y no se puede mostrar. */
.s-trampa, .sw-trampa {
  position: absolute !important;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

.s-lead__enviar, .sw-enviar {
  flex: 1 1 auto;
  min-height: 48px;
  border-radius: var(--r-md);
  background: var(--p);
  color: var(--p-txt);
  font: 650 14px/1 var(--f);
  cursor: pointer;
}
.s-lead__enviar:hover, .sw-enviar:hover { background: var(--p-hover); }
.s-lead__enviar[aria-busy="true"] { opacity: .7; cursor: progress; }

.s-lead__ok, .sw-lead-ok {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 14px 16px;
  border-radius: var(--r-md);
  background: var(--ok-bg);
  color: var(--ok-tx);
  font: 500 13.5px/1.5 var(--f);
}
.s-lead__error, .sw-lead-error {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 14px 16px;
  border-radius: var(--r-md);
  background: var(--error-bg);
  color: var(--error-tx);
  font: 500 13.5px/1.5 var(--f);
}

/* =============================================================================
 * 16. AVISOS
 * ========================================================================== */

.s-aviso {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 11px 16px;
  border-radius: var(--r-md);
  background: rgb(12 17 24 / .9);
  color: #fff;
  font: 500 13px/1.35 var(--f);
  box-shadow: 0 14px 34px rgb(6 11 18 / .4);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}

/* =============================================================================
 * 17. PANTALLA DE CARGA — tres momentos + error
 * ========================================================================== */

.s-carga {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(120% 90% at 50% 0%, #17222F 0%, #0A0F16 70%);
  color: #fff;
  font-family: var(--f);
}
.s-carga[hidden] { display: none; }
.s-carga--sale { animation: s-carga-sale 420ms var(--ease) forwards; }
@keyframes s-carga-sale { to { opacity: 0; visibility: hidden; } }

.s-carga__bloque {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 26px;
  width: min(340px, calc(100% - 48px));
}
.s-carga__marca-grupo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
.s-carga__marca { height: 40px; width: auto; max-width: 200px; object-fit: contain; }
.s-carga__proyecto { font: 600 14.5px/1.3 var(--f); color: rgb(255 255 255 / .94); text-align: center; }
/* El spinner sólo se ve mientras no hay riel con avance real. */
.s-carga__spinner {
  width: 18px; height: 18px;
  border-radius: var(--r-full);
  border: 2px solid rgb(255 255 255 / .22);
  border-top-color: #fff;
  animation: s-gira .9s linear infinite;
}
@keyframes s-gira { to { transform: rotate(360deg); } }

.s-carga__grupo { width: 100%; display: flex; flex-direction: column; gap: 9px; }
.s-carga__riel {
  position: relative;
  height: 4px;
  border-radius: var(--r-full);
  background: rgb(255 255 255 / .14);
  overflow: hidden;
}
.s-carga__relleno {
  position: absolute;
  inset: 0 auto 0 0;
  border-radius: var(--r-full);
  background: #fff;
  transition: width var(--ms-nor) var(--ease);
}
/* La cola que dice «esto sigue bajando»: se apaga sola al llegar al umbral. */
.s-carga__riel::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: 22%;
  border-radius: var(--r-full);
  background: linear-gradient(90deg, transparent, rgb(255 255 255 / .5), transparent);
  animation: s-cola 1.6s linear infinite;
}
.s-carga--sale .s-carga__riel::after { display: none; }
@keyframes s-cola { 0% { transform: translateX(-110%); } 100% { transform: translateX(360%); } }

.s-carga__fila { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.s-carga__paso { font: 500 12.5px/1.35 var(--f); color: rgb(255 255 255 / .62); }
.s-carga__pct  { font: 700 12.5px/1 var(--f-num); color: #fff; }

/* Momento 2: al 50% se entra SOLO, no hay botón. Lo único que cambia es el
 * texto del paso y la marca de listo; el riel se queda en el porcentaje real
 * (saltar a 100% es mentir sobre lo que hay descargado). */
.s-carga[data-listo="1"] .s-carga__paso {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: #fff;
  font-weight: 600;
}
.s-carga[data-listo="1"] .s-carga__paso::before {
  content: "";
  width: 15px; height: 15px;
  background: currentColor;
  color: #5BD08A;
  -webkit-mask: no-repeat center/15px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7'/%3E%3C/svg%3E");
  mask: no-repeat center/15px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7'/%3E%3C/svg%3E");
}
.s-carga[data-listo="1"] .s-carga__riel::after { display: none; }

.s-carga__pie {
  position: absolute;
  left: 0; right: 0; bottom: calc(18px + env(safe-area-inset-bottom));
  text-align: center;
  font: 400 11.5px/1 var(--f);
  color: rgb(255 255 255 / .4);
}

/* Momento 3: completando en segundo plano. Discreto, no modal. */
.s-carga-fondo {
  position: absolute;
  bottom: calc(18px + env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%);
  z-index: 46;
  display: flex;
  align-items: center;
  gap: 10px;
  height: 34px;
  padding: 0 14px;
  border-radius: var(--r-full);
  background: var(--placa-fuerte);
  border: 1px solid var(--placa-borde);
  color: rgb(255 255 255 / .86);
  font: 500 12px/1 var(--f);
  pointer-events: none;
  -webkit-backdrop-filter: var(--placa-blur);
  backdrop-filter: var(--placa-blur);
}
.s-carga-fondo__spinner {
  width: 14px; height: 14px;
  border-radius: var(--r-full);
  border: 2px solid rgb(255 255 255 / .28);
  border-top-color: #fff;
  animation: s-gira .9s linear infinite;
}

/* Error de carga: hoy no existe y es la pantalla muerta del producto. */
.s-error {
  position: absolute;
  inset: 0;
  z-index: 88;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(120% 90% at 50% 0%, #1E1A20 0%, #0A0F16 70%);
  color: #fff;
  font-family: var(--f);
}
.s-error[hidden] { display: none; }
.s-error__bloque {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  width: min(380px, calc(100% - 48px));
  text-align: center;
}
.s-error__icono {
  width: 46px; height: 46px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-full);
  background: rgb(214 90 74 / .16);
  color: #F09385;
}
.s-error__titulo { font: 700 17px/1.3 var(--f); }
.s-error__texto  { font: 400 13.5px/1.55 var(--f); color: rgb(255 255 255 / .66); text-wrap: pretty; }
.s-error__acciones { display: flex; gap: 8px; width: 100%; }
.s-error__acciones > * {
  flex: 1 1 auto;
  min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-md);
  font: 650 13.5px/1 var(--f);
  cursor: pointer;
  text-decoration: none;
}
.s-error__reintentar { background: #fff; color: #12181F; }
.s-error__salida     { background: transparent; border: 1px solid rgb(255 255 255 / .22); color: #fff; }

/* =============================================================================
 * 18. PORTADA
 * ========================================================================== */

.s-portada { background: #0B1017; }   /* posición: §1.bis */
.s-portada__fondo,
.s-blur {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
}
.s-blur { filter: blur(24px); transform: scale(1.06); transition: opacity 600ms var(--ease); }
.s-blur--fuera { opacity: 0; }
.s-portada::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to top, rgb(4 8 14 / .84) 0%, rgb(4 8 14 / .36) 34%, transparent 62%),
    linear-gradient(to bottom, rgb(0 0 0 / .34), transparent 22%);
}
.s-portada > *:not(.s-portada__fondo):not(.s-blur) { z-index: 1; }
.s-portada--sale { animation: s-portada-sale 520ms var(--ease) forwards; }
@keyframes s-portada-sale { to { opacity: 0; transform: scale(1.03); visibility: hidden; } }

.s-portada__logo { height: 46px; width: auto; max-width: 220px; object-fit: contain; }
.s-portada__titular { max-width: min(46ch, calc(100% - 96px)); }
.s-portada__titulo {
  font: 700 clamp(2rem, 1.2rem + 3.4vw, 3rem)/1.05 var(--f);
  letter-spacing: -.025em;
  color: #fff;
  text-shadow: 0 2px 14px rgb(0 0 0 / .35);
  margin-bottom: 8px;
}
.s-portada__sub {
  font: 400 clamp(.95rem, .85rem + .4vw, 1.0625rem)/1.5 var(--f);
  color: rgb(255 255 255 / .88);
  text-shadow: 0 1px 8px rgb(0 0 0 / .4);
  text-wrap: pretty;
}

/* =============================================================================
 * 19. TRANSICIÓN ENTRE ESCENAS (video / fotos) + BOTÓN SALTAR
 * ========================================================================== */

.s-trans {
  position: absolute;
  inset: 0;
  z-index: 57;
  background: #05080D;
}
.s-trans video,
.s-trans img { width: 100%; height: 100%; object-fit: cover; display: block; }
.s-trans__pie {
  position: absolute;
  left: var(--margen); right: var(--margen);
  bottom: calc(var(--margen) + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.s-trans__riel {
  position: relative;
  height: 3px;
  border-radius: var(--r-full);
  background: rgb(255 255 255 / .18);
  overflow: hidden;
}
.s-trans__relleno { position: absolute; inset: 0 auto 0 0; border-radius: var(--r-full); background: #fff; }
.s-trans__saltar {
  align-self: flex-end;
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px;
  padding: 0 18px;
  border-radius: var(--r-full);
  background: var(--placa-fuerte);
  border: 1px solid rgb(255 255 255 / .24);
  color: #fff;
  font: 650 13px/1 var(--f);
  cursor: pointer;
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
}
.s-trans__destino {
  position: absolute;
  top: calc(var(--margen) + env(safe-area-inset-top));
  left: var(--margen);
  font: 600 11px/1 var(--f);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgb(255 255 255 / .5);
}

/* =============================================================================
 * 20. FICHA DE UNIDAD (unidades.js) Y PINES SOBRE PLANO
 * ========================================================================== */

.s-unidad {
  display: flex;
  flex-direction: column;
  width: min(420px, calc(100% - 24px));
  border-radius: var(--r-xl);
  background: var(--fg);
  color: var(--fg-txt);
  box-shadow: var(--panel-sombra);
  overflow: hidden;
}
@media (max-width: 767px) {
  .s-unidad {
    width: 100%;
    height: 88dvh;
    border-radius: 22px 22px 0 0;
    box-shadow: 0 -18px 50px rgb(6 11 18 / .4);
  }
  .s-unidad::before {
    content: "";
    width: 38px; height: 4px;
    margin: 10px auto 4px;
    border-radius: var(--r-full);
    background: var(--fg-borde);
  }
}
.s-unidad__codigo { font: 700 24px/1.1 var(--f); letter-spacing: -.01em; }
.s-unidad__precio { font: 700 21px/1.1 var(--f-num); }
.s-unidad__datos {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--fg-3);
  border: 1px solid var(--fg-3);
  border-radius: var(--r-md);
  overflow: hidden;
}
.s-unidad__dato { padding: 11px 13px; background: var(--fg); }
.s-unidad__dato dt {
  font: 500 11px/1 var(--f);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--fg-txt-3);
  margin-bottom: 2px;
}
.s-unidad__dato dd { font: 600 14px/1.2 var(--f-num); color: var(--fg-txt); }
.s-unidad__plano { width: 100%; border-radius: var(--r-md); background: var(--fg-2); }

/* Estado: color MÁS forma MÁS texto. Nunca sólo color. */
.s-estado {
  display: inline-flex; align-items: center; gap: 7px;
  height: 26px; padding: 0 11px;
  border-radius: var(--r-full);
  font: 600 12px/1 var(--f);
}
.s-estado__punto { width: 9px; height: 9px; border-radius: var(--r-full); }
.s-estado--disponible { background: var(--ok-bg); color: var(--ok-tx); }
.s-estado--disponible .s-estado__punto { background: var(--ok); }
.s-estado--reservada { background: var(--aviso-bg); color: var(--aviso); }
.s-estado--reservada .s-estado__punto { background: transparent; border: 2px dotted var(--aviso); }
.s-estado--vendida { background: var(--error-bg); color: var(--error-tx); }
.s-estado--vendida .s-estado__punto {
  background: var(--error);
  background-image: linear-gradient(45deg, transparent 44%, #fff 44%, #fff 56%, transparent 56%);
}
.s-estado--proximamente { background: var(--fg-3); color: var(--fg-txt-2); }
.s-estado--proximamente .s-estado__punto { background: transparent; border: 2px solid var(--fg-txt-3); }

.s-pin {
  position: absolute;
  display: inline-flex; align-items: center;
  height: 26px; padding: 0 10px;
  border-radius: var(--r-full);
  background: var(--fg);
  color: var(--fg-txt);
  font: 700 12px/1 var(--f-num);
  box-shadow: 0 6px 16px rgb(6 11 18 / .3);
  border: 2px solid var(--ok);
  cursor: pointer;
  transition: transform var(--ms-rap) var(--ease);
}
.s-pin:hover { transform: scale(1.15); z-index: 2; }
.s-pin[aria-pressed="true"] { box-shadow: 0 0 0 3px var(--p-borde), 0 6px 16px rgb(6 11 18 / .3); }
.s-pin--reservada { border-color: var(--aviso); border-style: dashed; }
.s-pin--vendida   { border-color: var(--error); opacity: .72; }

/* Hueco reservado para lo que viene (4D, vuelo 3D). No dibuja nada hoy. */
.s-futuro { display: none; }

/* =============================================================================
 * 21. TRAMOS  (los mismos cuatro del layout: desktop / tablet / móvil / compacto)
 * -----------------------------------------------------------------------------
 * Regla del tramo compacto: QUITAR, NO ENCOGER. La letra no baja de 13 px y los
 * controles no bajan de 44 px de área táctil; lo que se va, se va al menú.
 * Qué desaparece en compacto (<380 px) y hay que apagar en el layout:
 *   dia_noche · qr · breadcrumbs · zoom · compartir · boton_avance
 * Todos siguen alcanzables desde el menú, que en ese tramo va a pantalla completa.
 * ========================================================================== */

/* tablet */
@media (max-width: 1023px) {
  .s-thumbs-caja { max-width: calc(100% - 180px); }
  .s-info__caja  { width: 196px; }
  .s-pisos       { width: 196px; }
  .s-menu        { width: min(320px, calc(100% - 24px)); }
}

/* =============================================================================
 * 21.MOVIL  EL TELÉFONO: LA CAPA ES UNA REJILLA, NO UN MONTÓN DE FLOTANTES
 * -----------------------------------------------------------------------------
 * Este es el cambio de fondo del 29-jul-2026 («la versión móvil hay que pulirla
 * al máximo: que no se vea desordenado, que nada se sobreponga, que esté bien
 * estructuralmente»).
 *
 * ANTES: los diez controles del recorrido eran diez cajas `position:absolute`
 * colocadas por JS, y en 375 px no caben. ui.js las apilaba a mano midiendo
 * rectángulos (apilarAbajo, apilarFilas, filaIzquierda, apartarFull,
 * colocarFiltros, colocarMinimapa): cada control que aparecía o desaparecía —un
 * contador de unidades, un canal de contacto, un título de dos líneas— movía a
 * todos los demás, y cualquier medida que llegara un frame tarde dejaba dos
 * pastillas encima. Eso no se arregla con más medidas: se arregla quitando el
 * posicionamiento absoluto.
 *
 * AHORA: `.s-capa-ui` es una REJILLA de 5 columnas × 8 filas y cada control tiene
 * su celda. Una rejilla NO PUEDE SOLAPAR: si un control crece, crece su fila; si
 * se apaga, su fila se cierra sola. Los `position:static !important` son los que
 * le quitan la palabra al JS —ui.js sigue escribiendo top/left/bottom en línea y
 * con `static` esos valores no significan nada—, así que esto funciona SIN tocar
 * ui.js y sin desactivar ninguno de sus apilados.
 *
 *   fila 1   menú · volver ·                        · QR · pantalla completa
 *   fila 2   logo del cliente                     · conmutador día/noche
 *   fila 3   migas
 *   fila 4   avisos          (0 px de alto mientras no hay ninguno)
 *   fila 5   LA IMAGEN       (1fr: todo lo que sobra)
 *   fila 6   ficha de la vista, de lado a lado
 *   fila 7   riel de plantas, horizontal y con scroll
 *   fila 8   barra de vistas · filtros · contacto
 *
 * Fuera de la rejilla a propósito: los tres diálogos (menú, QR, formulario) y las
 * flechas ‹ ›, que se dibujan ENCIMA y siguen absolutos.
 * ========================================================================== */
@media (max-width: 767px) {
  .sr { --margen: 12px; }

  .s-capa-ui {
    display: grid;
    /* SEIS COLUMNAS, y las tres últimas son fijas a propósito:
     *   1  el menú           2  volver          3  el hueco (1fr)
     *   4  el FAB de filtros  5  QR             6  pantalla completa / contacto
     * Las columnas `auto` las ENSANCHA cualquier elemento que las cruce, y eso es
     * lo que separaba el QR del botón de pantalla completa (el conmutador
     * día/noche cruzaba las dos últimas y las dejaba de 82 px) y lo que dejaba a
     * pantalla completa a 40 px del borde. Con las dos últimas clavadas en 44 y
     * todo lo ancho cruzando la columna FLEXIBLE, los dos botones quedan pegados
     * entre sí y pegados al borde derecho, siempre. */
    grid-template-columns: auto auto minmax(0, 1fr) auto 44px 44px;
    grid-template-rows: auto auto auto auto minmax(0, 1fr) auto auto auto;
    align-items: center;
    justify-items: stretch;
    gap: 8px;
    /* prepararContenedor() escribe el padding EN LÍNEA (solo el safe-area) y un
     * estilo en línea gana: hay que repetirlo para sumarle el margen del diseño. */
    padding-top:    calc(env(safe-area-inset-top, 0px) + var(--margen)) !important;
    padding-right:  calc(env(safe-area-inset-right, 0px) + var(--margen)) !important;
    padding-bottom: calc(env(safe-area-inset-bottom, 0px) + var(--margen)) !important;
    padding-left:   calc(env(safe-area-inset-left, 0px) + var(--margen)) !important;
  }
  /* Los velos crecen: el de abajo tiene que cubrir el dock completo. */
  .s-capa-ui::before { height: 170px; }
  .s-capa-ui::after  { height: 290px; }

  /* -- entrar en la rejilla: se le quita la palabra al JS ------------------- */
  .s-capa-ui > .s-btn--menu,
  .s-capa-ui > .s-btn--volver,
  .s-capa-ui > .s-btn--compartir,
  .s-capa-ui > .s-btn--qr,
  .s-capa-ui > .s-btn--full,
  .s-capa-ui > .s-btn--filtros,
  .s-capa-ui > .s-logo-caja,
  .s-capa-ui > .s-dianoche,
  .s-capa-ui > .s-migas,
  .s-capa-ui > .s-avisos,
  .s-capa-ui > .s-avance-flotante,
  .s-capa-ui > .s-info,
  .s-capa-ui > .s-pisos,
  .s-capa-ui > .s-thumbs-caja,
  .s-capa-ui > .s-contacto {
    position: static !important;
    inset: auto !important;
    margin: 0 !important;
    max-width: 100%;
  }

  /* -- una celda por control ----------------------------------------------- */
  .s-capa-ui > .s-btn--menu      { grid-area: 1 / 1 / 2 / 2; justify-self: start; }
  .s-capa-ui > .s-btn--volver    { grid-area: 1 / 2 / 2 / 3; justify-self: start; }
  .s-capa-ui > .s-btn--compartir { grid-area: 1 / 3 / 2 / 4; justify-self: end; }
  .s-capa-ui > .s-btn--qr        { grid-area: 1 / 5 / 2 / 6; justify-self: end; }
  .s-capa-ui > .s-btn--full      { grid-area: 1 / 6 / 2 / 7; justify-self: end; }
  .s-capa-ui > .s-logo-caja      { grid-area: 2 / 1 / 3 / 4; justify-self: start; }
  .s-capa-ui > .s-dianoche       { grid-area: 2 / 3 / 3 / 7; justify-self: end; }
  .s-capa-ui > .s-migas          { grid-area: 3 / 1 / 4 / 7; justify-self: start; }
  .s-capa-ui > .s-avisos         { grid-area: 4 / 1 / 5 / 7; }
  /* El enlace al avance de obra viaja en la esquina libre, no en el dock. */
  .s-capa-ui > .s-avance-flotante { grid-area: 5 / 1 / 6 / 4; justify-self: start; align-self: end; }
  .s-capa-ui > .s-info           { grid-area: 6 / 1 / 7 / 7; }
  .s-capa-ui > .s-pisos          { grid-area: 7 / 1 / 8 / 7; }
  .s-capa-ui > .s-thumbs-caja    { grid-area: 8 / 1 / 9 / 4; align-self: end; min-width: 0; }
  .s-capa-ui > .s-btn--filtros   { grid-area: 8 / 4 / 9 / 5; align-self: end; }
  .s-capa-ui > .s-contacto       { grid-area: 8 / 5 / 9 / 7; align-self: end; justify-self: end; }

  /* -- EL DOCK ES UNA SOLA FAMILIA: VIDRIO OSCURO --------------------------
   * La ficha y el riel venían en tarjeta BLANCA y la barra de vistas en placa
   * OSCURA: tres pastillas pegadas en el pie con dos lenguajes distintos, que es
   * la mitad de la sensación de «desordenado». Sobre la imagen manda el oscuro
   * (DISENO §2.3), que es el que no se pelea con el render. */
  .s-info[data-pres="pie"] .s-info__caja,
  .s-pisos {
    background: var(--placa);
    border: 1px solid var(--placa-borde);
    box-shadow: none;
    color: #fff;
    -webkit-backdrop-filter: var(--placa-blur);
    backdrop-filter: var(--placa-blur);
  }

  /* La ficha del pie es UNA LÍNEA: tipo de vista + nombre, con puntos suspensivos.
   * De dos líneas se comía 34 px de imagen para repetir un dato que ya está en el
   * menú y en la barra de vistas. */
  .s-info[data-pres="pie"] .s-info__caja {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 10px;
    min-height: 46px;
    padding: 7px 14px;
    border-radius: var(--r-md);
  }
  .s-info[data-pres="pie"] .s-info__etiqueta {
    flex: 0 1 auto;
    min-width: 0;
    margin: 0;
    overflow: hidden;
    white-space: nowrap;
    color: rgb(255 255 255 / .6);
  }
  .s-info[data-pres="pie"] .s-info__titulo {
    flex: 1 1 auto;
    min-width: 0;
    display: block;
    font: 650 14px/1.25 var(--f);
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .s-info[data-pres="pie"] .s-variantes { flex: 0 0 auto; }

  /* Chips de planta sobre el vidrio oscuro. */
  .s-piso { color: rgb(255 255 255 / .78); font-size: 12.5px; padding: 8px 12px; }
  .s-piso:hover { background: rgb(255 255 255 / .12); }
  .s-piso--activo { background: #fff; color: #141A21; }
  .s-piso__tipo { color: rgb(255 255 255 / .5); }
  .s-piso--activo .s-piso__tipo { color: rgb(20 26 33 / .55); }

  /* -- el resto del tramo --------------------------------------------------- */
  .s-btn--flotante { padding: 0 14px; font-size: 13px; }
  .s-btn--menu     { padding: 0 14px; }
  .s-thumbs-caja   { padding: 5px; }
  .s-menu__logo    { height: 44px; max-width: 158px; margin-bottom: 18px; }
  .s-menu__item    { font-size: 15px; min-height: 46px; }
  .s-minimapa      { display: none !important; }
  .s-lead          { top: auto !important; height: 88dvh; border-radius: 22px 22px 0 0; width: 100%; left: 0 !important; right: 0 !important; bottom: 0 !important; }
  .s-avisos        { justify-items: stretch; }
  .s-logo { height: 28px; max-width: 132px; }

  /* DOS PASTILLAS QUE NO SON DE ESTA CAPA Y CAÍAN ENCIMA DEL DOCK.
   * `.s-carga-fondo` cuelga de la raíz del visor (§17) y `.su-barra` la monta
   * unidades.js, las dos ancladas al pie: con el dock puesto se sobreponían a la
   * ficha y al riel. Se levantan por encima del dock. Los números son la altura
   * del dock lleno (12 + 52 + 8 + 46 + 8 + 46); si algún control está apagado,
   * flotan un poco más alto, que es inofensivo —lo que no puede pasar es que
   * tapen un control. */
  .s-carga-fondo { bottom: calc(env(safe-area-inset-bottom, 0px) + 194px) !important; }
  .su-barra { bottom: calc(env(safe-area-inset-bottom, 0px) + 240px) !important; }
}

/* compacto */
/* compacto: la fila superior se queda en iconos y el título de la vista manda.
 * `qr`, `dia_noche` y `breadcrumbs` los apaga el layout en este tramo, así que
 * sus filas de la rejilla se cierran solas. */
@media (max-width: 379px) {
  .s-btn--menu .s-btn__texto { display: none; }
  .s-btn--menu { width: 44px; padding: 0; }
  .s-thumb__titulo { display: none; }
  .s-thumb { padding: 4px; }
  .s-carga__bloque { width: calc(100% - 32px); }
  .s-capa-ui { gap: 6px; }
  .s-info[data-pres="pie"] .s-info__etiqueta { display: none; }
}

/* Celular acostado: sólo menú, volver y hotspots (DISENO §6). */
@media (max-height: 479px) and (orientation: landscape) {
  .s-thumbs-caja,
  .s-pisos,
  .s-info,
  .s-migas,
  .s-dianoche,
  .s-zoom,
  .s-logo-caja,
  .s-avance-flotante { display: none !important; }
  /* Con el dock apagado, las dos pastillas ajenas vuelven al pie. */
  .s-carga-fondo { bottom: calc(env(safe-area-inset-bottom, 0px) + 14px) !important; }
  .su-barra { bottom: calc(env(safe-area-inset-bottom, 0px) + 14px) !important; }
}

/* =============================================================================
 * 21.bis  ESTADOS QUE PONE EL JS Y PINTA ESTA HOJA
 * -----------------------------------------------------------------------------
 * El trato: el JS cambia UN atributo, la hoja hace el resto. Ninguno de estos
 * estados necesita que el JS toque un color, un tamaño ni un tiempo.
 *
 *   .s-carga[data-listo="1"]   →  §17, momento «ya puedes entrar» (entra solo)
 *   .s-carga-fondo             →  §17, la píldora discreta del pie
 *   .s-error[hidden] fuera     →  §17, error de carga
 *   .s-trans + __saltar        →  §19, transición A→B
 *   [aria-expanded] en hotspot →  §11, etiqueta abierta al primer toque
 *   #cabecera[data-abierto=1]  →  acá abajo, menú servido abierto
 *   [data-oculto="1"] en pista →  acá abajo, la pista de arrastre se va
 * ========================================================================== */

/* --- menú servido (capa A) ------------------------------------------------- */
.sw-menu-btn {
  position: absolute;
  top: calc(var(--margen) + env(safe-area-inset-top));
  left: calc(var(--margen) + env(safe-area-inset-left));
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 44px;
  padding: 0 17px;
  border-radius: var(--r-full);
  background: var(--placa);
  border: 1px solid var(--placa-borde);
  color: #fff;
  font: 650 13px/1 var(--f);
  cursor: pointer;
  -webkit-backdrop-filter: var(--placa-blur);
  backdrop-filter: var(--placa-blur);
}
.sw-menu-btn:hover { background: var(--placa-fuerte); }

/* Cerrado, el índice de escenas es una sección más del documento. Abierto, se
 * convierte en panel: lateral en escritorio, pantalla completa en compacto. */
#cabecera[data-abierto="1"] ~ .sw-doc #sw-escenas {
  position: fixed;
  top: 12px; left: 12px; bottom: 12px;
  z-index: 70;
  width: min(340px, calc(100% - 24px));
  margin: 0;
  padding: 22px 12px 12px;
  border-radius: var(--r-xl);
  background: var(--fg);
  box-shadow: var(--panel-sombra);
  overflow-y: auto;
}
#cabecera[data-abierto="1"] ~ .sw-doc #sw-escenas::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: rgb(9 14 20 / .34);
  -webkit-backdrop-filter: blur(7px);
  backdrop-filter: blur(7px);
}
#cabecera[data-abierto="1"] ~ .sw-doc #sw-escenas .sw-rejilla { grid-template-columns: 1fr; gap: 2px; }
#cabecera[data-abierto="1"] ~ .sw-doc #sw-escenas .sw-escena { border: 0; padding: 10px 12px; border-radius: 10px; }
#cabecera[data-abierto="1"] ~ .sw-doc #sw-escenas .sw-escena:hover { background: var(--fg-3); }
@media (max-width: 379px) {
  #cabecera[data-abierto="1"] ~ .sw-doc #sw-escenas {
    top: 0; left: 0; right: 0; bottom: 0;
    width: 100%;
    border-radius: 0;
    padding-bottom: calc(12px + env(safe-area-inset-bottom));
  }
}

/* --- pista de arrastre ----------------------------------------------------- */
/* Aparece con la escena 360 y se va cuando el visitante mueve la cámara: el JS
 * sólo pone data-oculto="1", la salida es de acá. */
.sw-pista,
.s-pista {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 34px;
  padding: 0 14px;
  border-radius: var(--r-full);
  background: var(--placa);
  border: 1px solid var(--placa-borde);
  color: rgb(255 255 255 / .9);
  font: 500 12.5px/1 var(--f);
  pointer-events: none;
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--ms-nor) var(--ease), transform var(--ms-nor) var(--ease);
  -webkit-backdrop-filter: var(--placa-blur);
  backdrop-filter: var(--placa-blur);
}
.sw-pista[data-oculto="1"],
.s-pista[data-oculto="1"] { opacity: 0; transform: translateY(6px); }
.sw-pista__icono { display: inline-flex; opacity: .75; animation: s-arrastra 2.4s ease-in-out infinite; }
@keyframes s-arrastra { 0%,100% { transform: translateX(-2px); } 50% { transform: translateX(2px); } }

/* =============================================================================
 * 22. CAPA A — EL DOCUMENTO SERVIDO (sw-*)
 * -----------------------------------------------------------------------------
 * Es lo que ven el buscador, un lector de pantalla y quien tenga el JS caído.
 * El visor lo oculta al montar (#sr-html), así que nunca compite con la capa B.
 * NO hay una regla `.sw a { color: X }`: cada pieza declara el suyo.
 * ========================================================================== */

.sw {
  font-family: var(--f);
  color: var(--fg-txt);
  background: var(--fg);
}
.sw-doc { max-width: 980px; margin: 0 auto; padding: 0 var(--e-5) var(--e-8); }
.sw-doc--pagina { padding-top: var(--e-6); }

.sw-hero { position: relative; min-height: 62dvh; display: flex; align-items: flex-end; overflow: hidden; background: #0B1017; }
.sw-hero__fondo { position: absolute; inset: 0; background-size: cover; background-position: center; }
.sw-hero::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgb(4 8 14 / .88), rgb(4 8 14 / .2) 52%, transparent);
}
.sw-hero__caja { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 14px; align-items: flex-start; padding: var(--e-6) var(--e-5) var(--e-5); max-width: 980px; margin: 0 auto; width: 100%; }
.sw-hero__logo { height: 34px; width: auto; max-width: 180px; object-fit: contain; }
.sw-titulo { font: 700 clamp(1.7rem, 1.2rem + 2vw, 2.25rem)/1.1 var(--f); letter-spacing: -.02em; color: #fff; }
.sw-titulo--pagina { color: var(--fg-txt); }
.sw-sub { font: 400 15px/1.5 var(--f); color: rgb(255 255 255 / .86); max-width: 56ch; }
.sw-etiqueta { font: 600 10.5px/1 var(--f); letter-spacing: .12em; text-transform: uppercase; color: var(--fg-txt-3); }
.sw-h2 { font: 700 17px/1.3 var(--f); color: var(--fg-txt); }
.sw-h2--titulo { overflow-wrap: anywhere; }
.sw-escena__img { border-radius: 14px; }
.sw-escena__enlace { overflow-wrap: anywhere; }
.sw-p  { font: 400 14px/1.6 var(--f); color: var(--fg-txt-2); text-wrap: pretty; }
.sw-nota { font: 400 12.5px/1.5 var(--f); color: var(--fg-txt-3); }
.sw-sec { display: flex; flex-direction: column; gap: var(--e-3); padding-top: var(--e-6); }
.sw-sec__cab { display: flex; align-items: baseline; justify-content: space-between; gap: var(--e-3); flex-wrap: wrap; }

/* Botones servidos: cada uno con su color propio y su propia especificidad. */
.sw-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 48px; padding: 0 24px;
  border-radius: var(--r-md);
  font: 650 14.5px/1 var(--f);
  text-decoration: none;
  cursor: pointer;
}
.sw-btn--primario { background: var(--p); color: var(--p-txt); border: 0; }
.sw-btn--primario:hover { background: var(--p-hover); color: var(--p-txt); text-decoration: none; }
.sw-btn--claro { background: #fff; color: #12181F; border: 0; }
.sw-btn--claro:hover { background: #F2F5F8; color: #12181F; text-decoration: none; }
.sw-btn--vidrio {
  background: rgb(255 255 255 / .12);
  border: 1px solid rgb(255 255 255 / .32);
  color: #fff;
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}
.sw-btn--vidrio:hover { background: rgb(255 255 255 / .2); color: #fff; text-decoration: none; }
.sw-btn--secundario { background: var(--fg); border: 1px solid var(--fg-borde); color: var(--fg-txt); }
.sw-btn--secundario:hover { background: var(--fg-3); color: var(--fg-txt); text-decoration: none; }

.sw-rejilla { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--e-3); }
.sw-tarjeta {
  display: flex; flex-direction: column; gap: 5px;
  padding: 16px 18px;
  border: 1px solid var(--fg-borde);
  border-radius: 14px;
  text-decoration: none;
  color: var(--fg-txt);
}
.sw-tarjeta:hover { background: var(--fg-2); text-decoration: none; color: var(--fg-txt); }
.sw-tarjeta__titulo { font: 700 15px/1.3 var(--f); color: var(--fg-txt); }
.sw-tarjeta__pie    { font: 400 13px/1.5 var(--f); color: var(--fg-txt-2); }

.sw-escena { padding: 13px 14px; border: 1px solid var(--fg-borde); border-radius: var(--r-md); }
.sw-escena__tipo { font: 600 10.5px/1 var(--f); letter-spacing: .1em; text-transform: uppercase; color: var(--fg-txt-3); margin-bottom: 3px; }
.sw-escena__enlace { font: 600 14.5px/1.3 var(--f); color: var(--p); text-decoration: none; }
.sw-escena__enlace:hover { text-decoration: underline; color: var(--p-hover); }

.sw-lead { padding: 20px; border-radius: 14px; background: var(--fg-2); display: flex; flex-direction: column; gap: 12px; }
.sw-lead__campos { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; }

.sw-vacio { padding: var(--e-7) var(--e-5); text-align: center; display: flex; flex-direction: column; gap: var(--e-2); align-items: center; }

.sw-barra { position: relative; height: 6px; border-radius: var(--r-full); background: var(--fg-3); overflow: hidden; }
.sw-barra--grande { height: 10px; }
.sw-barra__relleno { position: absolute; inset: 0 auto 0 0; width: calc(var(--pct) * 1%); border-radius: var(--r-full); background: var(--p); }

.sw-etapa-estado { display: inline-flex; align-items: center; gap: 7px; height: 24px; padding: 0 10px; border-radius: var(--r-full); font: 600 11.5px/1 var(--f); background: var(--fg-3); color: var(--fg-txt-2); }
.sw-etapa-estado__punto { width: 8px; height: 8px; border-radius: var(--r-full); background: currentColor; }
.sw-etapa-estado--en_curso { background: var(--aviso-bg); color: var(--aviso); }
.sw-etapa-estado--completada { background: var(--ok-bg); color: var(--ok-tx); }
.sw-etapa-estado--completada .sw-etapa-estado__punto { border-radius: var(--r-full); }
.sw-etapa-estado--pendiente .sw-etapa-estado__punto { background: transparent; border: 2px solid currentColor; }

.sw-scrollx { overflow-x: auto; }
.sw-tabla { width: 100%; border-collapse: collapse; font: 400 13.5px/1.4 var(--f); }
.sw-tabla th, .sw-tabla td { padding: 12px 14px; border-bottom: 1px solid var(--fg-3); text-align: left; }
.sw-tabla thead th { position: sticky; top: 0; background: var(--fg); font: 600 12px/1 var(--f); letter-spacing: .04em; text-transform: uppercase; color: var(--fg-txt-3); }
.sw-tabla td:last-child, .sw-tabla th:last-child { text-align: right; font-family: var(--f-num); }

/* Por debajo de 640 px la tabla deja de ser tabla. */
@media (max-width: 639px) {
  .sw-tabla, .sw-tabla thead, .sw-tabla tbody, .sw-tabla tr, .sw-tabla th, .sw-tabla td { display: block; }
  .sw-tabla thead { display: none; }
  .sw-tabla tr { border: 1px solid var(--fg-borde); border-radius: var(--r-md); padding: 6px 0; margin-bottom: 10px; }
  .sw-tabla td { display: flex; justify-content: space-between; gap: 12px; border: 0; padding: 8px 14px; }
  .sw-tabla td::before { content: attr(data-et); font: 600 12px/1.4 var(--f); color: var(--fg-txt-3); }
}

.sw-insignia {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 12px;
  border-radius: var(--r-full);
  background: var(--fg-2);
  font: 500 11.5px/1 var(--f);
  color: var(--fg-txt-3);
  text-decoration: none;
}
.sw-insignia:hover { color: var(--fg-txt-2); text-decoration: none; }

.sw-borrador {
  display: flex; align-items: center; gap: 9px;
  padding: 10px 16px;
  background: var(--aviso-bg);
  color: var(--aviso);
  font: 600 12.5px/1.4 var(--f);
}

/* Puerta de contraseña */
.sw-puerta {
  min-height: 100dvh;
  display: flex; align-items: center; justify-content: center;
  padding: var(--e-5);
  background: radial-gradient(120% 90% at 50% 0%, #17222F 0%, #0A0F16 70%);
}
.sw-puerta__caja {
  width: min(400px, 100%);
  padding: 28px;
  border-radius: var(--r-xl);
  background: var(--fg);
  color: var(--fg-txt);
  box-shadow: 0 30px 80px rgb(6 11 18 / .5);
  display: flex; flex-direction: column; gap: 14px;
}
.sw-puerta__logo { height: 40px; width: auto; max-width: 180px; object-fit: contain; }
