/*
 * La hoja del recorrido.
 *
 * ── UNA PANTALLA, UN ARCHIVO ────────────────────────────────────────────────────────────────
 *
 * Este archivo es el INDICE: cada pantalla o componente tiene su hoja en `estilo/`, y aqui se
 * juntan EN EL ORDEN DE LA CASCADA. El orden es parte del estilo —a igual especificidad gana la
 * regla que se lee despues—, asi que no se reordena sin medir. El sitio sirve UNA hoja: el montaje
 * sustituye cada `@import` por su archivo (`tools/hoja-del-recorrido.mjs`). Receta en
 * `Motor/README.md` §Una Pantalla, Un Archivo.
 *
 * Las medidas salen de las fichas visuales del original —`Spec/01 · Masterplan.md`,
 * `02 · Piso.md`, `03 · Unidad.md` y `04 · Ficha.md`—, que estan tomadas al pixel. Los colores y
 * la tipografia NO: los pone la vista desde `development.brand` en tiempo de arranque, asi que
 * aqui solo hay reservas por si el manifiesto no los trae.
 */

/* 🧱 Lo que es de toda pantalla: los tokens (`:root`, y los de la piel `web3d`), el documento, la tipografia propia, los iconos y los avisos del motor (la pieza que no llego, el arranque roto). */

:root {
  /*
   * La caja del escenario, en pixeles. La mide la vista en cada `resize` a partir del viewport
   * vivo y de la RELACION que declara la configuracion; aqui no hay ningun 16/9 clavado, porque
   * Casaporte se produce phone first en 9:16 y el encuadre es un parametro (Master Plan §Phone
   * First). Las reservas valen para el primer cuadro, antes de que corra el JS.
   */
  --escenario-ancho: 100vw;
  --escenario-alto: 100vh;

  --primario: #164056;
  --sobre-primario: #ffffff;
  --familia: ui-sans-serif;
  /*
   * LA PILA ENTERA, Y EXISTE POR UN BUG MEDIDO. Toda esta hoja escribia `font: 600 14px/20px
   * var(--pila)`, y ESO NO ES CSS VALIDO: `inherit` es una palabra que solo vale como valor UNICO de
   * una declaracion, nunca dentro de un atajo, asi que el navegador tiraba la declaracion ENTERA
   * —peso, tamanio e interlinea incluidos— y no avisaba de nada. Medido en Chrome 152: el boton
   * de la antesala salia a `13.3333px`, que es el valor por defecto que el navegador le da a un
   * `<button>`, en vez de los `600 14px/20px` que mide la ficha. Un atajo con `var()` dentro si
   * es valido, asi que la pila va aqui y se usa donde antes iba `inherit`.
   */
  --pila: var(--familia), ui-sans-serif, system-ui, sans-serif;

  --tinta: #171717;
  /* #5f5f5f y no el #737373 de la referencia: aquel da 4.0:1 sobre los rellenos grises (#ececed,
     la etapa activa) y la prueba de contraste (`test/contraste.test.ts`) exige AA en toda pantalla. */
  --tinta-suave: #5f5f5f;
  --superficie: #f5f5f5;
  --borde: max(16px, env(safe-area-inset-left, 0px));
  --borde-arriba: max(16px, env(safe-area-inset-top, 0px));
  --borde-abajo: max(16px, env(safe-area-inset-bottom, 0px));

  --sombra-boton: inset 0 0 0 1px rgb(0 0 0 / 0.15), 0 1px 2px rgb(0 0 0 / 0.05);
  --sombra-chip: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  --curva: cubic-bezier(0.4, 0, 0.2, 1);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: #000;
  font-family: var(--familia), ui-sans-serif, system-ui, sans-serif;
  color: var(--tinta);
  -webkit-font-smoothing: antialiased;
}

body { opacity: 0; transition: opacity 0.3s var(--curva); }
body.listo { opacity: 1; }

/* ── Lo que esta lane no monta, dicho y no fingido ─────────────────────────────────────────── */
.fuera-de-alcance {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  gap: 8px;
  text-align: center;
  background: rgb(0 0 0 / 0.72);
  backdrop-filter: blur(6px);
  color: #fff;
  z-index: 45;
}
.fuera-de-alcance .que { margin: 0; font: 600 18px/28px var(--pila); }
.fuera-de-alcance .cuando { margin: 0; font: 400 14px/20px var(--pila); color: rgb(255 255 255 / 0.7); }

/*
 * UNA PIEZA DEL MANIFIESTO QUE NO LLEGÓ. No es la pantalla rota: es la pantalla que NO se pintó,
 * y por eso se dibuja encima de la que el visitante sigue mirando y no la sustituye. Misma caja
 * que `.fuera-de-alcance`, un peldaño por encima en `z-index` porque las dos pueden coincidir.
 */
.sin-pieza {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  gap: 10px;
  justify-items: center;
  text-align: center;
  padding: 0 24px;
  background: rgb(0 0 0 / 0.72);
  backdrop-filter: blur(6px);
  color: #fff;
  z-index: 46;
}
.sin-pieza .que { margin: 0; font: 600 18px/28px var(--pila); }
.sin-pieza .cuando { margin: 0; font: 400 14px/20px var(--pila); color: rgb(255 255 255 / 0.7); }
.sin-pieza .reintentar {
  margin-top: 6px;
  padding: 10px 20px;
  border: 0;
  border-radius: 999px;
  background: var(--primario);
  color: var(--sobre-primario);
  font: 600 14px/20px var(--pila);
  cursor: pointer;
}

.reventado {
  margin: 0;
  padding: 24px;
  color: #ff6b6b;
  background: #000;
  font: 400 12px/18px var(--pila);
  white-space: pre-wrap;
}

/* ══ EL MENU DEL SHOWROOM · iconos de linea, vias de un toque, mapa vivo, disponibilidad ═════════
 * 📋 Menu-Del-Showroom, 23-sep-2026. Mismo lenguaje que el rediseño web3d: Work Sans, el
 * color de marca como unico acento, iconos de linea fina (Ipanema §5), botones de 40–48 px.
 */
.icono { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }

.via-redonda .icono { width: 20px; height: 20px; }

/* ══ LA PIEL WEB3D · `brand.theme: "web3d"` ═══════════════════════════════════════════════════
 *
 * El lenguaje de diseño de Web3D (Ipanema), copiado de sus capturas
 * (`Factory/Docs/Competencia/Ipanema/`, medido en `Inteligencia De Web360 · Ipanema.md` §5):
 * botones redondos de 40 px a 16 del borde con paso 56, grises de Untitled UI
 * (#101828 · #344054 · #d0d5dd · #f2f4f7), el color del desarrollo sólo en el acento, tira de
 * niveles oscura a sangre, rótulo de lugar en píldora, tarjeta con iconos de línea y panel y menú
 * a sangre. TODO va bajo `[data-tema="web3d"]`: un desarrollo sin tema conserva la piel
 * `classic` al píxel. Los iconos son máscaras SVG en `currentColor`; el texto del botón queda
 * para el lector de pantalla y el `title`.
 */
:root[data-tema="web3d"] {
  --oscuro: #344054;
  --velo: #101828;
  --apagado: #d0d5dd;
  --tenue: #f2f4f7;
  --linea: #eaecf0;
  --tinte: color-mix(in srgb, var(--primario) 18%, #fff);
  --tinta: #101828;
  --tinta-suave: #667085;
  --i-menu: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round'%3E%3Cpath d='M4 7h16M8 12h12M12 17h8'/%3E%3C/svg%3E");
  --i-volver: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 14L4 9l5-5'/%3E%3Cpath d='M4 9h10.5a5.5 5.5 0 0 1 0 11H11'/%3E%3C/svg%3E");
  --i-pantalla: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 4h6v6M20 4l-7 7M10 20H4v-6M4 20l7-7'/%3E%3C/svg%3E");
  --i-cerrar: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E");
  --i-mas: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M20 20l-4.8-4.8M10.5 7.5v6M7.5 10.5h6'/%3E%3C/svg%3E");
  --i-menos: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M20 20l-4.8-4.8M7.5 10.5h6'/%3E%3C/svg%3E");
  --i-area: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6h13v14H4zM20 6v14M18.5 6h3M18.5 20h3M4 3h13M4 1.5v3M17 1.5v3'/%3E%3C/svg%3E");
  --i-cama: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 18v-6a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v6M3 15h18M3 18v2M21 18v2M5 10V6a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v4M8 10V8h3v2M13 10V8h3v2'/%3E%3C/svg%3E");
  --i-bano: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 12h18v2a5 5 0 0 1-5 5H8a5 5 0 0 1-5-5zM6 12V5a2 2 0 0 1 4 0M7 19l-1 2M17 19l1 2'/%3E%3C/svg%3E");
}

:root[data-tema="web3d"] {
  --pila: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter", system-ui, sans-serif;
  --etiqueta: #1d1d1f;
  /* 0.8 y no el 0.6 de Apple: a 0.66 la secundaria daba 3.98:1 sobre blanco y 3.69:1 sobre relleno. */
  --etiqueta-2: rgb(60 60 67 / 0.8);
  --relleno: rgb(120 120 128 / 0.14);
  --separador: rgb(60 60 67 / 0.16);
  --material: rgb(255 255 255 / 0.74);
  --material-grueso: rgb(250 250 252 / 0.9);
  --filo: inset 0 0 0 0.5px rgb(0 0 0 / 0.08);
  --sombra-flota: 0 1px 2px rgb(0 0 0 / 0.06), 0 8px 24px rgb(0 0 0 / 0.1);
  --sombra-hoja: 0 1px 2px rgb(0 0 0 / 0.06), 0 24px 64px rgb(0 0 0 / 0.18);
  --desenfoque: saturate(180%) blur(20px);
  /*
   * LAS SUPERFICIES SIGUEN AL TEMA. En oscuro la tinta se vuelve clara («--etiqueta: #f5f5f7»), asi
   * que un fondo claro FIJO bajo texto con token es texto blanco sobre blanco (Contacto, Location y
   * Availability, 26-sep). Toda superficie con texto usa uno de estos, nunca #fff/#fafafa:
   *   --lienzo          la pagina (systemBackground)
   *   --lienzo-elevado  tarjetas, pastillas, campos (secondarySystemGroupedBackground)
   *   --lienzo-hundido  la tarjeta apagada: vendida, sin accion
   * Las reglas base los usan con respaldo (`var(--lienzo-elevado, #fff)`): la piel classic no los
   * define y queda al pixel. `test/contraste.test.ts` lo mide en navegador en cada pantalla.
   */
  --lienzo: #ffffff;
  --lienzo-elevado: #ffffff;
  --lienzo-hundido: #fafafa;
  --lienzo-ficha: #f7f6f5;
  /* El color del desarrollo como TEXTO: oscurecido hasta 4.5:1 sobre los rellenos grises. */
  --primario-texto: color-mix(in srgb, var(--primario) 78%, #000);
  --resorte: cubic-bezier(0.32, 0.72, 0, 1);
  --t: 0.35s;
  --tinta: var(--etiqueta);
  --tinta-suave: var(--etiqueta-2);
  --oscuro: var(--etiqueta);
  --linea: var(--separador);
}

@media (prefers-color-scheme: dark) {
  :root[data-tema="web3d"] {
    --etiqueta: #f5f5f7;
    --etiqueta-2: rgb(235 235 245 / 0.6);
    --relleno: rgb(118 118 128 / 0.28);
    --separador: rgb(84 84 88 / 0.6);
    --material: rgb(30 30 32 / 0.72);
    --material-grueso: rgb(28 28 30 / 0.92);
    --filo: inset 0 0 0 0.5px rgb(255 255 255 / 0.12);
    --lienzo: #000;
    --lienzo-elevado: #1c1c1e;
    --lienzo-hundido: #141416;
    --lienzo-ficha: #000;
    /* El color del desarrollo como TEXTO sobre lienzo oscuro: se aclara hasta leerse. */
    --primario-texto: color-mix(in srgb, var(--primario) 55%, #fff);
  }
}

[data-tema="web3d"] body { font-family: var(--pila); }

/* ══ EL PULIDO DE VENTA (💄, 23-sep-2026) ════════════════════════════════════════════════════
 * Informe `Factory/Docs/Competencia/Por Qué El Nuestro Se Ve Barato.md` §4, huecos de interfaz:
 * #5 contraste · #6 fuente propia y logotipo · #11 lema · #9 ficha · #13 tira · #14 menú.
 * Todo bajo `[data-tema="web3d"]` salvo el `@font-face`, que no descarga nada hasta que una
 * familia lo pida (`brand.fontFamily: "Inter"`): la piel `classic` sigue al píxel.
 */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fuentes/inter-latin-wght-normal.woff2") format("woff2-variations"), url("fuentes/inter-latin-wght-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fuentes/inter-latin-ext-wght-normal.woff2") format("woff2-variations"), url("fuentes/inter-latin-ext-wght-normal.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
.solo-lector { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* #6 · La familia del desarrollo primero; la del sistema, de respaldo mientras llega (swap). */
:root[data-tema="web3d"] {
  --pila: var(--familia), -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
  /* #5 · La línea secundaria que se lee: .85 sobre material claro da ≥ 7:1 (la de .66 daba ≈ 3.9:1 sobre foto). */
  --etiqueta-legible: rgb(60 60 67 / 0.88);
}

@media (prefers-color-scheme: dark) {
  :root[data-tema="web3d"] { --etiqueta-legible: rgb(235 235 245 / 0.86); }
}

[data-tema="web3d"] body { font-feature-settings: "cv11", "ss01"; }

:root {
  --i-lupa: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.5 15.5L21 21'/%3E%3C/svg%3E");
  --i-planta: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linejoin='round'%3E%3Cpath d='M12 3l9 5-9 5-9-5z'/%3E%3Cpath d='M3 13l9 5 9-5'/%3E%3C/svg%3E");
  --i-seccion: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round'%3E%3Crect x='4' y='4' width='16' height='16' rx='3'/%3E%3Cpath d='M8 9h8M8 13h8M8 17h5'/%3E%3C/svg%3E");
}
/* 🧱 El escenario (`escenario.ts`): la caja de la relacion del arte, las laminas apiladas y el clip encima. */

/* ── El escenario · Spec §2 ───────────────────────────────────────────────────────────────────
 * NO es el viewport: es una caja de relacion fija que lo CUBRE y se centra. Con la relacion de
 * la ficha —16:9— y sus dos viewports da exactamente lo medido: 1440×900 → 1600×900 en
 * x=−80, y 390×844 → 1500×844 en x=−555. La medida la hace `vista/geometria.ts`, que es donde
 * esta explicado por que se cubre y no se estira.
 */
/*
 * `clip` y no `hidden`, y la diferencia se mide: `hidden` crea un contenedor SCROLLABLE, y al
 * tocar un poligono que desborda por un lado el navegador desplaza ese contenedor para
 * «revelarlo». Medido a 390 px de ancho: 313 px de corrimiento, la lamina y la mascara movidas y
 * cada zona fuera de su sitio. `clip` no crea contenedor de scroll, asi que no hay nada que
 * desplazar. Mismo recorte, cero deriva.
 */
.recorrido { position: fixed; inset: 0; overflow: hidden; overflow: clip; }

.escenario {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--escenario-ancho);
  height: var(--escenario-alto);
  /*
   * ACERCAR Y ARRASTRAR SON UN `transform`, no un contenedor desplazable, y la diferencia se
   * midió: la referencia resuelve el teléfono con `min-width: 1366px`, que crea un scroller de
   * verdad, y un contenedor desplazable es justo lo que estropeaba cada polígono —al tocar uno
   * que desborda, el navegador lo desplaza para «revelarlo» y se lleva lámina y máscara con él,
   * 313 px de corrimiento a 390 px de ancho—. Por eso el escenario va a `overflow: clip` y el
   * encuadre viaja aquí. Los topes los pone `geometria.ts`, y el gate los mide.
   */
  --zoom: 1;
  --paneo-x: 0px;
  --paneo-y: 0px;
  transform: translate(-50%, -50%) scale(var(--zoom)) translate(var(--paneo-x), var(--paneo-y));
  transition-property: transform;
  transition-timing-function: ease-out;
  transition-duration: 0ms;
  overflow: hidden;
  overflow: clip;
  background: #000 center / cover no-repeat;
}
/*
 * `touch-action: pinch-zoom` Y NO `none`, y es la diferencia entre que el arrastre funcione o no.
 *
 * Sin declararlo, el navegador se queda el gesto para desplazar la página y dispara
 * `pointercancel` en cuanto el dedo se mueve: medido, el arrastre avanzaba UN tramo de ocho y se
 * moría. `none` lo arreglaría pero se llevaría por delante el pellizco para acercar, que aquí no
 * se bloquea a propósito —la referencia sí lo bloquea y su propia ficha lo anota como defecto—.
 * `pinch-zoom` deja el pellizco al navegador y el arrastre de un dedo a esta capa.
 */
.escenario.arrastrable { cursor: grab; touch-action: pinch-zoom; user-select: none; }
.escenario img { -webkit-user-drag: none; }
.escenario.arrastrando { cursor: grabbing; }

.lienzo, .capa-mascara, .clips { position: absolute; inset: 0; }

.lamina, .lamina-saliente, .bucle {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition-property: opacity;
  /* El fundido entre dos laminas registradas (Ipanema ②: 0.6 s ease-out): la nueva sube encima de
     la vieja, que no se quita hasta que la tapa. Se lee como la misma camara, no como otra foto. */
  transition-timing-function: ease-out;
}

.clips { z-index: 30; pointer-events: none; }
.clip {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition-property: opacity;
  transition-timing-function: var(--curva);
}
.clip[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .lamina, .clip, .rotulo { transition-duration: 0.01ms !important; animation: none !important; }
}

/* La planta que se va crece con el suelo y la que llega viene de mas lejos (`lamina(…, viaje)`). */
[data-tema="web3d"] .lamina, [data-tema="web3d"] .lamina-saliente {
  transition-property: opacity, scale;
}

/* ── 🧭 La losa que se levanta (`losa.ts`, `escenario.ts` · Piso-Al-Dedo-Motor, 29-sep-2026) ─────────
 * Entre la planta de abajo y los poligonos: la sombra sobre el piso de abajo, tres laminas de canto y,
 * mientras dura el paso, la planta de arriba misma. Todo recortado por la silueta (`piece.silhouette`)
 * y colocado por `escenario.ts`; aqui solo la materia. */
.losa { position: absolute; inset: 0; pointer-events: none; perspective-origin: 50% 50%; }
.losa-sombra, .losa-canto {
  position: absolute; inset: 0; width: 100%; height: 100%;
  visibility: hidden; will-change: transform, opacity;
  mask-size: 100% 100%; -webkit-mask-size: 100% 100%;
  mask-repeat: no-repeat; -webkit-mask-repeat: no-repeat;
}
.losa-canto { background: linear-gradient(180deg, #d9d3c7, #8f887c); }
.losa-sombra { background: #000; }
/* El dedo en vertical es de la losa y no de la pagina (ver `.arrastrable`: `pinch-zoom` y no `none`). */
.escenario.con-losa { touch-action: pinch-zoom; user-select: none; }
/* 🧱 Lo que se dibuja SOBRE el arte (`mascara.ts`, `cuartos.ts`): los poligonos, sus chips, los estados de venta y el filtro en la planta, la leyenda, los rotulos de cuarto y los recintos que se tocan. */

/* ── La mascara · Spec §2 y §5.3 ──────────────────────────────────────────────────────────── */
.capa-mascara { z-index: 40; pointer-events: none; }

.mascara { position: absolute; inset: 0; width: 100%; height: 100%; }

.zona {
  --color-zona: var(--primario);
  fill: var(--color-zona);
  stroke: var(--color-zona);
  stroke-width: 0;
  fill-opacity: 0;
  pointer-events: auto;
  /* Instantaneo, medido: el poligono aparece de golpe mientras todo lo demas se funde. Spec §6.2 */
  transition-duration: 0s;
}
.zona.viva { cursor: pointer; }
/* INVISIBLE EN REPOSO, en toda pantalla: el arte manda y el poligono solo aparece bajo el dedo
   (Ipanema, masterplan y nivel). El borde no escala con el `viewBox` estirado: 1.5 px siempre. */
.zona { vector-effect: non-scaling-stroke; stroke: #fff; stroke-opacity: 0; transition: fill-opacity 0.15s ease-out, stroke-opacity 0.15s ease-out; }
.zona.encendida { fill-opacity: 0.28; stroke-width: 1.5px; stroke-opacity: 0.9; }
.zona.apagada.encendida { fill: #fff; fill-opacity: 0.18; stroke-opacity: 0.6; }
/* Con resaltado renderizado (`hotspot.hover`) el poligono es solo zona de toque: la capa pinta. */
.zona.solo-toque, .zona.solo-toque.encendida { fill-opacity: 0; stroke-opacity: 0; }
.resaltes { position: absolute; inset: 0; pointer-events: none; }
.resalte {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; transition: opacity 0.2s ease-out;
}
.resalte.encendido { opacity: 1; }

/* La unidad que se esta mirando, dentro del minimapa de su ficha. */
.zona.destacada { fill-opacity: 0.75; stroke-width: 0.6; }

/*
 * 🏙️ LA TORRE QUE INVITA (`mascara.ts`, opcion `invitar`; `geometria.ts`, `invitacion`). En reposo
 * cada nivel vivo lleva un contorno blanco FINO —1 px, 38 %, con un halo oscuro de 1 px para que se
 * lea sobre cielo claro y sobre fachada—, y al llegar sube un barrido de luz de piso en piso
 * (`--turno`, 0 = el de abajo). Bajo el puntero manda lo de antes: la capa renderizada, y los
 * demas contornos se apagan para no competir con ella. Sin movimiento: contornos quietos.
 */
.mascara.invita { filter: drop-shadow(0 0 1px rgb(0 0 0 / 0.35)); }
.mascara.invita .zona.viva:not(.atenuado) { stroke: #fff; stroke-width: 1px; stroke-opacity: 0.38; }
.mascara.invita .zona.viva.encendida:not(.solo-toque) { stroke-width: 1.5px; stroke-opacity: 0.9; }
.mascara.invita .zona.viva.solo-toque.encendida,
.mascara.invita:has(.zona.encendida) .zona.viva:not(.encendida) { stroke-opacity: 0; animation: none; }

@media (prefers-reduced-motion: no-preference) {
  .mascara.invita .zona.viva:not(.atenuado) {
    animation: barrido-piso 0.9s var(--curva) calc(var(--turno, 0) * 70ms + 250ms) backwards;
  }
}

/* `backwards` y no `both`: al terminar, la regla de reposo vuelve a mandar y el asomo la pisa. */
@keyframes barrido-piso {
  0% { stroke-opacity: 0; fill: #fff; fill-opacity: 0; }
  35% { stroke-opacity: 0.95; fill: #fff; fill-opacity: 0.2; }
  100% { stroke-opacity: 0.38; fill: #fff; fill-opacity: 0; }
}

/* El aviso «Toca un Nivel»: sobre el techo de la torre (o bajo su base), llega cuando el barrido
   corona y se va al primer asomo de la visita. No se toca: el toque es de los niveles. */
.aviso-invita {
  position: absolute;
  transform: translate(-50%, calc(-100% - 14px));
  display: inline-flex; align-items: center; gap: 7px;
  height: 28px; padding: 0 12px 0 10px;
  border-radius: 14px;
  background: rgb(255 255 255 / 0.92);
  color: var(--tinta);
  font: 600 13px/18px var(--pila);
  white-space: nowrap;
  box-shadow: var(--sombra-chip);
  pointer-events: none;
  transition: opacity 0.25s ease-out;
}
.aviso-invita.debajo { transform: translate(-50%, 14px); }
.aviso-invita::before {
  content: ''; width: 7px; height: 7px; border-radius: 9999px;
  background: var(--primario); box-shadow: 0 0 0 3px color-mix(in srgb, var(--primario) 22%, transparent);
}
.aviso-invita.ido { opacity: 0; }

@media (prefers-reduced-motion: no-preference) {
  .aviso-invita { animation: aparece-aviso 0.5s var(--curva) calc(var(--pisos, 0) * 70ms + 500ms) backwards; }
}

@keyframes aparece-aviso { from { opacity: 0; } to { opacity: 1; } }

/* ── Los rotulos · Spec §5.2 ──────────────────────────────────────────────────────────────── */
.rotulos { position: absolute; inset: 0; }

.rotulo {
  position: absolute;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 22px;
  padding: 0 8px 0 6px;
  border-radius: 11px;
  background: #fff;
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.12);
  transition: opacity 0.15s ease-out;
  white-space: nowrap;
  pointer-events: auto;
  animation: aparece-rotulo 0.12s ease-out backwards;
}
/* El punto lleva el color del ESTADO cuando el dato lo trae (`unitStatuses[].color`, un piso) y
   el de la pieza cuando no (`hotspot.fill`, el masterplan). Lo pone `mascara.ts` sobre el CHIP,
   asi que la reserva tiene que vivir aqui: declarada en `.punto` pisaria al valor heredado y
   todos los puntos saldrian del color de marca. */
.rotulo { --color-punto: var(--primario); }
.rotulo.vivo { cursor: pointer; }
.rotulo .punto {
  width: 7px;
  height: 7px;
  border-radius: 9999px;
  background: var(--color-punto);
  border: 1px solid #fff;
  box-shadow: 0 1px 3px rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
}
.rotulo .texto { font: 600 12px/16px var(--pila); color: var(--tinta); }
/* EL CHIP QUE SOLO SALE AL ASOMAR: el nivel del edificio en el masterplan. */
.rotulo.al-asomar { opacity: 0; pointer-events: none; animation: none; }
.rotulo.al-asomar.encendido { opacity: 1; }
.rotulo.al-asomar.apagado .texto::after { content: attr(data-pendiente); margin-left: 6px; font-weight: 400; color: var(--tinta-suave); }

/*
 * El estado que rotula un punto —«100% Vendido», «Proximamente»—, con el texto y el COLOR que le
 * da `towerStatuses[]`. Hasta v2.0.0 aqui salia la clave cruda en monoespaciada, fea a proposito,
 * porque no habia campo donde viviera ese texto. Ver `app.ts`, `rotuloDeEstado`.
 */
.rotulo .nota {
  --color-nota: var(--tinta-suave);
  font: 600 11px/16px var(--pila);
  color: var(--color-nota);
  padding-left: 4px;
  border-left: 1px solid #e5e5e5;
}
.rotulo.apagado:not(.al-asomar) { opacity: 0.7; }

@keyframes aparece-rotulo { from { opacity: 0; } to { opacity: 1; } }

/* La unidad vendida en la planta: atenuada y sin toque (su estado no es `selectable`). */
.mascara .zona.apagada { cursor: default; }

@media (min-width: 521px) {
  [data-tema="web3d"] body:has(.chrome .titular-nivel) .rotulo { scale: calc(1 / var(--ajuste)); transform-origin: 0 0; }
}

/* Los chips de unidad: legibles y tocables (alto 32, número en 15). */
[data-tema="web3d"] .rotulo {
  height: 32px; gap: 8px;
  padding: 0 12px 0 10px;
  border-radius: 16px;
  background: var(--material-grueso);
  -webkit-backdrop-filter: var(--desenfoque);
  backdrop-filter: var(--desenfoque);
  box-shadow: var(--filo), 0 2px 8px rgb(0 0 0 / 0.12);
  transition: opacity var(--t) var(--resorte), transform var(--t) var(--resorte);
}
[data-tema="web3d"] .rotulo .punto { width: 8px; height: 8px; border: 0; box-shadow: none; }
[data-tema="web3d"] .aviso-invita {
  height: 32px; padding: 0 14px 0 12px; border-radius: 16px;
  background: var(--material-grueso);
  -webkit-backdrop-filter: var(--desenfoque);
  backdrop-filter: var(--desenfoque);
  box-shadow: var(--filo), 0 2px 8px rgb(0 0 0 / 0.12);
  color: var(--etiqueta);
  font: 600 14px/20px var(--pila);
}
[data-tema="web3d"] .aviso-invita::before { background: var(--primario-texto, var(--primario)); }
[data-tema="web3d"] .rotulo .texto { font: 600 15px/20px var(--pila); color: var(--etiqueta); font-variant-numeric: tabular-nums; }
[data-tema="web3d"] .rotulo .nota { font: 500 13px/18px var(--pila); border-left-color: var(--separador); }
[data-tema="web3d"] .rotulo.vivo:hover { box-shadow: var(--filo), 0 4px 16px rgb(0 0 0 / 0.18); }

@media (max-width: 520px) {
  [data-tema="web3d"] body:has(.chrome .titular-nivel) .rotulo { scale: calc(1 / var(--ajuste)); transform-origin: 0 0; }
  /* El chip de unidad en dos renglones: número arriba, recámaras y superficie debajo. */
  [data-tema="web3d"] body:has(.chrome .titular-nivel) .rotulo:has(.nota) {
    height: auto; padding: 5px 8px; border-radius: 14px;
    display: grid; grid-template-columns: auto auto; column-gap: 6px; align-items: center;
    /* Centrado en su punto: dos unidades vecinas caben a 390 sin encimarse. */
    transform: translate(-50%, -50%) !important;
  }
  [data-tema="web3d"] body:has(.chrome .titular-nivel) .rotulo .nota {
    grid-column: 1 / -1; padding-left: 0; border-left: 0;
    font: 500 11px/14px var(--pila); color: var(--etiqueta-2);
  }
}

[data-tema="web3d"] body:has(.chrome .titular-nivel) .rotulo:has(.nota) { background: var(--material-grueso); }
[data-tema="web3d"] body:has(.chrome .titular-nivel) .rotulo .nota { color: var(--etiqueta-legible); font-weight: 600; }

/* ── 🎨 Estados de venta, filtro en el edificio e idioma ───────────────────────────────────────
   Estado: CONTORNO FINO de su color (`unitStatuses[].color`) y nada encima del arte (Victor,
   25-sep-2026: la trama de rayas tapaba el render). El que no es el primero de `unitStatuses[]`
   (`patron-*` ≠ liso: vendida, apartada…) lleva además un velo leve que lo apaga sin taparlo; la
   distinción sin color va en el texto de la pastilla y de la leyenda. Filtro: `coincide` se
   ilumina aunque el polígono sea sólo de toque; `atenuado` se oscurece. */
.zona.con-estado { fill-opacity: 0; stroke: var(--color-zona); stroke-width: 1px; stroke-opacity: 0.9; vector-effect: non-scaling-stroke; }
.zona.con-estado:not(.patron-liso) { fill: #fff; fill-opacity: 0.18; stroke: rgb(255 255 255 / 0.75); }
.zona.con-estado.encendida { fill: var(--color-zona); fill-opacity: 0.16; stroke: #fff; stroke-width: 1.5px; stroke-opacity: 1; }
.zona.coincide, .zona.solo-toque.coincide {
  fill: var(--primario); fill-opacity: 0.55; stroke: #fff; stroke-width: 2px; stroke-opacity: 1;
  animation: late-coincide 1.6s ease-in-out 2;
}
.zona.con-estado.coincide { fill: var(--color-zona); fill-opacity: 0.45; }
.zona.atenuado, .zona.solo-toque.atenuado { fill: #000; fill-opacity: 0.5; stroke-opacity: 0; }
.zona.atenuado.encendida { fill-opacity: 0.3; }
.rotulo.atenuado:not(.al-asomar) { opacity: 0.35; }
/* En la fachada el chip del nivel sale al asomar; con filtro, los niveles que cumplen lo enseñan. */
.rotulo.al-asomar.coincide { opacity: 1; pointer-events: auto; }
@keyframes late-coincide { 50% { fill-opacity: 0.8; } }

@media (prefers-reduced-motion: reduce) {
  .zona.coincide { animation: none; }
}

/* ── 🏷️ Rótulos de cuarto (`cuartos.ts`) ──────────────────────────────────────────────────────
   El nombre de la hoja, editorial: pequeño, sin caja, centrado en su recinto. Tinta oscura con
   halo claro, en los dos temas (el arte no cambia con el tema): se lee sobre render claro y
   sobre un mueble oscuro sin tapar el arte. No se tocan: el toque es del
   polígono de la unidad que queda debajo. En teléfono sólo los principales, los demás con zoom. */
.cuartos { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
.cuarto {
  position: absolute; transform: translate(-50%, -50%); max-width: 9em; text-align: center;
  font: 500 11px/13px var(--pila); letter-spacing: 0.01em; color: rgb(28 26 24 / 0.86);
  text-shadow: 0 0 2px rgb(255 255 255 / 0.95), 0 0 6px rgb(255 255 255 / 0.8);
  white-space: normal; text-wrap: balance;
}
.cuarto.secundario { font-size: 9.5px; line-height: 11px; color: rgb(28 26 24 / 0.7); }
.cuarto.tapado { visibility: hidden; }

@media (max-width: 520px) {
  .cuarto { font-size: 9.5px; line-height: 11px; max-width: 7em; }
  .cuarto.secundario { display: none; }
  .acercada .cuarto.secundario { display: block; }
}

/* ── 🛗 El núcleo de la planta (`nucleo.ts`, `mascara.ts` `pintarNucleo`) ─────────────────────────
   Dónde está el elevador, por dónde se entra a la residencia y dónde están las escaleras (y si suben o
   bajan), en tres segundos. El cubo del elevador se vela de claro con un filo fino (deja de leerse como
   caja hueca) y la caja de escalera se vela apenas, sin trazo (el render la corta a 1.20 m). La
   entrada es la flecha del color del desarrollo, de la puerta del elevador al vestíbulo. Nada se toca:
   el toque sigue siendo de la unidad. El arte no cambia con el tema, así que esto tampoco. */
.nucleo { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; overflow: visible; }
.pieza-nucleo { fill: rgb(255 255 255 / 0.32); stroke: rgb(28 26 24 / 0.32); stroke-width: 0.75px; vector-effect: non-scaling-stroke; }
/* ✒️ Sin recuadro punteado (Victor, 29-sep-2026 15:25): la caja de escalera se vela apenas, sin trazo. */
.pieza-nucleo.escalera { fill: rgb(255 255 255 / 0.18); stroke: none; }
.pieza-nucleo.de-servicio { fill: rgb(255 255 255 / 0.22); stroke: none; }
.flecha-nucleo { stroke: var(--primario, #164056); stroke-width: var(--trazo-flecha, 0.42); stroke-linecap: round; }
.flecha-nucleo.de-servicio { stroke: rgb(28 26 24 / 0.55); }
.nucleo marker path { fill: var(--primario, #164056); }
.nucleo-marcas { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
/*
 * ✒️ LA CIRCULACIÓN SE ROTULA COMO LOS CUARTOS (Victor, 29-sep-2026 15:25: «las píldoras blancas se ven
 * cero editoriales»). Era una pastilla blanca con sombra por pieza; ahora es texto fino sin caja, la
 * misma tinta y el mismo halo claro que `.cuarto`, con su glifo pequeño delante y el sentido (↑↓) detrás.
 * La entrada lleva el color del desarrollo, como su flecha; el servicio, la tinta secundaria.
 */
.marca-nucleo {
  position: absolute; transform: translate(-50%, -50%); display: inline-flex; align-items: center; gap: 3px;
  padding: 0; white-space: nowrap;
  background: none; box-shadow: none;
  font: 500 11px/13px var(--pila); letter-spacing: 0.01em; color: rgb(28 26 24 / 0.86);
  text-shadow: 0 0 2px rgb(255 255 255 / 0.95), 0 0 6px rgb(255 255 255 / 0.8);
}
.marca-nucleo .simbolo {
  width: 11px; height: 11px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 0 1.5px rgb(255 255 255 / 0.95)) drop-shadow(0 0 3px rgb(255 255 255 / 0.8));
}
.marca-nucleo .sentido { font-weight: 500; letter-spacing: 0.02em; opacity: 0.8; }
.marca-nucleo.entrada { color: var(--primario-texto, var(--primario, #164056)); font-weight: 600; }
.marca-nucleo.de-servicio { color: rgb(28 26 24 / 0.7); font-size: 9.5px; line-height: 11px; }
.marca-nucleo.de-servicio .simbolo { width: 10px; height: 10px; }
/* La entrada sigue a su flecha: el rótulo arranca en la punta, hacia dentro de la residencia. */
.marca-nucleo.hacia-izquierda { transform: translate(calc(-100% - 2px), -50%); }
.marca-nucleo.hacia-derecha { transform: translate(2px, -50%); }
.marca-nucleo.hacia-arriba { transform: translate(-50%, calc(-100% - 2px)); }
.marca-nucleo.hacia-abajo { transform: translate(-50%, 2px); }
/* Pisada por otra de más rango: se queda en su símbolo y sus flechas. */
.marca-nucleo.compacta .nombre { display: none; }
.marca-nucleo.tapada { visibility: hidden; }

@media (max-width: 520px) {
  .marca-nucleo { gap: 2px; font-size: 9.5px; line-height: 11px; }
  /* El nombre se queda también en el teléfono, como los cuartos principales: el glifo solo no se leía. */
  .marca-nucleo.de-servicio, .flecha-nucleo.de-servicio { display: none; }
  .acercada .marca-nucleo:not(.compacta) .nombre { display: inline; }
  .acercada .flecha-nucleo.de-servicio { display: inline; }
  .acercada .marca-nucleo.de-servicio { display: inline-flex; }
}

/* ── 🛋️ La planta por cuarto (`mascara.ts` `zonasDeCuarto`, `ficha/cuarto.ts` `abrirCuarto`) ─
   Cada recinto de la planta de la ficha se toca: asomar/tocar lo ilumina con un velo del color del
   desarrollo y enciende su rótulo (aunque estuviera tapado o fuera secundario); el que tiene fotos
   o tour lleva cursor de mano y abre su hoja. Nada se pinta en reposo: el arte manda. */
.recintos { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.recinto {
  fill: transparent; stroke: transparent; stroke-width: 0.25; vector-effect: non-scaling-stroke;
  pointer-events: auto; cursor: default; outline: none;
  transition: fill 0.2s var(--curva), stroke 0.2s var(--curva);
}
.recinto.abre { cursor: pointer; }
.recinto.iluminado { stroke: rgb(255 255 255 / 0.95); stroke-width: 2; }
/* El foco: lo demás de la planta se apaga y el recinto queda con su luz. */
.velo-recinto { fill: rgb(0 0 0 / 0.38); pointer-events: none; opacity: 0; transition: opacity 0.2s var(--curva); }
.recintos.con-foco .velo-recinto { opacity: 1; }
.recinto:focus-visible { stroke: var(--primario); stroke-width: 2.5; }
/* El nombre del recinto encendido sube a una pastilla: se lee sobre cualquier mueble. El arte no
   cambia con el tema, así que la pastilla tampoco (blanca, tinta oscura). */
.cuarto.iluminado {
  visibility: visible; display: block; z-index: 1; max-width: none; white-space: nowrap;
  padding: 3px 9px; border-radius: 999px; background: rgb(255 255 255 / 0.94); color: rgb(12 12 14);
  font: 600 12px/16px var(--pila); text-shadow: none; box-shadow: 0 1px 2px rgb(0 0 0 / 0.12), 0 4px 12px rgb(0 0 0 / 0.14);
}

@media (prefers-reduced-motion: reduce) {
  .recinto, .velo-recinto { transition: none; }
}

/* ── 🅿️ Cajones y bodegas (`mascara.ts`, `hotspot.space`; `views[].spaces` del contrato) ─────────────
   El color ES el dato —el tipo: residente, carga eléctrica, visitas, servicio, reservado, bodega—, así que
   el espacio va pintado en reposo, tenue, con su borde; asomar lo enciende y la residencia elegida
   llena los suyos y apaga los demás. Uno común (visitas, reservado) se mira y no se toca. */
.zona.espacio { fill-opacity: 0.3; stroke: var(--color-zona); stroke-width: 1px; stroke-opacity: 0.9; }
.zona.espacio.encendida,
.zona.espacio.apagada.encendida { fill: var(--color-zona); fill-opacity: 0.55; stroke: #fff; stroke-width: 1.5px; stroke-opacity: 1; }
.zona.espacio.destacada { fill-opacity: 0.85; stroke: #fff; stroke-width: 2px; stroke-opacity: 1; }
.mascara:has(.zona.espacio.destacada) .zona.espacio:not(.destacada):not(.encendida) { fill-opacity: 0.12; stroke-opacity: 0.4; }
/* El chip de un cajón no cambia de tamaño con el de su vecino y no bloquea el toque del de al lado. */
.rotulo.de-espacio.al-asomar.encendido { pointer-events: none; z-index: 2; }
.rotulo.de-espacio.fijo { z-index: 3; }
/* 🧱 El chrome (`chrome.ts`): lo que flota sobre el viewport en toda pantalla del recorrido. La marca, los mandos redondos, ambientes, areas, el QR, las acciones de arriba, las migas y el filtro puesto. */

/* ── El chrome · Spec §3 ──────────────────────────────────────────────────────────────────── */
.chrome { position: fixed; inset: 0; z-index: 50; pointer-events: none; }
.chrome > * { pointer-events: auto; }
.chrome.ocupado > * { pointer-events: none; }

.chrome button {
  font-family: inherit;
  border: 0;
  cursor: pointer;
  transition: 0.15s var(--curva);
}
.chrome button:active { transform: scale(0.95); }

.marca {
  position: absolute;
  top: calc(var(--borde-arriba) + 64px);
  left: var(--borde);
  width: 120px;
  height: 48px;
  object-fit: contain;
}

/* Los 40 × 40 redondos. Spec §3: todos iguales, a 16 px del borde. */
.volver, .pantalla-completa, .flecha {
  position: absolute;
  width: 40px;
  height: 40px;
  border-radius: 9999px;
  background: var(--primario);
  color: var(--sobre-primario);
  box-shadow: var(--sombra-boton);
}
.volver::before, .pantalla-completa::before, .flecha::before {
  display: block;
  font: 600 18px/1 ui-sans-serif, system-ui, sans-serif;
}
.volver { top: var(--borde-arriba); left: calc(var(--borde) + 112px); }
.volver::before { content: "←"; }
/*
 * EL VOLVER QUE DICE A DONDE VUELVE · `1242.1, 16 · 125.9 × 40`, `#f5f5f5` (Spec/04 §3).
 *
 * Con nombre deja de ser el redondo de 40 y se va al carril de la derecha, que es de donde
 * cuelga el chrome de la pantalla en la que esta —el de la izquierda es el de la marca—. El
 * ancho lo pone el texto: es lo unico que puede decir «a donde».
 */
.volver.con-nombre {
  width: auto;
  left: auto;
  right: calc(var(--borde) + 56px);
  padding: 0 16px;
  background: var(--superficie);
  color: var(--tinta);
  font: 600 14px/20px var(--pila);
}
.volver.con-nombre::before { content: "← "; display: inline; font: inherit; }
/* Y entonces el de ambiente se aparta, igual que con el `2D ⇄ 3D`. */
.chrome:has(.volver.con-nombre) .ambientes { right: calc(var(--borde) + 200px); }

/* Acercar y Alejar · ficha visual del piso §3: `16, 796` y `16, 844`, apilados abajo a la izquierda. */
.acercar, .alejar {
  position: absolute;
  left: var(--borde);
  width: 40px;
  height: 40px;
  border-radius: 9999px;
  box-shadow: var(--sombra-boton);
}
.acercar { bottom: calc(var(--borde-abajo) + 48px); background: var(--primario); color: var(--sobre-primario); }
.alejar { bottom: var(--borde-abajo); background: var(--superficie); color: var(--tinta); }
.acercar::before, .alejar::before { display: block; font: 600 20px/1 ui-sans-serif, system-ui, sans-serif; }
.acercar::before { content: "+"; }
.alejar::before { content: "−"; }
.acercar[disabled], .alejar[disabled] { opacity: 0.5; cursor: default; }
.pantalla-completa {
  top: var(--borde-arriba);
  right: var(--borde);
  background: var(--superficie);
  color: var(--tinta);
}
.pantalla-completa::before { content: "⤢"; }

.flecha { top: calc(50% - 20px); }

.flecha.anterior { left: var(--borde); }
.flecha.anterior::before { content: "‹"; }
.flecha.siguiente { right: var(--borde); }
.flecha.siguiente::before { content: "›"; }

/*
 * El interruptor de ambiente · `1216, 16 · 152 × 48` (Spec §3), a 72 px del borde derecho.
 *
 * DOS MEDIDAS QUE ESTABAN MAL Y SE VEN. El alto salia 50 y no 48 porque el `border: 1px` suma
 * por arriba y por abajo: pasa a `inset box-shadow`, que pinta igual y no ocupa. Y el ancho
 * salia 132.6 en vez de 152 porque las pastillas se ajustaban al texto; con `min-width: 70px`
 * dos rotulos cortos dan los 152 exactos —70 + 4 de hueco + 70 + 8 de relleno— y uno largo
 * sigue creciendo, que es lo que tiene que pasar cuando el manifiesto trae otras palabras.
 */
.ambientes {
  position: absolute;
  top: var(--borde-arriba);
  /* 0.6 y no 0.3: el interruptor flota tambien sobre pantallas-documento blancas, y ahi el vidrio
     claro dejaba el ambiente apagado a 1.6:1. */
  right: calc(var(--borde) + 56px);
  display: flex;
  gap: 4px;
  padding: 4px;
  border-radius: 9999px;
  background: rgb(0 0 0 / 0.6);
  backdrop-filter: blur(12px);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.2);
}
.ambiente {
  min-width: 70px;
  padding: 0 14px;
  height: 40px;
  border-radius: 9999px;
  background: transparent;
  color: rgb(255 255 255 / 0.9);
  font: 600 12px/16px var(--pila);
  transition: background 0.3s var(--curva), color 0.3s var(--curva);
}
.ambiente.activo { background: #fff; color: #000; }

.indice {
  position: absolute;
  left: 50%;
  bottom: var(--borde-abajo);
  transform: translateX(-50%);
  padding: 6px 12px;
  border-radius: 9999px;
  background: rgb(0 0 0 / 0.4);
  backdrop-filter: blur(8px);
  color: #fff;
  font: 600 12px/16px var(--pila);
}

/* El panel de areas. Spec §5.4: solo los puntos que llevan a algun sitio. */
.areas {
  position: absolute;
  top: calc(var(--borde-arriba) + 64px);
  right: var(--borde);
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px;
  border-radius: 16px;
  background: rgb(255 255 255 / 0.8);
  backdrop-filter: blur(8px);
}
.area {
  min-width: 100px;
  min-height: 40px;
  padding: 8px 16px;
  border-radius: 12px;
  background: var(--superficie);
  color: var(--tinta);
  font: 600 12px/16px var(--pila);
  text-align: left;
}
.area:hover { background: #e9e9e9; }

.chrome:has(.vistas) .ambientes { right: calc(var(--borde) + 176px); }

/* La marca es chrome del RECORRIDO y el panel de la ficha ocupa su sitio. */
.pantalla:has(.panel.abierto) ~ .chrome .marca { display: none; }
/* Sobre un documento blanco, el logotipo de sobre el arte no se lee: el cajon del menu lleva el
   suyo, que es el que el contrato declara para papel (`brand.navbarLogo`). */
body.en-documento .chrome .marca { display: none; }
/*
 * Con una capa abierta, el «atrás» es CERRARLA. Dos flechas en la misma esquina y con destinos
 * distintos es peor que una: la de salir de la ficha vuelve cuando la capa se cierra.
 *
 * Y EL BOTON DE MENU TAMPOCO, porque estaba TAPANDO LA ÚNICA SALIDA. El menú vive en `16, 16`
 * y el `✕` de la capa también —a la izquierda a propósito: el hueco de la derecha lo ocupan el
 * interruptor de ambiente y el de pantalla completa—, pero el chrome va en `z-50` y la capa en
 * `z-4`, así que el menú se dibujaba encima y el `✕` no se podía pulsar. Medido en
 * `ficha-terminaciones-1440x900.png`: en esa esquina sólo se ve `Menú`. Una capa es modal; el
 * menú vuelve al cerrarla.
 */
.pantalla:has(.capa) ~ .chrome .volver,
.pantalla:has(.capa) ~ .chrome .menu-boton { display: none; }

/* ── El carrusel de la pestaña · `16, 430` y `1384, 430` ───────────────────────────────────── */
.ficha .flecha { top: calc(50% - 20px); z-index: 3; }
/*
 * CON EL PANEL ABIERTO, `‹` SE CORRE A SU DERECHA. En la referencia se queda en `16, 430`, que
 * es justo debajo del panel de detalle, y allí **no se puede pulsar**: el contenedor del
 * escenario lleva `isolate` y el `z-50` de la flecha sólo compite dentro de ese contexto, así
 * que el panel gana (`Spec/04` §5.6). Resultado suyo: en escritorio el carrusel sólo avanza.
 * Aquí la flecha sale del panel y funciona; la posición medida se recupera al cerrarlo.
 */
.ficha:has(.panel.abierto) .flecha.anterior { left: calc(var(--borde) + 376px); }

/* ══ EL MENU LATERAL · Spec/01 §5.6 ═══════════════════════════════════════════════════════════
 * La navegacion que cruza todas las pantallas. Cajon que entra desde la izquierda sobre un velo.
 * Medido: velo `#000/0.4` con `blur(4px)`; panel `24, 32 · 384 × 836`, radio 16, sombra
 * `0 25px 50px -12px rgb(0 0 0 / 0.25)`; items de 44 de alto con paso 44 y sangria 16.
 */
.menu-boton {
  position: fixed;
  top: var(--borde-arriba);
  left: var(--borde);
  height: 40px;
  padding: 8px 12px;
  border-radius: 9999px;
  background: var(--primario);
  color: var(--sobre-primario);
  font: 600 14px/20px var(--pila);
  box-shadow: var(--sombra-boton);
}

.pantalla-seccion .flecha {
  position: fixed;
  top: calc(50% - 20px);
  width: 40px;
  height: 40px;
  border-radius: 9999px;
  border: 0;
  background: var(--primario);
  color: var(--sobre-primario);
  box-shadow: var(--sombra-boton);
  cursor: pointer;
  z-index: 3;
}
.pantalla-seccion .flecha.anterior { left: var(--borde); }
.pantalla-seccion .flecha.anterior::before { content: "‹"; display: block; font: 600 20px/1 ui-sans-serif, system-ui, sans-serif; }
.pantalla-seccion .flecha.siguiente { right: var(--borde); }
.pantalla-seccion .flecha.siguiente::before { content: "›"; display: block; font: 600 20px/1 ui-sans-serif, system-ui, sans-serif; }

.visor .flecha {
  position: fixed;
  top: calc(50% - 20px);
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 9999px;
  background: var(--primario);
  color: var(--sobre-primario);
  cursor: pointer;
}
.visor .flecha.anterior { left: var(--borde); }
.visor .flecha.anterior::before { content: "‹"; display: block; font: 600 20px/1 ui-sans-serif, system-ui, sans-serif; }
.visor .flecha.siguiente { right: var(--borde); }
.visor .flecha.siguiente::before { content: "›"; display: block; font: 600 20px/1 ui-sans-serif, system-ui, sans-serif; }

/* ── 390 × 844 · Spec §3 «Chrome en 390×844»: mismas cajas, tres cambios ──────────────────── */
@media (max-width: 520px) {
  .ambiente { padding: 0 10px; }
  .marca { width: 96px; height: 40px; }
  .areas { top: auto; bottom: calc(var(--borde-abajo) + 56px); }
  .ambiente { min-width: 0; }

  .chrome:has(.vistas) .ambientes { right: calc(var(--borde) + 56px); }

  /* Las flechas y el contador viven en la mitad de arriba, que es la que enseña la lámina. */
  .ficha:has(.panel.abierto) .flecha { top: calc(22% - 20px); }
  .ficha:has(.panel.abierto) .flecha.anterior { left: 12px; }
}

[data-tema="web3d"] .menu-boton::before,
[data-tema="web3d"] .volver::before,
[data-tema="web3d"] .pantalla-completa::before,
[data-tema="web3d"] .acercar::before,
[data-tema="web3d"] .alejar::before,
[data-tema="web3d"] .asa-pisos:not(.cerrada)::before,
[data-tema="web3d"] .menu-cerrar::before {
  content: "";
  display: block;
  width: 20px;
  height: 20px;
  margin: auto;
  background: currentColor;
  -webkit-mask: var(--icono) center / contain no-repeat;
  mask: var(--icono) center / contain no-repeat;
}

/* ── Los mandos redondos: menú (acento) · volver (oscuro) · pantalla completa (oscuro) ────── */
[data-tema="web3d"] .menu-boton {
  --icono: var(--i-menu);
  width: 40px; height: 40px; padding: 0;
  font-size: 0; color: #fff;
  background: var(--primario);
  box-shadow: 0 1px 2px rgb(16 24 40 / 0.1);
}
[data-tema="web3d"] .volver,
[data-tema="web3d"] .volver.con-nombre {
  --icono: var(--i-volver);
  left: calc(var(--borde) + 56px);
  width: 40px; height: 40px; padding: 0;
  font-size: 0;
  background: var(--oscuro); color: #fff;
  box-shadow: 0 1px 2px rgb(16 24 40 / 0.1);
}
[data-tema="web3d"] .volver.con-nombre::before { font-size: 0; }
[data-tema="web3d"] .pantalla-completa {
  --icono: var(--i-pantalla);
  background: var(--oscuro); color: #fff;
  box-shadow: 0 1px 2px rgb(16 24 40 / 0.1);
}
[data-tema="web3d"] .menu-boton,
[data-tema="web3d"] .volver,
[data-tema="web3d"] .pantalla-completa,
[data-tema="web3d"] .acercar,
[data-tema="web3d"] .alejar,
[data-tema="web3d"] .asa-pisos:not(.cerrada),
[data-tema="web3d"] .menu-cerrar { line-height: 0; }
/* El icono va absoluto en el centro: el texto del boton (a 0 px) sigue siendo un nodo y en
   flujo empujaria el icono hacia arriba. */
[data-tema="web3d"] .menu-boton::before,
[data-tema="web3d"] .volver::before,
[data-tema="web3d"] .pantalla-completa::before,
[data-tema="web3d"] .acercar::before,
[data-tema="web3d"] .alejar::before,
[data-tema="web3d"] .asa-pisos:not(.cerrada)::before,
[data-tema="web3d"] .menu-cerrar::before { position: absolute; inset: 0; }
[data-tema="web3d"] .flecha,
[data-tema="web3d"] .pantalla-seccion .flecha {
  background: var(--oscuro); color: #fff;
  box-shadow: 0 1px 2px rgb(16 24 40 / 0.1);
}
[data-tema="web3d"] .acercar,
[data-tema="web3d"] .alejar {
  width: 36px; height: 36px;
  left: var(--borde);
  background: var(--oscuro); color: #fff;
}
[data-tema="web3d"] .acercar { --icono: var(--i-mas); bottom: calc(var(--borde-abajo) + 46px); }
[data-tema="web3d"] .alejar { --icono: var(--i-menos); }
[data-tema="web3d"] .acercar[disabled],
[data-tema="web3d"] .alejar[disabled] { opacity: 1; background: var(--apagado); color: #fff; }

[data-tema="web3d"] .chrome:has(.pisos:not(.cerrada)) .pantalla-completa { right: calc(85px + var(--borde)); }

[data-tema="web3d"] .pantalla:has(.panel.abierto) ~ .chrome .volver { left: calc(375px + var(--borde)); }

@media (max-width: 520px) {
  [data-tema="web3d"] .chrome:has(.pisos:not(.cerrada)):not(:has(.tarjeta)) .pantalla-completa { right: calc(95px + var(--borde)); }

  [data-tema="web3d"] .pantalla:has(.panel.abierto) ~ .chrome .volver { left: calc(var(--borde) + 56px); }
}

/* ── Mandos: un solo lenguaje ───────────────────────────────────────────────────────────────── */
[data-tema="web3d"] .menu-boton,
[data-tema="web3d"] .volver,
[data-tema="web3d"] .volver.con-nombre,
[data-tema="web3d"] .pantalla-completa,
[data-tema="web3d"] .flecha,
[data-tema="web3d"] .pantalla-seccion .flecha,
[data-tema="web3d"] .acercar,
[data-tema="web3d"] .alejar {
  width: 44px; height: 44px;
  border-radius: 22px;
  background: var(--material);
  -webkit-backdrop-filter: var(--desenfoque);
  backdrop-filter: var(--desenfoque);
  color: var(--etiqueta);
  box-shadow: var(--filo), var(--sombra-flota);
  transition: transform var(--t) var(--resorte), background-color var(--t) var(--resorte), opacity var(--t) var(--resorte);
}
[data-tema="web3d"] .menu-boton { top: var(--borde-arriba); left: var(--borde); }
[data-tema="web3d"] .volver,
[data-tema="web3d"] .volver.con-nombre { top: var(--borde-arriba); left: calc(var(--borde) + 52px); }
[data-tema="web3d"] .pantalla-completa { top: var(--borde-arriba); right: var(--borde); }
[data-tema="web3d"] .flecha { top: calc(50% - 22px); }
[data-tema="web3d"] .chrome button:active,
[data-tema="web3d"] .flecha:active { transform: scale(0.94); }
[data-tema="web3d"] .flecha::before { font: 400 28px/1 var(--pila); }

/* Acercar y alejar: UNA cápsula vertical abajo a la derecha, como Mapas. */
[data-tema="web3d"] .acercar,
[data-tema="web3d"] .alejar { left: auto; right: var(--borde); }
[data-tema="web3d"] .acercar { bottom: calc(var(--borde-abajo) + 44px); border-radius: 22px 22px 0 0; box-shadow: var(--filo); }
[data-tema="web3d"] .alejar { bottom: var(--borde-abajo); border-radius: 0 0 22px 22px; box-shadow: var(--filo), var(--sombra-flota); }
[data-tema="web3d"] .alejar::after {
  content: ""; position: absolute; top: 0; left: 10px; right: 10px;
  border-top: 0.5px solid var(--separador);
}
[data-tema="web3d"] .acercar[disabled],
[data-tema="web3d"] .alejar[disabled] { background: var(--material); color: var(--etiqueta-2); opacity: 0.6; }

[data-tema="web3d"] .chrome:has(.pisos:not(.cerrada)) .pantalla-completa { right: var(--borde); }

@media (max-width: 520px) {
  [data-tema="web3d"] .chrome:has(.pisos) .acercar { bottom: calc(var(--borde-abajo) + 64px + 44px); }
  [data-tema="web3d"] .chrome:has(.pisos) .alejar { bottom: calc(var(--borde-abajo) + 64px); }

  [data-tema="web3d"] .chrome:has(.pisos:not(.cerrada)):not(:has(.tarjeta)) .pantalla-completa { right: var(--borde); }
}

/* ══ PENDIENTES DEL PILOTO (📱 Motor-Pendientes, 23-sep-2026) ══════════════════════════════════ */

/* El QR de la vista (Ipanema ⑭): tercer mando redondo arriba a la izquierda, tras menú y volver. */
[data-tema="web3d"] .boton-qr {
  --icono: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linejoin='round'%3E%3Cpath d='M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h2v2h-2zM18 18h2v2h-2zM14 18h2M18 14h2'/%3E%3C/svg%3E");
  position: absolute;
  top: var(--borde-arriba); left: calc(var(--borde) + 104px);
  width: 44px; height: 44px; padding: 0;
  border-radius: 22px;
  font-size: 0; line-height: 0;
  background: var(--material);
  -webkit-backdrop-filter: var(--desenfoque);
  backdrop-filter: var(--desenfoque);
  color: var(--etiqueta);
  box-shadow: var(--filo), var(--sombra-flota);
}
[data-tema="web3d"] .chrome:not(:has(.volver)) .boton-qr { left: calc(var(--borde) + 52px); }
[data-tema="web3d"] .boton-qr::before {
  content: ""; position: absolute; inset: 0;
  width: 20px; height: 20px; margin: auto;
  background: currentColor;
  -webkit-mask: var(--icono) center / contain no-repeat;
  mask: var(--icono) center / contain no-repeat;
}
.qr-dialogo {
  width: min(360px, calc(100vw - 32px));
  padding: 16px 24px 24px;
  border: 0; border-radius: 28px;
  background: var(--lienzo, #fff); color: var(--etiqueta, #111);
  box-shadow: 0 24px 80px rgb(0 0 0 / 0.25);
  font-family: var(--pila);
  text-align: center;
}
.qr-dialogo::backdrop { background: rgb(0 0 0 / 0.4); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
.qr-cabeza { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.qr-titulo { margin: 0; font: 700 20px/25px var(--pila); }
.qr-cerrar {
  width: 32px; height: 32px; border: 0; border-radius: 16px;
  background: var(--relleno, #eee); color: inherit; font-size: 0; cursor: pointer; position: relative;
}
.qr-cerrar::before { content: "✕"; font: 500 14px/32px var(--pila); position: absolute; inset: 0; }
.qr-codigo { display: block; width: 100%; aspect-ratio: 1; border-radius: 12px; }
.qr-pista { margin: 12px 0 16px; font: 400 13px/18px var(--pila); color: var(--etiqueta-2, #666); }
.qr-pdf {
  width: 100%; height: 50px; border: 0; border-radius: 14px;
  background: var(--primario); color: #fff;
  font: 600 17px/22px var(--pila); cursor: pointer;
}

/* ── La portada: logotipo, lema, dirección, CTA ─────────────────────────────────────────────── */
[data-tema="web3d"] .marca { display: none; }

/* ── El dedo (📱, 23-sep-2026) ────────────────────────────────────────────────────────────────
   Con puntero grueso ningún control se toca en menos de 44 × 44 px (Apple HIG; Material pide 48).
   Los que flotan sobre el arte agrandan su ZONA DE TOQUE con un `::after` transparente y no su
   dibujo: el círculo de 30 px se sigue viendo de 30 y se toca de 44. Los que van en fila crecen de
   verdad, porque ahí el hueco sobra. Medido con la sonda de `Desarrollos/<inquilino>/6 · Showroom/Notas/Móvil Y Rendimiento.md` (inquilino piloto). */
@media (pointer: coarse) {
  .cerrar-panel, .cerrar-tarjeta, .menu-cerrar, .marca-poi, .interruptor-entorno, .asa-riel { overflow: visible; }
  .cerrar-panel::after, .cerrar-tarjeta::after, .menu-cerrar::after, .marca-poi::after, .interruptor-entorno::after, .asa-riel::after {
    content: ''; position: absolute; inset: -8px;
  }
  .cerrar-panel, .cerrar-tarjeta, .menu-cerrar, .asa-riel { isolation: isolate; }
  .asa-riel { position: relative; } /* estática: sin esto su `::after` tomaría la caja del riel entero */
  .piso, .pastilla-filtro, .filtro-mapa, .modo, .via-redonda { min-height: 44px; }
  .via-redonda, .pastilla-filtro, .piso { min-width: 44px; }
  .abrir-residencia, .ver-en-planta, select.control { min-height: 44px; }
  .maplibregl-ctrl-group button { width: 44px; height: 44px; }
}
/* ── Toques ≥ 44 px CON CUALQUIER PUNTERO (J4 · 🧹 Remates, 25-sep-2026) ───────────────────────
   El bloque de arriba sólo se enciende con `pointer: coarse`, y un portátil táctil o una tableta con
   ratón dicen `fine`: ahí el ✕ seguía de 30 px. La zona de toque es invisible, así que no cuesta nada
   tenerla siempre: el dibujo sigue fino (30, 32, 36 px) y el dedo toca 44+. Los de la fila del pie del
   menú (idioma, Legal) crecen de verdad: el hueco ya estaba. Los que la regla nombra ya tienen posición
   propia (absolute/fixed/relative), así que su `::after` se ancla a ellos. */
.cerrar-tarjeta, .menu-cerrar, .interruptor-entorno, .barra-cerrar, .flecha, .hoja-legal-cerrar, .qr-cerrar { overflow: visible; }
.cerrar-tarjeta::after, .menu-cerrar::after, .interruptor-entorno::after, .barra-cerrar::after,
.hoja-legal-cerrar::after, .qr-cerrar::after { content: ''; position: absolute; inset: -8px; }
.flecha::after { content: ''; position: absolute; inset: -6px; border-radius: 9999px; }

/* La leyenda: abajo a la IZQUIERDA en la planta, sobre la tira de niveles en teléfono. A la derecha
   la columna es de la tira y del zoom, y la leyenda se comía los niveles de abajo: a 1280×720 tapaba
   el 1.5 y el 1 (✨ Pulir-Torre, 27-sep-2026). */
.leyenda-estados {
  position: absolute; left: var(--borde); bottom: var(--borde-abajo); z-index: 3;
  display: flex; flex-direction: column; gap: 2px; padding: 8px 10px;
  border-radius: 14px; background: var(--material, rgb(255 255 255 / 0.92)); color: var(--tinta);
  box-shadow: var(--filo, none), var(--sombra-chip);
  -webkit-backdrop-filter: var(--desenfoque, none); backdrop-filter: var(--desenfoque, none);
  pointer-events: none;
}
.leyenda-estado { display: flex; align-items: center; gap: 8px; min-height: 22px; font: 500 12px/16px var(--pila); }
.leyenda-estado .muestra {
  width: 14px; height: 14px; border-radius: 4px; flex: none; box-sizing: border-box;
  background-color: var(--color-estado); border: 1.5px solid var(--color-estado);
}
/* La muestra dice lo que hace el polígono: el primer estado es un color lleno; los demás, un
   contorno hueco como su velo. El texto es la distinción sin color, nunca una trama. */
.leyenda-estado:not(.patron-liso) .muestra { background-color: transparent; }
.leyenda-estado .cuantas { margin-left: auto; padding-left: 10px; color: var(--tinta-suave); font-variant-numeric: tabular-nums; }

@media (max-width: 520px) {
  .leyenda-estados { flex-direction: row; gap: 12px; right: auto; left: 50%; transform: translateX(-50%); bottom: calc(var(--borde-abajo) + 72px); padding: 6px 12px; }
  .leyenda-estado .cuantas { display: none; }
}

/* La pastilla del filtro puesto: arriba al centro, con su «quitar» de 44 px. */
.filtro-activo {
  position: absolute; top: calc(var(--borde-arriba) + 56px); left: 50%; transform: translateX(-50%); z-index: 6;
  display: flex; align-items: center; gap: 4px; max-width: calc(100vw - 2 * var(--borde));
  padding: 0 0 0 16px; min-height: 44px; border-radius: 22px;
  background: var(--primario); color: var(--sobre-primario); box-shadow: var(--sombra-chip);
  font: 600 13px/18px var(--pila);
}
.filtro-activo .texto { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.quitar-filtro {
  flex: none; width: 44px; height: 44px; border: 0; border-radius: 22px; cursor: pointer;
  background: transparent; color: inherit; position: relative;
}
.quitar-filtro::before, .quitar-filtro::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 14px; height: 1.8px; border-radius: 1px; background: currentColor;
}
.quitar-filtro::before { transform: translate(-50%, -50%) rotate(45deg); }
.quitar-filtro::after { transform: translate(-50%, -50%) rotate(-45deg); }
.quitar-filtro:focus-visible { outline: 2px solid var(--sobre-primario); outline-offset: -4px; }

/* ══ 🍎 LA PORTADA COMO LA HARÍA APPLE (25-sep-2026) ════════════════════════════════════════════
 * `Desarrollos/<inquilino>/6 · Showroom/Notas/<inquilino> · Interfaz Apple.md` (inquilino piloto). Sólo `web3d`.
 *   Arriba: ☰ · marca ········ 🔍 · Contact (la única acción de color).
 *   Derecha: la barra de niveles (pastilla = minitorre; abierta = botonera; abrirla explota).
 *   Abajo al centro: la cápsula del giro ‹ • • › con sus paradas. Pantalla completa sólo al hover.
 *   Dentro del nivel y la ficha, migas en lugar de «Regresar». Sin QR suelto (va en Share). */

/* La marca: en su pastilla de material, en tinta (el logotipo es monocromo). */
[data-tema="web3d"] .chrome:has(.acciones) > .marca {
  display: block;
  top: var(--borde-arriba); left: calc(var(--borde) + 52px);
  width: auto; height: 44px; box-sizing: border-box;
  padding: 15px 16px; border-radius: 22px;
  background: var(--material);
  -webkit-backdrop-filter: var(--desenfoque); backdrop-filter: var(--desenfoque);
  box-shadow: var(--filo), var(--sombra-flota);
  color: var(--etiqueta);
}
[data-tema="web3d"] .marca-pastilla .logotipo {
  display: block; width: 104px; height: 14px; background: currentColor;
  -webkit-mask: var(--logotipo) left center / contain no-repeat; mask: var(--logotipo) left center / contain no-repeat;
}
[data-tema="web3d"] .chrome:has(.migas) > .marca { display: none; }
/* En el teléfono no cabe (🩹 CSS-Reglas-Muertas, 27-sep-2026): el chip «Choose a Level» cuelga del
   techo de la torre y en 375 × 667 cae en `116, 34 → 259, 66`, encima de la pastilla (`68, 16 → 204, 60`);
   en 390 la roza 5 px y en 320 la pastilla queda a 3 px de las acciones. Desde 600 px no toca nada. */
@media (max-width: 560px) {
  [data-tema="web3d"] .chrome:has(.acciones) > .marca { display: none; }
}

/* Pantalla completa: fuera del reposo. Aparece al pasar el ratón, abajo a la derecha; no en teléfono. */
[data-tema="web3d"] .chrome > .pantalla-completa {
  top: auto; bottom: var(--borde-abajo); right: var(--borde);
  opacity: 0; pointer-events: none;
}

@media (hover: hover) and (pointer: fine) {
  [data-tema="web3d"] body:hover .chrome > .pantalla-completa { opacity: 1; pointer-events: auto; }
}

@media (hover: none), (max-width: 520px) {
  [data-tema="web3d"] .chrome > .pantalla-completa { display: none; }
}

[data-tema="web3d"] .chrome:has(.acercar) > .pantalla-completa { right: calc(var(--borde) + 52px); }

/* Arriba a la derecha: lupa + Contact. */
[data-tema="web3d"] .acciones {
  position: absolute; top: var(--borde-arriba); right: var(--borde); z-index: 6;
  display: flex; gap: 8px; align-items: center;
}
[data-tema="web3d"] .acciones .lupa {
  position: relative; width: 44px; height: 44px; padding: 0; border-radius: 22px; font-size: 0; line-height: 0;
  background: var(--material); color: var(--etiqueta);
  -webkit-backdrop-filter: var(--desenfoque); backdrop-filter: var(--desenfoque);
  box-shadow: var(--filo), var(--sombra-flota);
}
[data-tema="web3d"] .acciones .lupa::before {
  content: ""; position: absolute; inset: 0; margin: auto; width: 20px; height: 20px; background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.9' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.5 15.5L20 20'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.9' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.5 15.5L20 20'/%3E%3C/svg%3E") center / contain no-repeat;
}
[data-tema="web3d"] .acciones .contactar {
  height: 44px; padding: 0 20px; border-radius: 22px;
  background: var(--primario); color: var(--sobre-primario, #fff);
  font: 600 15px/20px var(--pila);
  box-shadow: 0 8px 24px color-mix(in srgb, var(--primario) 35%, transparent);
}

/* 🔍 En el teléfono la lupa se queda en la portada (Victor, 28-sep-2026, Remates Del Showroom ③): ahí
   sólo están ☰ y Contact. Donde hay migas (nivel, ficha) no cabe junto a ellas y se busca desde el menú. */
@media (max-width: 520px) {
  [data-tema="web3d"] .chrome:has(.migas) .acciones .lupa { display: none; }
}

/* Con la hoja de la unidad abierta en teléfono, Contact ya está en la hoja. */
[data-tema="web3d"] .chrome:has(.menu) .acciones { visibility: hidden; }

/* Las migas: <Desarrollo> › Level 6 › 601. */
[data-tema="web3d"] .migas {
  position: absolute; top: var(--borde-arriba); left: calc(var(--borde) + 52px); z-index: 6;
  height: 44px; padding: 0 18px; border-radius: 22px;
  display: flex; align-items: center; gap: 6px; max-width: calc(100vw - 2 * var(--borde) - 52px - 150px);
  background: var(--material); color: var(--etiqueta);
  -webkit-backdrop-filter: var(--desenfoque); backdrop-filter: var(--desenfoque);
  box-shadow: var(--filo), var(--sombra-flota);
  font: 500 15px/20px var(--pila); white-space: nowrap;
}
[data-tema="web3d"] .migas .miga { background: none; border: 0; padding: 0; font: inherit; color: var(--etiqueta-2); overflow: hidden; text-overflow: ellipsis; }
[data-tema="web3d"] .migas button.miga { cursor: pointer; }
[data-tema="web3d"] .migas button.miga:hover { color: var(--etiqueta); }
[data-tema="web3d"] .migas .miga.aqui { color: var(--etiqueta); font-weight: 600; }
[data-tema="web3d"] .migas .miga-sep { color: var(--etiqueta-2); font-size: 13px; }

@media (max-width: 520px) {
  [data-tema="web3d"] .migas { padding: 0 14px; font-size: 14px; }
}

[data-tema="web3d"] .migas .miga { min-width: 0; }
[data-tema="web3d"] .migas .miga.aqui { flex: none; }

@media (max-width: 520px) {
  [data-tema="web3d"] .migas:has(> .miga ~ .miga ~ .miga) > .miga:first-child,
  [data-tema="web3d"] .migas:has(> .miga ~ .miga ~ .miga) > .miga:first-child + .miga-sep { display: none; }
  /* Con dos migas, la del desarrollo es el botón de vuelta y no se corta («Zig›» con «Level 12 · PHA»): cede la del
     nivel, que el titular repite entero justo debajo. */
  [data-tema="web3d"] .migas > .miga:first-child { flex: none; }
  [data-tema="web3d"] .migas > .miga.aqui { flex: 0 1 auto; }
}

[data-tema="web3d"] .giro .flecha {
  position: relative; inset: auto; top: auto; left: auto; right: auto;
  width: 36px; height: 36px; background: transparent; box-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
[data-tema="web3d"] .giro .flecha::before { font: 400 24px/1 var(--pila); }

/* En las pantallas del menú manda «volver»: la pastilla de la marca no va. */
[data-tema="web3d"] .chrome:has(.volver) > .marca { display: none; }
/* 🧱 La portada que vende: el edificio a sangre, su nombre o logotipo, lema, direccion y un solo boton. */

/*
 * LA PORTADA QUE VENDE: el edificio entero a sangre, su nombre y un solo boton. Un velo abajo
 * para que el nombre se lea sobre cualquier arte, sin tapar el edificio.
 */
.portada {
  position: absolute;
  inset: auto 0 0 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  padding: 120px var(--borde) calc(var(--borde-abajo) + 40px);
  background: linear-gradient(to top, rgb(16 24 40 / 0.62), rgb(16 24 40 / 0));
  pointer-events: none;
}
.portada > * { pointer-events: auto; }
.nombre-desarrollo {
  margin: 0;
  font: 300 clamp(44px, 9vw, 96px)/1 var(--pila);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 1px 12px rgb(0 0 0 / 0.25);
}
.portada .cta { position: static; transform: none; }
.cta {
  position: absolute;
  left: 50%;
  bottom: calc(var(--borde-abajo) + 48px);
  transform: translateX(-50%);
  height: 48px;
  padding: 0 32px;
  border-radius: 9999px;
  background: var(--primario);
  color: var(--sobre-primario);
  font: 600 14px/20px var(--pila);
  box-shadow: var(--sombra-boton);
}

/* ── La portada: `Discover` blanco de 250 × 48, radio 24 ──────────────────────────────────── */
[data-tema="web3d"] .cta {
  min-width: 250px; height: 48px;
  border-radius: 24px;
  background: #fff; color: var(--velo);
  font: 500 15px/20px var(--pila);
  box-shadow: none;
}

/* ── La portada ─────────────────────────────────────────────────────────────────────────────── */
[data-tema="web3d"] .portada { gap: 24px; padding-bottom: calc(var(--borde-abajo) + 48px); background: linear-gradient(to top, rgb(0 0 0 / 0.55), rgb(0 0 0 / 0)); }
[data-tema="web3d"] .nombre-desarrollo { font: 700 clamp(48px, 9vw, 96px)/1 var(--pila); letter-spacing: 0.02em; text-transform: none; }
[data-tema="web3d"] .cta {
  min-width: 200px; height: 52px; padding: 0 32px;
  border-radius: 26px;
  background: rgb(255 255 255 / 0.86);
  -webkit-backdrop-filter: var(--desenfoque);
  backdrop-filter: var(--desenfoque);
  color: #1d1d1f;
  font: 600 17px/22px var(--pila);
  transition: transform var(--t) var(--resorte);
}

[data-tema="web3d"] .portada { gap: 0; }
[data-tema="web3d"] .nombre-desarrollo { letter-spacing: -0.02em; margin: 0; }
[data-tema="web3d"] .nombre-desarrollo.con-logotipo { line-height: 0; }
[data-tema="web3d"] .logotipo {
  display: block;
  width: clamp(240px, 36vw, 520px); aspect-ratio: 183 / 24;
  background: #fff;
  -webkit-mask: var(--logotipo) center / contain no-repeat;
  mask: var(--logotipo) center / contain no-repeat;
  filter: drop-shadow(0 1px 12px rgb(0 0 0 / 0.25));
}
[data-tema="web3d"] .lema {
  margin: 28px 0 0; display: flex; flex-direction: column; align-items: center;
  font: 300 clamp(20px, 2.2vw, 28px)/1.3 var(--pila); letter-spacing: -0.015em;
  color: #fff; text-align: center; text-wrap: balance;
  text-shadow: 0 1px 16px rgb(0 0 0 / 0.35);
}
[data-tema="web3d"] .lema .renglon:last-child { font-weight: 500; }
[data-tema="web3d"] .portada-direccion {
  margin: 14px 0 32px; font: 500 12px/16px var(--pila); letter-spacing: 0.14em; text-transform: uppercase;
  color: rgb(255 255 255 / 0.86);
}
[data-tema="web3d"] .cta { letter-spacing: -0.01em; }

@media (max-width: 520px) {
  [data-tema="web3d"] .logotipo { width: min(78vw, 300px); }
  [data-tema="web3d"] .lema { padding: 0 24px; }
}

/*
 * ── EL TEXTO VA DONDE LA FOTO TIENE AIRE (26-sep-2026) ─────────────────────────────────────────
 * La portada nueva centra la torre con la entrada y el muro del nombre abajo al centro: el bloque
 * pegado al pie los tapaba. Ahora la portada ocupa la pantalla entera y se parte en dos: arriba,
 * en el cielo, el logotipo (y en escritorio el lema en un renglón); abajo, en la banda de la
 * calle, lo que queda y el CTA. Cada banda lleva su velo corto; el centro —torre, entrada, muro—
 * queda limpio. El texto no atrapa el dedo: sólo el CTA; los polígonos de nivel siguen tocables.
 */
[data-tema="web3d"] .portada {
  inset: 0;
  justify-content: flex-start;
  padding: calc(var(--borde-arriba) + 14px) var(--borde) calc(var(--borde-abajo) + 28px);
  background:
    linear-gradient(to bottom, rgb(0 0 0 / 0.34), rgb(0 0 0 / 0) 26%),
    linear-gradient(to top, rgb(0 0 0 / 0.56), rgb(0 0 0 / 0) 30%);
}
[data-tema="web3d"] .portada > * { pointer-events: none; }
[data-tema="web3d"] .portada > .cta { pointer-events: auto; }
[data-tema="web3d"] .portada .logotipo { width: clamp(220px, 24vw, 340px); }
[data-tema="web3d"] .portada .lema {
  margin-top: 16px; flex-direction: row; flex-wrap: wrap; justify-content: center; column-gap: 0.3em;
  max-width: 860px; font-size: clamp(18px, 1.6vw, 22px);
}
/* Escritorio: lema arriba con el logotipo; dirección y CTA empujados al pie. */
[data-tema="web3d"] .portada .portada-direccion { margin: auto 0 16px; text-shadow: 0 1px 8px rgb(0 0 0 / 0.5); }
[data-tema="web3d"] .portada .lema + .cta,
[data-tema="web3d"] .portada .nombre-desarrollo + .cta { margin-top: auto; }

/* Retrato (teléfono): el cielo sólo cabe el logotipo; lema, dirección y CTA bajan a la calle. */
@media (max-aspect-ratio: 4 / 5) {
  [data-tema="web3d"] .portada { background:
    linear-gradient(to bottom, rgb(0 0 0 / 0.3), rgb(0 0 0 / 0) 14%),
    linear-gradient(to top, rgb(0 0 0 / 0.6), rgb(0 0 0 / 0) 30%); }
  [data-tema="web3d"] .portada .logotipo { width: min(56vw, 240px); }
  [data-tema="web3d"] .portada .lema {
    margin: auto 0 0; padding: 0; flex-direction: column; font-size: 17px; line-height: 1.3;
  }
  /* La dirección ya vive en el menú; aquí empujaría el lema sobre el muro de la entrada. */
  [data-tema="web3d"] .portada .portada-direccion { display: none; }
  [data-tema="web3d"] .portada .lema ~ .cta { margin-top: 20px; }
}
/* 🧱 La torre y sus niveles: la tira de pisos, las vistas, el titulo del nivel, el descenso y el entorno (`descenso.ts`), la minitorre (`minimapa.ts`), el giro y la barra de niveles. */

/* «Floors» / «Whole building»: pildora abajo al centro, sobre el arte. */
.pisos-explotar {
  position: absolute; left: 50%; bottom: calc(var(--borde-abajo, 16px) + 8px); transform: translateX(-50%);
  z-index: 60; pointer-events: auto; cursor: pointer;
  padding: 10px 22px; border: 0; border-radius: 999px;
  background: var(--primario); color: var(--sobre-primario, #fff);
  font: 600 14px/1 var(--familia, system-ui), system-ui, sans-serif; letter-spacing: 0.04em;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
}
.pisos-explotar.armar { background: rgba(255, 255, 255, 0.94); color: #222; }
.chrome .pisos-explotar:active { transform: translateX(-50%) scale(0.95); }
.ocupado .pisos-explotar { opacity: 0.5; pointer-events: none; }

/* ── El piso ──────────────────────────────────────────────────────────────────────────────── */

/*
 * El rotulo del sitio · `16, 144 · 60.7 × 24` (Spec/02 §3), debajo del logotipo.
 *
 * Estaba CENTRADO ARRIBA en `664, 16`, en pildora clara sobre tinta oscura: Δ +644 en x, −128 en
 * y, y los cuatro atributos visuales invertidos. Ahi arriba competia por el carril con los
 * mandos; aqui cuelga del logotipo —`16, 80` mas sus 48 de alto mas 16 de hueco— y el bloque de
 * identidad queda junto.
 */
.donde {
  position: absolute;
  pointer-events: none;
  top: calc(var(--borde-arriba) + 128px);
  left: var(--borde);
  padding: 4px 8px;
  border-radius: 0;
  background: rgb(0 0 0 / 0.4);
  backdrop-filter: blur(8px);
  font: 600 12px/16px var(--pila);
  color: #fff;
}

/*
 * El interruptor de vista · `1256, 16 · 112 × 48` (Spec/02 §3), arriba a la derecha.
 *
 * Estaba ABAJO AL CENTRO, `659, 838`: Δ −597 en x y +822 en y, encima del arte y justo sobre la
 * franja donde el telefono espera el aviso de arrastre. Sube con el resto del chrome superior.
 *
 * Y CUANDO LOS DOS EXISTEN, EL CHROME SE CORRE EN VEZ DE SUPERPONERSE. En un piso con dia y
 * noche este interruptor y el de ambiente caen en el mismo carril de la derecha; el de ambiente
 * se aparta 120 px —112 de esta pildora mas 8 de hueco— en lugar de pisarse. Dos botones en el
 * mismo pixel son un bug, no un detalle.
 */
.vistas {
  position: absolute;
  top: var(--borde-arriba);
  /* 0.6 y no 0.3, igual que `.ambientes`: el vidrio claro no sostiene 4.5:1 sobre fondos claros. */
  right: calc(var(--borde) + 56px);
  display: flex;
  gap: 4px;
  padding: 4px;
  border-radius: 9999px;
  background: rgb(0 0 0 / 0.6);
  backdrop-filter: blur(12px);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.2);
}

.vista {
  min-width: 48px;
  height: 40px;
  padding: 0 18px;
  border-radius: 9999px;
  background: transparent;
  color: rgb(255 255 255 / 0.9);
  font: 600 12px/16px var(--pila);
}
.vista.activa { background: #fff; color: #000; }

/*
 * La tira de pisos · `1340.9, 80 · 91.1 × 684`, pildoras de `75.1 × 40` con paso 44 y radio 12
 * (Spec/02 §3). Medida vieja: `1351.7, 135 · 72.3 × 630` con pildoras de 30 y radio 8.
 *
 * Y EL ORDEN IBA AL REVES, que es lo que se nota sin medir nada: `9°` encabezaba la lista y
 * `Terraza` la cerraba. Se invierte EN EL DOM y no aqui con `column-reverse`: esa propiedad
 * cambia lo que se ve y deja el orden de TABULACION al reves, o sea que el teclado subiria el
 * edificio al contrario que el ojo. Ver `chrome.ts`.
 */
.pisos {
  position: absolute;
  top: calc(var(--borde-arriba) + 64px);
  right: var(--borde);
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: calc(100% - var(--borde-arriba) - 200px);
  overflow-y: auto;
  padding: 8px;
  border-radius: 16px;
  background: rgb(255 255 255 / 0.8);
  backdrop-filter: blur(8px);
  scrollbar-width: thin;
}
.piso {
  min-width: 75px;
  height: 40px;
  flex: 0 0 auto;
  border-radius: 12px;
  background: transparent;
  color: var(--tinta);
  font: 600 12px/16px var(--pila);
}
/*
 * `Ocultar Pisos` ⇄ `Mostrar Pisos` · `1384, 788 · 40 × 40` y `334, 732 · 40 × 40` (Spec/02 §3).
 * La misma regla da las dos: pegado al borde derecho, 56 px por encima del borde de abajo.
 * En escritorio la tira nace ABIERTA y en telefono CERRADA, y eso lo dice la media query; la
 * clase solo aparece cuando el visitante decide otra cosa. Ver `chrome.ts`, `tiraAbierta`.
 */
.asa-pisos {
  position: absolute;
  right: var(--borde);
  bottom: calc(var(--borde-abajo) + 56px);
  width: 40px;
  height: 40px;
  border-radius: 9999px;
  background: var(--superficie);
  color: var(--tinta);
  box-shadow: var(--sombra-boton);
}
/* Una palabra, no tres lineas: el icono «≡» se leia como menu (rediseno web3d). */
.asa-pisos { width: auto; padding: 0 16px; font: 600 13px/20px var(--pila); }
.asa-pisos.cerrada { background: var(--primario); color: var(--sobre-primario); }
.pisos.cerrada { display: none; }
.piso:hover { background: var(--superficie); }
.piso.activo { background: var(--primario); color: var(--sobre-primario); }
.piso.mudo { opacity: 0.35; cursor: default; }

@media (max-width: 520px) {
  /*
   * A 390 EL CARRIL DE ARRIBA YA ESTA LLENO —`Menú`, `Volver` y `Pantalla completa`— y el
   * `2D ⇄ 3D` no cabe al lado del interruptor de ambiente: 112 + 118 px en los 166 que quedan
   * libres. Baja una fila en vez de superponerse, que es la misma regla de arriba aplicada
   * donde el ancho manda.
   */
  .vistas { top: calc(var(--borde-arriba) + 48px); right: var(--borde); }
  /*
   * LA TIRA NACE CERRADA, como en la referencia (`Spec/02` §3.3): a 390 px tapaba `72.3 × 422` de
   * un arte del que el telefono solo ve el 26 %, y con el los rotulos `34-03`, `34-09` y los de
   * la banda derecha. Se abre con el asa, y entonces baja por debajo del carril de mandos.
   */
  .pisos { display: none; top: calc(var(--borde-arriba) + 96px); max-height: calc(100% - var(--borde-arriba) - 216px); }
  .pisos.abierta { display: flex; }
  .asa-pisos { background: var(--primario); color: var(--sobre-primario); }
  .asa-pisos.abierta { background: var(--superficie); color: var(--tinta); }
  /*
   * CON LA TARJETA ABIERTA, EL ASA NO ESTA. A 390 px la tarjeta es un cajon de abajo
   * —`12, 474 · 366 × 302`— y el asa cae DENTRO de esa caja, en `334, 732`: se dibujaria encima
   * del dato que el visitante acaba de pedir. Se cierra la tarjeta y vuelve. (La referencia la
   * deja puesta y su cajon la tapa igual; aqui no se copia el solape.)
   */
  .chrome:has(.tarjeta) .asa-pisos, .chrome:has(.tarjeta) .pisos { display: none; }

  /* El rotulo del sitio cuelga del logotipo, que aqui mide 40 de alto y no 48. */
  .donde { top: calc(var(--borde-arriba) + 120px); }
}

/* «Floors» es secundario: píldora blanca arriba a la derecha, donde Ipanema pone `Galería`. */
[data-tema="web3d"] .pisos-explotar {
  top: var(--borde-arriba); bottom: auto;
  left: auto; right: calc(var(--borde) + 56px);
  transform: none;
  height: 40px; padding: 0 16px;
  border-radius: 20px;
  background: #fff; color: var(--tinta);
  font: 500 14px/14px var(--pila); letter-spacing: 0;
  box-shadow: 0 1px 2px rgb(16 24 40 / 0.1);
}
[data-tema="web3d"] .chrome .pisos-explotar:active { transform: scale(0.95); }
[data-tema="web3d"] .chrome:not(:has(.pantalla-completa)) .pisos-explotar { right: var(--borde); }

/* ── El nivel: rótulo de lugar y tira oscura a sangre ─────────────────────────────────────── */
[data-tema="web3d"] .donde {
  top: calc(var(--borde-arriba) + 60px);
  padding: 3px 18px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--oscuro) 78%, transparent);
  backdrop-filter: none;
  font: 500 12px/16px var(--pila);
}
[data-tema="web3d"] .pisos {
  top: 0; right: 0; bottom: 0;
  width: 85px;
  max-height: none;
  gap: 0;
  padding: 80px 8px 16px;
  border-radius: 0;
  background: var(--oscuro);
  backdrop-filter: none;
}
[data-tema="web3d"] .piso {
  width: 100%; min-width: 0; height: 40px;
  border-radius: 20px;
  color: #fff;
  font: 500 13px/16px var(--pila);
}
[data-tema="web3d"] .piso:hover { background: rgb(255 255 255 / 0.1); }
[data-tema="web3d"] .piso.activo { background: var(--tenue); color: var(--oscuro); }
[data-tema="web3d"] .piso.mudo { opacity: 0.35; }
/* El asa: con la tira abierta es su ✕; cerrada, la píldora `Levels` (Ipanema `Cambiar planta`). */
[data-tema="web3d"] .asa-pisos:not(.cerrada) {
  --icono: var(--i-cerrar);
  top: var(--borde-arriba); bottom: auto; right: 22px;
  width: 40px; padding: 0;
  font-size: 0;
  background: transparent; color: #fff; box-shadow: none;
  z-index: 1;
}
[data-tema="web3d"] .asa-pisos.cerrada {
  top: var(--borde-arriba); bottom: auto; right: calc(var(--borde) + 56px);
  height: 40px; padding: 0 16px;
  border-radius: 20px;
  background: #fff; color: var(--tinta);
  font: 500 14px/14px var(--pila);
  box-shadow: 0 1px 2px rgb(16 24 40 / 0.1);
}

@media (max-width: 520px) {
  /* Ipanema a 390: la tira nace abierta y tapa el borde derecho; ✕ la cierra. */
  [data-tema="web3d"] .pisos:not(.cerrada) { display: flex; top: 0; max-height: none; }
  [data-tema="web3d"] .asa-pisos:not(.cerrada) { background: transparent; color: #fff; }
  [data-tema="web3d"] .asa-pisos.cerrada { background: #fff; color: var(--tinta); }
  [data-tema="web3d"] .pisos { width: 95px; }
  /* Con la tarjeta abierta (hoja inferior) la tira y su ✕ se van, igual que en `classic`. */
  [data-tema="web3d"] .chrome:has(.tarjeta) .pisos,
  [data-tema="web3d"] .chrome:has(.tarjeta) .asa-pisos { display: none; }

  [data-tema="web3d"] .donde { top: calc(var(--borde-arriba) + 60px); }
}

/* ══ EL OFICIO · LA PIEL WEB3D CON CRITERIO DE APPLE (HIG) ═══════════════════════════════════
 *
 * Encima de la piel de Ipanema, no en su lugar: el flujo y las cajas de arriba siguen, esto
 * cambia el oficio (`Desarrollos/<inquilino>/6 · Showroom/Notas/<inquilino> · Diseño.md`, del inquilino piloto). Reglas:
 *   · Una familia (la del sistema: SF en Apple) y una escala: 34 título · 22 · 17 · 15 · 13.
 *   · Un solo lenguaje de mandos: círculos de 44 en MATERIAL (blanco translúcido + desenfoque)
 *     con el icono de línea en tinta. El color del desarrollo sólo en la acción principal.
 *   · Espaciado en múltiplos de 8; movimiento de 0.35 s con curva de resorte, sin esperar cargas.
 *   · El nivel se nombra grande («Level 8») con lo que hay debajo («2 residences · 1 available»);
 *     la tira es una cápsula flotante; la unidad se abre en hoja inferior arrastrable (Mapas).
 * `.titular-nivel` y `.asa-hoja` las dibuja `chrome.ts` en todas las pieles; `classic` las oculta aquí.
 */
.titular-nivel, .asa-hoja { display: none; }

/* «Floors» y las pestañas de vista: cápsulas de material, texto 15. */
[data-tema="web3d"] .pisos-explotar,
[data-tema="web3d"] .asa-pisos.cerrada {
  height: 44px; padding: 0 20px;
  top: var(--borde-arriba);
  border-radius: 22px;
  background: var(--material);
  -webkit-backdrop-filter: var(--desenfoque);
  backdrop-filter: var(--desenfoque);
  color: var(--etiqueta);
  font: 600 15px/20px var(--pila);
  box-shadow: var(--filo), var(--sombra-flota);
}
[data-tema="web3d"] .pisos-explotar { right: calc(var(--borde) + 52px); }

/* ── El nivel: título grande, plano con aire sobre lienzo, tira flotante ────────────────────── */
[data-tema="web3d"] .donde { display: none; }
[data-tema="web3d"] .titular-nivel {
  display: block;
  position: absolute;
  top: calc(var(--borde-arriba) + 60px);
  left: var(--borde);
  pointer-events: none;
  }
[data-tema="web3d"] .titular-nivel-titulo { margin: 0; font: 700 34px/41px var(--pila); letter-spacing: 0.01em; color: var(--etiqueta); }
[data-tema="web3d"] .titular-nivel-resumen { margin: 0; font: 400 15px/20px var(--pila); color: var(--etiqueta-2); }
[data-tema="web3d"] .titular-nivel.entra { animation: entra-titular var(--t) var(--resorte) backwards; }
@keyframes entra-titular { from { opacity: 0; transform: translateY(8px); } }

[data-tema="web3d"] body:has(.chrome .titular-nivel) .recorrido { background: var(--lienzo); }

@media (min-width: 521px) {
  /* El plano ENTERO, con 176 px de aire a los lados y 120 arriba y abajo: una hoja sobre lienzo,
     no una foto a sangre. El chip compensa la escala para seguir leyéndose a su tamaño. */
  [data-tema="web3d"] body:has(.chrome .titular-nivel) .escenario {
    --ajuste: var(--ajuste-escritorio, 1); /* número, lo calcula `medirViewport` */
    transform: translate(-50%, -50%) scale(calc(var(--zoom) * var(--ajuste))) translate(var(--paneo-x), var(--paneo-y));
    transition-timing-function: var(--resorte);
    border-radius: 16px;
    background-color: var(--lienzo);
    box-shadow: 0 0 0 0.5px var(--separador), 0 24px 80px rgb(0 0 0 / 0.1);
  }
}

/* La tira: cápsula flotante de material, centrada a la derecha; el activo en tinta. */
[data-tema="web3d"] .asa-pisos:not(.cerrada) { display: none; }
[data-tema="web3d"] .pisos {
  top: 50%; bottom: auto; right: var(--borde);
  transform: translateY(-50%);
  width: auto; min-width: 104px;
  max-height: calc(100% - var(--borde-arriba) - var(--borde-abajo) - 208px);
  gap: 2px; padding: 6px;
  border-radius: 24px;
  background: var(--material);
  -webkit-backdrop-filter: var(--desenfoque);
  backdrop-filter: var(--desenfoque);
  box-shadow: var(--filo), var(--sombra-flota);
  scrollbar-width: none;
}
[data-tema="web3d"] .piso {
  height: 36px; padding: 0 16px;
  border-radius: 18px;
  color: var(--etiqueta);
  font: 500 15px/20px var(--pila);
  white-space: nowrap;
  transition: background-color var(--t) var(--resorte), color var(--t) var(--resorte);
}
[data-tema="web3d"] .piso:hover { background: var(--relleno); }
[data-tema="web3d"] .piso.activo { background: var(--etiqueta); color: var(--lienzo); font-weight: 600; }

/* CUANDO LA TIRA NO CABE Y SE DESPLAZA (1280×720: 15 niveles en 480 px), el nivel del borde se
   cortaba en seco y nada decía que había más. Un velo del material, pegado arriba y abajo, aparece
   del lado donde quedan niveles y se va al llegar al tope. Va atado al desplazamiento de la propia
   tira: si cabe, la línea de tiempo no existe, la animación no se aplica y el velo queda en 0. */
@supports (animation-timeline: scroll()) {
  @media (min-width: 521px) {
    [data-tema="web3d"] .pisos::before,
    [data-tema="web3d"] .pisos::after {
      content: ''; flex: none; position: sticky; z-index: 1; height: 28px; pointer-events: none; opacity: 0;
      margin-inline: -6px; animation-timeline: scroll(); animation-fill-mode: both; animation-timing-function: linear;
    }
    [data-tema="web3d"] .pisos::before {
      top: -6px; margin-top: -6px; margin-bottom: -22px; border-radius: 24px 24px 0 0;
      background: linear-gradient(var(--material-grueso, #fff), transparent);
      animation-name: tira-velo-arriba;
    }
    [data-tema="web3d"] .pisos::after {
      bottom: -6px; margin-bottom: -6px; margin-top: -22px; border-radius: 0 0 24px 24px;
      background: linear-gradient(transparent, var(--material-grueso, #fff));
      animation-name: tira-velo-abajo;
    }
    @keyframes tira-velo-arriba { 0% { opacity: 0; } 6%, 100% { opacity: 1; } }
    @keyframes tira-velo-abajo { 0%, 94% { opacity: 1; } 100% { opacity: 0; } }
  }
}

@media (max-width: 520px) {
  /* Teléfono: la tira se tumba abajo, de lo bajo a lo alto, como un control segmentado. */
  [data-tema="web3d"] .pisos,
  [data-tema="web3d"] .pisos:not(.cerrada) {
    display: flex;
    flex-direction: row-reverse;
    top: auto; bottom: var(--borde-abajo); left: var(--borde); right: var(--borde);
    transform: none;
    width: auto; min-width: 0; max-height: none;
    overflow-x: auto; overflow-y: hidden;
    border-radius: 24px;
  }
  [data-tema="web3d"] .piso { flex: 0 0 auto; width: auto; }

  [data-tema="web3d"] .titular-nivel { top: calc(var(--borde-arriba) + 56px); }
  [data-tema="web3d"] .titular-nivel-titulo { font-size: 28px; line-height: 34px; }
}

/* El pellizco táctil lo lleva la capa (`app.ts`) donde hay acercar; el navegador no amplía la página. */
[data-tema="web3d"] body:has(.chrome .acercar) .escenario { touch-action: none; }

@media (max-width: 520px) {
  /* Teléfono en vertical: con la planta 9:16 (`piece.portrait`) el plano cabe ENTERO entre el
     título y la tira, como en escritorio. Sin ella, se recortaría igual que antes. */
  [data-tema="web3d"] body:has(.chrome .titular-nivel) .escenario {
    --ajuste: var(--ajuste-telefono, 1); /* número, lo calcula `medirViewport` */
    transform: translate(-50%, calc(-50% + 20px)) scale(calc(var(--zoom) * var(--ajuste))) translate(var(--paneo-x), var(--paneo-y));
    transition-timing-function: var(--resorte);
  }
}

/* ── El descenso (🌅, 23-sep-2026) ────────────────────────────────────────────────────────────
   Foto cenital y planta son UNA pieza registrada (`.descenso-registrado` vive dentro de la caja)
   escalada en modo COVER: a sangre en cualquier ventana, sin marco, sin halo, sin tarjeta. La foto
   se acerca al bajar de nivel con la ley y la curva medidas en la referencia (`escenario.ts`,
   FUNDIDO_PISO); como `--descenso` ≥ 1 y la caja cubre la ventana, nunca asoma un borde. */
/* La capa NO anima nada: su `transition-duration` en linea (`escenario.ts`, `descenso`) es solo para que la
   herede la foto (`.descenso-suelo`). Con la `transition-property` por defecto —`all`— animaba tambien su
   inclinacion de la losa (el suelo iba 850 ms detras del dedo) y hasta su `visibility`. */
.descenso-registrado { display: none; transition-property: none; }
[data-tema="web3d"][data-con-suelo="si"]:not([data-sin-entorno="si"]) body:has(.chrome .titular-nivel) .descenso-registrado:not([hidden]) {
  display: block; position: absolute; inset: 0; pointer-events: none;
  background: #6f7a78 center / cover no-repeat;
  --descenso: 1;
}
.descenso-suelo {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none;
  transform: scale(var(--descenso));
  /* El filtro es el desenfoque del suelo, que se enfoca al bajar (`descenso.ts`, `filtroDelSuelo`). */
  transition-property: transform, filter;
  transition-duration: inherit;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
/* El nivel que es FOTO y no planta —el Roof, su vista aérea (`data-nivel-foto`, app.ts)— va a sangre,
   como la portada, en escritorio y en teléfono: enmarcada en negro se leía a medio cargar. */
[data-tema="web3d"][data-nivel-foto="si"] body:has(.chrome .titular-nivel) .escenario {
  --ajuste: var(--ajuste-a-sangre, 1) !important;
  transform: translate(-50%, -50%) scale(calc(var(--zoom) * var(--ajuste))) translate(var(--paneo-x), var(--paneo-y)) !important;
  border-radius: 0 !important;
}
/* El nivel encuadrado por su ANCLA: a su escala (`--ajuste-del-nivel`) y centrado en ella (`--centro-ancla-*`),
   no en la lámina. Sin el centro, un nivel de cámara más ancha salía corrido y cortado (el Nivel 1 piloto).
   CON Y SIN ENTORNO: «Hide Surroundings» sólo quita el fondo. Estas reglas llevaban `:not([data-sin-entorno])`
   y al esconder el entorno la planta volvía al encuadre de la lámina —un zoom que entraba y salía— (Victor 29-sep). */
[data-tema="web3d"][data-con-suelo="si"] body:has(.chrome .titular-nivel) .escenario {
  --ajuste: var(--ajuste-del-nivel, 1) !important;
  transform: translate(calc(-50% + var(--centro-util-x, 0px)), calc(-50% + var(--centro-util-y, 0px))) scale(calc(var(--zoom) * var(--ajuste))) translate(var(--paneo-x), var(--paneo-y)) translate(var(--centro-ancla-x, 0px), var(--centro-ancla-y, 0px)) !important;
}

/* Teléfono y tableta en vertical: el nivel ENTERO entre título y tira (`--ajuste-plano-telefono`, lo mide
   `medirViewport` con las zonas seguras). Lo que la caja deja al aire es el mismo suelo, difuminado
   y apagado: un velo, no una franja negra. */
@media (max-width: 1024px) and (orientation: portrait) {
  [data-tema="web3d"][data-con-suelo="si"] body:has(.chrome .titular-nivel) .escenario {
    --ajuste: var(--ajuste-plano-telefono, var(--ajuste-del-nivel, 1)) !important;
    transform: translate(calc(-50% + var(--centro-plano-telefono-x, 0px)), calc(-50% + var(--centro-plano-telefono, 0px))) scale(calc(var(--zoom) * var(--ajuste))) translate(var(--paneo-x), var(--paneo-y)) translate(var(--centro-ancla-x, 0px), var(--centro-ancla-y, 0px)) !important;
  }
  [data-tema="web3d"][data-con-suelo="si"]:not([data-sin-entorno="si"]) body:has(.chrome .titular-nivel) .recorrido { background: #3d4442; }
  [data-tema="web3d"][data-con-suelo="si"]:not([data-sin-entorno="si"]) body:has(.chrome .titular-nivel) .recorrido::before {
    content: ''; position: absolute; inset: -48px; pointer-events: none;
    background: var(--suelo-velo, none) center / cover no-repeat;
    filter: blur(24px) brightness(0.7);
  }
  [data-tema="web3d"] .titular-nivel { top: calc(var(--borde-arriba) + 52px); }
  [data-tema="web3d"] .titular-nivel-titulo { font-size: 28px; line-height: 34px; }
  [data-tema="web3d"] .titular-nivel-resumen { font-size: 14px; line-height: 18px; }
}

/* La planta va sin marco en `web3d`: sin radio, sin sombra, sin lienzo ni miniatura opaca. La
   planta trae alfa; detras queda el suelo o, con «Hide Surroundings», el lienzo claro de `.recorrido`. */
[data-tema="web3d"] body:has(.chrome .titular-nivel) .escenario {
  border-radius: 0 !important; box-shadow: none !important; background: transparent !important;
}

[data-tema="web3d"] body:has(.chrome .titular-nivel) .lamina,
[data-tema="web3d"] body:has(.chrome .titular-nivel) .lamina-saliente {
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
/* «Hide Surroundings»: interruptor secundario bajo el titulo del nivel. */
.interruptor-entorno { display: none; }
[data-tema="web3d"][data-con-suelo="si"] body:has(.chrome .titular-nivel) .interruptor-entorno {
  display: inline-flex; align-items: center;
  position: fixed; z-index: 30;
  top: calc(var(--borde-arriba) + 170px); left: var(--borde);
  height: 30px; padding: 0 12px; border-radius: 15px;
  font: 500 13px/1 var(--pila); color: var(--etiqueta);
  background: rgb(255 255 255 / 0.82); border: 0.5px solid var(--separador);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  cursor: pointer;
}
[data-tema="web3d"] .interruptor-entorno[data-oculto="si"] { background: var(--etiqueta); color: var(--lienzo); }

@media (max-width: 520px) {
  [data-tema="web3d"][data-con-suelo="si"] body:has(.chrome .titular-nivel) .interruptor-entorno { top: calc(var(--borde-arriba) + 128px); height: 28px; font-size: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  .descenso-suelo { transition-duration: 0.01ms !important; }
}

/* El título del nivel sobre la foto a sangre: un halo claro detrás de la letra, sin caja. */
[data-tema="web3d"][data-con-suelo="si"]:not([data-sin-entorno="si"]) .titular-nivel-titulo,
[data-tema="web3d"][data-con-suelo="si"]:not([data-sin-entorno="si"]) .titular-nivel-resumen {
  text-shadow: 0 0 12px rgb(255 255 255 / 0.9), 0 0 3px rgb(255 255 255 / 0.9);
}

/* ── #5 · El título del nivel en una placa de material (no halo) ────────────────────────────── */
[data-tema="web3d"] .titular-nivel {
  padding: 10px 16px 12px; border-radius: 18px;
  background: var(--material-grueso);
  -webkit-backdrop-filter: var(--desenfoque);
  backdrop-filter: var(--desenfoque);
  box-shadow: var(--filo), var(--sombra-flota);
}
[data-tema="web3d"] .titular-nivel-titulo { letter-spacing: -0.02em; }
[data-tema="web3d"] .titular-nivel-resumen { color: var(--etiqueta-legible); font-weight: 500; }
[data-tema="web3d"][data-con-suelo="si"]:not([data-sin-entorno="si"]) .titular-nivel-titulo,
[data-tema="web3d"][data-con-suelo="si"]:not([data-sin-entorno="si"]) .titular-nivel-resumen { text-shadow: none; }

/* ── #13 · La tira con números solos ────────────────────────────────────────────────────────── */
[data-tema="web3d"] .pisos { min-width: 64px; }
[data-tema="web3d"] .piso { font-variant-numeric: tabular-nums; text-align: center; justify-content: center; }

/* La placa del título crece 22 px: el interruptor «solo plano» baja lo mismo en teléfono. */
@media (max-width: 520px) {
  [data-tema="web3d"][data-con-suelo="si"] body:has(.chrome .titular-nivel) .interruptor-entorno { top: calc(var(--borde-arriba) + 152px); }
}

/* Teléfono en vertical: «Hide Surroundings» sube a la fila de los mandos, a la derecha, y deja el hueco
   entre título y tira entero para el plano (`--ajuste-plano-telefono`). */
@media (max-width: 520px) and (orientation: portrait) {
  [data-tema="web3d"][data-con-suelo="si"] body:has(.chrome .titular-nivel) .interruptor-entorno { top: calc(var(--borde-arriba) + 7px); left: auto; right: var(--borde); height: 30px; }
  [data-tema="web3d"][data-con-suelo="si"] body:has(.chrome .pantalla-completa) .interruptor-entorno { right: calc(var(--borde) + 52px); }
}

/* ══ 🧭 LA MINITORRE: el minimapa del EDIFICIO · `vista/minimapa.ts` (`.minimapa` es el de la PLANTA, en la ficha) ═════════════════════════════════════════
 * Escritorio: abajo a la izquierda, perfil de la torre + «Level 6». Teléfono: cápsula de 44 px
 * arriba a la derecha, bajo pantalla completa, fuera de la planta y lejos de la tira de abajo. */
.minitorre {
  position: absolute; z-index: 30;
  left: var(--borde); bottom: var(--borde-abajo);
  font-family: var(--pila);
}
.minitorre-boton {
  display: flex; align-items: center; gap: 12px;
  min-height: 44px; padding: 8px 14px 8px 10px;
  border-radius: 16px;
  background: var(--material, rgb(255 255 255 / 0.86));
  -webkit-backdrop-filter: var(--desenfoque, blur(12px)); backdrop-filter: var(--desenfoque, blur(12px));
  color: var(--etiqueta, #171717);
  box-shadow: var(--filo, none), var(--sombra-flota, 0 8px 24px rgb(0 0 0 / 0.1));
}
.minitorre .perfil { display: flex; flex-direction: column; align-items: center; gap: 2px; width: 30px; }
.minitorre .trazo {
  display: block; width: var(--ancho, 100%); height: 3px; border-radius: 1.5px;
  background: color-mix(in srgb, var(--etiqueta, #171717) 26%, transparent);
}
.minitorre .trazo.aqui { height: 4px; background: var(--primario, #111); box-shadow: 0 0 0 1px var(--primario, #111); }
.minitorre-texto { display: flex; flex-direction: column; text-align: left; }
.minitorre-texto .nivel { font: 600 15px/20px var(--pila); }
.minitorre-texto .unidad { font: 400 13px/18px var(--pila); color: var(--etiqueta-2, var(--tinta-suave)); font-variant-numeric: tabular-nums; }
.minitorre-niveles {
  position: absolute; left: 0; bottom: calc(100% + 8px);
  display: flex; flex-direction: column;
  width: 180px; max-height: min(60vh, 580px); overflow-y: auto; padding: 6px;
  border-radius: 16px;
  background: var(--material-grueso, rgb(255 255 255 / 0.95));
  -webkit-backdrop-filter: var(--desenfoque, blur(12px)); backdrop-filter: var(--desenfoque, blur(12px));
  box-shadow: var(--filo, none), var(--sombra-hoja, 0 24px 64px rgb(0 0 0 / 0.18));
  animation: entra-buscador-tel 0.2s var(--resorte, ease-out) backwards;
}
.minitorre-nivel {
  display: flex; align-items: center; justify-content: space-between;
  min-height: 44px; padding: 0 12px; border-radius: 10px;
  font: 400 15px/20px var(--pila); color: var(--etiqueta, #171717); text-align: left;
}
.minitorre-nivel:hover, .minitorre-nivel:focus-visible { background: var(--relleno, rgb(0 0 0 / 0.06)); outline: 0; }
.minitorre-nivel.aqui { font-weight: 600; background: var(--relleno, rgb(0 0 0 / 0.06)); }
.minitorre-nivel.aqui::after { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--primario, #111); }
.minitorre-nivel .libres {
  min-width: 22px; padding: 1px 7px; border-radius: 999px; text-align: center;
  font: 600 12px/18px var(--pila); color: var(--sobre-primario, #fff); background: var(--primario, #111);
}
.minitorre-nivel.aqui .libres { margin-left: auto; margin-right: 8px; }

@media (max-width: 520px) {
  .minitorre { left: auto; right: var(--borde); bottom: auto; top: calc(var(--borde-arriba) + 56px); }
  .minitorre-boton { flex-direction: column; gap: 0; min-width: 44px; padding: 8px 7px; border-radius: 14px; }
  .minitorre-texto { display: none; }
  .minitorre .perfil { gap: 1.5px; }
  .minitorre .trazo { height: 2.5px; }
  .minitorre-niveles { left: auto; right: 0; bottom: auto; top: calc(100% + 8px); max-height: calc(100dvh - 220px); }
}

.minitorre-nivel { background: transparent; width: 100%; }
/* En la ficha, abajo a la izquierda está el pie del panel (CTA y vías): la minitorre sube arriba,
   junto a pantalla completa, y su lista cae hacia abajo. */
.minitorre.en-ficha { left: auto; bottom: auto; top: var(--borde-arriba); right: calc(var(--borde) + 56px); }
.minitorre.en-ficha .minitorre-niveles { left: auto; right: 0; bottom: auto; top: calc(100% + 8px); }
.minitorre.en-ficha .perfil { gap: 1.5px; }
.minitorre.en-ficha .trazo { height: 2px; }
.minitorre.en-ficha .trazo.aqui { height: 3px; }
/* En el teléfono la minitorre de la ficha va en la fila de mandos (menú, migas, pantalla completa),
   que mide 44 px. Con un trazo por nivel la cápsula crecía con el edificio —70 px con 13 niveles— y
   mordía la planta de abajo. El perfil tiene alto FIJO y los trazos se reparten en él. */
@media (max-width: 520px) {
  .minitorre.en-ficha .minitorre-boton { min-height: 44px; height: 44px; padding: 7px; }
  .minitorre.en-ficha .perfil { height: 30px; gap: 0; justify-content: space-between; }
  .minitorre.en-ficha .trazo { height: 1px; }
  .minitorre.en-ficha .trazo.aqui { height: 2.5px; box-shadow: none; }
}

[data-tema="web3d"] .chrome:has(.migas) .titular-nivel { top: calc(var(--borde-arriba) + 60px); }

/* La cápsula del giro, abajo al centro. */
[data-tema="web3d"] .giro {
  position: absolute; left: 50%; bottom: var(--borde-abajo); transform: translateX(-50%); z-index: 5;
  display: flex; align-items: center; gap: 4px; height: 44px; padding: 0 4px; border-radius: 22px;
  background: var(--material); color: var(--etiqueta);
  -webkit-backdrop-filter: var(--desenfoque); backdrop-filter: var(--desenfoque);
  box-shadow: var(--filo), var(--sombra-flota);
}

[data-tema="web3d"] .giro .puntos { display: flex; gap: 6px; padding: 0 6px; }
[data-tema="web3d"] .giro .punto { width: 7px; height: 7px; border-radius: 4px; background: var(--etiqueta-2); opacity: 0.45; transition: width var(--t) var(--resorte); }
[data-tema="web3d"] .giro .punto.activo { width: 20px; background: var(--etiqueta); opacity: 1; }
[data-tema="web3d"] .chrome:has(.barra-niveles.abierta) .giro { opacity: 0; pointer-events: none; }

@media (max-width: 520px) {
  [data-tema="web3d"] .giro { bottom: calc(var(--borde-abajo) + 76px); }
}

/* ── La barra de niveles ── */
[data-tema="web3d"] .barra-niveles {
  position: absolute; right: var(--borde); top: 50%; transform: translateY(-50%); z-index: 6;
}
[data-tema="web3d"] .barra-pastilla {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  width: 44px; padding: 14px 0 12px; border-radius: 22px; cursor: pointer;
  background: var(--material); color: var(--etiqueta-2);
  -webkit-backdrop-filter: var(--desenfoque); backdrop-filter: var(--desenfoque);
  box-shadow: var(--filo), var(--sombra-flota);
}
[data-tema="web3d"] .barra-pastilla .perfil { display: flex; flex-direction: column; align-items: center; gap: 4px; width: 20px; }
[data-tema="web3d"] .barra-pastilla .trazo { display: block; height: 3px; width: var(--ancho, 100%); border-radius: 2px; background: var(--etiqueta-2); opacity: 0.5; }
[data-tema="web3d"] .barra-pastilla .trazo.libre { background: #4f7a5a; opacity: 1; }
[data-tema="web3d"] .barra-pastilla .rotulo-vertical { writing-mode: vertical-rl; transform: rotate(180deg); font: 600 11px/1 var(--pila); letter-spacing: 0.02em; }
[data-tema="web3d"] .barra-panel { display: none; }
[data-tema="web3d"] .barra-niveles.abierta .barra-pastilla { display: none; }
[data-tema="web3d"] .barra-niveles.abierta .barra-panel {
  display: block; width: 256px; max-height: calc(100vh - 2 * var(--borde-arriba) - 120px); overflow-y: auto;
  padding: 14px 8px 8px; border-radius: 24px;
  background: var(--material-grueso); color: var(--etiqueta);
  -webkit-backdrop-filter: var(--desenfoque); backdrop-filter: var(--desenfoque);
  box-shadow: var(--filo), var(--sombra-hoja);
  animation: barra-entra var(--t) var(--resorte);
}
@keyframes barra-entra { from { opacity: 0; transform: translateX(16px) scale(0.98); } }
[data-tema="web3d"] .barra-cabeza { display: flex; align-items: center; justify-content: space-between; padding: 0 6px 0 10px; }
[data-tema="web3d"] .barra-titulo { margin: 0; font: 700 22px/28px var(--pila); }
[data-tema="web3d"] .barra-cerrar {
  position: relative; width: 30px; height: 30px; border-radius: 15px; padding: 0; font-size: 0;
  background: var(--relleno); color: var(--etiqueta-2);
}
[data-tema="web3d"] .barra-cerrar::before {
  content: ""; position: absolute; inset: 0; margin: auto; width: 14px; height: 14px; background: currentColor;
  -webkit-mask: var(--i-cerrar) center / contain no-repeat; mask: var(--i-cerrar) center / contain no-repeat;
}
[data-tema="web3d"] .barra-resumen { margin: 2px 10px 8px; padding-bottom: 10px; border-bottom: 0.5px solid var(--separador); font: 400 13px/18px var(--pila); color: var(--etiqueta-2); }
[data-tema="web3d"] .barra-lista { display: flex; flex-direction: column; }
[data-tema="web3d"] .barra-nivel {
  display: flex; align-items: center; gap: 12px; height: 44px; padding: 0 10px 0 6px; border-radius: 12px;
  background: none; border: 0; color: var(--etiqueta); font: 500 15px/1 var(--pila); text-align: left; cursor: pointer;
}
[data-tema="web3d"] .barra-nivel .barra-tecla {
  flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 16px;
  border: 1.5px solid var(--separador); font: 600 13px/1 var(--pila); font-variant-numeric: tabular-nums;
}
[data-tema="web3d"] .barra-nivel .barra-nombre { flex: 1; }
[data-tema="web3d"] .barra-nivel .barra-cuenta { display: flex; align-items: center; gap: 6px; font: 400 13px/1 var(--pila); color: var(--etiqueta-2); }
[data-tema="web3d"] .barra-nivel .barra-cuenta::before { content: ""; width: 7px; height: 7px; border-radius: 4px; background: #a39a8f; }
/* Un nivel sin residencias (lobby) no tiene estado de venta: ni texto ni punto. */
[data-tema="web3d"] .barra-nivel .barra-cuenta:empty { display: none; }
[data-tema="web3d"] .barra-nivel.libre .barra-tecla { border-color: #4f7a5a; color: #4f7a5a; }
[data-tema="web3d"] .barra-nivel.libre .barra-cuenta { color: #4f7a5a; }
[data-tema="web3d"] .barra-nivel.libre .barra-cuenta::before { background: #4f7a5a; }
[data-tema="web3d"] .barra-nivel.vendido .barra-nombre { color: var(--etiqueta-2); }
[data-tema="web3d"] .barra-nivel:hover:not([disabled]),
[data-tema="web3d"] .barra-nivel:focus-visible { background: var(--relleno); }
[data-tema="web3d"] .barra-nivel:hover:not([disabled]) .barra-tecla,
[data-tema="web3d"] .barra-nivel:focus-visible .barra-tecla { background: var(--primario); border-color: var(--primario); color: #fff; box-shadow: 0 0 0 4px color-mix(in srgb, var(--primario) 22%, transparent); }
[data-tema="web3d"] .barra-nivel[disabled] { opacity: 0.4; cursor: default; }

@media (prefers-color-scheme: dark) {
  [data-tema="web3d"] .barra-nivel.libre .barra-tecla, [data-tema="web3d"] .barra-nivel.libre .barra-cuenta { color: #8fc49c; border-color: #8fc49c; }
  [data-tema="web3d"] .barra-pastilla .trazo.libre { background: #8fc49c; }
}

/* Teléfono: la barra es una hoja que se jala desde abajo; abierta, una botonera de 4 columnas. */
@media (max-width: 520px) {
  [data-tema="web3d"] .barra-niveles { top: auto; transform: none; left: 8px; right: 8px; bottom: 8px; }
  [data-tema="web3d"] .barra-pastilla {
    width: 100%; flex-direction: row; justify-content: space-between; gap: 0;
    height: 64px; padding: 18px 20px 0; border-radius: 28px; position: relative;
    color: var(--etiqueta);
  }
  [data-tema="web3d"] .barra-pastilla::before { content: ""; position: absolute; top: 8px; left: 50%; width: 36px; height: 5px; margin-left: -18px; border-radius: 3px; background: var(--etiqueta-2); opacity: 0.5; }
  [data-tema="web3d"] .barra-pastilla .perfil { display: none; }
  [data-tema="web3d"] .barra-pastilla .rotulo-vertical { writing-mode: horizontal-tb; transform: none; font: 700 22px/28px var(--pila); letter-spacing: 0; }
  [data-tema="web3d"] .barra-niveles.abierta .barra-panel { width: auto; max-height: 62vh; border-radius: 28px; padding: 22px 12px 16px; position: relative; animation-name: hoja-sube; }
  [data-tema="web3d"] .barra-niveles.abierta .barra-panel::before { content: ""; position: absolute; top: 8px; left: 50%; width: 36px; height: 5px; margin-left: -18px; border-radius: 3px; background: var(--etiqueta-2); opacity: 0.5; }
  [data-tema="web3d"] .barra-lista { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px 0; }
  [data-tema="web3d"] .barra-nivel { flex-direction: column; height: auto; gap: 5px; padding: 0; justify-content: flex-start; text-align: center; }
  [data-tema="web3d"] .barra-nivel .barra-tecla { width: 56px; height: 56px; border-radius: 28px; font-size: 19px; }
  [data-tema="web3d"] .barra-nivel .barra-nombre { display: none; }
  [data-tema="web3d"] .barra-nivel .barra-cuenta { font-size: 11px; }
  [data-tema="web3d"] .barra-nivel .barra-cuenta::before { display: none; }
  [data-tema="web3d"] .barra-nivel:hover:not([disabled]) { background: none; }
}

@keyframes hoja-sube { from { transform: translateY(40px); opacity: 0; } }

/* El resumen corto de la pastilla: sólo en teléfono, donde la pastilla es la hoja plegada. */
[data-tema="web3d"] .barra-pastilla .resumen-corto { display: none; }

@media (max-width: 520px) {
  [data-tema="web3d"] .barra-pastilla .resumen-corto { display: flex; align-items: center; gap: 6px; font: 400 13px/1 var(--pila); color: #4f7a5a; }
  [data-tema="web3d"] .barra-pastilla .resumen-corto::before { content: ""; width: 7px; height: 7px; border-radius: 4px; background: currentColor; }
}

@media (max-width: 520px) and (prefers-color-scheme: dark) {
  [data-tema="web3d"] .barra-pastilla .resumen-corto { color: #8fc49c; }
}

/* «Hide Surroundings» en teléfono: arriba a la derecha chocaba con Contact; va bajo el título del nivel. */
@media (max-width: 520px) {
  [data-tema="web3d"][data-con-suelo="si"] body:has(.chrome .migas) .interruptor-entorno { top: calc(var(--borde-arriba) + 146px); left: var(--borde); right: auto; }
}

/* «Hide Surroundings» en oscuro: el fondo blanco fijo dejaba la tinta clara sin leerse. */
@media (prefers-color-scheme: dark) {
  [data-tema="web3d"][data-con-suelo="si"] body:has(.chrome .titular-nivel) .interruptor-entorno:not([data-oculto="si"]) { background: var(--material); }
}
/* 🧱 La tarjeta de una unidad sobre su nivel (`chrome.ts`): cifras, sus dos CTA y su cierre; en telefono, la hoja inferior. */

/* ── La tarjeta de unidad, sobre el plano del piso · `16, 80 · 320 × …` ─────────────────────── */
.tarjeta {
  position: absolute;
  left: var(--borde);
  top: calc(var(--borde-arriba) + 64px);
  width: 320px;
  max-height: calc(100% - var(--borde-arriba) - var(--borde-abajo) - 128px);
  overflow-y: auto;
  padding: 16px;
  border-radius: 16px;
  border: 2px solid #fff;
  background: #fff;
  box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
  scrollbar-width: thin;
}
.tarjeta .cabeza { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding-right: 40px; }
.tarjeta .nombre { font: 600 20px/28px var(--pila); }
.tarjeta .tipologia { margin: 4px 0 0; font: 400 12px/16px var(--pila); color: var(--tinta-suave); }
.tarjeta .precio { margin: 8px 0 0; font: 600 24px/32px var(--pila); color: var(--tinta); }
.tarjeta .resumen {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: 0 12px;
  margin: 12px 0 0;
}
.tarjeta .clave { font: 400 12px/25px var(--pila); color: var(--tinta-suave); }
.tarjeta .valor { margin: 0; font: 500 14px/25px var(--pila); text-align: right; }
.tarjeta .mandos { display: flex; gap: 8px; margin-top: 12px; }
.tarjeta .cifras { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 10px 0 0; font: 500 13px/18px var(--pila); color: var(--tinta); }
/* 🅿️ En el nivel de sus cajones: cuáles son («3 spaces · Level B1 · B1-007 to B1-009 + storage room»). */
.tarjeta .espacios-de-la-unidad { margin: 8px 0 0; font: 500 13px/18px var(--pila); color: var(--tinta); }
.tarjeta .cifra + .cifra::before { content: "·"; margin-right: 14px; color: var(--tinta-suave); }
.pedir-info {
  flex: 1;
  min-height: 40px;
  border-radius: 9999px;
  background: #fff;
  color: var(--primario);
  box-shadow: inset 0 0 0 1px var(--primario);
  font: 600 14px/20px var(--pila);
}

.pie-pegajoso .pedir-info { background: var(--primario); color: var(--sobre-primario); box-shadow: none; }
.ver-ficha {
  flex: 1;
  min-height: 40px;
  border-radius: 9999px;
  background: var(--primario);
  color: var(--sobre-primario);
  font: 600 14px/20px var(--pila);
}
.cerrar-tarjeta {
  position: absolute;
  top: 18px;
  right: 18px;
  width: 40px;
  height: 40px;
  border-radius: 9999px;
  background: var(--superficie);
  color: var(--tinta-suave);
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.1);
}
.cerrar-tarjeta::before { content: "✕"; display: block; font: 600 14px/1 ui-sans-serif, system-ui, sans-serif; }

@media (max-width: 520px) {
  .tarjeta { left: 12px; right: 12px; width: auto; top: auto; bottom: calc(var(--borde-abajo) + 52px); max-height: 60%; }
}

/* ── Rediseno web3d ──────────────────────────────────────────────────────────────────────── */
/* Los dos CTA de la tarjeta caben en una linea a 320 px: nunca parten la palabra en dos renglones. */
.tarjeta .mandos { flex-wrap: wrap; }
.tarjeta .mandos button { flex: 1 1 auto; white-space: nowrap; padding: 0 12px; font-size: 13px; }

/* En telefono la tarjeta es cajon inferior: el zoom que quedaba debajo se va mientras este abierta. */
@media (max-width: 520px) {
  .chrome:has(.tarjeta) .acercar, .chrome:has(.tarjeta) .alejar { display: none; }
}

[data-tema="web3d"] .tarjeta .cifra::before {
  content: "";
  display: block;
  width: 20px;
  height: 20px;
  margin: auto;
  background: currentColor;
  -webkit-mask: var(--icono) center / contain no-repeat;
  mask: var(--icono) center / contain no-repeat;
}

/* ── La tarjeta de la unidad: centrada sobre el nivel, cifras con icono, dos CTA ──────────── */
[data-tema="web3d"] .tarjeta {
  left: calc(50% - 210px); top: 26%;
  width: 335px;
  padding: 20px;
  border: 0; border-radius: 12px;
  text-align: center;
  box-shadow: 0 12px 16px -4px rgb(16 24 40 / 0.08), 0 4px 6px -2px rgb(16 24 40 / 0.03);
}
[data-tema="web3d"] .tarjeta .cabeza { justify-content: center; padding: 0 28px; }
[data-tema="web3d"] .tarjeta .nombre { font: 500 16px/19.2px var(--pila); color: var(--oscuro); }
[data-tema="web3d"] .tarjeta .tipologia { display: none; }
[data-tema="web3d"] .tarjeta .cifras {
  justify-content: center; gap: 20px;
  margin: 14px 0 0; padding: 12px 0;
  border-block: 1px solid var(--linea);
  font: 400 14px/20px var(--pila); color: var(--oscuro);
}
[data-tema="web3d"] .tarjeta .cifra { display: inline-flex; align-items: center; gap: 8px; }
[data-tema="web3d"] .tarjeta .cifra::before { width: 20px; height: 20px; margin: 0; color: var(--primario); }
[data-tema="web3d"] .tarjeta .cifra-area { --icono: var(--i-area); }
[data-tema="web3d"] .tarjeta .cifra-recamaras { --icono: var(--i-cama); }
[data-tema="web3d"] .tarjeta .cifra-banos { --icono: var(--i-bano); }
[data-tema="web3d"] .tarjeta .palabra { display: none; }
[data-tema="web3d"] .tarjeta .mandos { margin-top: 16px; gap: 8px; }
[data-tema="web3d"] .pedir-info {
  min-height: 36px; border-radius: 18px;
  background: #fff; color: var(--oscuro);
  box-shadow: inset 0 0 0 1px var(--apagado);
  font: 500 14px/20px var(--pila);
}
[data-tema="web3d"] .ver-ficha { min-height: 36px; border-radius: 18px; font: 500 14px/20px var(--pila); }
[data-tema="web3d"] .cerrar-tarjeta {
  top: 12px; right: 12px; width: 28px; height: 28px;
  background: transparent; box-shadow: none; color: var(--tinta-suave);
}

[data-tema="web3d"] .pie-pegajoso .pedir-info { min-height: 44px; border-radius: 22px; white-space: nowrap; }

@media (max-width: 520px) {
  [data-tema="web3d"] .tarjeta {
    left: 0; right: 0; bottom: 0; top: auto;
    width: auto;
    border-radius: 12px 12px 0 0;
    padding-bottom: calc(var(--borde-abajo) + 8px);
  }
}

/* ── La unidad: hoja inferior arrastrable, como Mapas ──────────────────────────────────────── */
[data-tema="web3d"] .tarjeta {
  --arrastre: 0px;
  top: auto; left: calc(50% - 200px); right: auto; bottom: var(--borde-abajo);
  width: 400px; max-height: none;
  padding: 8px 24px 24px;
  border-radius: 28px;
  text-align: left;
  background: var(--material-grueso);
  -webkit-backdrop-filter: var(--desenfoque);
  backdrop-filter: var(--desenfoque);
  box-shadow: var(--filo), var(--sombra-hoja);
  transform: translateY(var(--arrastre));
  transition: transform var(--t) var(--resorte);
  touch-action: none;
  overflow: visible;
}
[data-tema="web3d"] .tarjeta.entra { animation: sube-hoja 0.4s var(--resorte) backwards; }
[data-tema="web3d"] .tarjeta.arrastrando { transition: none; }
@keyframes sube-hoja { from { transform: translateY(calc(100% + 32px)); } }
[data-tema="web3d"] .asa-hoja { display: block; width: 36px; height: 5px; margin: 0 auto 16px; border-radius: 3px; background: var(--separador); cursor: grab; }
[data-tema="web3d"] .tarjeta .cabeza { justify-content: flex-start; gap: 12px; padding: 0 40px 0 0; }
[data-tema="web3d"] .tarjeta .nombre { font: 700 28px/34px var(--pila); color: var(--etiqueta); }
/*
 * La tinta del estado es su color mezclado con la de la hoja al 55 %: al 85 %, el gris de «Sold» (#A39A8F)
 * daba 2.89:1 sobre la hoja clara (🗺️, 28-sep-2026). Al 55 % pasa AA en claro (≈5:1) y en oscuro (≈7.7:1),
 * y el verde de «Available» sigue leyendose verde.
 */
[data-tema="web3d"] .tarjeta .estado {
  padding: 4px 10px; border-radius: 12px;
  background: color-mix(in srgb, var(--color-estado) 16%, transparent);
  color: color-mix(in srgb, var(--color-estado) 55%, var(--etiqueta));
  font: 600 13px/16px var(--pila);
}
[data-tema="web3d"] .tarjeta .cifras {
  justify-content: flex-start; gap: 24px;
  margin: 8px 0 0; padding: 0; border: 0;
  font: 400 17px/22px var(--pila); color: var(--etiqueta-2);
}
[data-tema="web3d"] .tarjeta .cifra::before { width: 20px; height: 20px; color: var(--etiqueta-2); }
[data-tema="web3d"] .tarjeta .mandos { margin-top: 24px; gap: 8px; }
[data-tema="web3d"] .tarjeta .pedir-info,
[data-tema="web3d"] .tarjeta .ver-ficha { min-height: 50px; border-radius: 14px; font: 600 17px/22px var(--pila); }
[data-tema="web3d"] .tarjeta .pedir-info { background: var(--relleno); color: var(--etiqueta); box-shadow: none; }
[data-tema="web3d"] .tarjeta .ver-ficha { background: var(--primario); color: var(--sobre-primario); }
[data-tema="web3d"] .cerrar-tarjeta {
  --icono: var(--i-cerrar);
  top: 20px; right: 20px; width: 30px; height: 30px;
  border-radius: 15px;
  background: var(--relleno); color: var(--etiqueta-2);
  box-shadow: none;
  font-size: 0;
}
[data-tema="web3d"] .cerrar-tarjeta::before {
  content: ""; position: absolute; inset: 7px; display: block;
  background: currentColor;
  -webkit-mask: var(--icono) center / contain no-repeat;
  mask: var(--icono) center / contain no-repeat;
}

[data-tema="web3d"] .pie-pegajoso .pedir-info { min-height: 50px; border-radius: 14px; background: var(--primario); color: var(--sobre-primario); box-shadow: none; font: 600 17px/22px var(--pila); }

@media (max-width: 520px) {
  [data-tema="web3d"] .chrome:has(.tarjeta) .acercar,
  [data-tema="web3d"] .chrome:has(.tarjeta) .alejar { display: none; }

  [data-tema="web3d"] .tarjeta {
    left: 8px; right: 8px; bottom: 8px;
    width: auto;
    padding: 8px 20px calc(var(--borde-abajo) + 4px);
    border-radius: 28px;
  }
}

/* La tarjeta anclada a su unidad (escritorio): la pone `anclarTarjeta`; aparece sin subir. */
[data-tema="web3d"] .tarjeta.anclada { bottom: auto; right: auto; }
[data-tema="web3d"] .tarjeta.anclada.entra { animation: aparece-tarjeta 0.3s var(--resorte) backwards; }
@keyframes aparece-tarjeta { from { opacity: 0; transform: scale(0.96); } }

/* ── La acción principal de la ficha, por estado (`ficha.ts` `pieDeVenta`) ───────────────────
   La libre: «Schedule a Visit» (un enlace, la vía `visit`); la vendida: «See Available
   Residences». Las dos ocupan el sitio del CTA y dejan los íconos de contacto a su lado. */
.pie-pegajoso a.pedir-info { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }
[data-tema="web3d"] .pie-pegajoso .pedir-info.accion-visita,
[data-tema="web3d"] .pie-pegajoso .pedir-info.ver-disponibles { flex: 1 1 auto; min-width: 0; padding-inline: 14px; }
[data-tema="web3d"] .pie-pegajoso .pedir-info.ver-disponibles {
  white-space: nowrap; padding-inline: 10px; font: 600 14px/18px var(--pila);
}

@media (max-width: 520px) {
  [data-tema="web3d"] .pie-pegajoso .pedir-info.ver-disponibles { font: 600 14px/18px var(--pila); }
}
/* 🧱 La ficha de unidad (`ficha.ts` y `ficha/`): panel, riel de pestanias, carrusel, minimapa, terminaciones, condiciones, compartir, el pie de venta y la hoja de un cuarto. */

/* ── LA FICHA DE UNIDAD ───────────────────────────────────────────────────────────────────────
 *
 * Medida contra la ficha visual de esta pantalla, que sí existe y sí está al píxel. Las cajas
 * de aquí son las suyas: panel `16, 80 · 360 × 804` —de `top: 5rem` a `bottom: 1rem`—, riel
 * `1268, 80 · 156 × 280` con seis píldoras de `156 × 40` y paso de 48, minimapa
 * `1224, 716 · 200 × 112`, flechas `16, 430` y `1384, 430`. Cada diferencia está anotada en
 * `Diferencias Contra La Referencia.md` §4.
 *
 * LO QUE SE VE DETRÁS ES EL ESCENARIO, el mismo del masterplan. Esta capa sólo flota encima.
 *
 * Las CLAVES de los campos van en monoespaciada gris a propósito: el contrato no trae el texto
 * que el visitante debería leer. Ver la cabecera de `vista/ficha.ts`.
 */
.pantalla { position: fixed; inset: 0; z-index: 45; pointer-events: none; }
.pantalla > * { pointer-events: none; }
.pantalla button, .pantalla a, .pantalla .panel, .pantalla .riel-caja, .pantalla .minimapa,
.pantalla .capa, .pantalla .tours, .pantalla .ruta-declarada,
/* Las pantallas del menu y la del comparador: son documentos enteros, no adornos sobre el arte. */
.pantalla .documento, .pantalla .mapa, .pantalla .contacto, .pantalla .comparador,
.pantalla .rotulo-lamina, .pantalla input, .pantalla select, .pantalla textarea { pointer-events: auto; }
.pantalla button, .pantalla a { font-family: inherit; }
.pantalla button { border: 0; cursor: pointer; transition: 0.15s var(--curva); }
.pantalla button:active { transform: scale(0.95); }

.ficha { position: fixed; inset: 0; }

/* ── El tour de terceros y la ruta declarada: ocupan el viewport entero ────────────────────── */
.tours, .ruta-declarada { position: fixed; inset: 0; z-index: 1; }
.tour { width: 100%; height: 100%; border: 0; display: block; background: #000; }
.tours .elegir { position: absolute; left: var(--borde); bottom: var(--borde-abajo); display: flex; gap: 4px; }
.elegir-tour {
  height: 32px;
  padding: 0 12px;
  border-radius: 9999px;
  background: rgb(0 0 0 / 0.45);
  color: rgb(255 255 255 / 0.7);
  font: 600 12px/16px var(--pila);
}
.elegir-tour.activo { background: #fff; color: #000; }

.ruta-declarada {
  display: grid;
  place-content: center;
  gap: 8px;
  padding: 24px;
  text-align: center;
  background: #000;
  color: #fff;
}
.ruta-declarada .que { margin: 0; font: 600 18px/28px ui-monospace, SFMono-Regular, Menlo, monospace; }
.ruta-declarada .params { margin: 0; font: 400 13px/20px ui-monospace, SFMono-Regular, Menlo, monospace; color: rgb(255 255 255 / 0.65); }
.ruta-declarada .cuando { margin: 0; max-width: 34ch; font: 400 13px/20px var(--pila); color: rgb(255 255 255 / 0.55); }

/* ── El panel de detalle · `16, 80 · 360 × 804` ─────────────────────────────────────────────── */
.panel {
  position: fixed;
  left: var(--borde);
  top: calc(var(--borde-arriba) + 64px);
  bottom: var(--borde-abajo);
  width: 360px;
  z-index: 2;
}
.datos { display: none; }
.panel.abierto .datos {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 16px;
  border-radius: 16px;
  border: 2px solid #fff;
  background: #fff;
  box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
  color: var(--tinta);
  overflow: hidden;
}
/* El asa: sólo cuando el panel está cerrado, y donde la referencia pone `Ficha Técnica`. */
.asa-panel {
  position: fixed;
  top: var(--borde-arriba);
  left: calc(var(--borde) + 232px);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 16px;
  border-radius: 9999px;
  background: var(--superficie);
  color: var(--tinta);
  font: 600 14px/20px var(--pila);
  box-shadow: var(--sombra-boton);
}
.panel.abierto .asa-panel { display: none; }
.asa-panel .icono { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }

.cerrar-panel {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 40px;
  height: 40px;
  border-radius: 9999px;
  background: var(--superficie);
  color: var(--tinta);
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.1);
}
.cerrar-panel::before { content: "✕"; display: block; font: 600 14px/1 ui-sans-serif, system-ui, sans-serif; }

.datos .cabeza { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding-right: 48px; }
.datos .titulo { margin: 0; font: 700 30px/36px var(--pila); }
.estado {
  --color-estado: var(--primario);
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding: 0 12px;
  border-radius: 9999px;
  background: var(--color-estado);
  color: #fff;
  color: var(--tinta-estado);
  font: 600 12px/12px var(--pila);
  white-space: nowrap;
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.1);
}
.datos .donde-esta { margin: 6px 0 0; font: 500 14px/20px var(--pila); color: var(--tinta-suave); }
.datos .tipologia { margin: 2px 0 0; font: 400 13px/18px var(--pila); color: var(--tinta-suave); }
.datos .precio { margin: 10px 0 0; font: 600 24px/32px var(--pila); color: var(--tinta); }

.datos .cuerpo { flex: 1; min-height: 0; overflow-y: auto; margin-top: 12px; scrollbar-width: thin; }

.campos {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: 2px 12px;
  margin: 0 0 12px;
  padding: 12px 0 0;
  border-top: 1px solid #e5e5e5;
}
.campos .grupo {
  grid-column: 1 / -1;
  margin-bottom: 4px;
  font: 600 11px/16px var(--pila);
  letter-spacing: 0.04em;
  color: var(--tinta-suave);
  text-transform: uppercase;
}
.campos .clave { font: 400 12px/25px var(--pila); color: var(--tinta-suave); }
.campos .valor { margin: 0; font: 500 14px/25px var(--pila); color: var(--tinta); text-align: right; }

.datos .pie { padding-top: 12px; border-top: 1px solid #e5e5e5; }
.datos .descargar {
  display: inline-block;
  padding: 10px 16px;
  border-radius: 9999px;
  background: var(--superficie);
  color: var(--tinta);
  font: 600 14px/20px var(--pila);
  text-decoration: none;
}
.datos .aviso { margin: 8px 0 0; font: 400 11px/16px var(--pila); color: var(--tinta-suave); }

/* ── El riel · `1268, 80 · 156 × 280`, píldoras `156 × 40`, paso 48 ─────────────────────────── */
.riel-caja {
  position: fixed;
  right: var(--borde);
  top: calc(var(--borde-arriba) + 64px);
  z-index: 2;
}
.riel { display: flex; flex-direction: column; gap: 8px; }
.pestania {
  width: 156px;
  height: 40px;
  padding: 0 16px;
  border-radius: 9999px;
  background: #fff;
  color: var(--tinta);
  font: 600 14px/20px var(--pila);
  text-align: left;
  box-shadow: var(--sombra-chip);
}
.pestania.activa { background: var(--primario); color: var(--sobre-primario); }
/* Una pestaña que abre CAPA y no cambia de ruta se marca: el visitante no vuelve con «atrás». */
.pestania.abre-capa::after { content: " ⧉"; opacity: 0.5; }
/* La unica del riel que deja de ser la ficha. Ver `ficha.ts`. */
.pestania.sale::after { content: " ↗"; opacity: 0.5; }
/* El asa del riel sólo existe en teléfono; aquí no se dibuja. */
.asa-riel { display: none; }

.ficha .contador {
  position: fixed;
  left: 50%;
  bottom: var(--borde-abajo);
  transform: translateX(-50%);
  padding: 6px 12px;
  border-radius: 9999px;
  background: rgb(0 0 0 / 0.4);
  backdrop-filter: blur(8px);
  color: #fff;
  font: 600 12px/16px var(--pila);
}
/*
 * En la galería la píldora dice el cuarto de la foto antes de la cuenta: «Kitchen  2 / 6». Va más
 * oscura que la del conteo solo: el blanco sobre negro al 40 % da 3:1 en el escenario claro, y un
 * nombre de cuarto es texto que se lee, no un contador (negro al 60 % ≈ 6:1, test/contraste).
 */
.ficha .contador.con-rotulo {
  background: rgb(0 0 0 / 0.6);
  display: flex;
  gap: 8px;
  align-items: baseline;
  max-width: calc(100vw - 2 * var(--borde) - 112px);
  padding: 7px 14px;
  font: 600 13px/18px var(--pila);
  white-space: nowrap;
}
.ficha .contador .cuarto-foto { overflow: hidden; text-overflow: ellipsis; }
.ficha .contador .cuenta-foto { flex: none; font-weight: 400; font-variant-numeric: tabular-nums; }

/* ── El minimapa · `1224, 716 · 200 × 112` ──────────────────────────────────────────────────── */
.minimapa {
  position: fixed;
  right: var(--borde);
  bottom: calc(var(--borde-abajo) + 56px);
  width: 200px;
  z-index: 2;
  border-radius: 16px;
  border: 2px solid #fff;
  overflow: hidden;
  background: #000;
  box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
}
/*
 * LA CAJA LA PONE LA IMAGEN, Y NO HAY NINGUNA RELACIÓN CLAVADA AQUÍ. Los polígonos son
 * fracciones de la pieza: con `object-fit: cover` —o con el `object-fit: fill` de la
 * referencia— la imagen se recorta o se deforma y la máscara no, y cada zona se despega del
 * plano. Con la imagen en flujo, `width: 100%` y alto automático, la caja adopta la relación del
 * archivo sea cual sea, y la máscara encima cuadra siempre.
 */
.minimapa .cuerpo { position: relative; }
.minimapa .plano { display: block; width: 100%; height: auto; }
.minimapa .zonas { position: absolute; inset: 0; }
.minimapa .titulo {
  position: absolute;
  inset: auto 0 0 0;
  padding: 6px 8px;
  background: linear-gradient(transparent, rgb(0 0 0 / 0.65));
  color: #fff;
  font: 500 12px/16px var(--pila);
}

/* ── La capa de terminaciones ──────────────────────────────────────────────────────────────── */
.capa {
  position: fixed;
  inset: 0;
  z-index: 4;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  padding: calc(var(--borde-arriba) + 56px) var(--borde) var(--borde-abajo);
  background: rgb(0 0 0 / 0.86);
  backdrop-filter: blur(8px);
  color: #fff;
}
/* A la IZQUIERDA: el hueco de la derecha lo ocupan el interruptor de ambiente y el de pantalla
   completa, que siguen vivos debajo. Dos botones en el mismo píxel son un bug, no un detalle. */
.capa .cerrar {
  position: fixed;
  top: var(--borde-arriba);
  left: var(--borde);
  width: 40px;
  height: 40px;
  border-radius: 9999px;
  background: var(--superficie);
  color: var(--tinta);
  box-shadow: var(--sombra-boton);
}
.capa .cerrar::before { content: "✕"; display: block; font: 600 16px/1 ui-sans-serif, system-ui, sans-serif; }

/*
 * LA CAPA DE TERMINACIONES CABE EN LA PANTALLA, y antes no: apilaba una habitacion debajo de
 * otra y con dos medía `1100 × 1622.3` en un viewport de 900 —722.3 px fuera— con la segunda
 * habitacion inalcanzable. Ahora es horizontal como la referencia (`Spec/04` §7, capa
 * `28.8, 45 · 1382.4 × 810`): el render se queda con el hueco y la columna de mando va al lado.
 * No crece con el numero de habitaciones, porque solo se enseña una.
 */
.terminaciones {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 260px;
  gap: 24px;
  max-width: 1382px;
  width: 100%;
  min-height: 0;
  margin: 0 auto;
}
.escena-terminaciones { display: flex; align-items: center; justify-content: center; min-width: 0; min-height: 0; }
.mando-terminaciones { display: flex; flex-direction: column; gap: 12px; min-height: 0; overflow-y: auto; }
.habitaciones { display: flex; flex-wrap: wrap; gap: 4px; }
.habitaciones .habitacion {
  height: 32px;
  padding: 0 14px;
  border-radius: 9999px;
  background: rgb(255 255 255 / 0.08);
  color: rgb(255 255 255 / 0.7);
  font: 600 12px/16px var(--pila);
}
.habitaciones .habitacion.activa { background: #fff; color: #000; }
.nombre-habitacion { margin: 0; font: 600 16px/24px var(--pila); }
.estilo-grande {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  border-radius: 16px;
  background: #111;
}
.estilos { display: flex; flex-direction: column; gap: 8px; }
.estilo {
  display: grid;
  gap: 4px;
  padding: 4px;
  border-radius: 12px;
  background: rgb(255 255 255 / 0.08);
  color: rgb(255 255 255 / 0.7);
}
.estilo.activo { background: #fff; color: #000; }
.miniatura { display: block; width: 94px; height: 104px; object-fit: cover; border-radius: 6px; }
.nombre-estilo { font: 600 11px/16px var(--pila); }

/* El CTA de la ficha, pegado al fondo del panel por mucho que se baje (Ipanema ⑩). */
.pie-pegajoso { position: sticky; bottom: 0; margin-top: auto; padding-top: 12px; background: #fff; display: flex; }

@media (max-width: 520px) {
  /* Y abajo, la tarjeta se pone ENCIMA del 2D⇄3D en vez de taparlo: a 390 px las dos cosas
     ocupan el ancho entero y la de arriba se comia el boton de la de abajo. */

  /*
   * LA FICHA EN TELÉFONO, medida contra `Spec/04 · Ficha.md` §8: allí el panel y el riel
   * DESAPARECEN y se esconden cada uno detrás de un botón, y el minimapa no se dibuja. Es la
   * misma pantalla con otro reparto, no otra pantalla.
   */
  /*
   * EL PANEL ES UN CAJÓN INFERIOR, no una pantalla entera. En la referencia el panel de teléfono
   * se abre a `0, 0 · 390 × 844` y tapa la lámina: «en teléfono el panel de detalle y la lámina
   * no pueden verse a la vez; en escritorio, sí» — lo anota su propia ficha, §8, entre lo que se
   * PIERDE a 390 px. Aquí ocupa la mitad de abajo y la unidad se sigue viendo. Es la única
   * medida de estas tres pantallas que no se copia, y se copia todo lo demás.
   */
  .panel { inset: 45% 12px var(--borde-abajo) 12px; width: auto; }
  .asa-panel { top: auto; bottom: var(--borde-abajo); left: 50%; transform: translateX(-50%); }
  .panel.abierto .datos { border-radius: 16px; }

  .ficha:has(.panel.abierto) .contador { bottom: auto; top: calc(var(--borde-arriba) + 100px); }

  /*
   * La columna de opciones · `154.3, 72 · 171.7 × 296` y su asa en `334, 72 · 40 × 40`
   * (Spec/04 §8). Dos correcciones: el relleno de 8 px, que es lo que separa la columna de los
   * `156 × 280` que median las pildoras a hueso; y el asa AL LADO y no encima, que es lo que
   * dejaba la columna 48 px mas abajo de donde su ficha la mide.
   */
  .riel-caja {
    top: calc(var(--borde-arriba) + 56px);
    right: var(--borde);
    display: flex;
    flex-direction: row-reverse;
    align-items: flex-start;
    gap: 8px;
  }
  .riel-caja .riel { padding: 8px; }
  .asa-riel {
    display: block;
    width: 40px;
    height: 40px;
    border-radius: 9999px;
    background: var(--superficie);
    color: var(--tinta);
    box-shadow: var(--sombra-boton);
    margin-left: auto;
  }
  .asa-riel::before { content: "⋯"; display: block; font: 600 20px/1 ui-sans-serif, system-ui, sans-serif; }
  .riel-caja .riel { display: none; }
  .riel-caja.abierto .riel { display: flex; }

  /* No se dibuja, igual que en la referencia: a 390 px taparía el arte que se está mirando. */
  .minimapa { display: none; }

  /* Y dentro de la ficha tampoco se dibuja `Pantalla completa`: la referencia no lo renderiza a
     390 px (`Spec/04` §8) y aqui caia justo encima del asa de la columna de opciones. */
  .pantalla:has(.ficha) ~ .chrome .pantalla-completa { display: none; }

  /* La capa de terminaciones gira a vertical: el render arriba y el mando debajo. */
  .terminaciones { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; }
  .estilos { flex-direction: row; flex-wrap: wrap; }

  .capa .cerrar { left: 12px; }
}

/* ── La ficha: panel blanco a sangre de 375 px, pie con canales ───────────────────────────── */
[data-tema="web3d"] .panel { left: 0; top: 0; bottom: 0; width: 375px; }
[data-tema="web3d"] .panel.abierto .datos {
  padding: 72px 20px 0;
  border: 0; border-radius: 0;
  box-shadow: none;
}
[data-tema="web3d"] .datos .titulo { font: 500 18px/24px var(--pila); color: var(--oscuro); }
[data-tema="web3d"] .datos .donde-esta,
[data-tema="web3d"] .datos .tipologia { font: 400 16px/22px var(--pila); color: var(--tinta-suave); }
[data-tema="web3d"] .cerrar-panel { top: 64px; right: 16px; width: 32px; height: 32px; background: var(--tenue); box-shadow: none; }
[data-tema="web3d"] .campos { column-gap: 0; border-top: 0; }

/* La planta de la ficha se encuadra ENTERA a la derecha del panel, sobre papel (Ipanema §⑧):
   el escenario se corre la mitad del panel y se achica hasta caber en lo que queda. */
@media (min-width: 521px) {
  [data-tema="web3d"] body:has(.ficha .panel.abierto) .recorrido { background: var(--lienzo-ficha); }
  [data-tema="web3d"] body:has(.ficha .panel.abierto) .escenario {
    transform: translate(calc(-50% + 187.5px), -50%) scale(0.6) translate(var(--paneo-x), var(--paneo-y));
    transform: translate(calc(-50% + 187.5px), -50%) scale(calc(var(--zoom) * var(--ajuste-ficha, 1))) translate(var(--paneo-x), var(--paneo-y));
  }
}

/* Con el panel CERRADO, la planta también entera (`--ajuste-ficha-cerrada`, `escenario.ts`): a sangre
   el arte del plano venía al filo y se cortaba. Sólo la PLANTA —la lámina que trae cuartos—; una foto
   de galería sigue a sangre, que es lo suyo. */
@media (min-width: 521px) {
  [data-tema="web3d"] body:has(.ficha .panel:not(.abierto)):has(.escenario .cuartos) .escenario {
    transform: translate(-50%, -50%) scale(calc(var(--zoom) * var(--ajuste-ficha-cerrada, 1))) translate(var(--paneo-x), var(--paneo-y));
    border-radius: 24px;
    box-shadow: 0 1px 2px rgb(0 0 0 / 0.05), 0 16px 48px rgb(0 0 0 / 0.08);
  }
  [data-tema="web3d"] body:has(.ficha .panel:not(.abierto)):has(.escenario .cuartos) .recorrido { background: var(--lienzo-ficha); }
}
@media (max-width: 520px) and (orientation: portrait) {
  [data-tema="web3d"] body:has(.ficha .panel:not(.abierto)):has(.escenario .cuartos) .escenario {
    transform: translate(-50%, calc(-50% + var(--centro-ficha-cerrada-telefono, 0px))) scale(calc(var(--zoom) * var(--ajuste-ficha-cerrada-telefono, 1))) translate(var(--paneo-x), var(--paneo-y));
    background: transparent;
  }
  [data-tema="web3d"] body:has(.ficha .panel:not(.abierto)):has(.escenario .cuartos) .recorrido { background: var(--lienzo-ficha); }
}

[data-tema="web3d"] .campos .grupo { font: 500 14px/20px var(--pila); color: var(--tinta); text-transform: none; letter-spacing: 0; padding-top: 16px; }
[data-tema="web3d"] .campos .clave,
[data-tema="web3d"] .campos .valor { padding: 10px 0; line-height: 24px; border-bottom: 1px solid var(--linea); }
[data-tema="web3d"] .campos .clave { font: 400 14px/24px var(--pila); color: var(--oscuro); }
[data-tema="web3d"] .pie-pegajoso {
  align-items: center; gap: 12px;
  margin: 0 -20px; padding: 12px 20px 16px;
  background: #fff; border-top: 1px solid var(--linea);
}

[data-tema="web3d"] .pie-pegajoso .via-redonda {
  flex: 0 0 36px; width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--tenue); color: var(--oscuro);
}
[data-tema="web3d"] .pie-pegajoso .via-redonda .icono { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.6; }
[data-tema="web3d"] .pestania {
  width: auto; min-width: 0; height: 40px;
  border-radius: 20px;
  background: #fff; color: var(--tinta-suave);
  font: 500 14px/20px var(--pila); text-align: center;
  box-shadow: 0 1px 2px rgb(16 24 40 / 0.1);
}
[data-tema="web3d"] .pestania.activa { background: var(--tinte); color: var(--primario); }
[data-tema="web3d"] .riel { align-items: flex-end; }

[data-tema="web3d"] .riel-caja { top: calc(var(--borde-arriba) + 64px); }

@media (max-width: 520px) {
  [data-tema="web3d"] .panel { inset: auto 0 0 0; width: auto; height: 46%; }
  [data-tema="web3d"] .panel.abierto .datos { padding-top: 20px; border-radius: 12px 12px 0 0; box-shadow: 0 -8px 24px rgb(16 24 40 / 0.12); }
  [data-tema="web3d"] .cerrar-panel { top: 12px; }
}

/* ── La ficha y el menú: misma tinta, misma escala ─────────────────────────────────────────── */
[data-tema="web3d"] .datos .titulo { font: 700 28px/34px var(--pila); color: var(--etiqueta); }
[data-tema="web3d"] .datos .donde-esta,
[data-tema="web3d"] .datos .tipologia { font: 400 15px/20px var(--pila); color: var(--etiqueta-2); }
[data-tema="web3d"] .campos .clave { font: 400 15px/22px var(--pila); color: var(--etiqueta-2); }
[data-tema="web3d"] .campos .valor { font: 500 15px/22px var(--pila); color: var(--etiqueta); }
[data-tema="web3d"] .campos .grupo { font: 600 13px/18px var(--pila); color: var(--etiqueta-2); text-transform: uppercase; letter-spacing: 0.04em; padding-top: 24px; }

/* ✨ Opaco: el material translúcido dejaba leer bajo el CTA lo que se desplazaba («Loan Amount»). */
[data-tema="web3d"] .pie-pegajoso { background: var(--lienzo); border-top-color: var(--separador); }
[data-tema="web3d"] .pestania {
  height: 36px; padding: 0 16px;
  border-radius: 18px;
  background: var(--material);
  -webkit-backdrop-filter: var(--desenfoque);
  backdrop-filter: var(--desenfoque);
  color: var(--etiqueta);
  font: 500 15px/20px var(--pila);
  box-shadow: var(--filo), var(--sombra-flota);
}
[data-tema="web3d"] .pestania.activa { background: var(--etiqueta); color: var(--lienzo); }

/* ── #9 · La ficha que vende ────────────────────────────────────────────────────────────────── */
[data-tema="web3d"] .interior-arriba { margin: -8px -8px 16px; position: relative; border-radius: 14px; overflow: hidden; aspect-ratio: 16 / 10; background: var(--relleno); }
[data-tema="web3d"] .interior-arriba img { width: 100%; height: 100%; object-fit: cover; display: block; }
[data-tema="web3d"] .pie-interior {
  position: absolute; left: 8px; bottom: 8px; padding: 3px 8px; border-radius: 8px;
  background: rgb(0 0 0 / 0.55); color: #fff; font: 500 11px/14px var(--pila);
}
[data-tema="web3d"] .datos .precio { font: 600 17px/22px var(--pila); letter-spacing: -0.01em; color: var(--etiqueta); margin: 8px 0 0; }
[data-tema="web3d"] .datos-clave { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1px; margin: 16px 0 0; border-radius: 12px; overflow: hidden; background: var(--separador); }
[data-tema="web3d"] .datos-clave .dato { background: var(--material-grueso); padding: 10px 12px; min-width: 0; }
/* Una fila incompleta no deja hueco gris: la última celda se estira hasta el borde. */
[data-tema="web3d"] .datos-clave .dato:last-child:nth-child(3n + 2) { grid-column: span 2; }
[data-tema="web3d"] .datos-clave .dato:last-child:nth-child(3n + 1) { grid-column: span 3; }
[data-tema="web3d"] .datos-clave .clave { font: 500 11px/14px var(--pila); letter-spacing: 0.04em; text-transform: uppercase; color: var(--etiqueta-legible); }
[data-tema="web3d"] .datos-clave .valor { margin: 2px 0 0; font: 600 15px/20px var(--pila); color: var(--etiqueta); overflow-wrap: anywhere; }
/* 🅿️ Los cajones de la residencia, en su propia fila (`ficha/campos.ts`, `espacios.ts`): la frase entera y el botón
   que abre su nivel con ellos resaltados. Una columna: «4 cajones · Nivel B2 · B2-033 a B2-036 + bodega · Nivel B1». */
[data-tema="web3d"] .datos-clave.espacios { grid-template-columns: minmax(0, 1fr); margin-top: 8px; }
[data-tema="web3d"] .datos-clave.espacios .valor { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; font-weight: 500; }
[data-tema="web3d"] .ver-espacios {
  min-height: 32px; padding: 0 12px; border: 0; border-radius: 9999px; cursor: pointer;
  /* Relleno gris y el color del desarrollo COMO TEXTO: 4.5:1 en claro y en oscuro (`--tinte` es claro en los dos). */
  background: var(--relleno); color: var(--primario-texto); font: 600 13px/18px var(--pila); white-space: nowrap;
}
[data-tema="web3d"] .ver-espacios:hover, [data-tema="web3d"] .ver-espacios:focus-visible { background: var(--primario); color: var(--sobre-primario); }
@media (pointer: coarse) { [data-tema="web3d"] .ver-espacios { min-height: 44px; } }
[data-tema="web3d"] .superficies { display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; margin: 16px 0 0; }
[data-tema="web3d"] .superficies .clave { font: 400 15px/20px var(--pila); color: var(--etiqueta-legible); }
[data-tema="web3d"] .superficies .valor { margin: 0; font: 500 15px/20px var(--pila); color: var(--etiqueta); text-align: right; font-variant-numeric: tabular-nums; }
[data-tema="web3d"] .destacados-titulo { margin: 24px 0 8px; font: 600 13px/18px var(--pila); letter-spacing: 0.04em; text-transform: uppercase; color: var(--etiqueta-legible); }
[data-tema="web3d"] .destacados { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
[data-tema="web3d"] .destacado { display: grid; gap: 2px; padding-left: 14px; border-left: 2px solid var(--primario); }
[data-tema="web3d"] .destacado-titulo { font: 600 15px/20px var(--pila); color: var(--etiqueta); }
[data-tema="web3d"] .destacado-texto { font: 400 14px/20px var(--pila); color: var(--etiqueta-legible); }
[data-tema="web3d"] .datos .descargar {
  display: inline-flex; align-items: center; gap: 8px; height: 44px; padding: 0 18px; border-radius: 22px;
  background: var(--relleno); color: var(--etiqueta); font: 600 15px/20px var(--pila); text-decoration: none;
}
/* ── 💲 Condiciones comerciales y compartir (25-sep-2026) ──────────────────────────────────────
   Bajo el precio: el plan de pagos por hitos, el apartado y la entrega, leídos de `unit.terms`.
   Debajo, «Share» con su aviso; el botón mide 44 px de alto en todo puntero. */
.condiciones { margin: 12px 0 0; }
.condiciones-titulo { margin: 0 0 6px; font: 600 12px/16px var(--pila); letter-spacing: 0.04em; text-transform: uppercase; opacity: 0.7; }
.plan-pagos { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; }
.tramo { display: grid; grid-template-columns: 3.2em minmax(0, 1fr) auto; align-items: baseline; gap: 8px; padding: 6px 0; font: 400 14px/20px var(--pila); }
.tramo-pct { font-weight: 600; font-variant-numeric: tabular-nums; }
.tramo-importe { font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.condiciones-extra { display: grid; grid-template-columns: auto 1fr; gap: 4px 16px; margin: 8px 0 0; font: 400 14px/20px var(--pila); }
.condiciones-extra .valor { margin: 0; text-align: right; font-weight: 500; font-variant-numeric: tabular-nums; }
.compartir-fila { position: relative; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 12px 0 0; flex-shrink: 0; }
.compartir {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; min-width: 44px; padding: 0 18px;
  border: 0; border-radius: 22px; background: var(--superficie, #f2f2f2); color: inherit; cursor: pointer;
  font: 600 15px/20px var(--pila);
}
.compartir .icono { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.aviso-compartir {
  margin: 0; padding: 6px 12px; border-radius: 16px; max-width: 100%;
  background: #1c1c1e; color: #fff; font: 500 13px/18px var(--pila);
  opacity: 0; transform: translateY(4px); pointer-events: none; transition: opacity 0.2s, transform 0.2s;
}
.aviso-compartir.visible { opacity: 1; transform: none; pointer-events: auto; }
.aviso-compartir:empty { display: none; }
.aviso-link { display: block; margin-top: 2px; font-weight: 400; overflow-wrap: anywhere; user-select: all; }
[data-tema="web3d"] .condiciones { margin: 12px 0 0; padding: 4px 12px 10px; border-radius: 12px; background: var(--material-grueso); box-shadow: inset 0 0 0 1px var(--separador); flex-shrink: 0; }
[data-tema="web3d"] .condiciones-titulo { margin: 6px 0 2px; color: var(--etiqueta-legible); opacity: 1; font: 500 11px/14px var(--pila); }
[data-tema="web3d"] .plan-pagos { background: var(--separador); }
[data-tema="web3d"] .tramo { background: var(--material-grueso); font: 400 15px/20px var(--pila); color: var(--etiqueta); }
[data-tema="web3d"] .tramo-pct { color: var(--primario); }
[data-tema="web3d"] .tramo-hito { color: var(--etiqueta-legible); }
[data-tema="web3d"] .tramo-importe { font-weight: 500; }
[data-tema="web3d"] .condiciones-extra { padding-top: 8px; border-top: 1px solid var(--separador); font: 400 15px/20px var(--pila); }
[data-tema="web3d"] .condiciones-extra .clave { color: var(--etiqueta-legible); }
[data-tema="web3d"] .condiciones-extra .valor { color: var(--etiqueta); }
[data-tema="web3d"] .compartir { background: var(--relleno); color: var(--etiqueta); }
[data-tema="web3d"] .compartir:focus-visible { background: var(--primario); color: var(--sobre-primario); }

@media (hover: hover) {
  [data-tema="web3d"] .compartir:hover { background: var(--primario); color: var(--sobre-primario); }
}

/* La ficha entera se desplaza (interior, datos, features); el pie de contacto queda pegado abajo. */
[data-tema="web3d"] .panel.abierto .datos { overflow-y: auto; scrollbar-width: thin; }
[data-tema="web3d"] .datos .cuerpo { flex: none; overflow: visible; }
[data-tema="web3d"] .interior-arriba, [data-tema="web3d"] .datos .cabeza { flex-shrink: 0; }

/* Teléfono en vertical con la ficha abierta: el plano de venta ENTERO sobre la hoja (46 %), no
   debajo de ella (`--ajuste-ficha-telefono`, lo mide `medirViewport`). */
@media (max-width: 520px) and (orientation: portrait) {
  [data-tema="web3d"] body:has(.ficha .panel.abierto) .escenario {
    transform: translate(-50%, calc(-50% + var(--centro-ficha-telefono, 0px))) scale(calc(var(--zoom) * var(--ajuste-ficha-telefono, 1))) translate(var(--paneo-x), var(--paneo-y));
  }
  [data-tema="web3d"] body:has(.ficha .panel.abierto) .recorrido { background: var(--lienzo-ficha); }
  [data-tema="web3d"] body:has(.ficha .panel.abierto) .escenario { background: transparent; }
}

/* El sello de la vendida en su ficha (`venta.ts`): la etiqueta del estado, rayada como en la planta. */
.sello-vendida {
  --color-estado: var(--tinta-suave);
  display: inline-flex; align-items: center; margin-left: 10px; padding: 3px 10px; border-radius: 6px;
  vertical-align: middle; font: 700 11px/16px var(--pila); letter-spacing: 0.08em; text-transform: uppercase;
  color: #fff; color: var(--tinta-estado); background-color: var(--color-estado);
  background-image: repeating-linear-gradient(135deg, rgb(255 255 255 / 0.22) 0 2px, transparent 2px 6px);
}

/* 🌙 La ficha en modo oscuro del sistema: el panel era `#fff` fijo y la tinta seguía al sistema
   (clara), así que el título, el nombre y el precio salían blanco sobre blanco. El panel toma el
   lienzo del tema (`--lienzo`: blanco en claro, negro en oscuro). */
[data-tema="web3d"] .panel.abierto .datos { background: var(--lienzo, #fff); }

@media (prefers-color-scheme: dark) {
  [data-tema="web3d"] .panel.abierto .datos { border-color: var(--lienzo, #000); }
  [data-tema="web3d"] .datos .pie { border-top-color: var(--separador); }
  /* Las vías redondas del pie y el comparador: `--tenue`/`--superficie` se quedaban claros con la
     tinta ya clara (icono y «Choose a Unit» invisibles). */
  [data-tema="web3d"] .pie-pegajoso .via-redonda { background: var(--relleno); color: var(--etiqueta); }
}

/* Donde se esta NUNCA se corta: las migas de arriba ceden y se abrevian con «…». En teléfono, con
   tres migas (desarrollo › piso › unidad) el desarrollo se cae: la marca ya lo dice y en 390 no
   cabian las tres —quedaba «Zigur › Level › 40»—. */
/* El «⋯» de las pestañas en teléfono es un boton flotante mas: material y tinta del tema. Con
   `--superficie` (siempre clara) en oscuro quedaba un circulo blanco con los puntos en blanco. */
[data-tema="web3d"] .asa-riel {
  background: var(--material); color: var(--etiqueta);
  -webkit-backdrop-filter: var(--desenfoque); backdrop-filter: var(--desenfoque);
  box-shadow: var(--filo), var(--sombra-flota);
}

/* La ficha: el aviso legal en una línea. */
[data-tema="web3d"] .ficha .aviso { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ── La tinta sobre el color de un estado ─────────────────────────────────────────────────────
 * `--color-estado` es un dato del manifiesto (`unitStatuses[].color`); el blanco fijo encima no se
 * lee sobre los claros (#94a3b8 «No disponible» 2.6:1, #a39a8f «Sold» 2.8:1). Se elige por la
 * claridad L* del propio color: por debajo de 50, blanco; por encima, negro. */
.estado, .sello-vendida { --tinta-estado: lch(from var(--color-estado) calc((50 - l) * infinity) 0 0); }

/* La hoja del cuarto: su nombre, sus fotos (carrusel) y, si hay, «Tour 360». Encima de todo. */
.hoja-cuarto {
  position: fixed; inset: 0; z-index: 90; display: grid; place-items: center;
  padding: var(--borde-arriba) var(--borde) var(--borde-abajo);
  background: rgb(0 0 0 / 0.55); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  animation: hoja-cuarto-entra 0.28s var(--resorte, var(--curva));
}
.hoja-cuarto .marco {
  position: relative; display: flex; flex-direction: column; gap: 12px;
  width: min(1100px, 100%); max-height: 100%; padding: 16px;
  border-radius: 20px; background: var(--lienzo-elevado, #fff); color: var(--etiqueta, var(--tinta));
  box-shadow: var(--sombra-hoja, 0 24px 64px rgb(0 0 0 / 0.18));
}
.hoja-cuarto .cabeza-cuarto { display: flex; align-items: center; gap: 12px; padding-inline: 4px; min-height: 36px; }
.hoja-cuarto h2 { margin: 0; flex: 1 1 auto; font: 650 20px/25px var(--pila); letter-spacing: -0.01em; }
.hoja-cuarto .contador-cuarto { font: 500 13px/18px var(--pila); color: var(--etiqueta-2, var(--tinta-suave)); font-variant-numeric: tabular-nums; }
.hoja-cuarto .cerrar-cuarto {
  flex: none; width: 36px; height: 36px; padding: 0; border: 0; border-radius: 50%; cursor: pointer;
  background: var(--relleno, rgb(120 120 128 / 0.14)); color: inherit;
}
.hoja-cuarto .cerrar-cuarto::before {
  content: ""; display: block; width: 18px; height: 18px; margin: auto; background: currentColor;
  -webkit-mask: var(--i-cerrar) center / contain no-repeat; mask: var(--i-cerrar) center / contain no-repeat;
}
.hoja-cuarto .foto-cuarto { position: relative; margin: 0; min-height: 0; border-radius: 12px; overflow: hidden; background: var(--relleno, #eee); }
.hoja-cuarto .foto-cuarto img { display: block; width: 100%; max-height: calc(100vh - 220px); aspect-ratio: 16 / 9; object-fit: cover; }
.hoja-cuarto .paso-cuarto {
  position: absolute; top: 50%; translate: 0 -50%; width: 40px; height: 40px; border: 0; border-radius: 50%;
  cursor: pointer; background: var(--material, rgb(255 255 255 / 0.74)); color: var(--etiqueta, #1d1d1f);
  -webkit-backdrop-filter: var(--desenfoque, blur(20px)); backdrop-filter: var(--desenfoque, blur(20px));
  font: 500 22px/1 var(--pila); box-shadow: var(--sombra-flota, none);
}
.hoja-cuarto .paso-cuarto.anterior { left: 12px; }
.hoja-cuarto .paso-cuarto.siguiente { right: 12px; }
.hoja-cuarto .tira-cuarto { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; padding: 2px; }
.hoja-cuarto .mini-cuarto {
  flex: none; width: 88px; aspect-ratio: 16 / 9; padding: 0; border: 0; border-radius: 8px; overflow: hidden;
  cursor: pointer; opacity: 0.6; background: none; outline-offset: 2px;
}
.hoja-cuarto .mini-cuarto img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hoja-cuarto .mini-cuarto.activa { opacity: 1; box-shadow: 0 0 0 2px var(--primario); }
.hoja-cuarto .tour-cuarto {
  align-self: flex-start; min-height: 40px; padding: 0 18px; border: 0; border-radius: 999px; cursor: pointer;
  background: var(--primario); color: var(--sobre-primario); font: 600 15px/20px var(--pila);
}
.hoja-cuarto .tours { position: relative; inset: auto; height: min(70vh, 640px); border-radius: 12px; overflow: hidden; }
.hoja-cuarto .tours .tour { width: 100%; height: 100%; border: 0; }
@keyframes hoja-cuarto-entra { from { opacity: 0; } to { opacity: 1; } }

@media (max-width: 520px) {
  .hoja-cuarto { padding: 0; place-items: end stretch; }
  .hoja-cuarto .marco { border-radius: 20px 20px 0 0; padding: 12px 12px calc(12px + env(safe-area-inset-bottom, 0px)); }
  .hoja-cuarto h2 { font-size: 17px; line-height: 22px; }
  .hoja-cuarto .foto-cuarto img { aspect-ratio: 4 / 3; }
  .hoja-cuarto .mini-cuarto { width: 64px; }
}

@media (prefers-reduced-motion: reduce) {
  .hoja-cuarto { animation: none; }
}

/* La miga flota encima del panel. Su material es translucido, así que al desplazar la ficha el
   contenido se alcanzaba a leer detrás: esta guarda opaca pertenece al panel y queda bajo la miga.
   ✨ Vive en `.panel`, que no se desplaza, y no en `.datos`, que sí: colgada de `.datos` con
   `absolute` se iba con el contenido al primer giro de rueda y el plan de pagos se leía detrás de
   las migas. Opaca de verdad: con el material translúcido también se alcanzaba a leer. */
@media (min-width: 521px) {
  [data-tema="web3d"] body:has(.chrome .migas) .panel.abierto::before {
    content: ""; position: absolute; inset: 0 0 auto; z-index: 1; height: 64px;
    background: var(--lienzo); pointer-events: none;
  }
}

[data-tema="web3d"] .datos .pie { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
[data-tema="web3d"] .datos .pie .aviso { flex-basis: 100%; }

/* ── ✨ Pulir-Ficha (27-sep-2026) ─────────────────────────────────────────────────────────────
 * Recorrida contra la referencia a 1440 y 390, claro y oscuro, es y en. Nota y capturas:
 * `Desarrollos/<Desarrollo>/6 · Showroom/Notas/… · Pulido · Ficha.md`. */

/* LA CRUZ VA SOBRE LA FOTO, como la de la referencia (`Spec/04` §4.1: `318, 98`, encima de la
   foto). Estaba DEBAJO: la foto viene después en el DOM y es `relative`, así que la tapaba y en
   escritorio el panel no se podía cerrar. Material translúcido para leerse sobre cualquier foto. */
[data-tema="web3d"] .cerrar-panel {
  top: 72px; right: 20px; z-index: 2;
  background: var(--material); color: var(--etiqueta);
  -webkit-backdrop-filter: var(--desenfoque); backdrop-filter: var(--desenfoque);
  box-shadow: var(--filo), var(--sombra-flota);
}
/* Con la cruz en la foto, la cabeza ya no le guarda sitio: el corazón va al borde derecho. */
[data-tema="web3d"] .datos:has(.interior-arriba) .cabeza { padding-right: 0; }
[data-tema="web3d"] .datos .cabeza > .corazon { margin: -8px -10px -8px auto; }

/* EL ASA DEL PANEL CERRADO, bajo el menú y con icono. En `web3d` las migas ocupan la fila de
   arriba y el asa quedaba DEBAJO de ellas (se asomaba «02» a la derecha de la miga). */
[data-tema="web3d"] .asa-panel {
  background: var(--material); color: var(--etiqueta);
  -webkit-backdrop-filter: var(--desenfoque); backdrop-filter: var(--desenfoque);
  box-shadow: var(--filo), var(--sombra-flota);
}
@media (min-width: 521px) {
  [data-tema="web3d"] .asa-panel { top: calc(var(--borde-arriba) + 56px); left: var(--borde); }
}

/* LA LÁMINA DE LA FICHA ES UNA HOJA: esquinas redondas y sombra. A sangre cuadrada, la planta
   (fondo claro de fábrica) era un rectángulo blanco duro sobre el negro del modo oscuro y un filo
   gris sin intención sobre el papel del claro. `overflow: clip` del escenario recorta la esquina. */
[data-tema="web3d"] body:has(.ficha .panel.abierto) .escenario {
  border-radius: 24px;
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.05), 0 16px 48px rgb(0 0 0 / 0.08);
}

/* Las pestañas inactivas, con el material grueso en oscuro: sobre la planta blanca el material
   fino se volvía gris medio y el riel parecía de dos colores. */
@media (prefers-color-scheme: dark) {
  [data-tema="web3d"] .pestania:not(.activa) { background: var(--material-grueso); }
}

/* Los nombres largos de los datos clave (es: «ESTACIONAMIENTO») se parten con guion y no se cortan. */
[data-tema="web3d"] .datos-clave .clave { -webkit-hyphens: auto; hyphens: auto; overflow-wrap: anywhere; }

/* «Share» en el pie, al lado de la hoja de venta (`ficha.ts`): sin el margen de cuando iba suelto. */
[data-tema="web3d"] .datos .pie .compartir-fila { margin: 0; }

/* El aviso legal: una línea, y entero al tocarlo. */
[data-tema="web3d"] .ficha .aviso { cursor: pointer; }
[data-tema="web3d"] .ficha .aviso.entero { white-space: normal; overflow: visible; }

@media (max-width: 520px) {
  /* A 390 la foto del interior se comía la hoja entera: el precio no se veía sin desplazar. */
  [data-tema="web3d"] .interior-arriba { aspect-ratio: 2 / 1; }
  [data-tema="web3d"] .cerrar-panel { top: 20px; }
  /* Con el panel cerrado el asa vive abajo al centro: el contador de la foto sube por encima. */
  .ficha:has(.panel:not(.abierto)) .contador { bottom: calc(var(--borde-abajo) + 52px); }
}

/* ── 🏷️ LOS CUARTOS DE LA PLANTA DE LA FICHA SE LEEN A SU TAMAÑO (Ensayo De Demo 28-sep-2026, S11) ──
   El escenario se achica para caber (`--ajuste-ficha*`, `escenario.ts`) y los rótulos de cuarto, que
   viven dentro, se achicaban con él: a 1440 medían ~6 px y a 390 no se leían. Cada encuadre de la ficha
   declara su escala (`--escala-planta`) y el rótulo la deshace: mide en pantalla lo que dice
   `mascara.css` (11 px; 9.5 px en teléfono). `despejar` (`mascara.ts`) mide en pantalla, así que el que
   ya no cabe se esconde igual que antes. */
@media (min-width: 521px) {
  [data-tema="web3d"] body:has(.ficha .panel.abierto) .escenario { --escala-planta: calc(var(--zoom, 1) * var(--ajuste-ficha, 1)); }
  [data-tema="web3d"] body:has(.ficha .panel:not(.abierto)):has(.escenario .cuartos) .escenario { --escala-planta: calc(var(--zoom, 1) * var(--ajuste-ficha-cerrada, 1)); }
}
@media (max-width: 520px) and (orientation: portrait) {
  [data-tema="web3d"] body:has(.ficha .panel.abierto) .escenario { --escala-planta: calc(var(--zoom, 1) * var(--ajuste-ficha-telefono, 1)); }
  [data-tema="web3d"] body:has(.ficha .panel:not(.abierto)):has(.escenario .cuartos) .escenario { --escala-planta: calc(var(--zoom, 1) * var(--ajuste-ficha-cerrada-telefono, 1)); }
}
[data-tema="web3d"] body:has(.ficha) .escenario .cuarto {
  font-size: calc(11px / var(--escala-planta, 1));
  line-height: calc(13px / var(--escala-planta, 1));
  text-shadow: 0 0 calc(2px / var(--escala-planta, 1)) rgb(255 255 255 / 0.95), 0 0 calc(6px / var(--escala-planta, 1)) rgb(255 255 255 / 0.8);
}
@media (max-width: 520px) {
  [data-tema="web3d"] body:has(.ficha) .escenario .cuarto {
    font-size: calc(10.5px / var(--escala-planta, 1));
    line-height: calc(12px / var(--escala-planta, 1));
  }
}

/* ══ 📱 LA FICHA A 390: PRIMERO LA RESIDENCIA (🧭 Showroom-Rápido-Motor · Plan del cruce §B4) ══════════════════════
   `ficha.ts` pinta en el teléfono la planta de la unidad arriba, luego nombre, precio, datos clave, la foto y
   las áreas; los pagos detrás de su entrada. La hoja nace en el 46 % y crece al leerla (`.expandida`). */
@media (max-width: 520px) {
  [data-tema="web3d"] .panel { transition: height var(--t, 0.35s) var(--resorte, ease); }
  [data-tema="web3d"] .panel.expandida { height: calc(100% - var(--borde-arriba) - 60px); }
  /* Expandida, la hoja pasa por debajo del «…» de las pestañas: se aparta mientras se lee. */
  [data-tema="web3d"] .ficha:has(.panel.expandida) .riel-caja { opacity: 0; pointer-events: none; }
  [data-tema="web3d"] .interior-arriba.planta-arriba {
    aspect-ratio: auto; height: 200px; margin: -8px -8px 16px;
    background: var(--relleno) center / contain no-repeat !important;
  }
  [data-tema="web3d"] .interior-arriba.planta-arriba img { object-fit: contain; padding: 8px; box-sizing: border-box; }
  [data-tema="web3d"] .cuerpo > .interior-arriba { margin: 16px 0 0; }

  [data-tema="web3d"] .entrada-pagos { margin: 20px 0 0; }
  [data-tema="web3d"] .entrada-pagos-resumen {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    min-height: 56px; padding: 0 16px;
    border-radius: 14px; background: var(--relleno);
    list-style: none; cursor: pointer;
  }
  [data-tema="web3d"] .entrada-pagos-resumen::-webkit-details-marker { display: none; }
  [data-tema="web3d"] .entrada-pagos-titulo { font: 600 17px/22px var(--pila); color: var(--etiqueta); }
  [data-tema="web3d"] .entrada-pagos-accion {
    display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 0 14px;
    border-radius: 18px; background: var(--primario); color: var(--sobre-primario, #fff);
    font: 600 14px/18px var(--pila);
  }
  [data-tema="web3d"] .entrada-pagos-accion::after { content: "›"; font-size: 18px; line-height: 1; transition: transform 0.2s; }
  [data-tema="web3d"] .entrada-pagos[open] .entrada-pagos-accion::after { transform: rotate(90deg); }
  [data-tema="web3d"] .entrada-pagos[open] .entrada-pagos-accion { background: var(--material-grueso); color: var(--etiqueta); }
  [data-tema="web3d"] .entrada-pagos > .condiciones { margin-top: 12px; }
  [data-tema="web3d"] .entrada-pagos > .condiciones > .condiciones-titulo { display: none; }
}
/* 🧱 El cotizador y la hoja de venta de la ficha `web3d` (`ficha/cotizador.ts`). */

/* ── 🧮 Cotizador y hoja de venta (26-sep-2026) ────────────────────────────────────────────────
   Bajo el precio de una unidad libre: el calendario de preventa (fecha · hito · importe) y el
   financiamiento a la entrega con su mensualidad en vivo. La cifra de la mensualidad es el único
   color del desarrollo. «Download Sheet» convive con la hoja del arquitecto en el pie. */
[data-tema="web3d"] .calendario { list-style: none; margin: 0; padding: 0; display: grid; }
[data-tema="web3d"] .pago {
  display: grid; grid-template-columns: 4.6em minmax(0, 1fr) auto; gap: 10px; align-items: baseline;
  padding: 9px 0; border-top: 1px solid var(--separador); font: 400 15px/20px var(--pila); color: var(--etiqueta);
}
[data-tema="web3d"] .pago:first-child { border-top: 0; }
[data-tema="web3d"] .pago-fecha { font: 400 13px/18px var(--pila); color: var(--etiqueta-legible); font-variant-numeric: tabular-nums; white-space: nowrap; }
[data-tema="web3d"] .pago-hito { min-width: 0; color: var(--etiqueta); }
[data-tema="web3d"] .pago-pct { font-weight: 600; color: var(--primario-texto); font-variant-numeric: tabular-nums; }
[data-tema="web3d"] .pago-nota { display: block; font: 400 12px/16px var(--pila); color: var(--etiqueta-legible); }
[data-tema="web3d"] .pago-importe { font-weight: 500; text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
[data-tema="web3d"] .pago-total { font-weight: 600; }
[data-tema="web3d"] .pago-total .pago-importe { font-weight: 600; }

[data-tema="web3d"] .financiar { margin: 10px -12px -10px; padding: 4px 12px 12px; border-top: 1px solid var(--separador); }
[data-tema="web3d"] .financiar-interruptor {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 48px; cursor: pointer;
  font: 600 15px/20px var(--pila); color: var(--etiqueta);
}
[data-tema="web3d"] .financiar-interruptor input {
  appearance: none; flex: none; position: relative; width: 51px; height: 31px; margin: 0; border-radius: 16px;
  background: var(--relleno); cursor: pointer; transition: background-color 0.2s;
}
[data-tema="web3d"] .financiar-interruptor input::before {
  content: ""; position: absolute; top: 2px; left: 2px; width: 27px; height: 27px; border-radius: 50%;
  background: #fff; box-shadow: 0 3px 8px rgb(0 0 0 / 0.15), 0 1px 1px rgb(0 0 0 / 0.16);
  transition: transform var(--t) var(--resorte);
}
[data-tema="web3d"] .financiar-interruptor input:checked { background: var(--primario); }
[data-tema="web3d"] .financiar-interruptor input:checked::before { transform: translateX(20px); }
[data-tema="web3d"] .financiar-interruptor input:focus-visible { outline: 2px solid var(--primario); outline-offset: 2px; }
[data-tema="web3d"] .financiar-campos { display: grid; gap: 16px; }
[data-tema="web3d"] .financiar-campos[hidden] { display: none; }

[data-tema="web3d"] .mensualidad { padding: 12px 14px; border-radius: 12px; background: var(--lienzo-elevado); box-shadow: var(--filo); }
[data-tema="web3d"] .mensualidad-rotulo { margin: 0; font: 500 11px/14px var(--pila); letter-spacing: 0.04em; text-transform: uppercase; color: var(--etiqueta-legible); }
[data-tema="web3d"] .mensualidad-cifra {
  margin: 2px 0 8px; font: 700 34px/41px var(--pila); letter-spacing: -0.02em; color: var(--primario-texto);
  font-variant-numeric: tabular-nums;
}
[data-tema="web3d"] .por-mes { margin-left: 2px; font: 500 17px/22px var(--pila); letter-spacing: 0; color: var(--etiqueta-legible); }
[data-tema="web3d"] .mensualidad-desglose { display: grid; grid-template-columns: auto 1fr; gap: 4px 16px; margin: 0; padding-top: 8px; border-top: 1px solid var(--separador); font: 400 13px/18px var(--pila); }
[data-tema="web3d"] .mensualidad-desglose .clave { color: var(--etiqueta-legible); }
[data-tema="web3d"] .mensualidad-desglose .valor { margin: 0; text-align: right; font-weight: 500; color: var(--etiqueta); font-variant-numeric: tabular-nums; }

[data-tema="web3d"] .campo-fin-fila { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
[data-tema="web3d"] .campo-fin-rotulo { font: 400 15px/20px var(--pila); color: var(--etiqueta); }
[data-tema="web3d"] .campo-fin-valor { font: 600 15px/20px var(--pila); color: var(--etiqueta); font-variant-numeric: tabular-nums; }
[data-tema="web3d"] .campo-fin input[type="range"] { display: block; width: 100%; height: 28px; margin: 4px 0 0; accent-color: var(--primario); cursor: pointer; }
[data-tema="web3d"] .campo-fin-nota { margin: 0; font: 400 12px/16px var(--pila); color: var(--etiqueta-legible); }
[data-tema="web3d"] .segmentado {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 2px; margin: 8px 0 0; padding: 2px;
  border-radius: 9px; background: var(--relleno);
}
[data-tema="web3d"] .segmento {
  min-height: 32px; padding: 0 4px; border: 0; border-radius: 7px; background: transparent; color: var(--etiqueta);
  font: 500 13px/18px var(--pila); cursor: pointer; transition: background-color 0.2s, box-shadow 0.2s;
}
[data-tema="web3d"] .segmento.activo { background: var(--lienzo-elevado); box-shadow: 0 1px 3px rgb(0 0 0 / 0.12), var(--filo); font-weight: 600; }
[data-tema="web3d"] .segmento:focus-visible { outline: 2px solid var(--primario); outline-offset: 1px; }

@media (pointer: coarse) {
  [data-tema="web3d"] .segmento { min-height: 40px; }
}

[data-tema="web3d"] .con-sufijo {
  display: inline-flex; align-items: center; gap: 2px; min-height: 36px; padding: 0 10px; border-radius: 8px;
  background: var(--relleno);
}
[data-tema="web3d"] .con-sufijo input {
  width: 4.2em; padding: 0; border: 0; background: transparent; color: var(--etiqueta); text-align: right;
  font: 600 15px/20px var(--pila); font-variant-numeric: tabular-nums;
}
[data-tema="web3d"] .con-sufijo input:focus { outline: none; }
[data-tema="web3d"] .con-sufijo:focus-within { box-shadow: 0 0 0 2px var(--primario); }
[data-tema="web3d"] .sufijo { font: 500 15px/20px var(--pila); color: var(--etiqueta-legible); }
/* EL DEDO (📱 Pulir-Celular midió el interés en 20 px de alto dentro de su caja de 36 y el deslizador
   en 28): el campo llena su caja, y con dedo la caja y el deslizador miden 44. El dibujo no cambia. */
[data-tema="web3d"] .con-sufijo input { align-self: stretch; }
@media (pointer: coarse) {
  [data-tema="web3d"] .con-sufijo { min-height: 44px; }
  [data-tema="web3d"] .campo-fin input[type="range"] { height: 44px; margin-top: -4px; margin-bottom: -8px; }
}
[data-tema="web3d"] .aviso-estimacion { margin: 0; font: 400 12px/16px var(--pila); color: var(--etiqueta-legible); }

[data-tema="web3d"] .descargar-hoja { border: 0; cursor: pointer; }
[data-tema="web3d"] .descargar-hoja .icono { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
[data-tema="web3d"] .descargar-hoja[aria-busy="true"] { cursor: progress; opacity: 0.7; }
[data-tema="web3d"] .descargar-hoja:focus-visible { outline: 2px solid var(--primario); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  [data-tema="web3d"] .financiar-interruptor input,
  [data-tema="web3d"] .financiar-interruptor input::before,
  [data-tema="web3d"] .segmento { transition: none; }
}
/* 🧱 El cajon del menu (`menu.ts`): su boton, sus filas, sus vias de un toque, el idioma y la hoja de Legal. */

.menu-velo {
  position: fixed;
  inset: 0;
  z-index: 85;
  background: rgb(0 0 0 / 0.4);
  backdrop-filter: blur(4px);
}
.menu {
  position: fixed;
  top: 32px;
  left: 24px;
  width: 384px;
  /* Alto FIJO y no `max-height`: la referencia mide `24, 32 · 384 × 836` a 900 de viewport, o sea
     el alto entero menos los dos margenes de 32. Un cajon que se encoge con su contenido cambia
     de tamanio al cambiar de desarrollo, y el pie deja de estar donde estaba. */
  height: calc(100% - 64px);
  z-index: 90;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  padding-bottom: 16px;
  border-radius: 16px;
  background: #fff;
  box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
  animation: entra-menu 0.3s var(--curva);
}
@keyframes entra-menu { from { opacity: 0; transform: translateX(-16px); } }
.menu-cerrar {
  position: absolute;
  top: 48px;
  right: 8px;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 9999px;
  background: var(--superficie);
  color: var(--tinta);
  cursor: pointer;
}
.menu-cerrar::before { content: "←"; display: block; font: 600 16px/1 ui-sans-serif, system-ui, sans-serif; }
.menu-marca { margin: 48px 16px 0; width: 352px; max-height: 160px; object-fit: contain; }
.menu-nombre { margin: 8px 16px 0; font: 600 12px/15px var(--pila); color: var(--primario); }
.menu-direccion { margin: 6px 16px 0; font: 400 12px/16.5px var(--pila); color: var(--tinta-suave); }
.menu-items { margin-top: 24px; display: flex; flex-direction: column; }
.menu-item {
  display: flex;
  align-items: center;
  gap: 14px;
  height: 44px;
  padding: 10px 0 10px 16px;
  border: 0;
  background: transparent;
  color: var(--tinta);
  font: 400 16px/24px var(--pila);
  text-align: left;
  cursor: pointer;
}
.menu-item .glifo { width: 16px; font-size: 14px; opacity: 0.75; }
.menu-item:hover { background: var(--superficie); }
/* El activo, dos capas y nada mas: el degradado sobre la fila y la barra de 4 × 36 a la
   izquierda. El peso NO cambia, igual que en la referencia. */
.menu-item.activo {
  position: relative;
  background: linear-gradient(to right, color-mix(in srgb, var(--primario) 18%, transparent), transparent);
  color: var(--primario);
  cursor: default;
}
.menu-item.activo::before {
  content: "";
  position: absolute;
  left: 0;
  top: 4px;
  width: 4px;
  height: 36px;
  border-radius: 0 9999px 9999px 0;
  background: var(--primario);
}
.menu-item.mudo { opacity: 0.4; cursor: default; }
.menu-aviso { margin: 16px; font: 400 11px/16px var(--pila); color: var(--tinta-suave); }

@media (max-width: 520px) {
  /* ── LAS OCHO PANTALLAS A 390 px ────────────────────────────────────────────────────────── */

  /* El cajon ocupa el ancho completo menos los margenes, y no cambia nada mas (Spec/01 §5.6). */
  .menu { left: 12px; right: 12px; width: auto; top: 16px; height: calc(100% - 32px); }
  .menu-marca { width: auto; margin: 48px 16px 0; }
  .menu-item { width: auto; }
}

.menu-item .glifo { display: inline-flex; width: 18px; opacity: 1; color: var(--primario); }
.menu-item .glifo .icono { width: 18px; height: 18px; }
.menu-vias { display: flex; justify-content: center; gap: 12px; margin: auto 16px 0; padding-top: 24px; }
.via-redonda {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 9999px;
  background: var(--superficie); color: var(--tinta); text-decoration: none;
  transition: background 0.2s var(--curva), color 0.2s var(--curva);
}
.via-redonda:hover, .via-redonda:focus-visible { background: var(--primario); color: var(--sobre-primario); }

/* ── El menú: 360 px a sangre, ✕ arriba, filas de 41 con línea ────────────────────────────── */
[data-tema="web3d"] .menu-velo { background: rgb(16 24 40 / 0.7); backdrop-filter: none; }
[data-tema="web3d"] .menu {
  top: 0; left: 0;
  width: 360px; height: 100%;
  padding: 0 20px 16px;
  border-radius: 0;
  box-shadow: none;
}
[data-tema="web3d"] .menu-cerrar {
  --icono: var(--i-cerrar);
  top: 16px; right: 20px; width: 32px; height: 32px;
  background: transparent; color: var(--oscuro);
}
[data-tema="web3d"] .menu-marca { margin: 72px auto 0; width: 200px; }
[data-tema="web3d"] .menu-nombre {
  margin: 72px 0 0;
  text-align: center;
  font: 600 26px/32px var(--pila); letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--velo);
}
[data-tema="web3d"] .menu-marca + .menu-nombre { display: none; }
[data-tema="web3d"] .menu-direccion { margin: 8px 0 0; text-align: center; color: var(--tinta-suave); }
[data-tema="web3d"] .menu-items { margin-top: 32px; }
[data-tema="web3d"] .menu-item {
  height: 41px; padding: 0;
  gap: 24px;
  border-bottom: 1px solid var(--linea);
  font: 500 16px/24px var(--pila); color: var(--oscuro);
}
[data-tema="web3d"] .menu-item:hover { background: transparent; color: var(--primario); }
[data-tema="web3d"] .menu-item.activo { background: none; color: var(--primario); border-bottom-color: var(--primario); }
[data-tema="web3d"] .menu-item.activo::before { display: none; }
[data-tema="web3d"] .menu-vias .via-redonda { background: var(--tenue); color: var(--oscuro); }

@media (max-width: 520px) {
  [data-tema="web3d"] .menu { left: 0; right: 0; width: auto; top: 0; height: 100%; }
}

[data-tema="web3d"] .menu-velo { background: rgb(0 0 0 / 0.24); }
[data-tema="web3d"] .menu {
  top: 8px; left: 8px; height: calc(100% - 16px);
  width: 360px;
  padding: 0 16px 16px;
  border-radius: 28px;
  background: var(--lienzo);
  box-shadow: var(--filo), var(--sombra-hoja);
  animation: entra-menu var(--t) var(--resorte) backwards;
}
@keyframes entra-menu { from { transform: translateX(-24px); opacity: 0; } }
[data-tema="web3d"] .menu-cerrar {
  top: 16px; right: 16px; width: 30px; height: 30px;
  border-radius: 15px;
  background: var(--relleno); color: var(--etiqueta-2);
}
[data-tema="web3d"] .menu-cerrar::before { inset: 7px; width: auto; height: auto; }
[data-tema="web3d"] .menu-nombre { margin: 64px 8px 0; text-align: left; font: 700 34px/41px var(--pila); letter-spacing: 0.01em; text-transform: none; color: var(--etiqueta); }
[data-tema="web3d"] .menu-direccion { margin: 4px 8px 0; text-align: left; font: 400 15px/20px var(--pila); color: var(--etiqueta-2); }
[data-tema="web3d"] .menu-items { margin-top: 24px; }
[data-tema="web3d"] .menu-item {
  height: 52px; padding: 0 8px; gap: 16px;
  border-radius: 12px;
  border-bottom: 0;
  font: 400 17px/22px var(--pila); color: var(--etiqueta);
  transition: background-color var(--t) var(--resorte);
}
[data-tema="web3d"] .menu-item:hover { background: var(--relleno); color: var(--etiqueta); }
[data-tema="web3d"] .menu-item.activo { background: var(--relleno); color: var(--etiqueta); font-weight: 600; border-bottom: 0; }
[data-tema="web3d"] .menu-item .icono,
[data-tema="web3d"] .menu-item svg { color: var(--etiqueta-2); }
[data-tema="web3d"] .menu-vias .via-redonda { background: var(--relleno); color: var(--etiqueta); }

@media (max-width: 520px) {
  [data-tema="web3d"] .menu { top: 0; left: 0; right: 0; width: auto; height: 100%; border-radius: 0; }
}

/* ── #14 · El menú con el logotipo en lugar del nombre ──────────────────────────────────────── */
[data-tema="web3d"] .menu-marca { display: block; width: 200px; height: auto; max-height: none; margin: 64px 8px 0; object-fit: contain; object-position: left; }
[data-tema="web3d"] .menu-marca + .menu-nombre { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); margin: 0; }
[data-tema="web3d"] .menu-marca ~ .menu-direccion { margin-top: 12px; }

[data-tema="web3d"] .menu-discretos button.menu-idioma, [data-tema="web3d"] .menu-discretos button.menu-legal { min-height: 44px; min-width: 44px; justify-content: center; }

/* La entrada del buscador en el cajón del menú: con forma de campo, arriba de las secciones. */
.menu-buscar {
  display: flex; align-items: center; gap: 12px;
  width: 100%; min-height: 44px; margin-top: 20px; padding: 0 14px;
  border-radius: 12px;
  background: var(--relleno, rgb(120 120 128 / 0.14)); color: var(--etiqueta-2, var(--tinta-suave));
  font: 400 17px/22px var(--pila); text-align: left;
}
.menu-buscar .glifo.lupa {
  flex: 0 0 18px; height: 18px; background: currentColor;
  -webkit-mask: var(--i-lupa) center / contain no-repeat; mask: var(--i-lupa) center / contain no-repeat;
}
.menu-buscar .texto { flex: 1; }
.menu-buscar .atajo {
  padding: 1px 7px; border-radius: 6px;
  border: 1px solid var(--separador, rgb(0 0 0 / 0.12));
  font: 500 12px/18px var(--pila);
}

@media (pointer: coarse) {
  .menu-buscar .atajo { display: none; }
}

/* El interruptor de idioma, al pie del cajón del menú. */
.menu-idioma { display: flex; align-items: center; gap: 6px; margin: 12px 16px 0; flex-wrap: wrap; }
.menu-idioma .etiqueta { font: 400 12px/16px var(--pila); color: var(--tinta-suave); margin-right: auto; }
.menu-idioma .idioma {
  min-height: 44px; min-width: 44px; padding: 0 14px; border: 0; border-radius: 22px; cursor: pointer;
  background: var(--relleno, rgb(0 0 0 / 0.06)); color: var(--tinta); font: 500 14px/20px var(--pila);
}
.menu-idioma .idioma.activo { background: var(--primario); color: var(--sobre-primario); cursor: default; }
.menu-idioma .idioma:focus-visible { outline: 2px solid var(--primario); outline-offset: 2px; }

/* ── El menú: marca clara en oscuro, un solo botón al pie, idioma y Legal en chico ── */
@media (prefers-color-scheme: dark) {
  [data-tema="web3d"] .menu-marca { filter: brightness(0) invert(1); }
}

[data-tema="web3d"] .menu-separador { height: 0.5px; margin: 8px 12px; background: var(--separador); }
[data-tema="web3d"] .menu-pie { margin-top: auto; padding: 16px 4px 0; display: flex; flex-direction: column; gap: 12px; }
[data-tema="web3d"] .menu-principal {
  display: flex; align-items: center; justify-content: center; gap: 8px; height: 50px; border-radius: 14px;
  background: var(--primario); color: var(--sobre-primario, #fff); text-decoration: none; font: 600 17px/22px var(--pila);
}
[data-tema="web3d"] .menu-principal .icono { width: 20px; height: 20px; }
[data-tema="web3d"] .menu-principal .detalle { display: none; }
[data-tema="web3d"] .menu-discretos { display: flex; justify-content: space-between; align-items: center; padding: 0 4px; }
[data-tema="web3d"] .menu-discretos button {
  display: inline-flex; align-items: center; gap: 6px; min-height: 32px; padding: 0 4px; margin: 0;
  background: none; border: 0; width: auto; flex-direction: row;
  font: 400 13px/1 var(--pila); color: var(--etiqueta-2); cursor: pointer;
}
[data-tema="web3d"] .menu-discretos button:hover { color: var(--etiqueta); }
[data-tema="web3d"] .menu-discretos .glifo .icono { width: 15px; height: 15px; }
[data-tema="web3d"] .menu-aviso, [data-tema="web3d"] .menu-vias { display: none; }

/* La hoja de Legal. */
.hoja-legal { position: fixed; inset: 0; z-index: 200; display: grid; place-items: center; padding: 16px; background: rgb(0 0 0 / 0.32); }
.hoja-legal-caja {
  position: relative; width: min(520px, 100%); max-height: 80vh; overflow-y: auto; padding: 24px 24px 28px; border-radius: 24px;
  background: var(--material-grueso, #fff); color: var(--etiqueta, #1d1d1f);
  -webkit-backdrop-filter: var(--desenfoque, none); backdrop-filter: var(--desenfoque, none);
  box-shadow: var(--sombra-hoja, 0 24px 64px rgb(0 0 0 / 0.2)); animation: hoja-sube 0.35s cubic-bezier(0.32, 0.72, 0, 1);
}
.hoja-legal-titulo { margin: 0 0 12px; font: 700 22px/28px var(--pila, system-ui); }
.hoja-legal-texto { margin: 0; font: 400 15px/22px var(--pila, system-ui); color: var(--etiqueta-2, #555); }
.hoja-legal-cerrar {
  position: absolute; top: 16px; right: 16px; width: 30px; height: 30px; border-radius: 15px; border: 0; padding: 0; cursor: pointer;
  background: var(--relleno, #eee);
}
.hoja-legal-cerrar::before { content: "✕"; font: 600 13px/30px var(--pila, system-ui); color: var(--etiqueta-2, #555); }

@media (max-width: 520px) {
  .hoja-legal { place-items: end stretch; padding: 8px; }
}
/* 🧱 La galeria del menu (`pantallas/galeria.ts`): la lamina a pantalla completa con su rotulo, flechas y contador. */

/* ══ LA GALERIA · Spec/06 §3 y Spec/07 §3 ════════════════════════════════════════════════════
 * Cuelga del MISMO escenario que el masterplan, asi que aqui solo vive lo que flota encima.
 * El rotulo es el unico rectangulo de esquinas vivas del recorrido, y es de ellos: radio 0.
 */
.pantalla-seccion { position: fixed; inset: 0; }
.rotulo-lamina {
  position: fixed;
  top: calc(var(--borde-arriba) + 128px);
  left: var(--borde);
  height: 24px;
  padding: 2px 8px;
  background: rgb(0 0 0 / 0.4);
  color: #fff;
  font: 500 14px/20px var(--pila);
  box-shadow: var(--sombra-chip);
}

.pantalla-seccion > .contador {
  position: fixed;
  left: 50%;
  bottom: var(--borde-abajo);
  transform: translateX(-50%);
  padding: 4px 12px;
  border-radius: 9999px;
  background: rgb(0 0 0 / 0.5);
  color: #fff;
  font: 600 12px/16px var(--pila);
}

/* ── Las secciones: rótulo de lámina como el de lugar ──────────────────────────────────────── */
[data-tema="web3d"] .rotulo-lamina {
  top: calc(var(--borde-arriba) + 60px);
  height: auto; padding: 3px 18px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--oscuro) 78%, transparent);
  font: 500 12px/16px var(--pila);
  box-shadow: none;
}

[data-tema="web3d"] .rotulo-lamina {
  padding: 8px 16px; border-radius: 18px;
  background: var(--material);
  -webkit-backdrop-filter: var(--desenfoque);
  backdrop-filter: var(--desenfoque);
  color: var(--etiqueta);
  font: 600 15px/20px var(--pila);
  box-shadow: var(--filo), var(--sombra-flota);
}
/* 🧱 La caja comun de las pantallas que no montan escenario (`pantallas.ts` `documento`): columna y titulo. */

/* ══ EL DOCUMENTO · la caja comun de lo que no monta escenario ════════════════════════════════
 * Avances de Obra y Unidades son PAGINAS con desplazamiento, no escenarios: columna centrada de
 * 1280 con 80 px de aire a los lados (Spec/05 §2), y 358 con 16 px en telefono.
 */
.documento {
  position: fixed;
  inset: 0;
  overflow-y: auto;
  background: var(--lienzo, #fff);
  color: var(--tinta);
  -webkit-overflow-scrolling: touch;
}
.documento .hoja { max-width: 1280px; margin: 0 auto; padding: 96px 0 64px; }
.titulo-pantalla { margin: 0 0 24px; font: 600 44px/46.2px var(--pila); color: var(--tinta); }

@media (max-width: 520px) {
  /*
   * LA PAGINA: de 3 columnas a 1, que es lo unico que cambia y es lo que mide su ficha —«nada
   * del contenido: la reticula pasa de 3 columnas a 1 y sigue entera»—. El titulo baja de 44 a
   * 30, igual que en la referencia, y la hoja se pega a 16 px de los bordes.
   */
  .documento .hoja { padding: 72px 16px 48px; }
  .titulo-pantalla { font: 600 30px/36px var(--pila); }
}

/* Las pantallas de documento (disponibilidad, etc.) entre 521 y 1328 px de ancho —teléfono en
   horizontal, iPad— iban pegadas al borde: la hoja mide 1280 sin relleno. Aire de 24 px, o la zona
   segura si es mayor (en horizontal el notch queda a un lado). */
@media (min-width: 521px) and (max-width: 1328px) {
  .documento .hoja {
    padding-left: max(24px, env(safe-area-inset-left, 0px));
    padding-right: max(24px, env(safe-area-inset-right, 0px));
  }
}
/* 🧱 El avance de obra que trae el manifiesto (`pantallas/linea-de-tiempo.ts`): etapas, fotos y visor. El que publica el desarrollador vive en `obra.css`. */

/* ══ AVANCES DE OBRA · Spec/08 ════════════════════════════════════════════════════════════════ */
.linea-tiempo {
  display: grid;
  grid-template-columns: minmax(200px, 240px) minmax(0, 1fr);
  gap: 20px 32px;
  align-items: start;
  padding: 20px 32px;
  border: 1px solid var(--separador, rgb(229 229 229 / 0.6));
  border-radius: 16px;
  background: var(--material-grueso, rgb(255 255 255 / 0.85));
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.05);
}
.etapas { display: flex; flex-direction: column; gap: 8px; }
.etapa {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-height: 56px;
  padding: 10px 16px;
  border: 0;
  border-radius: 16px;
  background: var(--relleno, rgb(245 245 245 / 0.8));
  text-align: left;
  cursor: pointer;
}
.etapa.activa { background: color-mix(in srgb, var(--primario) 14%, var(--lienzo-elevado, #fff)); }
.etapa .nombre { font: 700 15.2px/21.7px var(--pila); color: var(--tinta); }
.etapa .meta { display: flex; gap: 8px; flex-wrap: wrap; align-items: baseline; }
.etapa .avance { font: 600 12px/16px var(--pila); color: var(--primario-texto, var(--primario)); }
.etapa .fecha { font: 400 12px/16px var(--pila); color: var(--tinta-suave); }
.fotos { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.fotos .foto {
  position: relative;
  aspect-ratio: 4 / 3;
  padding: 0;
  border: 0;
  border-radius: 16px;
  overflow: hidden;
  background: var(--superficie);
  cursor: pointer;
}
.fotos .foto img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.5s ease-out;
}
.fotos .foto:hover img { transform: scale(1.05); }

/* El visor. `contain` y no `fill`: la referencia usa `fill` y deformara la primera foto que no
   sea 4:3. Ver `pantallas/linea-de-tiempo.ts`. */
.visor {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: grid;
  place-items: center;
  background: rgb(0 0 0 / 0.4);
  backdrop-filter: blur(4px);
}
.visor .grande { max-width: 90vw; max-height: 90vh; object-fit: contain; }
.visor .cerrar {
  position: fixed;
  top: var(--borde-arriba);
  right: var(--borde);
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 9999px;
  background: var(--superficie);
  cursor: pointer;
}
.visor .cerrar::before { content: "✕"; display: block; font: 600 16px/1 ui-sans-serif, system-ui, sans-serif; }
.visor .contador {
  position: fixed;
  left: 50%;
  bottom: var(--borde-abajo);
  transform: translateX(-50%);
  padding: 4px 12px;
  border-radius: 9999px;
  background: rgb(0 0 0 / 0.5);
  color: #fff;
  font: 600 12px/16px var(--pila);
}

@media (max-width: 520px) {
  /* La columna de etapas deja de ser columna y se apila encima de la galeria; las fotos, a 2. */
  .linea-tiempo { grid-template-columns: minmax(0, 1fr); padding: 16px; }
  .fotos { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* El estado de una etapa del avance de obra («Complete», «In Progress»): heredaba la tinta blanca
   de otra `.clave` y no se leía. */
.etapa .clave { font: 500 12px/16px var(--pila); color: var(--tinta-suave); }
.etapa .avance + .clave::before, .etapa .clave + .fecha::before { content: none; }
/* 🧱 Unidades con VARIAS torres (`pantallas/unidades.ts`): areas, grupos y la lista con buscador, orden y filtro. */

/* ══ UNIDADES · Spec/05 ═══════════════════════════════════════════════════════════════════════
 * Retícula de 3 columnas con `gap-x 24` y `gap-y 40` a 1440 y 1 columna a 390 (Spec/05 §2).
 */
.inventario { display: flex; flex-direction: column; gap: 24px; }
.miga { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.miga-paso, .miga-fin {
  height: 32px;
  padding: 6px 14px;
  border: 0;
  border-radius: 9999px;
  background: var(--superficie);
  color: var(--tinta);
  font: 600 14px/20px var(--pila);
}
.miga-paso { cursor: pointer; }
.miga-fin { background: color-mix(in srgb, var(--primario) 14%, #fff); color: var(--primario); }
.tarjetas { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 40px 24px; }
.lista-unidades .tarjetas { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; }
.tarjeta-area, .tarjeta-grupo, .tarjeta-unidad {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: 16px;
  background: var(--lienzo-elevado, #fff);
  box-shadow: 0 1px 3px rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
}
.tarjeta-area > img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; display: block; }
/* Un area sin nada dentro se lista, se mira y no se entra. Es la unica senal que da la
   referencia —`opacity: 0.7`— y aqui ademas no trae boton. */
.tarjeta-area.muda { opacity: 0.7; }
.tarjeta-area .cuerpo, .tarjeta-grupo, .tarjeta-unidad { padding: 16px 24px 24px; gap: 8px; display: flex; flex-direction: column; }
.tarjeta-area .cuerpo { padding: 16px 24px 24px; }
.tarjeta-area .nombre, .tarjeta-grupo .nombre { margin: 0; font: 700 24px/30px var(--pila); color: var(--primario); }
.insignia, .cuenta {
  align-self: flex-start;
  height: 24px;
  padding: 4px 12px;
  border-radius: 9999px;
  background: var(--color-estado, var(--primario));
  color: #fff;
  font: 600 12px/16px var(--pila);
  box-shadow: var(--sombra-chip);
}
.cuentas { display: flex; gap: 6px; flex-wrap: wrap; }
.explorar, .ver-ficha, .salto {
  height: 44px;
  padding: 0 20px;
  border: 0;
  border-radius: 9999px;
  background: var(--primario);
  color: var(--sobre-primario);
  font: 600 14px/20px var(--pila);
  cursor: pointer;
}
.salto { background: var(--superficie); color: var(--tinta); }
.tarjeta-unidad .mandos, .comparador .mandos { display: flex; gap: 8px; flex-wrap: wrap; margin-top: auto; }
.tarjeta-unidad .mandos .ver-ficha, .tarjeta-unidad .mandos .salto { height: 40px; }
.tarjeta-unidad .cabeza { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.tarjeta-unidad .nombre { font: 700 24px/32px var(--pila); color: var(--tinta); }
.tarjeta-unidad .tipologia, .tarjeta-grupo .tipologia { margin: 0; font: 400 12px/16px var(--pila); color: var(--tinta-suave); }
.tarjeta-unidad .precio { margin: 0; font: 600 18px/24px var(--pila); }
.tarjeta-grupo .resumen, .tarjeta-unidad .resumen, .totales {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 12px;
  margin: 0;
}
.tarjeta-grupo .clave, .tarjeta-unidad .clave, .totales .clave, .arbol .clave, .lugar .clave, .contacto .clave {
  font: 400 12px/22px var(--pila);
  color: var(--tinta-suave);
}
.tarjeta-grupo .valor, .tarjeta-unidad .valor, .totales .valor { margin: 0; font: 500 13px/22px var(--pila); text-align: right; }
.barra { display: flex; gap: 12px; flex-wrap: wrap; }
.control {
  height: 40px;
  padding: 4px 16px;
  border: 1px solid var(--separador, #e5e5e5);
  border-radius: 9999px;
  background: var(--lienzo-elevado, #fff);
  color: var(--tinta);
  font: 400 14px/20px var(--pila);
}
.buscador { min-width: 222px; }
.filtros { display: flex; gap: 8px; flex-wrap: wrap; }
.filtro {
  height: 32px;
  padding: 6px 14px;
  border: 0;
  border-radius: 9999px;
  background: var(--lienzo-elevado, #fff);
  box-shadow: inset 0 0 0 1px var(--separador, rgb(0 0 0 / 0.15));
  color: var(--tinta);
  font: 600 14px/20px var(--pila);
  cursor: pointer;
}
.filtro::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 8px;
  border-radius: 9999px;
  background: var(--color-estado, var(--primario));
}
.filtro.activo { background: var(--color-estado, var(--primario)); color: #fff; }
.filtro.activo::before { background: #fff; }
.cuantas { margin: 0; font: 400 12px/16px var(--pila); color: var(--tinta-suave); }
.arbol { padding-top: 12px; border-top: 1px solid #e5e5e5; }
.arbol .carpetas { margin: 8px 0 0; padding: 0; list-style: none; opacity: 0.55; }
.arbol .carpetas .raiz { font: 600 13px/22px var(--pila); }
.arbol .carpetas .hija { padding-left: 16px; font: 400 13px/22px var(--pila); }

@media (max-width: 520px) {
  .tarjetas, .lista-unidades .tarjetas { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .barra { flex-direction: column; }
  .buscador { min-width: 0; width: 100%; }
}
/* 🧱 Location clasica (`mapa.ts`, el plano propio). La viva (MapLibre) vive en `ubicacion.css`, que se pide al abrirla. */

/* ══ UBICACION · Spec/09 ══════════════════════════════════════════════════════════════════════ */
.mapa { position: fixed; inset: 0; background: #eef1f3; }
.mapa-incrustado, .plano-mapa { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.plano-mapa { background: repeating-linear-gradient(0deg, #e7ecef 0 1px, #f3f6f8 1px 48px), repeating-linear-gradient(90deg, #e7ecef 0 1px, #f3f6f8 1px 48px); }
.plano-mapa.midiendo { cursor: crosshair; }
.lienzo-mapa { position: absolute; inset: 0; width: 100%; height: 100%; }
.lienzo-mapa .solar { fill: var(--color-solar, var(--primario)); fill-opacity: 0.35; stroke: var(--color-solar, var(--primario)); stroke-width: 2; }
.lienzo-mapa .poi { fill: var(--color-poi, var(--primario)); stroke: #fff; stroke-width: 2; }
.lienzo-mapa .anclaje { fill: var(--primario); stroke: #fff; stroke-width: 3; }
.lienzo-mapa .regla { stroke: var(--primario); stroke-width: 2; stroke-dasharray: 6 4; }
.rotulos-mapa { position: absolute; inset: 0; pointer-events: none; }
.rotulo-poi {
  position: absolute;
  transform: translate(-50%, -160%);
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 2px 8px;
  border: 0;
  border-radius: 8px;
  background: rgb(255 255 255 / 0.92);
  box-shadow: var(--sombra-chip);
  white-space: nowrap;
  pointer-events: auto;
  cursor: pointer;
}
.rotulo-poi .texto { font: 600 12px/14.4px var(--pila); color: #374151; }
.rotulo-poi .lejos { font: 400 11px/14.4px var(--pila); color: var(--tinta-suave); }
.rotulo-poi.aqui { background: var(--primario); cursor: default; }
.rotulo-poi.aqui .texto { color: var(--sobre-primario); }
.medida {
  position: absolute;
  left: 50%;
  top: var(--borde-arriba);
  transform: translateX(-50%);
  padding: 4px 12px;
  border-radius: 9999px;
  background: var(--primario);
  color: var(--sobre-primario);
  font: 600 14px/20px var(--pila);
}
.vistas-mapa {
  position: absolute;
  top: calc(var(--borde-arriba) + 48px);
  right: var(--borde);
  z-index: 2;
  display: flex;
  gap: 4px;
  padding: 4px;
  border-radius: 9999px;
  background: rgb(0 0 0 / 0.3);
  backdrop-filter: blur(12px);
}
.vistas-mapa .vista {
  height: 32px;
  padding: 0 14px;
  border: 0;
  border-radius: 9999px;
  background: transparent;
  color: rgb(255 255 255 / 0.7);
  font: 600 12px/16px var(--pila);
  cursor: pointer;
}
.vistas-mapa .vista.activa { background: #fff; color: #000; }
.mandos-mapa {
  position: absolute;
  left: var(--borde);
  bottom: var(--borde-abajo);
  z-index: 2;
  display: flex;
  gap: 8px;
}
.mandos-mapa button {
  height: 40px;
  min-width: 40px;
  padding: 0 12px;
  border: 0;
  border-radius: 9999px;
  background: #fff;
  color: var(--tinta);
  font: 600 14px/20px var(--pila);
  box-shadow: var(--sombra-boton);
  cursor: pointer;
}
.mandos-mapa .medir.activo { background: var(--primario); color: var(--sobre-primario); }
.lugar {
  position: absolute;
  top: calc(var(--borde-arriba) + 96px);
  right: var(--borde);
  z-index: 2;
  width: 320px;
  max-height: 60%;
  overflow-y: auto;
  padding: 16px;
  border-radius: 16px;
  background: rgb(255 255 255 / 0.92);
  backdrop-filter: blur(8px);
  box-shadow: var(--sombra-chip);
}
.lugar > .direccion { margin: 0 0 12px; font: 600 14px/20px var(--pila); color: var(--primario); }
.lugar .pois { display: flex; flex-direction: column; gap: 10px; }
.poi-fila { display: grid; grid-template-columns: 10px 1fr auto; gap: 4px 8px; align-items: baseline; }
.poi-fila .punto { width: 8px; height: 8px; border-radius: 9999px; background: var(--color-poi, var(--primario)); }
.poi-fila .nombre { font: 600 13px/18px var(--pila); }
.poi-fila .lejos { font: 400 12px/18px var(--pila); color: var(--tinta-suave); }
.poi-fila .direccion { grid-column: 2 / 4; font: 400 12px/16px var(--pila); color: var(--tinta-suave); }

@media (max-width: 520px) {
  /* El mapa: la ficha del lugar deja de flotar a la derecha y pasa a ser un cajon de abajo, que
     es lo unico que queda legible cuando el plano no cabe. */
  .lugar { top: auto; left: 12px; right: 12px; bottom: calc(var(--borde-abajo) + 56px); width: auto; max-height: 40%; }
  .vistas-mapa { top: calc(var(--borde-arriba) + 48px); }
}
/* 🧱 Contacto (`pantallas/contacto.ts`, `contacto.ts`): el formulario, el contacto de un toque, el lead y la tarjeta del numero. */

/* ══ CONTACTO · Spec/10 ═══════════════════════════════════════════════════════════════════════
 * Dos capas y nada mas: una fotografia a sangre y un panel blanco pegado a la derecha, `890, 0 ·
 * 550 × 900`. A 390 px la fotografia NO se pide y el panel se lleva el viewport entero.
 */
.contacto { position: fixed; inset: 0; background: #fff; }
.contacto .foto-fondo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.panel-contacto {
  position: absolute;
  top: 0;
  right: 0;
  width: 550px;
  height: 100%;
  overflow-y: auto;
  padding: 48px 56px 32px;
  background: var(--lienzo, #fff);
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.panel-contacto .titulo-pantalla { font: 700 20px/28px var(--pila); color: var(--primario); margin: 0; }
.campos-form { display: flex; flex-direction: column; gap: 16px; }
.campo { display: flex; flex-direction: column; gap: 4px; }
.campo .etiqueta { font: 500 12px/16px var(--pila); color: var(--tinta-suave); }
.campo .control { width: 100%; }
/* El unico control con radio 16, igual que en la referencia: un area de texto redonda no cabe. */
.campo .area { height: auto; min-height: 64px; border-radius: 16px; padding: 12px 16px; resize: vertical; font: var(--pila); }
.enviar {
  height: 40px;
  border: 0;
  border-radius: 9999px;
  background: var(--primario);
  color: var(--sobre-primario);
  font: 600 14px/20px var(--pila);
  cursor: pointer;
}
.sin-destino { display: none; margin: 0; font: 400 13px/18px var(--pila); color: #b45309; }
.sin-destino.visible { display: block; }

@media (max-width: 520px) {
  /* El panel de contacto se lleva el viewport entero y la fotografia NO se pide. El texto de los
     campos SUBE de 14 a 16 px: es el truco estandar para que iOS no acerque al enfocar, y la
     unica pantalla del recorrido que mejora al achicarse. */
  .contacto .foto-fondo { display: none; }
  .panel-contacto { width: 100%; padding: 72px 32px 32px; }
  .panel-contacto .control { font: 400 16px/24px var(--pila); }
  .panel-contacto .enviar { height: 48px; }
}

/* ── Contacto de un toque ── */
.contacto.directo .panel-contacto { justify-content: center; gap: 20px; padding: 48px 56px; }
.contacto.directo .titulo-pantalla { font: 500 28px/34px var(--pila); color: var(--tinta); }
.contacto.directo .asunto { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 12px 16px; border-radius: 12px; background: color-mix(in srgb, var(--primario) 10%, #fff); }
.contacto.directo .asunto .etiqueta { font: 500 12px/16px var(--pila); color: var(--tinta-suave); }
.contacto.directo .asunto .valor { font: 600 16px/22px var(--pila); color: var(--primario); }
.contacto.directo .pista { margin: 0; font: 400 14px/20px var(--pila); color: var(--tinta-suave); }
.vias { display: flex; flex-direction: column; gap: 10px; }
.via {
  display: flex; align-items: center; gap: 14px;
  min-height: 56px; padding: 8px 20px; border-radius: 9999px;
  border: 1px solid #e5e5e5; background: #fff; color: var(--tinta); text-decoration: none;
  transition: border-color 0.2s var(--curva), background 0.2s var(--curva);
}
.via:hover, .via:focus-visible { border-color: var(--primario); }
.via .icono { width: 22px; height: 22px; color: var(--primario); }
.via .texto { display: flex; flex-direction: column; }
.via .titulo { font: 600 15px/20px var(--pila); }
.via .detalle { font: 400 13px/18px var(--pila); color: var(--tinta-suave); }
.via.principal { background: var(--primario); border-color: var(--primario); color: var(--sobre-primario); min-height: 64px; }
.via.principal .icono, .via.principal .detalle { color: color-mix(in srgb, var(--sobre-primario) 85%, transparent); }
.via.via-email { min-height: 44px; border-color: transparent; padding-left: 20px; }
.via.via-email .titulo { font-weight: 500; }
.contacto.directo .aviso { margin: 8px 0 0; font: 400 11px/16px var(--pila); color: var(--tinta-suave); }

@media (max-width: 720px) {
  .contacto.directo .panel-contacto { padding: 72px 20px 24px; justify-content: flex-start; }
}

/* ══ EL FORMULARIO DEL LEAD · `vista/contacto.ts`, `formularioDeLead` ══════════════════════════
 * Debajo de los toques en la pantalla de contacto; solo existe con backend. `data-estado`:
 * listo · enviando · enviado · error. Lo escrito nunca se borra. */
.form-lead { display: flex; flex-direction: column; gap: 16px; margin-top: 8px; padding-top: 20px; border-top: 1px solid color-mix(in srgb, var(--tinta) 12%, transparent); }
.form-lead .campo .etiqueta { color: var(--tinta-suave); }
/* El campo es blanco (`.control`) en cualquier piel: la tinta del panel oscuro lo dejaba ilegible. */
.form-lead .control { color: #171717; caret-color: #171717; }
.form-lead .control[aria-invalid='true'] { border-color: #b42318; box-shadow: 0 0 0 3px color-mix(in srgb, #b42318 18%, transparent); }
.form-lead .enviar { width: 100%; height: 48px; }
/* Turnstile (`guardiaTurnstile`): invisible salvo que Cloudflare pida interaccion; entonces, centrado. */
.form-lead .turnstile { display: flex; justify-content: center; }
.form-lead .turnstile:empty { display: none; }
.form-lead .enviar[disabled] { opacity: 0.6; cursor: default; }
.form-lead .estado-envio { margin: 0; min-height: 20px; font: 500 14px/20px var(--pila); color: var(--tinta-suave); }
.form-lead[data-estado='enviado'] .estado-envio { color: #067647; }
.form-lead[data-estado='error'] .estado-envio { color: #b42318; }

/* La hoja de Contact en oscuro: las vías eran tarjetas blancas fijas con tinta clara encima. */
[data-tema="web3d"] .via:not(.principal) { background: var(--relleno); color: var(--etiqueta); border-color: transparent; }
[data-tema="web3d"] .via .detalle { color: var(--etiqueta-2); }

/* ── 🧷 Contacto legible en claro y oscuro (Apple) ─────────────────────────────────────────────
   «Asking About · Level 8» era `color-mix(primario 10%, #fff)`: caja blanca fija con rótulo
   `--tinta-suave` (claro en oscuro, invisible) y valor en acento que parecía texto seleccionado.
   Ahora es un relleno del sistema: rótulo secundario, valor en etiqueta primaria. Los campos del
   lead dejan el `#fff` fijo y siguen al tema igual. */
[data-tema="web3d"] .contacto.directo .asunto { background: var(--relleno); user-select: text; }
[data-tema="web3d"] .contacto.directo .asunto .etiqueta { color: var(--etiqueta-2); }
[data-tema="web3d"] .contacto.directo .asunto .valor { color: var(--etiqueta); }
[data-tema="web3d"] .form-lead .control {
  background: var(--relleno); border-color: transparent;
  color: var(--etiqueta); caret-color: var(--primario);
}
[data-tema="web3d"] .form-lead .control::placeholder { color: var(--etiqueta-2); }
[data-tema="web3d"] .form-lead .control:focus-visible { outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--primario) 35%, transparent); }
[data-tema="web3d"] .form-lead .campo .etiqueta { color: var(--etiqueta-2); }
[data-tema="web3d"] .form-lead { border-top-color: var(--separador); }
[data-tema="web3d"] .form-lead .control[aria-invalid='true'] { border-color: #ff453a; }
/* El número de WhatsApp sobre el acento: la regla web3d de `.via .detalle` lo volvía gris oscuro. */
[data-tema="web3d"] .via.principal .detalle { color: color-mix(in srgb, var(--sobre-primario) 85%, transparent); }

/* ── 🧷 La hoja de Contact, premium (Victor 26-sep) ──────────────────────────────────────────
   Contexto en chip · un renglón con el número y sus dos acciones (tarjeta de contacto de iOS,
   `tarjetaDeNumero`) · entrada con resorte y salida con fantasma (`despedida` en `pantallas/contacto.ts`). */
[data-tema="web3d"] .contacto.directo .panel-contacto { gap: 24px; }
[data-tema="web3d"] .contacto.directo .titulo-pantalla { font: 700 34px/41px var(--pila); letter-spacing: -0.02em; margin: 0; }
[data-tema="web3d"] .contacto.directo .asunto {
  flex-direction: row; align-items: center; align-self: flex-start; gap: 8px;
  height: 36px; padding: 0 16px; border-radius: 18px; margin: -8px 0 0;
}
[data-tema="web3d"] .contacto.directo .asunto .etiqueta { font: 400 13px/1 var(--pila); }
[data-tema="web3d"] .contacto.directo .asunto .etiqueta::after { content: ""; display: inline-block; width: 3px; height: 3px; margin: 0 0 2px 8px; border-radius: 50%; background: currentColor; vertical-align: middle; }
[data-tema="web3d"] .contacto.directo .asunto .valor { font: 600 15px/1 var(--pila); }
[data-tema="web3d"] .contacto.directo .pista { font: 400 15px/21px var(--pila); color: var(--etiqueta-2); }
[data-tema="web3d"] .vias { gap: 10px; }

.tarjeta-numero {
  display: flex; align-items: center; gap: 12px; padding: 14px 14px 14px 20px;
  border-radius: 22px; background: var(--relleno, #f2f2f7);
}
.tarjeta-numero .numero { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.tarjeta-numero .numero .etiqueta { font: 400 13px/16px var(--pila); color: var(--etiqueta-2, #6e6e73); }
.tarjeta-numero .numero .valor { font: 600 19px/24px var(--pila); color: var(--etiqueta, #1d1d1f); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; white-space: nowrap; }
.tarjeta-numero .acciones-numero { display: flex; gap: 8px; }
.tarjeta-numero .accion {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  width: 76px; height: 60px; border-radius: 14px; text-decoration: none;
  background: var(--lienzo, #fff); color: var(--primario);
  transition: transform 0.2s var(--resorte, ease), background 0.2s;
}
.tarjeta-numero .accion .icono { width: 22px; height: 22px; }
.tarjeta-numero .accion .texto { display: flex; }
.tarjeta-numero .accion .titulo { font: 600 12px/14px var(--pila); }
.tarjeta-numero .accion.via-whatsapp { background: var(--primario); color: var(--sobre-primario, #fff); }
.tarjeta-numero .accion:active { transform: scale(0.96); }
.tarjeta-numero .accion:focus-visible { outline: 2px solid var(--primario); outline-offset: 2px; }

@media (hover: hover) {
  .tarjeta-numero .accion:hover { filter: brightness(1.06); }
}

@media (prefers-color-scheme: dark) {
  [data-tema="web3d"] .tarjeta-numero .accion:not(.via-whatsapp) { background: rgb(255 255 255 / 0.1); color: var(--etiqueta); }
}

@media (max-width: 520px) {
  .tarjeta-numero { padding: 12px 12px 12px 16px; }
  .tarjeta-numero .numero .valor { font-size: 17px; }
  .tarjeta-numero .accion { width: 64px; height: 56px; }
}

/* Entrada: el arte funde, el panel sube con resorte y sus piezas llegan escalonadas. */
@keyframes contacto-sube { from { opacity: 0; transform: translateY(18px); } }
@keyframes contacto-funde { from { opacity: 0; } }
@keyframes contacto-sale { to { opacity: 0; transform: translateY(12px); } }

@media (prefers-reduced-motion: no-preference) {
  .contacto.directo:not(.saliendo) .foto-fondo { animation: contacto-funde 0.5s var(--curva) both; }
  .contacto.directo:not(.saliendo) .panel-contacto > * { animation: contacto-sube 0.6s var(--resorte, cubic-bezier(0.32, 0.72, 0, 1)) both; }
  .contacto.directo:not(.saliendo) .panel-contacto > :nth-child(2) { animation-delay: 40ms; }
  .contacto.directo:not(.saliendo) .panel-contacto > :nth-child(3) { animation-delay: 80ms; }
  .contacto.directo:not(.saliendo) .panel-contacto > :nth-child(4) { animation-delay: 120ms; }
  .contacto.directo:not(.saliendo) .panel-contacto > :nth-child(n+5) { animation-delay: 160ms; }
  .contacto.directo.saliendo { pointer-events: none; z-index: 50; animation: contacto-sale 0.28s var(--curva) both; }
}

/* La columna del panel encogía la tarjeta por debajo de sus botones: nada en `.vias` se encoge. */
.vias > * { flex-shrink: 0; }
.tarjeta-numero .accion { width: auto; min-width: 76px; padding: 0 12px; }

@media (max-width: 520px) {
  .tarjeta-numero .accion { min-width: 64px; padding: 0 10px; } .tarjeta-numero .acciones-numero { gap: 6px; }
}

/* El asunto es una sola entidad («Residence PHA · Level 10»), no dos renglones independientes. */
@media (max-width: 520px) {
  [data-tema="web3d"] .contacto.directo .asunto .valor {
    white-space: nowrap; font-size: clamp(12px, 3.55vw, 16px); letter-spacing: -0.01em;
  }
}
/* 🧱 El comparador de dos mitades (`pantallas/comparador.ts`). En `web3d` lo reemplaza la coleccion (`coleccion.css`). */

/* ══ EL COMPARADOR · Spec/11 ══════════════════════════════════════════════════════════════════
 * Dos mitades, y la orientacion del corte cambia con el viewport: vertical a 1440 (720 × 900 cada
 * una) y horizontal a 390 (390 × 422). No hay separador dibujado: el corte es el borde.
 */
.comparador { position: fixed; inset: 0; display: grid; grid-template-columns: 1fr 1fr; background: var(--lienzo, #fff); }
.mitad { position: relative; overflow: hidden; background: var(--lienzo, #fff); display: flex; flex-direction: column; }
.lienzo-mitad { position: absolute; inset: 0; }
.lamina-mitad, .tour-mitad { width: 100%; height: 100%; object-fit: cover; border: 0; display: block; }
.mitad .hueco { margin: auto; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.elegir-unidad {
  width: 188.8px;
  height: 48px;
  border: 0;
  border-radius: 9999px;
  background: var(--superficie);
  color: var(--tinta);
  font: 600 14px/20px var(--pila);
  cursor: pointer;
}
.mitad .hueco .cuando { margin: 0; font: 400 14px/20px var(--pila); color: var(--tinta-suave); }
.chip-unidad {
  position: absolute;
  top: 64px;
  left: 8px;
  display: flex;
  gap: 8px;
  align-items: baseline;
  padding: 4px 12px;
  border-radius: 9999px;
  /* La referencia pinta este chip en `#2563eb`, que es el UNICO azul de un sitio que por lo demas
     es su primario. Aqui va el primario de marca: el color sale del manifiesto, no del capricho. */
  background: color-mix(in srgb, var(--primario) 90%, transparent);
  color: var(--sobre-primario);
  font: 700 12px/16px var(--pila);
}
.chip-unidad .tipologia { font: 400 11px/16px var(--pila); opacity: 0.8; }
.mitad .medios {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 4px;
  padding: 4px;
  border-radius: 9999px;
  background: rgb(255 255 255 / 0.85);
  backdrop-filter: blur(8px);
}
.mitad .medio {
  height: 28px;
  padding: 0 10px;
  border: 0;
  border-radius: 9999px;
  background: transparent;
  color: var(--tinta);
  font: 600 12px/16px var(--pila);
  cursor: pointer;
}
.mitad .medio.activo { background: var(--primario); color: var(--sobre-primario); }
.mitad .mandos { position: absolute; left: 8px; bottom: 8px; }
.mitad .cambiar {
  width: 111.2px;
  height: 36px;
  border: 0;
  border-radius: 9999px;
  background: rgb(0 0 0 / 0.5);
  color: #fff;
  font: 600 14px/20px var(--pila);
  cursor: pointer;
}
.mitad .mandos .ver-ficha, .mitad .mandos .salto { height: 36px; padding: 0 14px; }
.elector {
  position: fixed;
  top: 0;
  right: 0;
  width: min(448px, 100%);
  height: 100%;
  z-index: 96;
  overflow-y: auto;
  padding: 16px;
  background: #fff;
  box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
}
.elector .cerrar {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 9999px;
  background: var(--superficie);
  cursor: pointer;
}
.elector .cerrar::before { content: "✕"; display: block; font: 600 14px/1 ui-sans-serif, system-ui, sans-serif; }
.elector .buscador { width: calc(100% - 56px); margin-bottom: 16px; }
.elector .filas { display: flex; flex-direction: column; gap: 4px; }
.elector .grupo { margin: 12px 0 4px; font: 600 11px/16.5px var(--pila); color: var(--tinta-suave); }
.fila-unidad {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 8px;
  min-height: 72px;
  padding: 12px 16px;
  border: 0;
  border-radius: 16px;
  background: var(--superficie);
  text-align: left;
  cursor: pointer;
}
.fila-unidad .nombre { font: 600 16px/24px var(--pila); }
.fila-unidad .tipologia { grid-column: 1; font: 400 12px/16px var(--pila); color: var(--tinta-suave); }
.fila-unidad .precio { grid-row: 1; grid-column: 2; font: 400 12px/24px var(--pila); }
.fila-unidad .estado {
  grid-column: 2;
  justify-self: end;
  padding: 2px 8px;
  border-radius: 9999px;
  background: var(--color-estado, var(--primario));
  color: #fff;
  font: 600 11px/16px var(--pila);
}
.comparador .ruta-declarada { position: absolute; inset: 0; grid-column: 1 / -1; }

@media (max-width: 520px) {
  /* EL CORTE GIRA DE VERTICAL A HORIZONTAL, y es la unica pantalla del recorrido que lo hace. */
  .comparador { grid-template-columns: minmax(0, 1fr); grid-template-rows: 1fr 1fr; }
  .chip-unidad { font: 700 10px/15px var(--pila); }
  .mitad .medio { height: 26px; padding: 0 8px; }
  .elector { width: 100%; }
}

@media (prefers-color-scheme: dark) {
  [data-tema="web3d"] .comparador, [data-tema="web3d"] .mitad { background: var(--lienzo, #000); }
  [data-tema="web3d"] .elegir-unidad, [data-tema="web3d"] .comparador .cambiar { background: var(--relleno); color: var(--etiqueta); }
}

/* El comparador enseña la planta ENTERA de cada mitad: recortada, dos plantas no se comparan. */
[data-tema="web3d"] .lamina-mitad { object-fit: contain; }
/* 🧱 El buscador global (`buscador.ts`) y su entrada en el menu. */

/* ══ 🔍 EL BUSCADOR GLOBAL · `vista/buscador.ts` (`busqueda.ts` decide qué casa) ═══════════════
 * Hoja encima de todo, abierta con `/`, ⌘K o «Search» del menú. Escritorio: panel centrado de
 * 640 px a 12 vh del borde. Teléfono: pantalla entera. Filas de 60 px, cerrar de 44 px. */
.buscador-velo {
  position: fixed; inset: 0; z-index: 120;
  background: rgb(0 0 0 / 0.32);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
.buscador {
  --b-lienzo: var(--lienzo, #fff);
  --b-tinta: var(--etiqueta, var(--tinta, #171717));
  --b-suave: var(--etiqueta-2, var(--tinta-suave));
  --b-relleno: var(--relleno, rgb(120 120 128 / 0.14));
  position: fixed; z-index: 121;
  top: 12vh; left: 50%; transform: translateX(-50%);
  width: min(640px, calc(100vw - 32px)); max-height: 72vh;
  display: flex; flex-direction: column;
  border-radius: 20px;
  background: var(--b-lienzo); color: var(--b-tinta);
  box-shadow: var(--filo, none), var(--sombra-hoja, 0 24px 64px rgb(0 0 0 / 0.18));
  font-family: var(--pila);
  overflow: hidden;
  animation: entra-buscador 0.25s var(--resorte, ease-out) backwards;
}
.buscador[hidden], .buscador-velo[hidden] { display: none; }
@keyframes entra-buscador { from { opacity: 0; transform: translateX(-50%) translateY(-8px) scale(0.98); } }
.buscador-cabeza {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 10px 10px 16px;
  border-bottom: 1px solid var(--separador, rgb(0 0 0 / 0.08));
}
.buscador-cabeza::before {
  content: ""; flex: 0 0 20px; height: 20px;
  background: var(--b-suave);
  -webkit-mask: var(--i-lupa) center / contain no-repeat; mask: var(--i-lupa) center / contain no-repeat;
}

.buscador-campo {
  flex: 1; min-width: 0; height: 44px;
  border: 0; outline: 0; background: transparent;
  font: 400 19px/24px var(--pila); color: var(--b-tinta);
}
.buscador-campo::placeholder { color: var(--b-suave); }
.buscador-campo::-webkit-search-cancel-button { display: none; }
.buscador-cerrar {
  flex: 0 0 auto; min-width: 44px; height: 44px; padding: 0 14px;
  border-radius: 22px; background: var(--b-relleno); color: var(--b-tinta);
  font: 600 15px/20px var(--pila);
}
.buscador-cuenta { margin: 0; padding: 8px 20px 0; font: 600 13px/18px var(--pila); color: var(--b-suave); }
.buscador-cuenta:empty { display: none; }
.buscador-lista { overflow-y: auto; padding: 6px 8px 10px; overscroll-behavior: contain; }
.buscador-fila {
  display: flex; align-items: center; gap: 14px;
  width: 100%; min-height: 60px; padding: 8px 12px;
  border-radius: 12px; text-align: left;
  background: transparent; color: var(--b-tinta);
  font-family: var(--pila);
}
.buscador-fila[aria-selected="true"] { background: var(--b-relleno); }
.buscador-fila .cuerpo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.buscador-fila .titulo { font: 600 17px/22px var(--pila); font-variant-numeric: tabular-nums; }
.buscador-fila .detalle {
  font: 400 14px/18px var(--pila); color: var(--b-suave); font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.buscador-fila .punto { flex: 0 0 10px; height: 10px; margin: 0 5px; border-radius: 50%; background: var(--color-estado, var(--b-suave)); }
.buscador-fila .glifo {
  flex: 0 0 20px; height: 20px; background: var(--b-suave);
  -webkit-mask: var(--i-planta) center / contain no-repeat; mask: var(--i-planta) center / contain no-repeat;
}
.buscador-fila .glifo.seccion { -webkit-mask-image: var(--i-seccion); mask-image: var(--i-seccion); }
.buscador-fila .estado {
  flex: 0 0 auto; padding: 3px 10px; border-radius: 999px;
  font: 600 13px/18px var(--pila);
  color: var(--color-estado, var(--b-suave));
  background: color-mix(in srgb, var(--color-estado, #888) 14%, transparent);
}
.buscador-fila .estado.apagado { opacity: 0.8; }
.buscador-fila .estado.neutro { color: var(--b-suave); background: var(--b-relleno); }
.buscador-fila.unidad:has(.estado.apagado) .titulo { color: var(--b-suave); }
/* 📍 Lugares cercanos («Things To Do»): el círculo de su categoría, como en Location, y los tiempos. */
.buscador-grupo { margin: 10px 12px 4px; font: 600 13px/18px var(--pila); color: var(--b-suave); }
.buscador-grupo:first-child { margin-top: 4px; }
.buscador-fila .lugar-circulo {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 32px; height: 32px; margin: 0 -6px;
  border-radius: 9999px; background: var(--color-poi, var(--primario)); color: #fff;
}
.buscador-fila .lugar-circulo .icono { width: 16px; height: 16px; stroke-width: 2; }
.buscador-fila .tiempos { display: flex; gap: 14px; }
.buscador-fila .tiempos .tiempo { display: inline-flex; align-items: center; gap: 4px; color: var(--b-tinta); font-weight: 600; }
.buscador-fila .tiempos .tiempo.sin { color: var(--b-suave); font-weight: 400; }
.buscador-fila .tiempos .icono { width: 14px; height: 14px; color: var(--b-suave); }
.buscador-sugerencias { padding: 12px 12px 8px; }
.buscador-sugerencias .etiqueta { margin: 0 0 10px; font: 600 13px/18px var(--pila); color: var(--b-suave); }
.buscador-sugerencias .pastillas { display: flex; flex-wrap: wrap; gap: 8px; }
.pastilla-sugerida {
  min-height: 44px; padding: 0 16px; border-radius: 22px;
  background: var(--b-relleno); color: var(--b-tinta);
  font: 500 15px/20px var(--pila);
}

@media (hover: hover) {
  .pastilla-sugerida:hover { filter: brightness(0.96); }
}

.buscador-vacio { padding: 28px 16px 24px; text-align: center; }
.buscador-vacio .que { margin: 0; font: 600 17px/22px var(--pila); }
.buscador-vacio .pista { margin: 6px 0 0; font: 400 15px/20px var(--pila); color: var(--b-suave); }

/* El precio de una fila de unidad: sigue al detalle con su «·»; a 390 baja a su renglón. */
.buscador-fila .detalle .precio::before { content: " · "; }

@media (max-width: 520px) {
  .buscador {
    top: 0; left: 0; transform: none;
    width: 100%; height: 100%; max-height: none; border-radius: 0;
    padding-top: env(safe-area-inset-top, 0px);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    animation-name: entra-buscador-tel;
  }
  @keyframes entra-buscador-tel { from { opacity: 0; transform: translateY(12px); } }
  .buscador-campo { font-size: 17px; }
  /* A 390 el precio no se corta: baja entero a su renglón, sin «·» colgando del de arriba. */
  .buscador-fila .detalle { white-space: normal; }
  .buscador-fila .detalle .precio { display: block; }
  .buscador-fila .detalle .precio::before { content: none; }
}

.buscador button, .menu-buscar, .minitorre button { border: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.buscador button:focus-visible, .minitorre button:focus-visible, .menu-buscar:focus-visible {
  outline: 2px solid var(--primario, #111); outline-offset: 2px;
}

/* «Show 4 on the Building» en la hoja del buscador. */
.buscador-barra { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
/* Con el botón puesto, la barra respira: antes el botón tocaba la raya de la cabeza. */
.buscador-barra:has(.buscador-en-edificio:not([hidden])) { padding: 10px 12px 2px 0; }
.buscador-barra:has(.buscador-en-edificio:not([hidden])) .buscador-cuenta { padding-top: 0; }
.buscador-barra .buscador-cuenta { flex: 1; }
.buscador .buscador-en-edificio {
  flex: none; min-height: 40px; padding: 0 16px; border-radius: 20px;
  background: var(--primario); color: var(--sobre-primario); font: 600 13px/18px var(--pila);
}

/* ══ 🔮 LA BÚSQUEDA CON IA · `busqueda-natural.ts` ═══════════════════════════════════════════════
 * Lo que se entendió va en pastillas que se quitan una a una (44 px de toque); cada fila dice POR QUÉ
 * cumple con su dato. «Entendiendo…» es discreto: la lista de siempre ya está debajo. */
.buscador-entendido {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 10px 12px 8px;
}
.buscador-entendido .etiqueta { font: 600 13px/18px var(--pila); color: var(--b-suave); margin-right: 2px; }
.buscador .pastilla-filtro {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 0 10px 0 16px; border-radius: 22px;
  background: color-mix(in srgb, var(--primario, #111) 10%, var(--b-lienzo));
  color: var(--b-tinta); font: 600 15px/20px var(--pila); text-align: left;
}
.pastilla-filtro .x {
  flex: 0 0 18px; height: 18px; border-radius: 50%;
  background: var(--b-suave);
  -webkit-mask: var(--i-x-circulo) center / contain no-repeat; mask: var(--i-x-circulo) center / contain no-repeat;
}
@media (hover: hover) {
  .buscador .pastilla-filtro:hover { filter: brightness(0.96); }
  .buscador .pastilla-filtro:hover .x { background: var(--b-tinta); }
}
.buscador-nota { margin: 0 20px 6px; font: 400 14px/19px var(--pila); color: var(--b-suave); }
/* «Ninguna Cumple Todo»: las salidas, centradas bajo su pista. */
.buscador-vacio .pastillas { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 14px; }
.buscador-pensando {
  display: inline-flex; align-items: center; gap: 8px; flex: 1;
  padding: 8px 20px 0; font: 600 13px/18px var(--pila); color: var(--b-suave);
}
.buscador-pensando[hidden] { display: none; }
.buscador-pensando::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--primario, #111);
  animation: pulso-buscador 1s ease-in-out infinite alternate;
}
@keyframes pulso-buscador { from { opacity: 0.25; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .buscador-pensando::before { animation: none; } }
/* Con «Entendiendo…» a la vista, la cuenta de la lista de siempre se aparta. */
.buscador-barra:has(.buscador-pensando:not([hidden])) .buscador-cuenta { display: none; }
.buscador-fila .detalle.porque { color: var(--b-tinta); }
.buscador-fila .detalle.porque::before { content: "✓ "; color: var(--primario, #111); font-weight: 700; }
.buscador .buscador-dictar {
  flex: 0 0 44px; height: 44px; border-radius: 22px; background: transparent;
  position: relative;
}
.buscador .buscador-dictar::before {
  content: ""; position: absolute; inset: 11px; background: var(--b-suave);
  -webkit-mask: var(--i-microfono) center / contain no-repeat; mask: var(--i-microfono) center / contain no-repeat;
}
.buscador .buscador-dictar.escuchando { background: color-mix(in srgb, var(--primario, #111) 14%, transparent); }
.buscador .buscador-dictar.escuchando::before { background: var(--primario, #111); }
.buscador {
  --i-microfono: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='9' y='3' width='6' height='11' rx='3'/%3E%3Cpath d='M5 11a7 7 0 0 0 14 0M12 18v3'/%3E%3C/svg%3E");
  --i-x-circulo: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' fill-rule='evenodd' d='M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20zM8.3 8.3a1 1 0 0 1 1.4 0L12 10.6l2.3-2.3a1 1 0 1 1 1.4 1.4L13.4 12l2.3 2.3a1 1 0 0 1-1.4 1.4L12 13.4l-2.3 2.3a1 1 0 0 1-1.4-1.4l2.3-2.3-2.3-2.3a1 1 0 0 1 0-1.4z'/%3E%3C/svg%3E");
}
@media (max-width: 520px) {
  .buscador-entendido { padding: 8px 8px 6px; }
  .buscador-nota { margin: 0 12px 6px; }
}
/* 🧱 Lo de Availability que va en la hoja principal (`pantallas/disponibilidad.ts`). El resto vive en `disponibilidad.css`, que se pide al abrirla y manda sobre esto. */

/* ── Ubicacion viva (MapLibre): vive en `ubicacion.css`, que pide `mapa.ts` al abrir Location. ── */

/* ── Disponibilidad ── */
.disponibilidad { display: flex; flex-direction: column; gap: 24px; }
.resumen-disponible { display: flex; flex-direction: column; gap: 10px; }
.cuenta-disponible { margin: 0; font: 500 18px/24px var(--pila); }
.barra-estados { display: flex; gap: 3px; height: 8px; border-radius: 9999px; overflow: hidden; max-width: 480px; }
.barra-estados .tramo { background: var(--color-estado); }
.leyenda { display: flex; gap: 16px; font: 400 13px/18px var(--pila); color: var(--tinta-suave); }
.leyenda-item::before, .pastilla-filtro.con-punto::before, .residencia .estado-residencia::before {
  content: ""; display: inline-block; width: 8px; height: 8px; margin-right: 6px; border-radius: 9999px; background: var(--color-estado);
}
.filtros-disponible { display: flex; flex-wrap: wrap; gap: 16px 32px; align-items: flex-end; padding: 16px 0; border-block: 1px solid var(--separador, #eee); }
.filtro-grupo { display: flex; flex-direction: column; gap: 6px; }
.filtro-grupo .etiqueta { font: 500 12px/16px var(--pila); color: var(--tinta-suave); }
.filtro-grupo .control { min-width: 160px; }
.pastillas { display: flex; flex-wrap: wrap; gap: 6px; }
.pastilla-filtro {
  display: inline-flex; align-items: center; height: 36px; padding: 0 14px; border: 1px solid var(--separador, #e5e5e5); border-radius: 9999px;
  background: var(--lienzo-elevado, #fff); color: var(--tinta); font: 500 13px/13px var(--pila); cursor: pointer;
}
.pastilla-filtro.activa { border-color: var(--primario); background: var(--primario); color: var(--sobre-primario); }
.residencias { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; }
.residencia { display: flex; flex-direction: column; gap: 8px; padding: 20px; border: 1px solid var(--separador, #eee); border-radius: 16px; background: var(--lienzo-elevado, #fff); }
.residencia .cabeza { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.residencia .nombre { font: 500 17px/22px var(--pila); }
.residencia .estado-residencia { display: inline-flex; align-items: center; font: 500 12px/16px var(--pila); color: var(--tinta-suave); }
.residencia .nivel { margin: 0; font: 400 13px/18px var(--pila); color: var(--tinta-suave); }
.residencia .cifras { display: flex; flex-wrap: wrap; gap: 4px 12px; margin: 0; font: 500 14px/20px var(--pila); }
.residencia .mandos { display: flex; gap: 8px; margin-top: 8px; }
.residencia .mandos button {
  flex: 1; height: 40px; border-radius: 9999px; font: 500 14px/14px var(--pila); cursor: pointer;
  border: 1px solid var(--primario); background: var(--lienzo-elevado, #fff); color: var(--primario-texto, var(--primario));
  padding: 0 12px; white-space: nowrap;
}
.residencia .mandos .abrir-residencia { background: var(--primario); color: var(--sobre-primario); }
.residencia.vendida { background: var(--lienzo-hundido, #fafafa); }
/* Atenuada por COLOR y no por opacidad: al 50 % el nivel quedaba a 2.1:1 (`test/contraste.test.ts`). */
.residencia.vendida .nombre, .residencia.vendida .cifras { color: var(--tinta-suave); }
.sin-resultados { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; color: var(--tinta-suave); }

@media (max-width: 720px) {
  .residencias { grid-template-columns: minmax(0, 1fr); }
  .filtros-disponible { gap: 12px; }
}

/* ── 🔽 Los filtros plegados (🧭 Showroom-Rápido-Motor · Plan del cruce §B5) ─────────────────────────────
   Una fila que dice lo que hay puesto y se despliega; debajo, las residencias sin esperar. */
.filtros-plegados { margin: 8px 0 16px; border-block: 1px solid var(--separador, #eee); }
.filtros-resumen {
  display: flex; align-items: center; gap: 12px;
  min-height: 48px; list-style: none; cursor: pointer;
  font: 600 15px/20px var(--pila, system-ui); color: var(--etiqueta, #1d1d1f);
}
.filtros-resumen::-webkit-details-marker { display: none; }
.filtros-resumen::after {
  content: ""; margin-left: auto; width: 8px; height: 8px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px); transition: transform 0.2s;
}
.filtros-plegados[open] > .filtros-resumen::after { transform: rotate(-135deg) translate(-2px, -2px); }
.filtros-puestos { font-weight: 400; color: var(--etiqueta-2, #6e6e73); }
.filtros-resumen.con-filtro .filtros-puestos { color: var(--primario-texto, var(--primario, #111)); font-weight: 600; }
.disponibilidad .filtros-plegados > .filtros-disponible { padding: 4px 0 16px; border: 0; }
/* 📱 El teléfono (✨ Pulir-Celular, 27-sep-2026): lo que cruza todas las pantallas cuando se mira con el dedo —zonas de toque, barras fijas, lo que se encima en 390 y 375—. Va AL FINAL del índice: corrige a las demás hojas, no compite con ellas. Medido en `Desarrollos/<Desarrollo>/6 · Showroom/Notas/<Desarrollo> · Pulido · Celular.md` (inquilino piloto). */

/* Los toques de 44 px con puntero grueso viven en `chrome.css` (§El dedo); ahí nacieron y ahí se
   reviven (🩹 CSS-Reglas-Muertas: estuvieron muertos por un comentario del 23 al 27-sep-2026). */

/* Sin el gris de WebKit al tocar: cada control ya contesta con su `:active` (escala 0.94–0.95), y
   el recuadro gris encima se veía como un error. Para que iOS aplique `:active` hace falta un
   `touchstart` en la página: lo pone `app.ts`. */
html { -webkit-tap-highlight-color: transparent; }

/* Las migas son el «atrás» del recorrido y cada una se tocaba de 20 px de alto dentro de una
   pastilla de 44: crecen hasta la pastilla sin mover el texto. */
[data-tema="web3d"] .migas button.miga { padding-block: 12px; margin-block: -12px; }

/* ── Las barras fijas ────────────────────────────────────────────────────────────────────────
   En una pantalla de documento (Avance de obra, Disponibilidad, Contacto…) los mandos de arriba
   flotan sobre la página, y al desplazarla el texto pasaba POR DEBAJO de ☰, ↶ y Contact: se leían
   las dos cosas encimadas. Una banda del color del lienzo, pegada arriba y que no ocupa sitio,
   hace de fondo a los mandos; el contenido se funde al entrar en ella. */
.documento::before {
  content: ''; display: block; position: sticky; top: 0; z-index: 3;
  height: calc(var(--borde-arriba) + 60px); margin-bottom: calc(-1 * (var(--borde-arriba) + 60px));
  background: linear-gradient(var(--lienzo, #fff) 62%, transparent);
  pointer-events: none;
}
/* Donde el navegador sabe atar una animación al desplazamiento, la banda sólo aparece al
   desplazar (como la barra de iOS) y puede ser más alta y más opaca: en reposo no toca el título. */
@supports (animation-timeline: scroll()) {
  .documento::before {
    height: calc(var(--borde-arriba) + 76px); margin-bottom: calc(-1 * (var(--borde-arriba) + 76px));
    background: linear-gradient(var(--lienzo, #fff) 72%, transparent);
    animation: banda-al-desplazar linear both; animation-timeline: scroll(nearest); animation-range: 0 48px;
  }
  @keyframes banda-al-desplazar { from { opacity: 0; } to { opacity: 1; } }
}

/* El pie pegado de la ficha era material al 90 % SIN desenfoque: las cifras del cotizador se
   leían a través, entre los botones redondos. Con el desenfoque del sistema es material de verdad. */
[data-tema="web3d"] .pie-pegajoso { -webkit-backdrop-filter: var(--desenfoque); backdrop-filter: var(--desenfoque); }

@media (max-width: 520px) {
  /* La leyenda de estados flota sobre la tira de niveles; con la tarjeta abierta (hoja inferior)
     caía ENCIMA de «Request information» y tapaba el botón. La tira ya se va con la tarjeta
     (`niveles.css`); la leyenda, también. */
  .chrome:has(> .tarjeta) > .leyenda-estados { display: none; }

  /* «Tap a Level» se quedaba a medio fundir detrás de la hoja de niveles, que es translúcida. */
  body:has(.barra-niveles.abierta) .aviso-invita { visibility: hidden; animation: none; }
}

/* La ficha en el teléfono: el escenario queda transparente sobre el papel, y ese `background:
   transparent` (atajo) devolvía el tamaño y la repetición a los de fábrica. El `placeholder` que
   `escenario.ts` pone en línea se repetía en mosaico —decenas de plantitas alrededor de la planta
   mientras cargaba, y un rayado tenue que se quedaba en lo transparente del arte—. */
@media (max-width: 520px) and (orientation: portrait) {
  [data-tema="web3d"] body:has(.ficha .panel.abierto) .escenario { background-image: none !important; }
}

/* Dos chips de unidad que se enciman (dos vecinas en 375) se quedan en su número: `mascara.ts`
   (`compactar`) marca `compacto` a las dos, y el renglón de recámaras y superficie se va. */
.rotulo.compacto .nota { display: none; }

/* ══ 📱 EL NIVEL A 390 (🧭 Showroom-Rápido-Motor, 29-sep-2026 · Plan del cruce «Según El Mejor», 29-sep-2026, §B2) ═══
   Cinco mandos rodeaban una planta que ocupa ~60 % de la pantalla. Queda lo que dice algo que no dice otro:
   · LA TIRA DE PIE: el edificio a la derecha, Roof arriba y el más bajo abajo —`chrome.ts` ya los pinta de
     arriba abajo—. Tumbada abajo el 1 quedaba a la izquierda y el edificio acostado. Cabe entera a 844 de alto;
     si no cabe, se desplaza y `centrarActivo` deja el activo a la vista.
   · SIN LA PLACA DEL TÍTULO: la miga ya dice «<Desarrollo> › Level 6». Del título queda lo que la miga no dice
     —«2 available · from $6.3M USD»—, en un renglón sin caja bajo la miga.
   · SIN LEYENDA: el estado lo dicen el punto y el gris de cada pastilla.
   · LAS VENDIDAS EN GRIS Y SIN PASTILLA (`mascara.ts`, `no-a-la-venta`); en la tira, el nivel vendido entero
     (`chrome.ts`, `agotado`) se apaga igual y se sigue tocando.
   · El zoom baja a la izquierda: la derecha es de la tira. */
@media (max-width: 520px) {
  [data-tema="web3d"] .chrome:has(.titular-nivel) .pisos,
  [data-tema="web3d"] .chrome:has(.titular-nivel) .pisos:not(.cerrada) {
    display: flex; flex-direction: column;
    top: calc(var(--borde-arriba) + 56px); bottom: auto; left: auto; right: var(--borde);
    transform: none;
    width: 52px; min-width: 0;
    max-height: calc(100% - var(--borde-arriba) - 56px - var(--borde-abajo));
    overflow-x: hidden; overflow-y: auto;
    gap: 0; padding: 4px;
    border-radius: 26px;
  }
  [data-tema="web3d"] .chrome:has(.titular-nivel) .piso {
    flex: 0 0 auto; width: 44px; min-width: 44px; height: 44px; min-height: 44px; padding: 0;
    border-radius: 22px; font-size: 14px;
  }
  /* El gris que aún pasa AA (4.5:1, `test/contraste.test.ts`): la tinta secundaria y el trazo fino. */
  [data-tema="web3d"] .chrome:has(.titular-nivel) .piso.agotado:not(.activo) { color: var(--etiqueta-2); font-weight: 400; }
  [data-tema="web3d"] .chrome:has(.titular-nivel) .asa-pisos { display: none; }

  [data-tema="web3d"] .chrome .titular-nivel {
    top: calc(var(--borde-arriba) + 52px); right: calc(var(--borde) + 60px);
    padding: 0; border-radius: 0;
    background: none; box-shadow: none;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  [data-tema="web3d"] .chrome .titular-nivel-titulo { display: none; }
  /* Un renglón, no una placa: sobre el suelo oscuro el halo solo no alcanzaba; un velo de material a su medida. */
  [data-tema="web3d"] .chrome .titular-nivel-resumen {
    display: inline-block; padding: 4px 10px; border-radius: 12px;
    font: 600 13px/18px var(--pila); color: var(--etiqueta);
    background: var(--material-grueso);
    -webkit-backdrop-filter: var(--desenfoque); backdrop-filter: var(--desenfoque);
    text-shadow: none !important;
  }

  [data-tema="web3d"] .chrome:has(.titular-nivel) > .leyenda-estados { display: none; }

  [data-tema="web3d"] .chrome:has(.titular-nivel) .acercar,
  [data-tema="web3d"] .chrome:has(.titular-nivel) .alejar { left: var(--borde); right: auto; }
  [data-tema="web3d"] .chrome:has(.titular-nivel) .acercar { bottom: calc(var(--borde-abajo) + 44px); }
  [data-tema="web3d"] .chrome:has(.titular-nivel) .alejar { bottom: var(--borde-abajo); }

  [data-tema="web3d"] body:has(.chrome .titular-nivel) .rotulo.no-a-la-venta {
    background: none; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none;
    --color-punto: var(--etiqueta-2);
  }
  [data-tema="web3d"] body:has(.chrome .titular-nivel) .rotulo.no-a-la-venta .texto,
  [data-tema="web3d"] body:has(.chrome .titular-nivel) .rotulo.no-a-la-venta .nota {
    color: var(--etiqueta-2);
    text-shadow: 0 0 8px rgb(255 255 255 / 0.9);
  }
}

/* 📱 LA FACHADA ES DEL DEDO (🧭 Showroom-Rápido-Motor · Plan del cruce «Según El Mejor» §B3). Con `touch-action` de
   fábrica el navegador se quedaba el arrastre vertical y mandaba `pointercancel`: el imán de niveles (`chrome.ts`,
   `imanDeNiveles`) se apagaba a medio gesto. Sin gesto del navegador, el vertical es del imán y el horizontal sigue
   siendo el giro (`app.ts`, «ARRASTRAR GIRA», que escucha `pointerup`). */
@media (pointer: coarse) {
  [data-tema="web3d"] body:has(.chrome .barra-niveles) .escenario { touch-action: none; }
}
