/* Sistema de diseno de Servipuertas. Editorial y sobrio: mucho blanco,
   tipografia grande, foto protagonista, un solo acento.
   Deliberadamente distinto de las webs hermanas: ni topbar de color, ni
   tarjetas con icono redondo, ni carrusel de testimonios, ni barra naranja. */
:root {
    /* Paleta SACADA DEL LOGO REAL, no inventada: azul marino #001860 (26,7 %
       de la tinta del logotipo) y cian #18C0F0 (5,1 %), medidos por muestreo
       de pixeles sobre el fichero descargado de la web viva. Lo que separa
       esta web de las hermanas es la maquetacion editorial, no el color. */
    --ink: #14120F;
    --ink-soft: #56524D;
    --paper: #FFFFFF;
    --paper-warm: #F7F7F9;
    /* Filete decorativo. Solo para separadores: no delimita ningun control,
       asi que no le aplica el 3:1 de WCAG 1.4.11. */
    --line: #E3E3E7;
    /* Filete que SI delimita un control (el borde de .btn--ghost y el de los
       campos del formulario). Contra los DOS fondos del sitio, medido en la
       Tarea 17 con la formula de luminancia de WCAG:
         sobre --paper (#FFFFFF): 3,59:1
         sobre --paper-warm (#F7F7F9): 3,36:1  <- el caso que manda
       El segundo es el que hay que mirar, no el primero: .btn--ghost vive
       dentro de contact_section(), que es una .section--warm. 3,36:1 pasa el
       3:1 de WCAG 1.4.11, pero con poco margen: aclarar este gris aunque sea
       un par de pasos lo tumba. */
    --line-strong: #85878C;
    /* Azul marino del logo: 16,16:1 sobre blanco. Vale para texto, enlaces y
       boton con texto blanco encima. */
    --accent: #001860;
    /* Para el hover se ACLARA, no se oscurece: #001860 ya esta casi en negro
       y oscurecerlo no se distinguiria. 9,90:1 con texto blanco. */
    --accent-hover: #103A9E;
    /* Cian del logo: 2,13:1 sobre blanco, asi que NO vale para texto ni para
       bordes sobre fondo claro. Solo sobre el azul marino, donde da 7,57:1. */
    --accent-cyan: #18C0F0;

    --measure: 68ch;      /* ancho maximo de una columna de texto legible */
    --page: 1180px;
    --step: 8px;
}

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

body {
    margin: 0;
    background: var(--paper);
    color: var(--ink);
    font: 400 18px/1.65 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
    font-family: "Source Serif 4", Georgia, "Times New Roman", serif;
    font-weight: 400;
    line-height: 1.15;
    letter-spacing: -0.01em;
    margin: 0 0 calc(var(--step) * 2);
}

h1 { font-size: clamp(2.25rem, 5vw, 3.5rem); }
h2 { font-size: clamp(1.75rem, 3.5vw, 2.5rem); }
h3 { font-size: 1.35rem; }

p { margin: 0 0 calc(var(--step) * 2); max-width: var(--measure); }

a { color: var(--accent); text-underline-offset: 3px; }
a:hover { color: var(--accent-hover); }

/* <code> aparece en 3 sitios del sitio entero, los tres en la politica de
   cookies (nombres de claves guardadas dentro de _gcl_ls). Sin regla, el
   navegador lo pinta con su monospace por defecto, mas grande de la cuenta
   al lado del texto. NO se toca el color: hereda --ink sobre --paper, el
   mismo par que ya se midio en el barrido de contraste. Unica excepcion a
   "no se toca el CSS" en la ronda de arreglo 3. */
code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.9em;
}

.wrap { max-width: var(--page); margin: 0 auto; padding: 0 calc(var(--step) * 3); }
.section { padding: calc(var(--step) * 12) 0; }
.section--warm { background: var(--paper-warm); }

/* Banda de acento. En el CUERPO de una pagina solo la usa la portada, en "Por
   que cuesta mas": es el unico argumento de la web que justifica el precio, y
   una sola banda de color le da un ancla a una maquetacion que por lo demas es
   blanco y gris. Sigue siendo una por pagina.
   (El bloque de contacto del pie tambien es azul marino desde que dejo de ser
   gris, pero no usa esta clase ni cuenta como banda de cuerpo: es el cierre y
   sale en las 72 paginas. Su regla vive en .contact-section.)
   Contrastes sobre #001860, medidos con la formula de luminancia de WCAG:
     #FFFFFF (texto y enlaces) .......... 16,16:1  (WCAG 1.4.3 pide 4,5:1)
     #18C0F0 (filete del .argument) ...... 7,57:1  (elemento no textual, 3:1)
   El cian NO se usa para texto largo aqui aunque pase: sobre blanco cae a
   2,13:1 y basta con que alguien mueva este bloque a una seccion clara para
   romperlo. Enlaces en blanco subrayado, que no depende del color. */
.section--accent {
    background: var(--accent);
    color: #FFFFFF;
}
.section--accent h2 { color: #FFFFFF; }
.section--accent .argument { border-left-color: var(--accent-cyan); }
.section--accent a {
    color: #FFFFFF;
    text-decoration: underline;
    text-underline-offset: 3px;
}
.section--accent a:hover { text-decoration-thickness: 2px; }


/* Boton unico. No hay variantes de color: uno primario solido y uno de texto. */
.btn {
    display: inline-flex; align-items: center; gap: var(--step);
    padding: 14px 28px;
    background: var(--accent); color: #FFFFFF;
    border: 1px solid var(--accent); border-radius: 2px;
    font-weight: 600; text-decoration: none;
}
.btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #FFFFFF; }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line-strong); }
.btn--ghost:hover { background: var(--paper-warm); color: var(--ink); border-color: var(--ink); }

/* Foto a sangre: sin marco, sin sombra, sin esquinas redondeadas. */
.figure { margin: 0; }
.figure img { display: block; width: 100%; height: auto; }
.figure figcaption {
    margin-top: var(--step);
    color: var(--ink-soft); font-size: 0.9rem;
}

.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* --- Cabecera ------------------------------------------------------------ */
.site-header {
    border-bottom: 1px solid var(--line);
    background: var(--paper);
}
.site-header__inner {
    display: flex;
    align-items: center;
    gap: calc(var(--step) * 4);
    padding: calc(var(--step) * 2) 0;
}
.site-header__logo { display: inline-flex; align-items: center; flex-shrink: 0; }
.site-header__logo img { display: block; height: 34px; width: auto; }

.site-nav { flex: 1 1 auto; }
.site-nav ul {
    display: flex;
    flex-wrap: wrap;
    gap: calc(var(--step) * 3);
    margin: 0;
    padding: 0;
    list-style: none;
}
.site-nav a {
    color: var(--ink);
    text-decoration: none;
    font-weight: 600;
    font-size: 0.95rem;
}
.site-nav a:hover { color: var(--accent); }

.site-header__cta { flex-shrink: 0; white-space: nowrap; }

/* Icono de hamburguesa dibujado con box-shadow (tres barras) en --ink-soft:
   7,76:1 sobre blanco, muy por encima del 3:1 que pide un elemento no
   textual, y es el icono lo que identifica el control.

   El borde usa --line-strong y no --line. Con --line (#E3E3E7 sobre el
   blanco de .site-header) el par daba 1,28:1 y contradecia el contrato que
   el propio token declara doce lineas mas arriba: "Solo para separadores: no
   delimita ningun control". No era incumplimiento de WCAG 1.4.11 -el borde
   era redundante, el icono ya aportaba el contraste-, pero /accesibilidad/
   publica el minimo no textual medido del sitio y una pagina de
   accesibilidad vale lo que valgan sus cifras: un borde de 1,28:1 alrededor
   de un boton se refuta en treinta segundos. Con --line-strong (#85878C) el
   par es 3,59:1 sobre blanco, que queda por encima del minimo publicado
   (3,36:1, el de .btn--ghost sobre .section--warm), asi que esa cifra sigue
   siendo el minimo del sitio y no cambia. */
.site-nav__toggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    background: transparent;
    border: 1px solid var(--line-strong);
    border-radius: 2px;
    padding: 0;
    cursor: pointer;
}
.site-nav__toggle::before {
    content: "";
    width: 18px;
    height: 2px;
    background: var(--ink-soft);
    box-shadow: 0 6px 0 var(--ink-soft), 0 -6px 0 var(--ink-soft);
}

@media (max-width: 860px) {
    .site-nav { display: none; }
    .site-nav--open {
        display: block;
        position: absolute;
        top: 100%; left: 0; right: 0;
        background: var(--paper);
        border-bottom: 1px solid var(--line);
        padding: calc(var(--step) * 2) calc(var(--step) * 3);
    }
    .site-nav--open ul { flex-direction: column; gap: var(--step); }
    .site-header__inner { position: relative; }
    .site-nav__toggle { display: inline-flex; }
}

/* --- Pie ------------------------------------------------------------------ */
.site-footer {
    background: var(--paper-warm);
    border-top: 1px solid var(--line);
    padding: calc(var(--step) * 8) 0 calc(var(--step) * 4);
    color: var(--ink-soft);
    font-size: 0.95rem;
}
.site-footer a { color: var(--ink-soft); }
.site-footer a:hover { color: var(--accent); }
.site-footer__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: calc(var(--step) * 4);
    margin-bottom: calc(var(--step) * 4);
}
.site-footer__grid h3 {
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    font-size: 0.9rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ink);
    margin-bottom: var(--step);
}
.site-footer__grid ul { list-style: none; margin: 0; padding: 0; }
.site-footer__grid li { margin-bottom: calc(var(--step) / 2); }

/* Las 36 zonas, agrupadas por comarca y plegadas con <details>/<summary>
   nativo (Tarea 16): mecanismo, no maquetacion fina. Los enlaces quedan en
   el HTML servido este el grupo abierto o cerrado. */
.site-footer__zonas {
    padding-top: calc(var(--step) * 3);
    border-top: 1px solid var(--line);
}
/* El desplegable es ahora el bloque entero, no cada comarca. En movil esto es
   la diferencia entre una fila y dieciocho antes del aviso legal.
   El area de pulsacion del summary supera los 44 px de alto que pide WCAG
   2.5.5 gracias al padding: en un pie, con el pulgar, ese es el criterio que
   manda. */
.site-footer__zonas > summary {
    cursor: pointer;
    display: flex;
    align-items: baseline;
    gap: var(--step);
    padding: calc(var(--step) * 1.5) 0;
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    color: var(--ink);
}
.site-footer__zonas-label {
    font-size: 0.9rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 600;
}
.site-footer__zonas-count { font-size: 0.85rem; color: var(--ink-soft); }
.site-footer__zonas[open] > summary { margin-bottom: var(--step); }
.footer-zonas {
    columns: 4;
    column-gap: calc(var(--step) * 4);
}
.footer-zonas__group {
    break-inside: avoid;
    margin-bottom: calc(var(--step) * 2);
}
.footer-zonas__group h4 {
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--ink);
    margin: 0 0 calc(var(--step) / 2) 0;
}
.footer-zonas__group ul { list-style: none; margin: 0; padding: 0 0 0 var(--step); }
.footer-zonas__group li { margin-bottom: calc(var(--step) / 2); }

@media (max-width: 860px) {
    .footer-zonas { columns: 2; }
}
@media (max-width: 560px) {
    .footer-zonas { columns: 1; }
}

/* --- Formulario de contacto ------------------------------------------------
   Rojo de error #B3261E: 6,54:1 sobre blanco, por encima del 4,5:1 de texto
   y del 3:1 de bordes de control (WCAG 1.4.3 y 1.4.11). */
:root {
    --error: #B3261E;
}

/* Fondo azul marino. Motivo en includes/contact-section.php: en gris se
   pegaba a la seccion de encima en 27 de las 72 paginas, y en blanco se habria
   pegado en las otras 45.
   OJO AL ALCANCE: el blanco se aplica a .contact-section__intro, NO a la
   seccion entera. El formulario esta dentro de .contact-form-card, que es
   blanca, y ahi dentro hay texto oscuro, un boton y el enlace a la politica de
   privacidad. Una regla de color sobre .contact-section los habria dejado en
   blanco sobre blanco. Contrastes sobre #001860:
     texto y titulo en #FFFFFF ......... 16,16:1  (1.4.3 pide 4,5:1)
     borde del boton en #FFFFFF ........ 16,16:1  (1.4.11 pide 3:1)
   El borde por defecto de .btn--ghost es --line-strong (#85878C) y sobre este
   azul da 4,50:1, o sea que PASARIA de sobra: se cambia a blanco por criterio,
   no por accesibilidad. El texto del boton tiene que ser blanco a la fuerza, y
   un borde gris junto a una etiqueta blanca se lee como boton desactivado. */
.contact-section { background: var(--accent); }
.contact-section__inner {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    gap: calc(var(--step) * 8);
    align-items: start;
}
.contact-section__intro { color: #FFFFFF; }
.contact-section__intro h2 { color: #FFFFFF; }
.contact-section__intro p { max-width: none; }
.contact-section__alt { margin-top: calc(var(--step) * 3); }
.contact-section__alt .btn--ghost {
    color: #FFFFFF;
    border-color: #FFFFFF;
}
.contact-section__alt .btn--ghost:hover {
    background: #FFFFFF;
    color: var(--accent);
    border-color: #FFFFFF;
}

.contact-form-card {
    background: var(--paper);
    border: 1px solid var(--line);
    padding: calc(var(--step) * 5);
}

.contact-form__row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: calc(var(--step) * 3);
}

.contact-form__field { margin-bottom: calc(var(--step) * 3); }
.contact-form__field label {
    display: block;
    font-weight: 600;
    font-size: 0.9rem;
    margin-bottom: calc(var(--step) / 2);
}

.contact-form__input {
    display: block;
    width: 100%;
    padding: 12px 14px;
    font: inherit;
    color: var(--ink);
    background: var(--paper);
    /* --line-strong: 3,59:1 sobre blanco, por encima del 3:1 de un borde de
       control (WCAG 1.4.11). Misma cifra que en las otras dos anotaciones de
       este mismo par en el fichero; aqui ponia 3,60 por redondeo. */
    border: 1px solid var(--line-strong);
    border-radius: 2px;
}
.contact-form__textarea { resize: vertical; min-height: 7.5em; }
.contact-form__input:focus {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
    border-color: var(--accent);
}
.contact-form__field--invalid .contact-form__input { border-color: var(--error); }
.contact-form__field__error { color: var(--error); font-size: 0.85rem; margin-top: calc(var(--step) / 2); }

/* Honeypot: oculto a la vista y, por el aria-hidden del contenedor (en el
   PHP), tambien al lector de pantalla. tabindex="-1" en el input lo saca
   ademas del orden de tabulacion. Solo lo "ve" un bot que rellena por
   nombre de campo sin renderizar CSS. */
.contact-form__honeypot {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
}

.contact-form__status {
    margin: 0 0 calc(var(--step) * 2);
    font-weight: 600;
    min-height: 1.5em;
}
.contact-form__status:empty { margin: 0; min-height: 0; }
.contact-form__status--error { color: var(--error); }
.contact-form__status--ok { color: var(--ink-soft); }

.contact-form__submit { width: 100%; justify-content: center; }

.contact-form__legal {
    margin: calc(var(--step) * 2) 0 0;
    font-size: 0.85rem;
    color: var(--ink-soft);
    max-width: none;
}

.contact-form__success {
    text-align: center;
    padding: calc(var(--step) * 6) calc(var(--step) * 4);
    background: var(--paper);
    border: 1px solid var(--line);
}
.contact-form__success h3 { margin-bottom: var(--step); }
.contact-form__success p { max-width: none; margin: 0; }

@media (max-width: 860px) {
    .contact-section__inner { grid-template-columns: 1fr; }
    .contact-form__row { grid-template-columns: 1fr; }
}

/* --- Portada ---------------------------------------------------------------
   Foto a sangre con texto encima. El contraste NO puede depender de lo que
   haya en la fotografia de fondo, asi que se calcula contra el PEOR CASO
   posible: un pixel blanco puro debajo del velo. Contra blanco, texto blanco:
     velo 0,88 -> 11,72:1     velo 0,70 -> 6,39:1
     velo 0,80 ->  9,00:1     velo 0,65 -> 5,39:1
     velo 0,75 ->  7,58:1     velo 0,60 -> 4,58:1   <- el limite real
   Estaba en 0,88, que sobra por mucho y deja pasar solo el 12 % de la
   fotografia: a ese nivel no se distinguia que hubiera una puerta detras.
   Ahora va PLANO al 0,65 -> 5,39:1 contra blanco puro, y pasa el 35 % de la
   foto en vez del 12 %.

   Plano y no un degradado lateral, que era lo primero que se probo: el texto
   del hero NO esta alineado a la izquierda, esta CENTRADO. '.hero__content'
   es flex y '.wrap' lleva 'margin: 0 auto', asi que el bloque se centra y
   ocupa del 29 % al 69 % del ancho (medido, no supuesto). Justo encima de la
   puerta, que en 'tarragona-4' cae en el centro del encuadre. Un degradado
   que oscurezca un lado tapa media puerta y deja la otra media del texto sin
   proteger. Si algun dia el texto se alinea a la izquierda de verdad, un
   degradado vuelve a tener sentido; mientras este centrado, no. */
.hero { position: relative; overflow: hidden; }
.hero__media { margin: 0; }
.hero__media img {
    display: block;
    width: 100%;
    height: min(80vh, 620px);
    object-fit: cover;
}
.hero__scrim {
    position: absolute;
    inset: 0;
    background: rgba(0, 24, 96, 0.65);
}
.hero__content {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
}
.hero__content .wrap { color: #FFFFFF; }
.hero__content h1 { color: #FFFFFF; max-width: 18ch; }
.hero__content p { color: #FFFFFF; max-width: 42ch; }
.hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: calc(var(--step) * 2);
    margin-top: calc(var(--step) * 3);
}
/* Boton fantasma sobre fondo oscuro: blanco sobre blanco/transparente, no la
   version --ink por defecto de .btn--ghost (seria casi negro sobre casi
   negro). Mismo peor caso de arriba: >= 11,7:1. */
.hero__actions .btn--ghost { background: transparent; color: #FFFFFF; border-color: #FFFFFF; }
.hero__actions .btn--ghost:hover { background: rgba(255, 255, 255, 0.15); color: #FFFFFF; border-color: #FFFFFF; }

/* Que instalamos: rejilla con foto. Antes era una lista de texto; se cambio
   porque cuatro gamas en prosa no se distinguen de un indice, y es justo donde
   la competencia local (irisal.com) sale ganando.
   Toda la tarjeta es el enlace, asi que su borde SI delimita un control y le
   toca el 3:1 de WCAG 1.4.11: --line-strong (3,59:1 sobre blanco) y no --line
   (1,28:1), que es solo decorativo.
   El "Ver ... →" va aria-hidden: es reclamo visual, y el nombre accesible del
   enlace ya lo da el nombre de la gama; sin eso un lector de pantalla lee dos
   veces lo mismo en cada tarjeta. */
.service-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
    gap: calc(var(--step) * 3);
}
.service-list__item { display: flex; }
.service-card {
    display: flex;
    flex-direction: column;
    width: 100%;
    text-decoration: none;
    color: var(--ink);
    border: 1px solid var(--line-strong);
    border-radius: 8px;
    overflow: hidden;
    background: var(--paper);
}
.service-card:hover { border-color: var(--accent); color: var(--ink); }
.service-card__media { display: block; }
.service-card__media img {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
}
.service-card__cuerpo {
    display: flex;
    flex-direction: column;
    gap: calc(var(--step) / 2);
    padding: calc(var(--step) * 2);
    flex: 1;
}
.service-card__nombre {
    font-family: "Source Serif 4", Georgia, "Times New Roman", serif;
    font-size: 1.25rem;
    line-height: 1.2;
}
.service-card__frase { color: var(--ink-soft); font-size: 0.9rem; flex: 1; }
.service-card__mas { color: var(--accent); font-weight: 600; font-size: 0.9rem; }

/* Las gamas sin foto propia (interiores y trastero: no existe ni una foto de
   obra de esas dos). En vez de un hueco o de una foto prestada, la tarjeta va
   entera en azul marino: distinta a proposito, no rota. Blanco sobre --accent,
   16,16:1. */
.service-list__item--sin-foto .service-card {
    background: var(--accent);
    border-color: var(--accent);
    color: #FFFFFF;
}
.service-list__item--sin-foto .service-card__frase,
.service-list__item--sin-foto .service-card__mas { color: #FFFFFF; }
.service-list__item--sin-foto .service-card:hover { border-color: #FFFFFF; color: #FFFFFF; }

/* Bloque de argumento (blindada/acorazada, por que cuesta mas): barra de
   acento a la izquierda para marcarlo como lo mas importante de la pagina,
   no una caja con sombra. */
.argument { border-left: 4px solid var(--accent); padding-left: calc(var(--step) * 4); }

/* Rejilla de fotos reales: relacion 3:4 fija recortada con object-fit, sin
   depender de las dimensiones reales (variables foto a foto). */
.photo-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: calc(var(--step) * 3);
}
.photo-grid .figure img { aspect-ratio: 3 / 4; height: auto; object-fit: cover; }

/* --- Resenas de Google -----------------------------------------------------
   Tarjeta al estilo de las de Google: avatar con la inicial, nombre y fecha
   arriba, estrellas debajo y el texto al final, en cuerpo pequeno.

   EL AMARILLO DE GOOGLE NO SE PUEDE USAR. El suyo exacto es #FBBC04 y da
   1,71:1 sobre blanco; las estrellas transmiten la nota, asi que son
   contenido no textual y les aplica el 3:1 de WCAG 1.4.11. Medidos:
     #FBBC04 (el de Google) .. 1,71:1  NO      #B8860B (darkgoldenrod) 3,25:1
     #F9AB00 ................. 1,93:1  NO      #A16207 (el elegido) .. 4,92:1
   Se usa #A16207: es el ambar mas oscuro que sigue leyendose como dorado y
   deja margen de verdad, no el 3,25:1 justo de darkgoldenrod. Y ademas cada
   tarjeta lleva un .sr-only con "N de 5 estrellas", porque un lector de
   pantalla no deberia tener que deletrear cinco simbolos.

   El borde de la tarjeta es --line (decorativo, 1,28:1) y es legitimo: la
   tarjeta no es un enlace ni un control, solo agrupa. */
:root { --estrella: #A16207; }

.resenas__intro { color: var(--ink-soft); max-width: 70ch; }
/* UNA SOLA FILA, y en movil tambien. Cinco tarjetas no caben a lo ancho de un
   movil, asi que la fila se desplaza en horizontal con ajuste por tarjeta:
   en escritorio entran las cinco de golpe y en movil se pasan con el dedo.
   Asi la seccion ocupa una franja, no medio scroll.
   Antes esto era una rejilla de 3+2 que ocupaba 504 px de alto solo de
   tarjetas. */
.resenas {
    list-style: none;
    margin: calc(var(--step) * 4) 0 0 0;
    padding: 0 0 var(--step) 0;
    display: flex;
    gap: var(--step);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    /* Que el foco del teclado no quede pegado al borde al desplazarse. */
    scroll-padding-left: var(--step);
    /* Las tarjetas se estiran a la altura de la mas alta de la fila, que es
       lo que deja los bordes cuadrados. Con el texto recortado a 4 lineas esa
       altura ya no se dispara. */
    align-items: stretch;
}
.resena {
    scroll-snap-align: start;
    /* Ancho fijo: sin esto flex las encoge de forma desigual segun el texto.
       En escritorio 1fr de cinco (~215px) entra en el ancho de pagina; en
       pantallas estrechas se fija a 78vw para que se vea media tarjeta
       siguiente y se entienda que la fila se desliza. */
    flex: 0 0 auto;
    width: clamp(200px, calc((100% - var(--step) * 4) / 5), 240px);
}
@media (max-width: 900px) {
    .resena { width: min(78vw, 280px); }
}
.resena figure {
    height: 100%;
    margin: 0;
    padding: calc(var(--step) * 1.5);
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 8px;
}
.resena__cab {
    display: flex;
    align-items: center;
    gap: calc(var(--step) / 1.5);
}
.resena__avatar {
    flex: 0 0 auto;
    width: 30px; height: 30px;
    border-radius: 50%;
    display: grid; place-items: center;
    background: var(--accent); color: #FFFFFF;
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    font-size: 0.85rem; font-weight: 600;
    line-height: 1;
}
.resena__quien { display: flex; flex-direction: column; min-width: 0; }
.resena__autor {
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    font-size: 0.82rem; font-weight: 600; color: var(--ink);
    /* El nombre no parte la tarjeta: si no cabe, se corta con puntos. */
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.resena__fecha { font-size: 0.75rem; color: var(--ink-soft); }
.resena__estrellas {
    margin: calc(var(--step) / 1.5) 0 calc(var(--step) / 2) 0;
    color: var(--estrella);
    letter-spacing: 0.08em;
    font-size: 0.85rem;
    line-height: 1;
}
/* Recortado a 4 lineas. El texto COMPLETO sigue en el HTML: el recorte es
   solo visual, asi que un lector de pantalla y un buscador lo leen entero y
   no se esconde nada. La entradilla avisa de que las largas se ven
   recortadas y enlaza al perfil de Google para leerlas enteras. */
.resena blockquote {
    margin: 0;
    font-size: 0.82rem;
    line-height: 1.45;
    color: var(--ink-soft);
    display: -webkit-box;
    -webkit-line-clamp: 4;
    line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Rejilla de zonas con cifra real. Toda la tarjeta es el enlace, asi que su
   borde delimita un control y necesita el 3:1 de WCAG 1.4.11: --line-strong,
   no --line (que es solo decorativo). */
.coverage-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: calc(var(--step) * 3);
}
.coverage-card {
    display: block;
    padding: calc(var(--step) * 3);
    border: 1px solid var(--line-strong);
    text-decoration: none;
    color: var(--ink);
}
.coverage-card:hover { border-color: var(--accent); }
.coverage-card__name { display: block; font-weight: 600; margin-bottom: calc(var(--step) / 2); }
.coverage-card__count { display: block; color: var(--ink-soft); font-size: 0.95rem; }
.coverage-card__count strong { color: var(--accent); }

@media (max-width: 860px) {
    .photo-grid { grid-template-columns: repeat(2, 1fr); }
    .coverage-grid { grid-template-columns: repeat(2, 1fr); }
    .service-list__item h3 { flex-basis: 100%; }
}
@media (max-width: 560px) {
    .photo-grid { grid-template-columns: 1fr 1fr; }
    .coverage-grid { grid-template-columns: 1fr; }
}

/* --- Boton flotante de WhatsApp --------------------------------------------
   Verde oscuro de marca (#075E54): el claro (#25D366) da 1,98:1 sobre blanco y
   no llega al 3:1 de WCAG 1.4.11 para un control. Este da 7,67:1, y el icono
   blanco encima, otro 7,67:1.
   56 px de lado, por encima de los 44 que pide WCAG 2.5.5 para el dedo.
   Abajo a la derecha y no a la izquierda, que es donde lo tiene la web vieja:
   a la izquierda taparia el inicio de las lineas de texto al hacer zoom. */
.whatsapp-float {
    position: fixed;
    right: calc(var(--step) * 2);
    bottom: calc(var(--step) * 2);
    z-index: 50;
    width: 56px; height: 56px;
    border-radius: 50%;
    display: grid; place-items: center;
    background: #075E54; color: #FFFFFF;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
}
.whatsapp-float:hover { background: #044A42; }
.whatsapp-float:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
@media (prefers-reduced-motion: no-preference) {
    .whatsapp-float { transition: background 0.15s ease; }
}

/* --- Comparador blindada / acorazada ---------------------------------------
   El dibujo va aria-hidden y la informacion la lleva la lista de texto de
   debajo: asi nada depende de que un lector de pantalla sepa recorrer un SVG.
   Ninguna pieza se distingue SOLO por el color, todas van rotuladas (WCAG
   1.4.1). Colores: --accent para lo nuevo de acero, #C9BFA8 para la madera que
   ya estaba, --line para el muro. El cian solo aparece como relleno translucido
   dentro de una pieza ya delimitada en azul, nunca solo. */
.comparador {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
    gap: calc(var(--step) * 4);
    margin-top: calc(var(--step) * 4);
}
.comparador__caso {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: calc(var(--step) * 3);
}
.comparador__caso h3 { margin-bottom: calc(var(--step) / 2); }
.comparador__resumen {
    margin: 0 0 calc(var(--step) * 2);
    color: var(--ink-soft);
    font-size: 0.95rem;
}
.comparador__svg {
    display: block;
    width: 100%;
    height: auto;
    background: var(--paper-warm);
    border-radius: 4px;
}
.comparador__svg .cmp-rot {
    font: 600 11px system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    fill: #14120F;
}
.comparador__svg .cmp-mini {
    font: 400 9px system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    fill: #56524D;
}
.comparador__svg .cmp-guia { stroke: #56524D; stroke-width: 1; }
.comparador__lista {
    margin: calc(var(--step) * 2) 0 0;
    padding-left: calc(var(--step) * 2.5);
    font-size: 0.95rem;
}
.comparador__lista li { margin-bottom: var(--step); }

.comparador__fotos { margin-top: calc(var(--step) * 5); }

/* --- Mapa de cobertura -----------------------------------------------------
   El contorno de Cataluna no es adorno: la primera version eran los 33 puntos
   sueltos sobre un rectangulo gris y no se leia como un mapa. Sale de
   data/catalunya-contorno.json (OpenStreetMap) y se proyecta con la misma
   funcion que los puntos, asi que no pueden descuadrarse.
   El mapa es decorativo y la informacion la lleva el pie de figura: en movil
   los puntos quedan entre 5 y 16 px y como enlaces no llegarian a los 44 px
   de WCAG 2.5.5. El <title> de cada punto se queda por el globo del raton.
   Ancho maximo de 560 px: el encuadre de Cataluna es casi cuadrado, y a todo
   lo ancho de la pagina serian mas de 1.100 px de alto de una sola figura. */
.mapa { margin: calc(var(--step) * 4) 0 0; max-width: 560px; }
.mapa__svg {
    display: block;
    width: 100%;
    height: auto;
    background: var(--paper);
    border-radius: 8px;
}
.mapa__tierra {
    fill: var(--paper-warm);
    stroke: var(--line-strong);
    stroke-width: 1;
    stroke-linejoin: round;
}
.mapa__punto circle {
    fill: var(--accent);
    fill-opacity: 0.85;
    stroke: var(--paper);
    stroke-width: 1.2;
}
.mapa__punto:hover circle { fill: var(--accent-hover); fill-opacity: 1; }
.mapa__rotulo {
    font: 600 12px system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    fill: var(--ink);
    paint-order: stroke;
    stroke: var(--paper-warm);
    stroke-width: 3;
    pointer-events: none;
}
.mapa__pie {
    margin-top: calc(var(--step) * 2);
    color: var(--ink-soft);
    font-size: 0.9rem;
    max-width: var(--measure);
}

.coverage-grid { margin-top: calc(var(--step) * 5); }

/* --- Donde trabajamos: mapa y zonas en el MISMO recuadro --------------------
   Antes el mapa iba solo, topado a 560 px dentro de una pagina de 1180, y la
   rejilla de zonas debajo: media pagina vacia a la derecha y el bloque entero
   casi 600 px mas largo de lo necesario. Ahora las dos mitades comparten
   recuadro y se leen a la vez: el mapa dice DONDE, las tarjetas dicen CUANTO.

   El borde es --line (decorativo, 1,28:1): delimita una caja, no un control,
   asi que no le aplica el 3:1 de WCAG 1.4.11. El borde de cada tarjeta si es
   un control y se queda en --line-strong. */
.cobertura {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: calc(var(--step) * 5);
    align-items: start;
    margin-top: calc(var(--step) * 4);
    padding: calc(var(--step) * 4);
    border: 1px solid var(--line);
}
/* Dentro del recuadro el mapa manda sobre su propia columna: el tope de 560 px
   existia para que no ocupara los 1180 px de la pagina de una sola figura, y
   aqui esa columna ya lo limita. */
.cobertura .mapa { margin: 0; max-width: none; }
.cobertura__zonas h3 { margin-bottom: calc(var(--step) * 3); }
/* Dos columnas SIEMPRE, tambien en movil: son ocho tarjetas y apiladas de una
   en una devuelven justo el scroll que este bloque venia a quitar. La regla
   gana a las de .coverage-grid de las media queries por especificidad (0,2,0
   frente a 0,1,0), no por orden. */
.cobertura .coverage-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: calc(var(--step) * 2);
    margin-top: 0;
}
.cobertura .coverage-card { padding: calc(var(--step) * 2) calc(var(--step) * 2.5); }
.cobertura .coverage-card__name { font-size: 1rem; }
.cobertura .coverage-card__count { font-size: 0.85rem; }
.cobertura__mas { margin: calc(var(--step) * 3) 0 0; }

/* Por debajo de 900 px las dos columnas no caben sin estrujar el mapa: se
   apilan, mapa primero. */
@media (max-width: 900px) {
    .cobertura {
        grid-template-columns: 1fr;
        gap: calc(var(--step) * 4);
        padding: calc(var(--step) * 3);
    }
    .cobertura .mapa { max-width: 480px; }
}

/* Foto de obra suelta dentro del texto: las cinco paginas de zona que tenian
   su foto en el banner y ahora lo comparten con el resto del sitio. Topada a
   420 px porque son verticales: a los 1116 px del .wrap una sola foto de una
   puerta ocupa dos pantallas. */
.figure--obra { max-width: 420px; margin-top: calc(var(--step) * 4); }
/* Misma relacion 3:4 recortada que la rejilla de fotos, por dos motivos: las
   fotos de obra tienen proporciones distintas una de otra, y sobre todo la
   imagen va en lazy -sin una relacion fija reserva cero alto hasta que carga y
   empuja el texto de debajo al aparecer. */
.figure--obra img { aspect-ratio: 3 / 4; object-fit: cover; }

/* --- Como trabajamos, cuatro pasos -----------------------------------------
   Los iconos van aria-hidden y son trazo puro: no aportan nada que no diga el
   titulo de al lado, que es la unica forma de que un icono sea seguro.
   El numero del paso tambien es aria-hidden: es un <ol>, y el lector de
   pantalla ya numera. Sin eso se oye "1 1 Nos cuentas el caso".
   Icono en --accent sobre --paper-warm: 15,10:1. */
.proceso {
    list-style: none;
    counter-reset: none;
    margin: calc(var(--step) * 4) 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
    gap: calc(var(--step) * 3);
}
.proceso__paso {
    position: relative;
    padding: calc(var(--step) * 3);
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 8px;
}
.proceso__icono { display: block; color: var(--accent); }
.proceso__numero {
    position: absolute;
    top: calc(var(--step) * 2);
    right: calc(var(--step) * 2);
    font: 600 0.8rem system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    color: var(--ink-soft);
}
.proceso__titulo {
    font-size: 1.1rem;
    margin: calc(var(--step) * 1.5) 0 calc(var(--step) / 2);
}
.proceso__texto {
    margin: 0;
    color: var(--ink-soft);
    font-size: 0.9rem;
    max-width: none;
}

/* --- Valoracion de Google --------------------------------------------------
   Las estrellas van en --estrella (#A16207, 4,92:1 sobre blanco y 4,60:1 sobre
   el gris calido): transmiten la nota, asi que son contenido no textual y les
   toca el 3:1 de WCAG 1.4.11. Y aun asi la nota va SIEMPRE escrita al lado en
   cifra, mas un .sr-only con la frase entera: el color y la forma no son el
   unico canal.
   Las huecas (☆) son el mismo color: lo que distingue una llena de una hueca
   es la forma, no el tono, que es lo que pide WCAG 1.4.1. */
.resenas__nota {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: calc(var(--step) / 1.5) var(--step);
    margin: 0 0 var(--step);
}
.resenas__cifra {
    font-family: "Source Serif 4", Georgia, "Times New Roman", serif;
    font-size: 2.5rem;
    line-height: 1;
    color: var(--ink);
}
.resenas__sobre { color: var(--ink-soft); font-size: 0.95rem; }
.resenas__estrellas { color: var(--estrella); font-size: 1.2rem; letter-spacing: 0.08em; }
.resenas__total { color: var(--ink-soft); font-size: 0.95rem; }

.footer-google { margin: 0 0 var(--step); display: flex; align-items: baseline; gap: var(--step); flex-wrap: wrap; }
.footer-google__cifra {
    font-family: "Source Serif 4", Georgia, "Times New Roman", serif;
    font-size: 1.6rem; line-height: 1; color: var(--ink);
}
.footer-google__estrellas { color: var(--estrella); letter-spacing: 0.06em; }
.footer-google__detalle { flex: 1 1 100%; color: var(--ink-soft); font-size: 0.85rem; }

/* --- Hero claro (portada + las 36 paginas de zona) -------------------------
   Foto apaisada y clara del fabricante con la pared de la izquierda vacia: el
   texto va ahi, en oscuro, y la fotografia se ve entera. Lo pinta hero_banner()
   (includes/hero-banner.php), asi que estas reglas mandan en 37 paginas: lo que
   se toque aqui hay que medirlo con el H1 mas largo del sitio, no solo con el
   de la portada.
   Las 6 paginas que quedan con .hero a secas -las de producto- siguen con su
   foto de obra oscura y su velo azul; por eso esto es una variante y no un
   cambio del .hero de base.

   EL VELO SIGUE EXISTIENDO, pero blanco y solo por la izquierda. La pared ya
   es clara, pero en esa misma franja hay un aplique y un interruptor casi
   negros (pixel medido: #18 0F 06) y encima de ellos el texto --ink daria
   1,01:1. Medido sobre ese peor pixel, con blanco al 0,72 sube a 9,8:1, muy por
   encima del 4,5:1 de WCAG 1.4.3. Sobre la pared, que ya es clara, apenas se
   nota: aclara en vez de tapar, que era justo lo que se pedia. */
/* LA FOTO Y EL TEXTO SE SUPERPONEN EN UNA CELDA DE REJILLA, no con position:
   absolute como el hero oscuro. El motivo es que ahora este banner lo llevan
   tambien las 36 paginas de zona, y ahi el H1 es mas largo ("Puertas blindadas
   y acorazadas en Santa Coloma de Gramenet") y la entradilla tambien. Con el
   texto en absolute, el .hero tiene la altura de la foto y overflow: hidden:
   un texto mas alto que la foto se CORTA sin avisar, y solo en algunos anchos.
   Superpuestos en la misma celda, la fila mide lo que mida el mas alto de los
   dos y no hay nada que cortar. */
.hero--claro {
    display: grid;
    min-height: min(80vh, 620px);
}
/* La FOTO sale del flujo (y el velo con ella): asi no manda en la altura de la
   banda -si mandara, la banda mediria el alto natural de la imagen a ese ancho,
   1.000 px en una pantalla de 1.900- y la unica que decide es la altura del
   texto contra el minimo de arriba. */
.hero--claro .hero__media,
.hero--claro .hero__scrim { position: absolute; inset: 0; }
.hero--claro .hero__media img { width: 100%; height: 100%; min-height: 0; }
/* relative + z-index, NO static: el velo esta posicionado y un elemento
   posicionado pinta por ENCIMA del contenido en flujo normal aunque vaya antes
   en el HTML. Con el texto en static, el velo blanco le pasaba por delante y el
   banner salia sin titulo (comprobado con elementFromPoint sobre el H1:
   devolvia .hero__scrim). Sigue estando en flujo, asi que sigue siendo el que
   decide el alto de la banda. */
.hero--claro .hero__content { position: relative; z-index: 1; min-width: 0; }

.hero--claro .hero__scrim {
    background: linear-gradient(
        90deg,
        rgba(255, 255, 255, 0.88) 0%,
        rgba(255, 255, 255, 0.80) 40%,
        rgba(255, 255, 255, 0.45) 54%,
        rgba(255, 255, 255, 0) 66%
    );
}
/* El bloque de texto se pega mas a la izquierda que el resto de la pagina.
   El .wrap normal se centra dentro de 1180 px, asi que en una pantalla ancha
   el texto arrancaba a 380 px del borde y dejaba media pared vacia. Aqui se
   suelta ese maximo y se usa un margen proporcional, topado a 104 px: en
   pantalla grande el texto sube a la zona clara de la pared y en pantalla
   normal se queda casi donde estaba. Rompe a proposito la alineacion con las
   secciones de debajo; en el banner se lee como intencion, no como descuadre. */
.hero--claro .hero__content .wrap {
    width: 100%;
    max-width: none;
    padding-inline: clamp(calc(var(--step) * 3), 5vw, 104px);
    color: var(--ink);
}
.hero--claro .hero__content h1 { color: var(--ink); }
/* El parrafo en --ink y no en --ink-soft: medido sobre los pixeles reales,
   --ink-soft daba 3,97:1 contra el interruptor de la pared -por debajo del
   4,5:1- porque justo ahi el velo ya esta bajando. Con --ink son 10,6:1, y ese
   margen aguanta que el recorte cambie en otros anchos de pantalla. */
.hero--claro .hero__content p { color: var(--ink); }
/* El texto se queda en la mitad izquierda, que es donde esta la pared y donde
   el velo protege. Si algun dia se ensancha, hay que volver a mirar el velo. */
.hero--claro .hero__content h1,
.hero--claro .hero__content p { max-width: min(42%, 28rem); }
/* Los botones NO llevan el ancho de la columna de texto: sumaban 453 px en un
   contenedor de 448 y se partian en dos lineas por cinco pixeles. Tienen su
   propio tope, con sitio de sobra para los dos, y siguen acabando dentro de la
   zona que el velo protege. */
.hero--claro .hero__actions { max-width: 32rem; }
/* Boton de texto: CON FONDO SOLIDO, no transparente. Medido a 885 px de ancho,
   el recorte lo dejaba justo encima del aplique oscuro de la pared y su
   etiqueta caia a 3,97:1, por debajo del 4,5:1. Con el fondo opaco el control
   deja de depender de lo que haya detras, en cualquier recorte y a cualquier
   ancho, igual que el boton principal. */
.hero--claro .hero__actions .btn--ghost {
    color: var(--ink);
    /* Borde en --ink-soft y no en --line-strong: aqui el borde limita con la
       FOTOGRAFIA, no con un fondo plano, y --line-strong solo pasa el 3:1 de
       WCAG 1.4.11 sobre la pared clara (3,25:1); sobre el aplique velado cae a
       2,31:1 y sobre la zona media a 1,90:1. --ink-soft aguanta los tres casos
       (7,01 / 4,98 / 4,09). */
    border-color: var(--ink-soft);
    background: var(--paper);
}
.hero--claro .hero__actions .btn--ghost:hover {
    background: var(--paper-warm);
    color: var(--ink);
    border-color: var(--ink);
}

/* En movil no hay pared: el recorte deja ver la puerta y el hueco, y un texto
   oscuro encima no se leeria. En vez de lavar la foto entera con un velo,
   la imagen pasa arriba y el texto debajo, sobre blanco. Se ve la foto entera
   y el texto se lee sin depender de lo que haya detras. */
@media (max-width: 860px) {
    /* Se deshace la superposicion: ni foto en absoluto ni altura minima de
       banda. Aqui la foto es una banda de 260 px y el texto va debajo. */
    .hero--claro { display: flex; flex-direction: column; min-height: 0; }
    .hero--claro .hero__media { order: 1; position: static; }
    .hero--claro .hero__media img { height: 260px; object-position: 62% center; }
    .hero--claro .hero__scrim { display: none; }
    .hero--claro .hero__content {
        position: static;
        order: 2;
        padding: calc(var(--step) * 5) 0 calc(var(--step) * 4);
        background: var(--paper);
    }
    .hero--claro .hero__content h1,
    .hero--claro .hero__content p,
    .hero--claro .hero__actions { max-width: none; }
}
