/* Plantilla de webs para gremios — hoja de estilo unica.
   Los colores salen de cliente.json, todo lo demas es fijo.

   Criterio de diseno, por si alguien viene a tocar esto dentro de un ano:
   la queja que origino esta version fue "se nota que esta hecha con IA". Los
   tics que delatan eso son concretos y aqui se evitan a proposito:

     - Nada de secciones alternando blanco y gris automaticamente. Hay UNA
       seccion oscura, elegida, y el resto va sobre papel.
     - Nada de redondeo blando ni sombras difusas en todo. Bordes secos.
     - Contraste tipografico de verdad: 900 contra 400, no "un poco mas grande".
     - Ritmo desigual: la galeria y la portada respiran mas que el resto.
     - Asimetria: la foto de portada se sale del contenedor, la primera foto de
       la galeria ocupa el cuadruple.

   Si vuelves a poner todo simetrico y redondeado, vuelve a parecer generada. */

/* ---------- Tipografia ----------
   Archivo, servida desde la propia web (ver fuentes/LEEME.txt: no usamos el CDN
   de Google por RGPD). Variable, asi que un solo fichero da del 400 al 900 y el
   contraste sale de ahi. */
@font-face{
  font-family:'Archivo';
  font-style:normal;
  font-weight:400 900;
  font-display:swap;
  src:url(fuentes/archivo-latin.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:'Archivo';
  font-style:normal;
  font-weight:400 900;
  font-display:swap;
  src:url(fuentes/archivo-latin-ext.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;
}

:root{
  --marca:#0e7490;
  --marca-oscura:#0a5566;
  --urgencia:#b45309;

  --tinta:#11161a;
  --tinta-media:#4b5560;
  --tinta-suave:#666f79;   /* 5,1:1 sobre blanco. El anterior (#727e8a)
                              daba 4,1 y aqui va texto pequeno */
  --papel:#ffffff;
  --papel-alt:#f2f4f6;
  --linea:#d7dee4;
  /* El borde de los campos del formulario va aparte de --linea, y no por gusto:
     --linea da 1,36:1 contra el papel y la norma pide 3:1 para el contorno de un
     control (WCAG 1.4.11). Con el borde de antes, en un movil a pleno sol no se
     veia donde habia que escribir. Este da 3,47:1. */
  --linea-campo:#7f8b99;
  --linea-fuerte:#11161a;
  --sombra:0 1px 2px rgba(15,25,35,.05), 0 14px 34px -22px rgba(15,25,35,.4);
  --radio:2px;              /* seco a proposito: el redondeo blando lee a SaaS */
  --ancho:70rem;
  --barra:4.5rem;           /* alto de la barra fija en movil */
  color-scheme:light;
}

*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0;
  font-family:'Archivo',-apple-system,BlinkMacSystemFont,"Segoe UI",Arial,sans-serif;
  font-size:17px;
  line-height:1.6;
  color:var(--tinta);
  background:var(--papel);
  -webkit-font-smoothing:antialiased;
  padding-bottom:var(--barra);
}
img{max-width:100%;display:block}
a{color:var(--marca)}

.envoltorio{max-width:var(--ancho);margin:0 auto;padding:0 1.1rem}

/* Contraste de escala real. El h1 es casi tres veces el cuerpo, y en 900. */
h1,h2,h3{margin:0 0 .6rem}
h1{
  font-size:clamp(2.5rem,8.5vw,4.6rem);
  font-weight:900;letter-spacing:-.038em;line-height:1.0;
  text-wrap:balance;
}
h2{
  font-size:clamp(1.75rem,5vw,2.7rem);
  font-weight:800;letter-spacing:-.032em;line-height:1.08;
}
h3{font-size:1.08rem;font-weight:700;letter-spacing:-.012em;line-height:1.25}
p{margin:0 0 1rem}

/* Ritmo desigual: la galeria y la portada mandan, el resto acompana. */
section{padding:3.4rem 0}
#trabajos{padding:4.4rem 0}

/* Una sola seccion oscura en toda la pagina, y es una decision, no un patron. */
.seccion-oscura{background:var(--tinta);color:#dde4ea}
.seccion-oscura h2{color:#fff}
.seccion-oscura .entradilla{color:#9dabb8}

/* ---------- Avisos de ejemplo y borrador ---------- */
.aviso-ejemplo{
  background:#3d2a05;color:#ffd77a;text-align:center;
  padding:.6rem 1rem;font-size:.86rem;font-weight:600;letter-spacing:.01em;
}
/* Borrador: color distinto al de ejemplo a proposito, para que de un vistazo se
   sepa si lo que estas mirando es una web ficticia o la de un cliente pendiente
   de dar el visto bueno. */
.aviso-borrador{
  background:#0d2b45;color:#9fd0ff;text-align:center;
  padding:.6rem 1rem;font-size:.86rem;font-weight:600;letter-spacing:.01em;
}

/* ---------- Cabecera ---------- */
.cabecera{
  position:sticky;top:0;z-index:40;background:var(--papel);
  border-bottom:1px solid var(--linea);
}
.cabecera .envoltorio{
  display:flex;align-items:center;justify-content:space-between;gap:1rem;
  min-height:3.7rem;
}
.logo{
  font-weight:900;font-size:1.1rem;letter-spacing:-.035em;
  text-decoration:none;color:var(--tinta);
}
.logo span{color:var(--marca)}
.nav{display:none;gap:1.5rem}
.nav a{color:var(--tinta-media);text-decoration:none;font-size:.94rem;font-weight:600}
.nav a:hover{color:var(--marca)}
.tel-cabecera{
  display:none;align-items:center;gap:.45rem;text-decoration:none;
  background:var(--marca);color:#fff;font-weight:800;font-size:.95rem;
  padding:.6rem 1.1rem;border-radius:var(--radio);white-space:nowrap;
  letter-spacing:-.01em;
}

/* ---------- Portada ----------
   Sin .envoltorio dentro: la foto tiene que poder llegar al borde de la
   pantalla. El texto lleva su propio padding alineado con el resto. */
.portada{display:grid;grid-template-columns:1fr;background:var(--papel)}
.portada-texto{
  padding:2.4rem 1.1rem 2.6rem;
  max-width:var(--ancho);width:100%;margin:0 auto;
}
.chapa{
  display:inline-flex;align-items:center;gap:.45rem;
  background:var(--urgencia);color:#fff;
  font-size:.78rem;font-weight:800;padding:.4rem .8rem;
  border-radius:var(--radio);margin-bottom:1.1rem;
  text-transform:uppercase;letter-spacing:.08em;
}
.entradilla{font-size:1.13rem;color:var(--tinta-media);max-width:46ch;margin-bottom:1.6rem}
.portada .entradilla{margin-top:1.1rem}

/* El telefono como elemento grafico, no como un boton mas. Quien entra en la web
   de un fontanero con una fuga no quiere leer: quiere llamar. */
.tel-grande{
  display:inline-flex;flex-direction:column;text-decoration:none;color:var(--tinta);
  border-left:5px solid var(--marca);padding:.1rem 0 .1rem 1rem;margin-bottom:.4rem;
}
.tel-grande span{
  font-size:.78rem;font-weight:800;text-transform:uppercase;letter-spacing:.11em;
  color:var(--tinta-suave);
}
.tel-grande strong{
  font-size:clamp(1.9rem,6.5vw,2.6rem);font-weight:900;
  letter-spacing:-.035em;line-height:1.1;
}
.tel-grande:hover strong{color:var(--marca)}

.botonera{display:flex;flex-wrap:wrap;gap:.7rem;align-items:center}
.boton{
  display:inline-flex;align-items:center;justify-content:center;gap:.55rem;
  padding:.95rem 1.5rem;border-radius:var(--radio);text-decoration:none;
  font-weight:800;font-size:1.02rem;letter-spacing:-.012em;
  border:2px solid transparent;cursor:pointer;
  transition:transform .12s ease, background-color .14s ease, color .14s ease;
}
.boton:active{transform:translateY(1px)}
.boton-principal{background:var(--marca);color:#fff}
/* Se oscurece con el color que ya trae el json de cada cliente, no con
   filter:brightness. El filtro sobre un color solido lo deslava en vez de
   oscurecerlo, y de paso se lleva por delante el suavizado del texto de encima. */
.boton-principal:hover{background:var(--marca-oscura)}
.boton-wa{background:#25d366;color:#0b2e18}
.boton-wa:hover{filter:brightness(1.05)}
.boton-linea{background:transparent;color:var(--tinta);border-color:var(--linea-fuerte)}
.boton-linea:hover{background:var(--tinta);color:#fff}

/* Foco visible. NO lo tenia ninguno: quien navega con teclado no sabia donde
   estaba, y el formulario es por donde entra el trabajo. Va con :focus-visible y
   no con :focus para que no aparezca al hacer clic con el raton, solo cuando de
   verdad hace falta. El outline-offset lo separa del boton para que se vea
   tambien sobre los de color solido. */
.boton:focus-visible{outline:3px solid var(--marca);outline-offset:3px}
.boton-principal:focus-visible{outline-color:var(--linea-fuerte)}

.confianza{
  display:flex;flex-wrap:wrap;gap:1.6rem;margin-top:1.8rem;
  padding-top:1.4rem;border-top:2px solid var(--tinta);
}
.confianza div{display:flex;flex-direction:column}
.confianza b{font-size:1.4rem;font-weight:900;letter-spacing:-.03em;line-height:1.1}
.confianza span{font-size:.78rem;color:var(--tinta-suave);text-transform:uppercase;letter-spacing:.09em;font-weight:600}

/* Dos arreglos que van juntos, y los dos vienen de envolver la imagen en
   <picture> para servir dos formatos:

   1. <picture> es display:inline y sin altura propia, asi que el height:100% de
      la imagen dejaba de resolverse contra nada. Como bloque, la cadena de
      alturas vuelve a funcionar.

   2. Un item de rejilla no se encoge por debajo del contenido salvo que se le
      diga (auto minimum). La imagen forzaba el ancho de la columna a su tamano
      real -1400 px- y la pagina entera se hacia mas ancha que la pantalla del
      movil: el texto y la barra de abajo salian cortados por la derecha. */
.portada > *{min-width:0}
/* overflow:hidden en la BASE, no solo en las variantes que lo tenian. El zoom
   "respirar" del final de la hoja escala la foto un 6% en TODAS las variantes,
   pero solo .v-clima y .v-escaparate la recortaban: en las webs de variante
   gremio la imagen escalada sobresalia de su contenedor y ensanchaba la pagina
   entera, asi que durante los 22 s que dura la animacion el movil se podia
   desplazar de lado y la barra de abajo salia cortada. Medido: 521 px de imagen
   en un viewport de 500.

   Es exactamente el fallo de c127cd9, que alli lo causaba el scale de GSAP y aqui
   el de CSS. La leccion es la misma y por eso se pone en la base: si algo escala
   la foto, su contenedor la recorta. */
.portada-foto{overflow:hidden}
.portada-foto picture{display:block;height:100%}
.portada-foto img{width:100%;aspect-ratio:4/3;object-fit:cover}

/* ---------- Servicios ---------- */
.rejilla{display:grid;gap:0;grid-template-columns:1fr;border-top:1px solid var(--linea)}
.tarjeta{
  background:transparent;border-bottom:1px solid var(--linea);
  padding:1.4rem 0;
}
.tarjeta h3{margin-bottom:.3rem}
.tarjeta p{margin:0;color:var(--tinta-media);font-size:.97rem}

/* ---------- Pasos ---------- */
.pasos{counter-reset:paso;display:grid;gap:1.6rem;grid-template-columns:1fr}
.paso{position:relative;padding-left:3.4rem}
.paso::before{
  counter-increment:paso;content:counter(paso);
  position:absolute;left:0;top:-.15rem;
  width:2.4rem;height:2.4rem;border-radius:var(--radio);
  background:var(--tinta);color:#fff;font-weight:900;font-size:1.1rem;
  display:flex;align-items:center;justify-content:center;
}
.paso p{margin:0;color:var(--tinta-media)}

/* ---------- Galeria ----------
   La primera foto ocupa el cuadruple. Es asimetria barata y es lo que mas aleja
   del aspecto de rejilla generada. En este oficio las fotos son el producto. */
.galeria{display:grid;gap:.4rem;grid-template-columns:repeat(2,1fr)}
.galeria a{display:block;overflow:hidden;background:var(--papel-alt);aspect-ratio:1/1}
.galeria a:first-child{grid-column:span 2;grid-row:span 2}
.galeria img{width:100%;height:100%;object-fit:cover;transition:transform .3s ease}
.galeria a:hover img{transform:scale(1.03)}

.visor{
  position:fixed;inset:0;z-index:90;background:rgba(10,14,18,.94);
  align-items:center;justify-content:center;padding:1.2rem;
  border:0;width:100%;height:100%;max-width:100%;max-height:100%;
}
/* Sin esto el dialog se veria abierto siempre: display:flex gana a
   dialog:not([open]){display:none} del navegador. */
.visor[open]{display:flex}
.visor::backdrop{background:rgba(10,14,18,.94)}
.visor img{max-width:100%;max-height:85vh;object-fit:contain}
.visor-cerrar{
  position:absolute;top:1rem;right:1rem;background:rgba(255,255,255,.14);
  color:#fff;border:0;width:2.6rem;height:2.6rem;border-radius:var(--radio);
  font-size:1.4rem;cursor:pointer;line-height:1;
}

/* ---------- Zona (la seccion oscura) ---------- */
.zonas{display:flex;flex-wrap:wrap;gap:.45rem;padding:0;margin:0;list-style:none}
.zonas li{
  background:transparent;border:1px solid #38454f;border-radius:var(--radio);
  padding:.45rem 1rem;font-size:.94rem;font-weight:600;color:#dde4ea;
}

/* ---------- Resenas ---------- */
#resenas{background:var(--papel-alt)}
.resena{
  background:var(--papel);border:1px solid var(--linea);border-radius:var(--radio);
  padding:1.4rem;
}
.resena blockquote{margin:0 0 .9rem;font-size:1.02rem}
.resena footer{font-size:.88rem;color:var(--tinta-suave);font-weight:700}
.estrellas{color:#e8a317;letter-spacing:.1em;font-size:.95rem;margin-bottom:.5rem}
#resenas .rejilla{border-top:0;gap:1rem}
#resenas .rejilla .resena{border-bottom:1px solid var(--linea)}

/* ---------- Formulario ----------
   Es por donde entra el trabajo, no un adorno del final de la pagina, y se cuida
   como tal. Dos de estos cambios no son estetica:

     - El borde de los campos usa --linea-campo (3:1 o mas) en vez de --linea
       (1,36:1). Ver el comentario de la variable arriba.
     - El foco visible de los botones y los campos, que esta con los botones. */
.caja-form{
  background:var(--papel);border:2px solid var(--tinta);border-radius:var(--radio);
  padding:1.5rem;
}
.campo{margin-bottom:1.15rem}
/* Versalitas espaciadas: el mismo registro que .pie h3 y .confianza span. No se
   inventa un estilo para el formulario, se usa el que ya tiene la casa. */
.campo label{
  display:block;font-weight:700;font-size:.78rem;margin-bottom:.5rem;
  text-transform:uppercase;letter-spacing:.09em;color:var(--tinta-media);
}
.campo input,.campo textarea{
  width:100%;padding:.95rem 1rem;font:inherit;font-size:1rem;
  border:1px solid var(--linea-campo);border-radius:var(--radio);
  background:var(--papel);color:var(--tinta);
  transition:border-color .14s ease;
}
.campo input:hover,.campo textarea:hover{border-color:var(--tinta-suave)}
.campo input:focus,.campo textarea:focus{border-color:var(--marca)}
.campo input:focus-visible,.campo textarea:focus-visible{
  outline:3px solid var(--marca);outline-offset:2px;
}
.campo input::placeholder,.campo textarea::placeholder{color:var(--tinta-suave);opacity:1}
.campo textarea{min-height:7.5rem;resize:vertical}
.campo small{display:block;color:var(--tinta-suave);font-size:.84rem;margin-top:.4rem}

/* El selector de fotos: se maquilla el control NATIVO en vez de esconderlo detras
   de una etiqueta bonita, que era la otra via. Escondiendolo se pierde el
   "2 archivos seleccionados" que escribe solo el navegador, y sin JavaScript no
   hay forma de recuperarlo -CSS no puede saber si un input de fichero lleva algo
   dentro-. En un formulario cuyo objetivo es que lleguen fotos, quedarse sin esa
   confirmacion es peor que un control feo.

   font:inherit es lo que arrastra tambien el texto del navegador a la tipografia
   de la web; sin el, "Ningun archivo seleccionado" sale en la fuente del sistema.
   El borde discontinuo es el gesto de "suelta algo aqui". */
.campo input[type=file]{
  font:inherit;font-size:.95rem;padding:.7rem;cursor:pointer;
  border-style:dashed;color:var(--tinta-media);
}
.campo input[type=file]::file-selector-button{
  font:inherit;font-weight:800;font-size:.88rem;
  margin-right:.85rem;padding:.55rem 1rem;cursor:pointer;
  border:2px solid var(--linea-fuerte);border-radius:var(--radio);
  background:transparent;color:var(--tinta);
  transition:background-color .14s ease, color .14s ease;
}
.campo input[type=file]:hover::file-selector-button{
  background:var(--tinta);color:var(--papel);
}

/* accent-color pinta la casilla del color de la marca sin maquetar nada a mano:
   sigue siendo el control del sistema, con su comportamiento y su accesibilidad
   intactos. Es una linea; hacerlo con un span y un pseudoelemento serian veinte y
   se romperia en algun navegador. */
.consentimiento{display:flex;gap:.7rem;align-items:flex-start;font-size:.88rem;color:var(--tinta-media)}
.consentimiento input{
  width:1.15rem;height:1.15rem;margin:.12rem 0 0;flex-shrink:0;
  accent-color:var(--marca);cursor:pointer;
}
/* Esto es una frase, no la etiqueta de un campo: se le quita el tratamiento de
   versalitas que llevan las demas. */
.consentimiento label{
  text-transform:none;letter-spacing:normal;font-size:.88rem;font-weight:400;
  color:var(--tinta-media);margin-bottom:0;cursor:pointer;
}
.caja-form .boton{width:100%;margin-top:.6rem;padding-top:1.05rem;padding-bottom:1.05rem}

/* ---------- Pie ---------- */
.pie{background:var(--tinta);color:#a9b6c2;padding:2.8rem 0 2rem;font-size:.95rem}
.pie a{color:#fff}
.pie h3{color:#fff;font-size:.8rem;margin-bottom:.7rem;text-transform:uppercase;letter-spacing:.09em}
.pie-rejilla{display:grid;gap:1.8rem;grid-template-columns:1fr}
.pie-legal{
  margin-top:2.2rem;padding-top:1.2rem;border-top:1px solid #29343d;
  font-size:.82rem;color:#7d8a96;display:flex;flex-wrap:wrap;gap:.4rem 1.2rem;
}

/* ---------- Barra fija de movil ---------- */
.barra{
  position:fixed;bottom:0;left:0;right:0;z-index:60;
  display:grid;grid-template-columns:1fr 1fr;gap:1px;
  background:var(--linea);border-top:1px solid var(--linea);
  padding-bottom:env(safe-area-inset-bottom);
}
.barra a{
  display:flex;align-items:center;justify-content:center;gap:.5rem;
  padding:1.05rem .5rem;text-decoration:none;font-weight:800;font-size:1.02rem;
}
.barra .accion{background:var(--marca);color:#fff}
.barra .wa{background:#25d366;color:#0b2e18}

/* ---------- Tablet ---------- */
@media (min-width:560px) and (max-width:819px){
  .rejilla{grid-template-columns:repeat(2,1fr);column-gap:2rem}
  .galeria{grid-template-columns:repeat(3,1fr)}
  .rejilla-2{display:grid;grid-template-columns:repeat(2,1fr);gap:1.6rem}
}

/* ---------- Escritorio ---------- */
@media (min-width:820px){
  body{padding-bottom:0}
  .barra{display:none}
  .nav{display:flex}
  .tel-cabecera{display:inline-flex}

  /* La foto se sale del contenedor y llega al borde derecho de la pantalla.
     El texto conserva la alineacion con el resto de la pagina gracias al
     max() del padding izquierdo. */
  .portada{grid-template-columns:1fr 1fr;align-items:stretch}
  .portada-texto{
    max-width:none;margin:0;
    padding:4.6rem 3.2rem 4.6rem max(1.1rem, calc((100vw - var(--ancho)) / 2));
    display:flex;flex-direction:column;justify-content:center;
  }
  .portada-foto{height:100%}
  .portada-foto img{height:100%;aspect-ratio:auto;min-height:34rem}

  .rejilla{grid-template-columns:repeat(3,1fr);column-gap:2.2rem}
  .pasos{grid-template-columns:repeat(3,1fr);gap:2.2rem}
  .galeria{grid-template-columns:repeat(4,1fr)}
  .pie-rejilla{grid-template-columns:repeat(3,1fr)}
  section{padding:5rem 0}
  #trabajos{padding:7rem 0}
  .rejilla-2{display:grid;grid-template-columns:1.05fr .95fr;gap:3rem;align-items:start}
}


/* ================== VARIANTE "CLIMA" ==================
   Aire acondicionado y calefaccion. No es un cambio de color: es otro registro,
   porque es otro negocio. El cliente de un fontanero tiene una averia y quiere
   llamar ya; el de un instalador de aire lleva semanas pensandoselo y se va a
   gastar varios miles de euros.

   De ahi las tres decisiones que cambian:
     - Portada tipo cartel, con el titular SOBRE la foto.
     - Titulares mas ligeros (700, no 900). Lo premium se lee ligero; el peso
       extremo lee a urgencia, que es justo lo que aqui no se vende.
     - Fondos con temperatura fria y mucho mas aire.

   Todo esto es CSS sobre la misma plantilla. No hay un segundo index.html.j2, y
   no lo tiene que haber: cada arreglo futuro se haria dos veces. */

.v-clima{
  /* Neutros sacados de la foto de portada, no elegidos a ojo: la habitacion sale
     en tonos 186-194, y el color de accion (#0e7490) es tono 191. Se usa 190,
     que armoniza con los dos. El tono medio de la imagen entera daba 164, pero
     eso lo arrastra la vegetacion del jardin, no la arquitectura.
     Contrastes comprobados: tinta 17,0:1 sobre blanco; tinta-media 7,1:1;
     tinta-suave 5,0:1; blanco sobre la seccion oscura 14,1:1. */
  --tinta:#131e20;
  --tinta-media:#495b5f;
  --tinta-suave:#607276;
  --papel-alt:#f2f5f5;
  --linea:#d4dee0;
  --linea-campo:#7d8b8f;   /* 3,52:1 sobre blanco */
  --linea-fuerte:#131e20;
  line-height:1.68;
}

/* --- Portada tipo cartel: foto de fondo, texto encima, abajo a la izquierda --- */
.v-clima .portada{grid-template-columns:1fr;min-height:74vh;align-items:end}
.v-clima .portada-texto,
.v-clima .portada-foto{grid-area:1/1}
/* overflow:hidden NO es decorativo: GSAP escala la foto un 12% para tener margen
   con el que hacer el parallax, y una imagen escalada sobresale de su contenedor.
   Sin recortarla, ensancha la pagina entera y en el movil el texto y la barra de
   abajo salen cortados por la derecha. */
.v-clima .portada-foto{height:100%;position:relative;overflow:hidden}
/* Encuadre centrado: cada imagen viene ya compuesta para su formato (la vertical
   para movil, la apaisada para escritorio), asi que no hay que forzar el recorte.
   Aqui hubo un object-position:10% 30% mientras una sola imagen servia los dos,
   porque centrada dejaba fuera dos tercios del aire acondicionado en movil. */
.v-clima .portada-foto img{
  width:100%;height:100%;aspect-ratio:auto;object-fit:cover;min-height:0;
}

/* El degradado no es decorativo: es lo unico que garantiza que el titular se lea
   sobre una foto cuyo contenido no controlamos. Sin esto, una imagen clara deja
   el texto blanco invisible. */
.v-clima .portada-foto::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,
    rgba(8,18,28,.12) 0%, rgba(8,18,28,.32) 45%, rgba(8,18,28,.84) 100%);
}

.v-clima .portada-texto{
  position:relative;z-index:2;color:#fff;
  padding:6rem 1.1rem 2.4rem;
  max-width:var(--ancho);margin:0 auto;width:100%;
  display:block;
}
.v-clima .portada-texto h1{
  font-weight:700;letter-spacing:-.028em;
  font-size:clamp(2.3rem,7.5vw,4.4rem);
  max-width:17ch;
  text-shadow:0 2px 26px rgba(8,18,28,.45);
}
.v-clima .portada .entradilla{color:#dbe6ee;max-width:44ch}
.v-clima .portada .confianza{border-top-color:rgba(255,255,255,.34)}
.v-clima .portada .confianza b{color:#fff}
.v-clima .portada .confianza span{color:#b6c6d3}
.v-clima .portada .boton-linea{color:#fff;border-color:rgba(255,255,255,.6)}
.v-clima .portada .boton-linea:hover{background:#fff;color:var(--tinta)}

/* --- Mas aire y titulares mas ligeros en el resto de la pagina --- */
.v-clima h2{font-weight:700;letter-spacing:-.024em}
.v-clima h3{font-weight:600}
.v-clima section{padding:4.4rem 0}
.v-clima .entradilla{max-width:42ch}
.v-clima .confianza b{font-weight:800}

/* La seccion oscura pasa de casi negro a azul profundo: mismo recurso, otra
   temperatura. */
.v-clima .seccion-oscura{background:#162f34}
.v-clima .zonas li{border-color:#31555b}
.v-clima .pie{background:#162f34}
.v-clima .pie-legal{border-top-color:#274a50}
.v-clima .paso::before{background:var(--marca);border-radius:50%}
.v-clima .caja-form{border:1px solid var(--linea);box-shadow:var(--sombra)}

@media (min-width:820px){
  .v-clima .portada{grid-template-columns:1fr;min-height:82vh}
  .v-clima .portada-texto{padding:8rem 1.1rem 3.6rem}
  .v-clima section{padding:6.4rem 0}
  .v-clima #trabajos{padding:8rem 0}
}


/* ================== VARIANTE "ESCAPARATE" ==================
   La segunda propuesta para el mismo instalador de aire. No existe porque haga
   falta otro oficio, sino porque a un cliente se le ensenan dos y elige: si solo
   ves una, la comparas con la que ya tienes en la cabeza.

   Frente a "clima", que es un cartel -foto a sangre y titular encima-, esta es
   de registro editorial. Lo que cambia, y por que:

     - Papel calido en vez de frio. El azul grisaceo de clima es tecnico; este
       tira a crema, que es donde vive la fotografia de interiores.
     - Portada partida y a toda altura, con el texto centrado sobre papel y la
       foto entera al lado. La foto no lleva texto encima, asi que se ve.
     - Secciones numeradas y un filete bajo cada titular. Es lo que da el aire de
       revista, y el filete ademas se dibuja al entrar.
     - Galeria a bandas de anchos distintos, no cuadricula.

   Y sobre todo: aqui GSAP anima de la cabecera al pie, no solo la portada. Es
   su argumento de venta, y por eso el json trae "animaciones": "gsap".

   Contrastes comprobados sobre el papel #fbf9f6: tinta 15,8:1; tinta-media
   7,0:1; tinta-suave 5,2:1; blanco sobre la seccion oscura 14,6:1. */

.v-escaparate{
  --tinta:#1b1815;
  --tinta-media:#57504a;
  --tinta-suave:#6b645c;
  --papel:#fbf9f6;
  --papel-alt:#f2ede5;
  --linea:#e2dad0;
  --linea-campo:#8d8073;   /* 3,65:1 sobre el papel calido */
  --linea-fuerte:#1b1815;
  --sombra:0 1px 2px rgba(27,24,21,.05), 0 16px 38px -26px rgba(27,24,21,.45);
  --ancho:74rem;
  line-height:1.7;
  counter-reset:seccion;
  background:var(--papel);
}

/* --- Cabecera: sin linea hasta que la portada se va ---
   La clase .compacta la pone GSAP (toggleClass). Sin JavaScript no llega nunca,
   y no pasa nada: se queda como esta, legible, con su fondo de papel. Por eso el
   estado de partida NO es transparente — sobre la foto de portada en movil no se
   leeria. */
.v-escaparate .cabecera{
  border-bottom-color:transparent;
  transition:border-color .3s ease, box-shadow .3s ease;
}
.v-escaparate .cabecera.compacta{
  border-bottom-color:var(--linea);
  box-shadow:0 12px 30px -26px rgba(27,24,21,.8);
}

/* --- Portada partida --- */
.v-escaparate .portada{background:var(--papel)}
/* En movil la foto va ARRIBA: es una portada de revista, se entra por la imagen.
   Con 4:5 en una pantalla de 390 el titular sigue entrando en el primer vistazo. */
.v-escaparate .portada-foto{order:-1;overflow:hidden}
/* El height:auto NO sobra. El <img> lleva width="1200" height="900" para que el
   navegador reserve el hueco antes de descargarla, y esos atributos entran como
   presentational hint: height queda en 900px, definida, y entonces el
   aspect-ratio no llega a calcular nada. La foto salia de 900 px de alto en el
   movil y dejaba el titular fuera de la pantalla. En la variante base no se veia
   porque 1200x900 ES el 4/3 que pedia su CSS: coincidian por casualidad.
   Cuadrada y no vertical, ademas, porque con 4:5 el titular se iba justo debajo
   del pliegue en una pantalla de 844 px de alto. */
.v-escaparate .portada-foto img{aspect-ratio:1/1;height:auto}
.v-escaparate .portada-texto{padding:2.6rem 1.1rem 2.8rem}

/* El filete de arriba es lo primero que se ve del texto, y marca el color de la
   marca sin tener que pintar un boton gigante. */
.v-escaparate .portada-texto::before{
  content:"";display:block;width:3.4rem;height:3px;
  background:var(--marca);margin-bottom:1.5rem;
}
.v-escaparate .portada-texto h1{
  font-weight:800;letter-spacing:-.035em;line-height:1.03;
  font-size:clamp(2.35rem,7vw,4.5rem);
  max-width:15ch;text-wrap:balance;
}
.v-escaparate .portada .entradilla{max-width:46ch;font-size:1.06rem}

/* Las palabras del titular las envuelve animacion.js para que asomen desde
   debajo de su linea. El padding/margin compensados dan sitio a las colas de la
   j y la g, que si no las corta el overflow:hidden. El hueco entre palabras NO
   se pone aqui: lo pone un espacio de verdad entre las cajas, para que el
   titular se pueda copiar y leer en voz alta. */
.v-escaparate .portada-texto h1 .palabra{
  display:inline-block;overflow:hidden;vertical-align:bottom;
  padding-bottom:.14em;margin-bottom:-.14em;
}
.v-escaparate .portada-texto h1 .palabra > span{display:inline-block}

/* --- Titulares numerados, con su filete --- */
.v-escaparate h2{font-weight:800;letter-spacing:-.03em}
.v-escaparate h3{font-weight:700}
.v-escaparate section h2{position:relative;padding-top:2.1rem}
.v-escaparate section h2::before{
  counter-increment:seccion;
  content:counter(seccion,decimal-leading-zero);
  position:absolute;top:0;left:0;
  font-size:.76rem;font-weight:800;letter-spacing:.2em;color:var(--marca);
}
.v-escaparate .seccion-oscura h2::before{color:#d9b98a}
/* El <i> lo crea animacion.js: sin JavaScript no existe, y no falta. Va en un
   elemento y no en un ::after porque GSAP no anima pseudoelementos. */
.v-escaparate h2 .filete{
  display:block;width:2.8rem;height:2px;margin-top:.85rem;
  background:var(--marca);transform-origin:left center;
}
.v-escaparate .seccion-oscura h2 .filete{background:#d9b98a}

.v-escaparate section{padding:4.6rem 0}
.v-escaparate .entradilla{max-width:44ch}

/* --- Servicios: filetes, no tarjetas --- */
.v-escaparate .tarjeta{padding:1.7rem 0}
.v-escaparate .tarjeta h3{margin-bottom:.45rem;font-size:1.08rem}

/* --- Pasos: circulos huecos ---
   Hubo aqui una linea que cosia los tres pasos y se quito. Por si alguien piensa
   en volver a ponerla, los tres motivos: con scrub solo se veia entera al final
   del recorrido y el resto del tiempo acababa en el aire; sobresalia casi una
   columna por detras del ultimo circulo; y obligaba a dos apanos, dar fondo de
   papel al h3 para que no le cruzara las letras, y leer el corte de 820 px desde
   el JavaScript para saber que eje estirar. Los circulos numerados marcan la
   secuencia de sobra. */
.v-escaparate .paso::before{
  background:var(--papel);color:var(--tinta);
  border:2px solid var(--tinta);border-radius:50%;
  font-size:1rem;
}

/* --- Galeria a bandas --- */
.v-escaparate .galeria{gap:.55rem}
.v-escaparate .galeria a:first-child{grid-row:auto;aspect-ratio:4/3}

/* --- La seccion oscura, en calido --- */
.v-escaparate .seccion-oscura{background:#211e1a;color:#e4ddd3}
.v-escaparate .seccion-oscura .entradilla{color:#aaa093}
.v-escaparate .zonas li{border-color:#443d34;color:#e4ddd3}
.v-escaparate .pie{background:#211e1a;color:#b3a99c}
.v-escaparate .pie-legal{border-top-color:#3a342c}
.v-escaparate #resenas{background:var(--papel-alt)}
.v-escaparate .caja-form{border:1px solid var(--linea);box-shadow:var(--sombra)}

/* El verde de WhatsApp, apagado. SOLO aqui: sobre el blanco frio de las demas
   variantes el #25d366 de la marca no desentona, y ese verde es lo unico que le
   dice al visitante que el boton abre WhatsApp -no lleva icono-. Sobre el papel
   crema chillaba. Este da 5,48:1 con el texto en blanco y se sigue leyendo verde
   de WhatsApp. El filter:none quita el brillo del hover de la hoja base, que
   ahora lo sustituye un color. */
.v-escaparate .boton-wa{background:#12793f;color:#fff}
.v-escaparate .boton-wa:hover{background:#0f6b3c;filter:none}
.v-escaparate .barra .wa{background:#12793f;color:#fff}

@media (min-width:820px){
  /* Reparto asimetrico: el texto pesa mas que la foto. Con 1fr 1fr, que es lo
     que hace la variante base, la portada queda partida por la mitad y eso lee a
     plantilla. */
  .v-escaparate .portada{grid-template-columns:1.12fr .88fr;min-height:min(88vh,46rem)}
  .v-escaparate .portada-foto{order:0;height:100%}
  .v-escaparate .portada-foto img{aspect-ratio:auto;height:100%;min-height:0}
  /* La sombra larga de escribir el padding de movil en atajo: al llevar dos
     clases le gana al de la variante base aunque este dentro de esta consulta,
     y el texto se quedaba pegado al borde izquierdo mientras el logo de la
     cabecera se alineaba con el contenedor. Se repite el max() a proposito. */
  .v-escaparate .portada-texto{
    padding:5.4rem 3.2rem 5.4rem max(1.1rem, calc((100vw - var(--ancho)) / 2));
  }
  .v-escaparate section{padding:6.6rem 0}
  .v-escaparate #trabajos{padding:8.5rem 0}

  /* Doce columnas para poder partir en dos bandas de anchos distintos: 7+5 y
     4+4+4. Es la asimetria que separa esto de una cuadricula.

     La altura la manda la rejilla (grid-auto-rows) y NO un aspect-ratio por
     foto. Con aspect-ratio, dos fotos de la misma banda pero de anchos distintos
     salen de alturas distintas y la banda queda con el borde de abajo dentado,
     que parece un fallo. Asi cada banda es recta y las dos bandas miden
     distinto, que es lo que se buscaba: 3 filas la de arriba, 2 la de abajo. */
  .v-escaparate .galeria{
    grid-template-columns:repeat(12,1fr);grid-auto-rows:8rem;gap:.7rem;
  }
  .v-escaparate .galeria a{aspect-ratio:auto;grid-column:span 4;grid-row:span 2}
  .v-escaparate .galeria a:first-child{grid-column:span 7;grid-row:span 3}
  .v-escaparate .galeria a:nth-child(2){grid-column:span 5;grid-row:span 3}
}

/* La linea de lectura, arriba del todo. La crea animacion.js y por eso no hay
   nada que esconder sin JavaScript: si no llega, no existe. */
.progreso{
  position:fixed;top:0;left:0;right:0;height:2px;z-index:60;
  background:var(--marca);transform:scaleX(0);transform-origin:left center;
  pointer-events:none;
}


/* ================== MOVIMIENTO ==================
   Sin librerias. Se valoro GSAP y salian 39 KB con ScrollTrigger: cuatro veces
   todo el HTML y el CSS de esta web juntos. Con IntersectionObserver y unas
   transiciones se consigue casi lo mismo por medio KB.

   REGLA QUE MANDA SOBRE TODO LO DEMAS: el contenido tiene que verse aunque el
   JavaScript no llegue nunca. Por eso se oculta SOLO dentro de .con-js, clase
   que anade un script minimo del <head>. Sin JS, no se oculta nada.

   Se anima opacity y transform, que el navegador resuelve en la tarjeta grafica.
   Animar top o height obligaria a recalcular la maquetacion en cada fotograma. */
.con-js .revelar{
  opacity:0;transform:translateY(16px);
  transition:opacity .7s cubic-bezier(.22,.61,.36,1),
             transform .7s cubic-bezier(.22,.61,.36,1);
}
.con-js .revelar.dentro{opacity:1;transform:none}

/* Escalonado entre hermanos: las tarjetas no entran todas de golpe. */
.con-js .revelar :is(.rejilla,.pasos,.galeria) > *{
  opacity:0;transform:translateY(14px);
  transition:opacity .55s ease-out, transform .55s ease-out;
}
.con-js .revelar.dentro :is(.rejilla,.pasos,.galeria) > *{opacity:1;transform:none}
.con-js .revelar.dentro :is(.rejilla,.pasos,.galeria) > *:nth-child(2){transition-delay:.06s}
.con-js .revelar.dentro :is(.rejilla,.pasos,.galeria) > *:nth-child(3){transition-delay:.12s}
.con-js .revelar.dentro :is(.rejilla,.pasos,.galeria) > *:nth-child(4){transition-delay:.18s}
.con-js .revelar.dentro :is(.rejilla,.pasos,.galeria) > *:nth-child(5){transition-delay:.24s}
.con-js .revelar.dentro :is(.rejilla,.pasos,.galeria) > *:nth-child(6){transition-delay:.30s}
.con-js .revelar.dentro :is(.rejilla,.pasos,.galeria) > *:nth-child(7){transition-delay:.36s}
.con-js .revelar.dentro :is(.rejilla,.pasos,.galeria) > *:nth-child(n+8){transition-delay:.42s}

/* La portada respira: un zoom lentisimo, una sola vez. Es la diferencia entre
   una foto pegada y una portada viva, y no cuesta un byte de JavaScript. */
@keyframes respirar{from{transform:scale(1.06)}to{transform:scale(1)}}
.portada-foto img{animation:respirar 22s cubic-bezier(.2,.5,.3,1) both}

/* Elevacion minima al pasar por encima de los botones. */
.boton{transition:transform .16s ease, background-color .16s ease, color .16s ease}
.boton-principal:hover,.boton-wa:hover{transform:translateY(-1px)}

/* Movimiento reducido: quieta y COMPLETA. Sin la segunda regla, quitar las
   transiciones dejaria .revelar en opacity:0 para siempre — la pagina se veria
   quieta y en blanco, que es peor que animada. */
/* Cuando anima GSAP, la libreria escribe opacity y transform en linea en cada
   fotograma. Dejar ademas una transition de CSS haria que el navegador volviera a
   interpolar cada una de esas escrituras: la animacion iria a tirones. Y el zoom
   de la portada lo sustituye el parallax, asi que se apaga.

   Ojo: aqui NO se revela nada. Si GSAP no llega, quien revela es el arranque de
   index.html.j2 anadiendo .dentro, que el CSS sigue respetando. */
.con-gsap .revelar,
.con-gsap .revelar :is(.rejilla,.pasos,.galeria) > *{transition:none}
.con-gsap .portada-foto img{animation:none}
/* Y por el MISMO motivo, las fotos de la galeria de escaparate: ahi GSAP les
   escribe el transform en cada fotograma para el parallax, y la transition del
   zoom al pasar por encima haria que el navegador reinterpolara cada escritura.
   Se acota a escaparate porque es la unica variante que anima esas fotos: en
   clima la transition es el zoom del hover y quitarla lo dejaria a saltos.
   Ojo con los dos selectores: .con-gsap va en el <html> y .v-escaparate en el
   <body>, asi que no se pueden juntar. */
.con-gsap .v-escaparate .galeria img{transition:none}

@media (prefers-reduced-motion:reduce){
  *{transition:none!important;animation:none!important;scroll-behavior:auto!important}
  .con-js .revelar,
  .con-js .revelar :is(.rejilla,.pasos,.galeria) > *{opacity:1!important;transform:none!important}
}
