/* =========================================================
   ALTURA — lo que el CRM agrega al diseño

   styles.css es el archivo del diseñador y se copia tal cual: cuando lo
   actualice, se pisa el archivo y listo. Todo lo que el sitio real necesita y
   la demo estática no tenía va acá, apoyado en los mismos tokens (--ink,
   --bronze, --line…) para que siga cambiando con la paleta elegida.

   Se carga DESPUÉS de styles.css.
   ========================================================= */

/* ------------------- logo subido por la inmobiliaria -------------------
   La demo dibujaba la marca con un SVG y texto. Casi todas tienen su logo
   cargado en el CRM, así que se usa ése; el alto lo fija el header y el ancho
   se acomoda solo, que es lo único que respeta logos apaisados y cuadrados a
   la vez. */
/* El alto lo fija `--logo-h`, que escribe el backend con el tamaño elegido en
   el CRM (chico / mediano / grande). El valor de acá es sólo la red por si la
   variable no llegara: es el tamaño original del diseño. */
.logo__img {
  display: block;
  width: auto;
  max-height: var(--logo-h, 48px);
  object-fit: contain;
}
.logo--footer .logo__img { max-height: var(--logo-h-footer, 44px); }

/* ------------------ textos que escribe la inmobiliaria ------------------
   Lo que carga una inmobiliaria no es prosa de diseñador: vienen cadenas de
   hashtags pegados, URLs largas y direcciones de correo. Medido en una real:
   `#entratativa#delpretepropiedadesvende#delpretepropiedadesalquila#inmobiliariamdp`,
   81 caracteres sin un solo espacio.

   Una "palabra" así no se puede cortar, y como el ancho mínimo de la columna
   lo fija su contenido más ancho, estiraba la grilla de "Nosotros" a 558 px
   dentro de una pantalla de 390: el texto se salía de la pantalla.

   `anywhere` y no `break-word`: sólo el primero achica el ancho MÍNIMO del
   elemento, que es justamente lo que descalabra la grilla. `break-word` deja
   de desbordar la línea pero no arregla el ancho de la columna.

   Va sobre toda la superficie de contenido y no sobre una lista corta de
   clases: probando el sitio con una cadena así en cada texto, rompían los
   títulos, las bajadas, los ítems, las etiquetas y los botones — casi todos
   salen del editor de secciones, así que cualquiera puede recibirla. Quedan
   afuera el menú y los datos que arma el sistema (precios, superficies), que
   no son texto libre.

   Sólo dentro de `.altura`: el diseño de siempre no se toca. */
.altura :is(h1, h2, h3, h4, p, li, dd, dt, figcaption, blockquote, label, .btn, .eyebrow) {
  overflow-wrap: anywhere;
}

/* ------------------- alto de la cabecera en páginas internas -------------
   El logo es el elemento más alto de la cabecera, así que la cabecera mide su
   alto más el padding de `.header` (1.1rem arriba y abajo). En la portada no
   importa —la cabecera flota sobre la foto— pero en las páginas internas es
   fija y opaca, y lo que empiece en el borde de arriba queda tapado.

   Cada página reservaba ese lugar por su cuenta, con números fijos que no
   coincidían entre sí: 76px en el mapa y en `.page-inner`, y en la ficha de
   propiedad directamente nada — las migas quedaban ATRÁS de la cabecera. Se
   veía poco porque están sobre el mismo crema. Una sola regla contra el alto
   real lo arregla para todas, y además acompaña al tamaño del logo. */
:root { --header-h: calc(var(--logo-h, 48px) + 2.2rem + 1px); }

.header--solid ~ main { padding-top: var(--header-h); }

/* El mapa ocupa la pantalla entera y ya venía reservando 76px por su cuenta.
   La regla de arriba le gana en especificidad y le pone el alto real; esto
   sólo deja explícito que el hueco ya no se cuenta dos veces. */
.header--solid ~ main.split { padding-top: var(--header-h); }

/* En un teléfono la cabecera se lleva una porción de pantalla que en el
   monitor no se nota: un logo grande dejaría el saludo de la portada sin
   lugar. Por eso cada tamaño tiene su propio tope para pantallas chicas. */
@media (max-width: 640px) {
  :root { --header-h: calc(var(--logo-h-mobile, 48px) + 2.2rem + 1px); }
  .logo__img { max-height: var(--logo-h-mobile, 48px); }
}

/* Sobre la foto del hero el header es transparente y un logo oscuro no se ve,
   así que ahí se lo aclara. En cuanto el header tiene fondo —al bajar
   (`is-stuck`) o en las páginas internas, que arrancan sólidas
   (`header--solid`)— vuelve a sus colores: sin excluir esa segunda clase, el
   logo queda blanco sobre fondo claro y desaparece.

   El blanqueo se puede apagar desde el CRM (`logo__img--color`): sirve cuando
   el logo ya es claro, o cuando la portada lo es y el blanco desaparecería.
   Como es un filtro y no un color, deja el logo en una silueta plana — se
   pierden los colores de la marca, y no toda inmobiliaria quiere eso. */
.header:not(.is-stuck):not(.header--solid):not(.header--ink) .logo__img:not(.logo__img--color) {
  filter: brightness(0) invert(1);
}

/* ------------------------ estado de la propiedad ------------------------
   Vendida, alquilada o reservada. Va sobre la foto y no como una etiqueta más
   abajo: es la información que decide si el visitante sigue leyendo o no. */
.card__state {
  position: absolute;
  bottom: .8rem;
  left: .8rem;
  z-index: 2;
  padding: .3rem .7rem;
  border-radius: 999px;
  background: var(--ink);
  color: var(--cream);
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
}
/* La etiqueta libre que carga la inmobiliaria puede convivir con la anterior,
   así que se corre para no taparla. */
.card__state--custom {
  bottom: auto;
  top: .8rem;
  left: auto;
  right: .8rem;
  background: var(--bronze);
  /* No `#fff` fijo: el acento lo elige la inmobiliaria y puede ser un amarillo
     o un celeste, donde el texto blanco desaparece. `--on-bronze` lo calcula el
     backend según la luminancia del color elegido. */
  color: var(--on-bronze, #fff);
}

/* En la tarjeta la etiqueta libre comparte la fila con las de operación y tipo.
   Antes iba clavada contra el borde derecho y la fila de la izquierda tenía
   reservado un ancho fijo (el del corazón de guardados, que este tema no
   dibuja). Ese ancho no alcanzaba: con "Departamento" y "Nuevo Ingreso" —los
   dos largos— la fila pasaba por debajo de la etiqueta y se veían encimadas.

   Compartiendo la fila el navegador las acomoda solo: mientras hay lugar la
   etiqueta queda a la derecha por el `margin-left: auto`, y cuando no entra
   baja a un segundo renglón, alineada a la derecha igual. Sin anchos fijos, así
   que da lo mismo cuánto midan los textos y en qué idioma estén. */
.card__tags {
  right: .85rem;
  max-width: none;
}
.card__tags .card__state--custom {
  position: static;
  inset: auto;
  margin-left: auto;
}

/* Que las tres entren en un renglón en la tarjeta angosta del listado, donde la
   foto mide 340 px y la fila tiene 311 para repartir. Con los tamaños del
   diseño, "Venta + Departamento + Nuevo Ingreso" suma 325 y la etiqueta libre
   caía sola al renglón de abajo: no se superponía, pero se veía como un error.

   Se recorta un poco de cada cosa en vez de achicar mucho una sola:

     - la etiqueta libre venía un punto más grande que las otras dos (.68 contra
       .62). Igualarlas es lo que más ancho devuelve, y de paso las tres se ven
       como una familia y no como una pegada encima;
     - el cuerpo de las tres, a .58rem;
     - el espaciado entre letras, de .14 a .11em. Es lo que menos se nota y lo
       que más rinde en un texto en mayúsculas;
     - el relleno lateral y la separación entre etiquetas.

   Medido sobre una tarjeta de 340 px: "Venta + Departamento + Nuevo Ingreso"
   pasa a sobrar 33 px, y hasta "Alquiler + Departamento + Nuevo Ingreso" —el
   peor caso real— entra con 17 de sobra.

   Achicarlas más no tendría sentido: "Alquiler Temporal" con una etiqueta de
   dos palabras no entra en un renglón por más que se recorte, y para eso está
   el salto de línea, que es la red que evita que se encimen. */
.card__tags { gap: .25rem; }
.card__tags .tag,
.card__tags .card__state--custom {
  font-size: .58rem;
  letter-spacing: .11em;
  padding-inline: .55rem;
}
.card__tags .card__state--custom { padding-block: .36rem; }

/* Lo mismo para la selección de texto, que el diseño pinta con el acento. */
::selection { color: var(--on-bronze, #fff); }

/* --------------------------- matrícula en el pie --------------------------- */
.footer__reg {
  margin-top: .6rem;
  font-size: .78rem;
  color: var(--muted);
}

.footer__college img { opacity: .85; }
.footer__college:hover img { opacity: 1; }

/* --------------- el buscador no se monta sobre la portada ---------------
   El diseño original sube el buscador 3,75 rem para que asome sobre el borde
   de abajo de la portada. Con la portada a `100svh` eso deja la tarjeta cortada
   por el borde de la pantalla: se ven las etiquetas y la mitad de los valores.

   Peor todavía, la tarjeta lleva `reveal`, que la mantiene invisible hasta que
   se la scrollea y después la deja visible para siempre. Resultado: al cargar
   la portada está limpia, y al bajar y volver a subir aparece esa media
   tarjeta. La misma posición mostraba dos cosas distintas según por dónde
   hubiera pasado el visitante.

   Sin el margen negativo la portada queda siempre igual —limpia— y el buscador
   empieza donde termina. Se pierde el efecto de tarjeta colgando, que con esta
   altura de portada no se llegaba a ver entero de todos modos. */
/* Al sacar la superposición la tarjeta quedaba pegada al borde de la foto. El
   relleno le da aire; es más chico que el de una sección normal
   (`clamp(4.5rem, 9vw, 8rem)`) porque el buscador sigue siendo parte de la
   apertura y no un bloque aparte. */
.search {
  margin-top: 0;
  padding-top: clamp(2rem, 4vw, 3.5rem);
}

/* Al quedar el buscador entre la portada y la sección siguiente, su caja
   —transparente— muestra el color del papel. Mientras abajo va una sección sin
   fondo propio no se nota, pero si va una que sí lo tiene (Propiedades y Zonas
   van en crema, Emprendimiento en tinta) aparece una banda de otro tono debajo
   de la tarjeta: se lee como una costura de dos colores, no como parte del
   diseño.

   La franja toma el color de la que sigue, sea cual sea: el orden lo elige la
   inmobiliaria desde el CRM y cualquiera de las once puede terminar ahí.

   Va con `:has()` sobre el hermano siguiente y no con una clase calculada en
   PHP porque varias secciones no dibujan nada cuando están vacías (Propiedades
   sin destacadas, Servicios sin ítems, Emprendimiento sin título): el blade
   sabe cuáles están encendidas, pero no cuál termina siendo la de al lado. En
   un navegador sin `:has()` se ve como hasta ahora — la banda de más, no una
   página rota.

   `inset: 0` cubre la caja entera y no una parte, porque acá el buscador ya no
   se monta sobre la portada: empieza justo donde la foto termina. */
.search::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
}
.search:has(+ .section--alt)::before { background: var(--cream-2); }
.search:has(+ .dev)::before { background: var(--ink); }

/* El botón de buscar también es tinta: sobre la franja en tinta desaparecía y
   la tarjeta se veía cortada a la derecha. Ahí va con el acento de la paleta,
   el mismo criterio que en la portada "Buscador protagonista". */
.search:has(+ .dev) .search__btn {
  background: var(--bronze-dk);
  color: var(--on-bronze, #fff);
  box-shadow: 0 0 0 1px var(--bronze-dk);
}
.search:has(+ .dev) .search__btn:hover {
  background: var(--bronze);
  box-shadow: 0 0 0 1px var(--bronze);
}

/* En el teléfono la portada mide 92svh a propósito, para que se vea que hay
   algo más abajo. Sin esto lo que asoma es la primera fila de la tarjeta
   —"OPERACIÓN / En Venta" cortado— y vuelve el mismo problema en chico.

   La cuenta va contra `lvh` y no contra `svh`, y ahí está el detalle: `svh` es
   la pantalla CON la barra del navegador y `lvh` la que queda cuando esa barra
   se esconde al scrollear. Como el visitante llega arriba justo después de
   scrollear, la pantalla visible en ese momento es la grande. Con `8svh` la
   tarjeta caía apenas debajo del pliegue chico y volvía a asomar en cuanto la
   barra se ocultaba; con esto queda debajo del pliegue en los dos estados.

   En un iframe las dos unidades valen lo mismo (no hay barra), así que esta
   diferencia no se puede ver probando así: sale de cómo están definidas. */
@media (max-width: 780px) {
  .search { padding-top: calc(100lvh - 92svh + 1rem); }
}

/* --------------------- buscador (portada y listado) ---------------------
   La caja del diseñador es una grilla de columnas fijas (`repeat(4, 1fr) auto`)
   y eso funciona sólo con exactamente cuatro campos. No siempre los hay: la
   inmobiliaria sin ciudades cargadas no muestra "Zona", la que no cargó tipos
   no muestra "Tipo", y ahí sobraban celdas grises a la derecha.

   Con flex se reparten solas, sean dos, tres o cuatro. Se conserva el truco de
   `gap: 1px` sobre fondo `--line` del original, que es lo que dibuja las
   divisiones entre campos. */
.search__card {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
}
.search__field { flex: 1 1 11rem; min-width: 0; }

/* El botón llena su celda en lugar de flotar adentro como pastilla: sin esto
   hereda de `.btn` el radio de 999px y el `translateY(-2px)` del hover, y en
   una caja con `overflow: hidden` se ve como un óvalo negro que se sale del
   borde redondeado y salta al pasar el mouse. */
.search__card .btn {
  flex: none;
  align-self: stretch;
  border-radius: 0;
  padding-inline: 2rem;
}
.search__card .btn:hover { transform: none; box-shadow: none; }

/* En el teléfono los campos van uno debajo del otro y el botón ocupa el ancho:
   partido en dos columnas, "Presupuesto" no entra en su celda. */
@media (max-width: 640px) {
  .search__field { flex: 1 1 100%; }
  .search__card .btn { flex: 1 1 100%; padding-block: 1rem; }
}

/* "Limpiar" del listado: un link discreto debajo y a la derecha, alineado con
   el borde de la caja. Va fuera del formulario — adentro era un hijo más de la
   grilla y caía a una segunda fila, dejando a la vista el fondo gris. */
.lsearch__extra {
  display: flex;
  justify-content: flex-end;
  margin-top: .7rem;
}
.lsearch__extra .lsearch__clear {
  background: none;
  padding: 0;
  font-size: .82rem;
  font-weight: 500;
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.lsearch__extra .lsearch__clear:hover { background: none; color: var(--ink); }

/* ---------------------- contador del carrusel ----------------------
   "02 / 04" se partía en dos renglones en el teléfono: la fila de controles se
   angosta y el contador es lo último, así que le tocaba el sobrante. Son cinco
   caracteres que siempre miden lo mismo (`tabular-nums`), no hay nada que
   ganar partiéndolos. */
.hslider__count { white-space: nowrap; }

/* --------------------- "Ver en el mapa" en el listado ---------------------
   Copia la forma de sus vecinos de la barra —el desplegable de orden y el
   grupo grilla/lista— para que se lea como un control más de "cómo veo estos
   resultados" y no como una promoción metida ahí.

   No usa `.btn` a propósito: esa clase anima el `svg` hacia la derecha al
   pasar el mouse, un gesto pensado para las flechas de "seguir leyendo". Con
   un pin de mapa parecería que se está por caer. */
.lbar__map {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .45rem 1rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--white);
  color: var(--ink);
  font-size: .84rem;
  font-weight: 500;
  white-space: nowrap;
  transition: background var(--t), color var(--t), border-color var(--t);
}
.lbar__map:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--cream);
}
.lbar__map svg { flex: none; }

/* En el teléfono la barra ya reparte orden y vista a los extremos; el botón
   entra tercero y sin el texto no se entendería, así que se deja pasar a la
   línea de abajo en vez de apretarlo. */
@media (max-width: 560px) {
  .lbar__tools { flex-wrap: wrap; gap: .8rem; }
}

/* ------------------------ "Ingresar" del pie ------------------------
   Entrada al CRM, la última de la columna "El sitio". Lleva un candado que la
   distingue de los links de contenido: quien busca una propiedad no tiene por
   qué entrar ahí.

   Acá va SÓLO la alineación del icono con el texto. Antes había además un
   `opacity: .75` para atenuarla, y eso la hacía desentonar con el resto de la
   lista; el candado ya alcanza para distinguirla. Si se vuelve a atenuar,
   vuelve el problema. */
.footer__login {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
}
/* Sin `flex: none` el candado se achica cuando el texto no entra. */
.footer__login svg { flex: none; }

/* ------------------------------ formularios ------------------------------
   El captcha lo dibuja Google en un iframe de ancho fijo (304px). En la
   columna angosta del formulario se desbordaba, así que se lo achica en
   pantallas chicas; el origen arriba a la izquierda evita que quede corrido. */
.form__captcha,
.subs__captcha {
  margin: 1rem 0;
}
@media (max-width: 380px) {
  .form__captcha .g-recaptcha,
  .subs__captcha .g-recaptcha {
    transform: scale(.86);
    transform-origin: 0 0;
  }
}

/* Aviso de error del backend (captcha sin marcar, validación que rebotó). */
.form__note.is-error {
  color: #b3261e;
  font-weight: 500;
}

/* Confirmación después de enviar. */
.form__ok {
  margin-bottom: 1.2rem;
  padding: .8rem 1rem;
  border-radius: var(--radius);
  border: 1px solid rgba(47, 79, 67, .3);
  background: rgba(47, 79, 67, .08);
  color: var(--forest);
  font-size: .9rem;
}

/* Mientras el envío viaja: sin esto se puede apretar dos veces y entran dos
   consultas iguales al CRM. */
.form__submit.is-sending {
  opacity: .6;
  pointer-events: none;
}

/* El campo con error ya tiene su estilo en styles.css para los que valida el
   JS; esto cubre los que marca el backend al recargar la página. */
.field.has-error input,
.field.has-error textarea {
  border-color: #b3261e;
}

/* ------------------------------ portada video ------------------------------
   (el resto de las reglas del iframe van en el propio hero, porque dependen
   de si hay video cargado) */
.herovideo__frame { z-index: 0; }

/* -------------------- portada buscador sin mosaico --------------------
   El mosaico de ocho fotos necesita ocho propiedades destacadas. Cuando hay
   menos, se cae a la foto de cabecera a pantalla completa: mismo contenedor,
   una sola imagen que cubre. */
.herosearch__bg--single {
  display: block;
  opacity: 1;
}
.herosearch__bg--single img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* El velo está calibrado para tapar el mosaico, que es claro y ruidoso. Sobre
   una foto sola borra la imagen entera y el hero queda negro, así que ahí se
   aclara — lo justo para que la foto se vea sin restarle contraste al texto. */
.herosearch__bg--single + .herosearch__veil {
  background:
    radial-gradient(120% 90% at 50% 45%,
      rgba(15, 13, 11, .5) 0%,
      rgba(15, 13, 11, .7) 55%,
      rgba(15, 13, 11, .86) 100%);
}

/* --------------------------- ficha de propiedad ---------------------------
   La demo ponía las iniciales de la inmobiliaria en un círculo; casi todas
   tienen el logo cargado, así que se usa ése. */
.agent__logo {
  flex: none;
  width: auto;
  max-height: 44px;
  object-fit: contain;
}

/* El mapa de la ficha es un canvas de Leaflet, no una foto: sin alto propio
   colapsa a cero y no se ve nada. El aspect-ratio del diseño lo cubre, pero
   Leaflet necesita además que el contenedor no sea `position: static`. */
.detail__map { background: var(--cream-2); }
.detail__map .leaflet-container { width: 100%; height: 100%; }

/* Cuando el video es un embed de YouTube o Vimeo, el iframe reemplaza a la
   foto de vista previa y tiene que ocupar la misma caja. */
.mediabox iframe { display: block; width: 100%; height: 100%; border: 0; }

/* ------------------------------- listado -------------------------------
   En la demo "Limpiar" era un <button type=reset>; acá es un link que vuelve
   al listado sin filtros, porque el filtrado es del servidor. */
a.lsearch__clear { display: inline-flex; align-items: center; text-decoration: none; }

/* Los chips de filtro son links y no botones: tienen que poder abrirse en
   otra pestaña y ser recorribles por Google. */
a.lchip { text-decoration: none; }

/* Los puntos suspensivos entre bloques de páginas. */
.pager__gap {
  padding: 0 .35rem;
  color: var(--muted);
  user-select: none;
}

/* --------------------------- notas y páginas ---------------------------
   El contenido del editor del CRM entra con la clase `post-content`. Acá sólo
   se le da el ancho de lectura y el ritmo vertical; los estilos de imágenes
   posicionadas y demás ya vienen de las hojas del sitio. */
.post-content > * + * { margin-top: 1.15rem; }
.post-content img { border-radius: var(--radius); }
.post-content h2 { margin-top: 2.4rem; }
.post-content ul,
.post-content ol { padding-left: 1.4rem; }
.post-content ul { list-style: disc; }
.post-content ol { list-style: decimal; }
.post-content li + li { margin-top: .4rem; }
.post-content a { color: var(--bronze); text-decoration: underline; }
.post-content blockquote {
  padding-left: 1.2rem;
  border-left: 3px solid var(--bronze);
  color: var(--muted);
  font-style: italic;
}

/* Una página institucional no lleva barra lateral: la columna de texto ocupa
   el ancho completo de la grilla. */
.note__grid--wide { grid-template-columns: minmax(0, 1fr); }

/* --------------------------- cambio de idioma ---------------------------
   Los estilos del selector viven en traductor.css, que es del diseñador y se
   carga sólo cuando la inmobiliaria tiene los idiomas activados. Acá va lo
   que hace falta para que entre bien en esta cabecera.

   El botón se cuelga como hermano del <nav>, así que en escritorio hay que
   separarlo del botón "Contactar" a mano. */
.header__inner > .gtr { margin-left: .75rem; }

@media (max-width: 980px) {
  /* Con el menú colapsado el <nav> desaparece de la barra y el selector
     quedaría pegado al burger. Se empuja contra él dejando aire. */
  .header__inner > .gtr { margin-left: auto; margin-right: .6rem; }
}

/* ------------------------------ accesibilidad ------------------------------
   El tema se apoya bastante en aparecer-al-scrollear y en fondos animados.
   Para quien pidió menos movimiento en su sistema, todo eso queda quieto y
   visible: sin esta regla, un elemento con `reveal` que nunca se anima queda
   invisible para siempre. */
@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1 !important;
    transform: none !important;
  }
  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}
