/* ===========================================================================
   ALVI · COMPONENTES

   AQUÍ NO HAY NI UN COLOR ESCRITO. Todos salen de theme.css como var(--...).
   =========================================================================== */


/* ===========================================================================
   BOTONES

   Tres niveles. La regla del proyecto: UN SOLO botón rojo por pantalla.
   Si en una página hay dos rojos compitiendo, uno de los dos está mal.

   No se le mete una flecha al final de la etiqueta. Si el botón dice
   "Pedir cita", ya se entiende que lleva a algún sitio.
   =========================================================================== */

.boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);

  /* Área táctil de sobra: el público entra con guantes o con prisa. */
  min-height: var(--touch);
  min-width: var(--touch);
  padding: var(--sp-3) var(--sp-6);

  font-family: var(--font-title);
  font-size: var(--fs-body);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;

  border: 2px solid var(--border-none);
  border-radius: var(--r-md);
  cursor: pointer;

  /* El texto SÍ puede partir. Prohibirlo hacía que una etiqueta larga como
     "Preguntar si llegamos a tu finca" midiera 315px y sacara la página de
     lado a 320. El que no parte es el botón flotante, que sí lo lleva. */
  text-wrap: balance;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}

/* El icono no se encoge: dentro de un botón estrecho, sin esto, se aplastaba
   hasta desaparecer y quedaba solo la palabra. */
.boton svg {
  flex: none;
}

/* --- Principal: la acción de la pantalla ---------------------------------- */
/* SE HUNDE 1px AL PULSAR, y nada más. Sin sombra que crezca ni escala que
   rebote: la pieza baja, como una tecla. Es lo que hace que un botón se sienta
   físico sin que parezca un juguete. */
.boton:active {
  transform: translateY(1px);
}

@media (prefers-reduced-motion: reduce) {
  .boton:active {
    transform: none;
  }
}

.boton--principal {
  background: var(--action-bg);
  color: var(--action-text);
}

.boton--principal:hover {
  background: var(--action-bg-hover);
  color: var(--action-text);
}

.boton--principal:active {
  background: var(--action-bg-hover);
}

/* --- Secundario: contorno verde ------------------------------------------- */
.boton--secundario {
  background: var(--bg-page);
  color: var(--action-ghost-text);
  border-color: var(--action-ghost-border);
}

.boton--secundario:hover {
  background: var(--action-ghost-bg-hover);
  color: var(--action-ghost-text);
}

/* --- Terciario: solo texto ------------------------------------------------ */
.boton--terciario {
  background: var(--bg-page);
  color: var(--text-brand);
  padding-inline: var(--sp-2);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

.boton--terciario:hover {
  color: var(--text-accent);
}

/* --- Sobre fondo oscuro --------------------------------------------------- */
.on-dark .boton--secundario,
.boton--sobre-oscuro {
  background: var(--border-none);
  color: var(--action-on-inverse-text);
  border-color: var(--action-on-inverse-border);
}

.on-dark .boton--secundario:hover,
.boton--sobre-oscuro:hover {
  background: var(--action-on-inverse-bg-hover);
  color: var(--action-on-inverse-text);
}

/* --- Ancho completo (móvil) ----------------------------------------------- */
.boton--completo {
  width: 100%;
}

/* --- Deshabilitado -------------------------------------------------------- */
.boton:disabled,
.boton[aria-disabled="true"] {
  background: var(--disabled-bg);
  color: var(--disabled-text);
  border-color: var(--disabled-border);
  cursor: not-allowed;
}


/* ===========================================================================
   CAMPOS DE FORMULARIO

   La etiqueta va SIEMPRE encima y siempre visible. Nunca se usa el texto de
   dentro del campo como etiqueta: en cuanto el usuario empieza a escribir
   desaparece y ya no se acuerda de qué le estaban preguntando.
   =========================================================================== */

.campo {
  display: block;
  margin-bottom: var(--sp-6);
  max-width: var(--w-narrow);
}

.campo__etiqueta {
  display: block;
  font-weight: 600;
  color: var(--field-label);
  margin-bottom: var(--sp-2);
}

.campo__ayuda {
  display: block;
  color: var(--field-hint);
  font-size: var(--fs-meta);
  margin-bottom: var(--sp-2);
}

.campo__control {
  width: 100%;
  min-height: var(--touch);
  padding: var(--sp-3) var(--sp-4);

  background: var(--field-bg);
  color: var(--text-body);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-tight);

  border: 2px solid var(--field-border);
  border-radius: var(--r-md);
}

.campo__control:hover {
  border-color: var(--field-border-active);
}

textarea.campo__control {
  min-height: calc(var(--touch) * 3);
  resize: vertical;
}

.campo__control:disabled {
  background: var(--disabled-bg);
  color: var(--disabled-text);
  border-color: var(--disabled-border);
  cursor: not-allowed;
}

/* --- Error ----------------------------------------------------------------
   El mensaje dice QUÉ pasa y CÓMO se arregla. No "campo inválido".
   Y no se marca solo con color: lleva texto, que también lo lee un daltónico
   y lo lee un lector de pantalla. */

.campo--error .campo__control {
  border-color: var(--field-error-border);
  background: var(--field-error-bg);
}

.campo__error {
  display: flex;
  gap: var(--sp-2);
  align-items: flex-start;
  margin-top: var(--sp-2);
  color: var(--field-error);
  font-weight: 600;
}

.campo__error svg {
  flex: none;
  width: 1.2em;
  height: 1.2em;
  margin-top: 0.15em;
}


/* ===========================================================================
   BUSCADOR DE RECAMBIO

   Componente propio, no un campo con más relleno. Es una de las tres cosas
   que de verdad viene a hacer aquí un agricultor (llamar, pedir cita, buscar
   una referencia), así que tiene presencia permanente y desproporcionada:
   64px de alto, ancho completo, etiqueta escrita y un ejemplo real dentro.

   Lo que NO se hace: esconderlo detrás de una lupa en la cabecera.
   =========================================================================== */

.buscador {
  background: var(--bg-tint);
  border: 1px solid var(--border-hairline);
  border-radius: var(--r-md);
  padding: var(--sp-6);
}

.buscador__etiqueta {
  display: block;
  font-family: var(--font-title);
  font-size: var(--fs-h3);
  font-weight: 600;
  margin-bottom: var(--sp-4);
}

.buscador__fila {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}

.buscador__campo {
  flex: 1 1 18rem;

  /* Sin esto la página desborda a 320px. Un input dentro de un contenedor
     flexible tiene min-width:auto, que resuelve a su ancho intrínseco (unos
     20 caracteres), y ese ancho NO se encoge: empuja la página entera de lado.
     El desbordamiento no se veía porque body lleva overflow-x:hidden, así que
     en vez de una barra horizontal salía el texto cortado, que es peor. */
  min-width: 0;

  min-height: 64px;
  padding: var(--sp-3) var(--sp-5);

  background: var(--field-bg);
  color: var(--text-body);
  font-family: var(--font-body);
  font-size: var(--fs-lead);

  border: 2px solid var(--field-border);
  border-radius: var(--r-md);
}

.buscador__campo::placeholder {
  color: var(--field-hint);
}

.buscador__boton {
  flex: 0 0 auto;
  min-height: 64px;
  padding-inline: var(--sp-8);
}

/* El texto de apoyo del buscador ocupa el ancho del componente, no la medida
   de lectura: dentro de una caja ancha, partirlo a 40 caracteres se lee como
   un descuadre. */
.buscador__pie {
  margin: var(--sp-4) 0 0;
  max-width: none;
  color: var(--text-muted);
  font-size: var(--fs-meta);
}

@media (max-width: 30rem) {
  .buscador__boton {
    flex: 1 1 100%;
  }
}


/* ===========================================================================
   FILA DE DATO · el componente del albarán

   Etiqueta a la izquierda, guía de puntos, dato a la derecha en cifras de
   ancho fijo. Es el formato de los papeles que el cliente de ALVI ya sabe
   leer: el albarán, el parte de trabajo, la ficha de referencia.

   Se usa en la ficha técnica, en el horario y en la confirmación de pedido.
   Es lo contrario de la rejilla de tarjetas iguales.
   =========================================================================== */

.albaran {
  margin: 0;
  border-top: 2px solid var(--border-strong);
}

.albaran__fila {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  padding-block: var(--sp-3);
  border-bottom: 1px solid var(--border-hairline);
}

.albaran__etiqueta {
  flex: 0 1 auto;
  color: var(--text-muted);
  margin: 0;
}

/* La guía de puntos: se estira para ocupar lo que sobre entre los dos textos. */
.albaran__guia {
  flex: 1 1 var(--sp-8);
  min-width: var(--sp-6);
  border-bottom: 2px dotted var(--border-strong);
  transform: translateY(-0.3em);
}

.albaran__dato {
  flex: 0 1 auto;
  min-width: 0;
  margin: 0;
  text-align: right;
  font-weight: 600;
  font-variant-numeric: tabular-nums;

  /* Los marcadores tipo {{DIRECCION_ALVI}} son una sola palabra larguísima:
     sin esto no parten y sacan la tabla fuera de la pantalla. */
  overflow-wrap: anywhere;
}

/* --- CUANDO LA FILA SE QUEDA ESTRECHA -------------------------------------

   LA GUÍA DE PUNTOS SOLO TIENE SENTIDO SI UNE DOS EXTREMOS EN UNA LÍNEA. En
   cuanto la etiqueta o el dato parten, la guía deja de unir nada y el patrón
   pierde su razón de ser: quedan dos textos rotos con unos puntos sueltos en
   medio.

   Pasaba, y medido no era donde parecía: a 360 y 414 ya se apilaba bien; se
   rompía de 440 a 560px de ventana, con "Proveedor de recambio ····
   Kramp · más de 500.000 referencias" partido en dos y dos líneas.

   VA POR CONSULTA DE CONTENEDOR Y NO POR ANCHO DE VENTANA, y es lo que hace
   que valga en los cinco sitios donde se usa este componente: la ficha de la
   empresa mide como mucho 774px, las columnas del pie son bastante más
   estrechas que la ventana, y la ficha de pieza va en una columna lateral. Con
   una media query habría que afinar un número distinto para cada uno; con la
   consulta, cada fila decide por su propio ancho.

   El corte son 35rem (560px): es lo que pide el par más largo del sitio,
   medido. Si algún día aparece uno más largo, esto vuelve a partirse y hay que
   volver a medir; no hay forma de que el CSS lo sepa solo.

   La forma apilada NO es la misma fila sin guía: la etiqueta baja a cuerpo de
   metadato y a tinta secundaria, y el dato pasa a alinearse a la izquierda. Lo
   que mantiene la lectura de documento es la regla fina de debajo de cada par,
   que se queda. */
.albaran {
  container-type: inline-size;
}

@container (max-width: 35rem) {
  .albaran__fila {
    display: block;
  }

  .albaran__guia {
    display: none;
  }

  .albaran__etiqueta {
    font-size: var(--fs-meta);
    color: var(--text-muted);
  }

  .albaran__dato {
    margin-top: var(--sp-1);
    text-align: left;
  }
}

/* Sin consulta de contenedor, el apilado por ancho de ventana de siempre. Se
   pierde el ajuste fino por contexto, no la legibilidad. */
@supports not (container-type: inline-size) {
  @media (max-width: 38rem) {
    .albaran__fila {
      display: block;
    }

    .albaran__guia {
      display: none;
    }

    .albaran__etiqueta {
      font-size: var(--fs-meta);
      color: var(--text-muted);
    }

    .albaran__dato {
      margin-top: var(--sp-1);
      text-align: left;
    }
  }
}


/* ===========================================================================
   HUECO DE IMAGEN

   Las fotos las aporta ALVI. Mientras no llegan, cada hueco dice qué foto
   espera y en qué proporción. Nunca parece una imagen rota: parece lo que es,
   un sitio reservado, y de paso es la lista de la compra para el cliente.
   =========================================================================== */

.hueco {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  text-align: center;

  aspect-ratio: var(--hueco-proporcion, 3 / 2);
  padding: var(--sp-4);

  background: var(--slot-bg);
  color: var(--slot-text);
  border: 2px dashed var(--slot-border);
  border-radius: var(--r-md);
}

/* Trama diagonal: es lo que hace que el hueco parezca un sitio reservado con
   intencion y no una imagen que no ha cargado. */
.hueco--trama {
  background-image: repeating-linear-gradient(135deg,
      var(--slot-trama) 0 2px,
      var(--border-none) 2px 16px);
}

/* SOLO DOS PROPORCIONES EN TODO EL SITIO, y es deliberado.

   Tres proporciones distintas en tres fotos es lo que hace que una página se
   vea improvisada. Aquí hay una ANCHA para las fotos de contexto —la nave, el
   taller, un servicio— y una CUADRADA para las de detalle, que son las piezas.
   El hero usa también la ancha, con un tope de altura.

   Había una tercera, 4:5, declarada y sin usar en ningún sitio. Fuera. */
.hueco--cuadrado   { --hueco-proporcion: 1 / 1; }   /* detalle: piezas */
.hueco--panoramico { --hueco-proporcion: 16 / 9; }  /* contexto: nave, taller */

.hueco svg {
  width: var(--sp-10);
  height: var(--sp-10);
}

/*
  El rótulo del hueco SEÑALIZA, no protagoniza.

  En la vuelta anterior me pasé de frenada: el nombre del archivo salía a
  cuerpo de subtítulo y era lo primero que se leía al entrar en la web, por
  delante del titular. La regla es sencilla: si el marcador compite en
  jerarquía con el titular del hero, está mal compuesto.

  Todo el grupo va al 50 % sobre la trama, en tinta secundaria y a cuerpo
  pequeño. Se ve lo justo para saber qué foto falta.
*/
.hueco__rotulo {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  opacity: 0.5;
}

.hueco__archivo {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--fs-meta);
  font-weight: 600;
  color: var(--slot-text);
  word-break: break-word;
}

.hueco__nota {
  margin: 0;
  font-size: var(--fs-meta);
  color: var(--slot-text);
  max-width: 44ch;
}

/* --- Hueco grande, con el rótulo en una esquina --------------------------
   En el hero el hueco ocupa toda la anchura, y un icono diminuto en el centro
   de un rectángulo de 1440px se lee como una página que no ha cargado. Con el
   rótulo compuesto arriba a la izquierda, el hueco tiene la misma dignidad
   que tendrá la foto: si el hero se sostiene con esto, con la foto real solo
   puede mejorar.

   Y va arriba a la izquierda a propósito, porque la esquina de abajo a la
   izquierda es justo donde se monta la placa verde. */
.hueco--rotulo-esquina {
  align-items: flex-start;
  justify-content: flex-start;
  text-align: left;
  padding: var(--sp-6);
}


/* ===========================================================================
   REGLA DE SECCIÓN Y FRANJA

   La jerarquía la dan el tamaño y una regla. No hay etiquetas en MAYÚSCULAS
   ESPACIADAS encima de cada título: es el tic más reconocible de una plantilla.
   =========================================================================== */

.regla {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3) var(--sp-5);
  margin-bottom: var(--sp-8);

  /* Se parte en pantalla estrecha. Sin esto, a 360px el título se estrujaba a
     cuatro líneas y el enlace de "ver todos" se salía de la pantalla. */
  flex-wrap: wrap;
}

/* La referencia de la sección. Mismo tipo tabulado y mismo cuerpo que las
   referencias de pieza del catálogo: si se leyeran seguidas, AL-FLT-01842 y
   SRV-01 tienen que parecer del mismo sistema, porque lo son.

   Va en tinta secundaria y a cuerpo de metadato: acompaña al título, no
   compite con él. Y no se sube de tamaño ni se pone en el verde de marca,
   que es la tentación evidente y lo convertiría en una etiqueta decorativa. */
.regla__codigo {
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-size: var(--fs-meta);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}

.regla__titulo {
  flex: 0 1 auto;
  margin: 0;
}

.regla__linea {
  flex: 1 1 var(--sp-16);
  min-width: var(--sp-8);
  height: 2px;
  background: var(--border-strong);
}

/* Con el título ya en su propia línea, la raya decorativa sobra. */
@media (max-width: 30rem) {
  .regla__titulo {
    flex: 1 1 100%;
  }

  .regla__linea {
    display: none;
  }
}

.regla__enlace {
  flex: 0 0 auto;
}

/* --- Franja de color ------------------------------------------------------
   Verde de lado a lado. El verde es la estructura y puede ocupar superficies
   grandes; el rojo no. */

.franja {
  background: var(--bg-inverse-soft);
  color: var(--text-on-inverse);
  padding-block: var(--sp-16);
}

.franja--oscura {
  background: var(--bg-inverse);
}

.franja--clara {
  background: var(--bg-alt);
  color: var(--text-body);
}


/* ===========================================================================
   SURCOS

   Líneas de 1px cada 11px, en diagonal de 12° sobre la horizontal, al 6 %.

   Está hecho con repeating-linear-gradient y NO con un SVG, aunque el encargo
   pedía SVG. El motivo es la otra regla, que manda más: ningún color fuera de
   theme.css. Un SVG en data: URI lleva el color del trazo escrito dentro del
   propio dato y no hay forma de que lea una variable. Con el degradado, la
   línea es var(--surco) y la opacidad la pone el elemento. El dibujo es el
   mismo; lo que cambia es dónde vive el color.

   Va en un pseudoelemento con z-index negativo para quedar por encima del
   fondo de la franja y por debajo del texto. El isolation: isolate es lo que
   impide que ese -1 se escape del bloque y se meta detrás de la página.
   =========================================================================== */

.surcos {
  position: relative;
  isolation: isolate;

  /* Por defecto, línea clara: los surcos solo se usan sobre color, y de las
     franjas de color casi todas son oscuras. El bloque lima lo cambia. */
  --surco: var(--surco-sobre-oscuro);
}

.surcos::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: repeating-linear-gradient(102deg,
              var(--surco) 0 1px, transparent 1px 11px);
  opacity: 0.06;
  pointer-events: none;
}


/* ===========================================================================
   BLOQUES DE COLOR

   Antes el verde solo existía en los botones y la página era crema de arriba
   abajo. Ahora las secciones alternan fondo de verdad, con una regla dura:
   ninguna página lleva tres secciones seguidas del mismo fondo.

   Los colores no se escriben aquí: se REAPUNTAN los tokens semánticos. Así el
   texto secundario, las reglas finas y las referencias de sección cambian
   solas al entrar en una franja oscura, en vez de tener que acordarse de cada
   uno. Es lo mismo que hace .on-dark en la cabecera.
   =========================================================================== */

/* EL ESCALÓN, NO EL COLOR BASE, Y ES UNA CORRECCIÓN MEDIDA.

   El encargo pedía esta franja en --c-brand-900. Puesta así, en /nosotros
   quedaba justo encima de la franja de cierre, que también es --c-brand-900
   desde que el sitio tiene UN solo oscuro estructural: las dos se fundían en
   un bloque continuo de 870px y el cierre dejaba de leerse como cierre.

   --bg-inverse-step existe exactamente para esto, y así está escrito en
   theme.css: "para separar dos zonas oscuras contiguas sin meter una línea".

   La regla que queda, y es coherente en todo el sitio: el color base es el
   PAPEL ESTRUCTURAL —cabecera, pie, placa del hero y franja de cierre—; una
   franja oscura que va DENTRO del contenido de una página usa el escalón.

   Contraste medido sobre el escalón: crema 15,17:1 y texto secundario
   12,96:1. No se pierde nada. */
.seccion--oscura {
  background: var(--bg-inverse-step);
  --surco: var(--surco-sobre-oscuro);

  --text-body: var(--text-on-inverse);
  --text-muted: var(--text-on-inverse-muted);
  --border-hairline: var(--border-on-inverse);

  /* Los enlaces también, y esto es lo que se olvida siempre: el color de
     enlace por defecto es un gris oscuro que sobre este fondo no se ve. */
  --text-brand: var(--text-on-inverse);
  --text-accent: var(--text-on-inverse-muted);

  color: var(--text-on-inverse);
}

/* UNO POR PÁGINA COMO MÁXIMO. Es para lo que de verdad quieres que se mire, y
   dos cosas que gritan a la vez no dejan oír a ninguna.
   El texto va en TINTA. Nunca blanco: 3,30:1. */
.seccion--lima {
  background: var(--bg-accent);
  --surco: var(--surco-sobre-lima);

  --text-body: var(--text-on-accent);
  --text-muted: var(--text-on-accent);
  --border-hairline: var(--text-on-accent);
  --text-brand: var(--text-on-accent);
  --text-accent: var(--text-on-accent);
  color: var(--text-on-accent);
}

.seccion--alt {
  background: var(--bg-alt);
}


/* ===========================================================================
   TELÉFONO COMPUESTO

   El teléfono no es un botón: es contenido. Va compuesto en Archivo, grande,
   con cifras de ancho fijo y agrupado como se dice en voz alta.

   El cuerpo se mide sobre la propia fuente: el número real ocupa 5,97 em, que
   a 320px de pantalla son 215px de los 275px disponibles. El max-width y el
   overflow-wrap son la red por si algún día se pone un texto más largo: antes
   parte de línea que sacar una barra de desplazamiento horizontal.
   =========================================================================== */

.tel {
  display: inline-block;
  max-width: 100%;
  overflow-wrap: anywhere;

  font-family: var(--font-title);
  font-weight: 700;
  line-height: var(--lh-tight);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  text-decoration: none;
  color: inherit;
}

.tel:hover {
  text-decoration: underline;
  text-decoration-thickness: 3px;
  text-underline-offset: 4px;
  color: inherit;
}

.tel--hero { font-size: var(--fs-tel-hero); }
.tel--pie { font-size: var(--fs-tel-footer); }
.tel--cabecera { font-size: var(--fs-tel-header); }

/* La línea de horario que va debajo del teléfono.
   El estado se dice con TEXTO y con peso, nunca con un punto verde o rojo:
   así lo entiende también quien no distingue esos dos colores. */
.horario-aviso {
  display: block;
  margin-top: var(--sp-2);
  font-size: var(--fs-meta);
  color: var(--text-muted);
}

.horario-aviso--dentro {
  font-weight: 600;
  color: var(--text-body);
}


/* ===========================================================================
   BOTÓN FLOTANTE DE WHATSAPP

   Lleva la palabra "WhatsApp" escrita al lado del icono. Un círculo con un
   bocadillo genérico es indistinguible del chat de soporte de cualquier web, y
   para alguien de 55 años que entra desde la finca no significa nada. Con la
   palabra escrita se entiende sin aprender ningún pictograma, y de paso evita
   meter el logotipo de una marca de terceros en el proyecto.

   Va en verde de marca, nunca en gris oscuro.

   Altura de 56px y esquina inferior derecha. El pie le reserva sitio con su
   propio relleno inferior para que no tape los enlaces legales.
   =========================================================================== */

.wasap {
  position: fixed;
  right: var(--sp-4);
  bottom: var(--sp-4);
  z-index: 90;

  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);

  min-height: 56px;
  padding-inline: var(--sp-5);
  max-width: calc(100vw - var(--sp-8));

  background: var(--wasap-bg);
  color: var(--wasap-text);
  border-radius: var(--r-pill);
  box-shadow: var(--shadow-floating);

  font-family: var(--font-title);
  font-size: var(--fs-body);
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;

  transition: background-color var(--dur) var(--ease);
}

.wasap:hover {
  background: var(--wasap-bg-hover);
  color: var(--wasap-text);
}

/* EL BOTÓN FLOTANTE NO EXISTE. Ni en móvil ni en escritorio.

   Se quitó primero de móvil, medido: la píldora mide 169x56 y se sentaba
   encima del botón principal, tapando el 49 % de "Añadir al pedido" a 360px y
   el 66 % a 390px, CENTRO INCLUIDO.

   En escritorio se dejó "porque allí no tapa nada". TAPABA. Medido con
   intersección de rectángulos, recorriendo cada página de arriba abajo:

       1280px  /contacto        100 % del valor "Cerrado" del domingo
       1280px  ficha de pieza    69 % de un valor de la ficha técnica
       1280px  ficha de pieza    24 % del botón "Añadir al pedido"
       1440px  /contacto         99 % del mismo valor
       1920px  todas              0 %

   Solo deja de tapar a partir de ~1670px, que es cuando la columna de
   contenido (72rem centradas) despeja los 185px del botón. Por debajo de eso
   siempre pisa algo, y no se arregla con relleno: al ser `position: fixed`, el
   contenido le pasa por debajo a mitad de scroll, no solo al final.

   Reservar un carril vacío de 185px a la derecha en todas las páginas era el
   precio de mantenerlo, y no lo vale: WhatsApp sigue estando en el hero, en el
   menú, en la banda de cierre y en el pie. Cuatro sitios donde no tapa nada.

   Si algún día se recupera, hay que medirlo con herramientas/contraste.py
   ampliado a intersecciones, no darlo por bueno mirando una captura. */
.wasap {
  display: none;
}

/* Con el pie a la vista, el botón flotante se quita: ahí ya hay un botón de
   WhatsApp a tamaño completo y, si se queda, tapa los enlaces legales. Se
   oculta sin transición, porque el único momento animado del sitio es el
   del hero. */
.wasap[data-oculto="true"] {
  display: none;
}

.wasap svg {
  flex: none;
  width: 28px;
  height: 28px;
}


/* ===========================================================================
   TARJETA DE CONTENIDO

   Nota: NO todo son tarjetas. Se usan donde varios elementos pesan lo mismo.
   Cuando uno manda sobre los demás, ese lleva otro tratamiento (más ancho,
   foto) y los demás van en filas con regla.
   =========================================================================== */

.tarjeta {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-6);
  background: var(--bg-paper);
  border: 1px solid var(--border-hairline);
  border-radius: var(--r-md);
}

.tarjeta__titulo {
  margin: 0;
  font-size: var(--fs-h3);
}

.tarjeta__texto {
  margin: 0;
  color: var(--text-muted);
}

.tarjeta__pie {
  margin-top: auto;
  padding-top: var(--sp-3);
}


/* ===========================================================================
   PRECIO

   El grande es el precio FINAL con IVA. Lo obliga la normativa de protección
   al consumidor: el precio destacado tiene que ser el que se paga.
   El de sin IVA va debajo, más pequeño y en gris, con la etiqueta escrita.
   =========================================================================== */

.precio {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}

.precio__final {
  font-family: var(--font-title);
  font-size: var(--fs-h2);
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.precio__base {
  color: var(--text-muted);
  font-size: var(--fs-meta);
  font-variant-numeric: tabular-nums;
}


/* ===========================================================================
   DISPONIBILIDAD Y PLAZO

   No es aviso de stock: ALVI es distribuidor con entrega directa, así que lo
   que se comunica es cuándo llega la pieza, no cuántas hay en una nave.

   Otra vez: texto, no color. Los tres estados se leen enteros y no dependen
   de distinguir un verde de un ámbar.
   =========================================================================== */

.stock {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-weight: 600;
}

/* Quedan pocas: mismo peso que "disponible", porque es igual de importante. */
.stock--pocas {
  color: var(--text-body);
}

/* Bajo pedido: más discreto, no es una alarma. Se encarga y ya está. */
.stock--bajo-pedido {
  color: var(--text-muted);
  font-weight: 400;
}

/* La coletilla del plazo, debajo de la línea de disponibilidad en la ficha. */
.stock__nota {
  margin-top: var(--sp-1);
  color: var(--text-muted);
  font-size: var(--fs-meta);
}


/* ===========================================================================
   SERVICIOS

   NO son cuatro tarjetas iguales. La reparación de averías es de lo que vive
   el taller, así que ocupa el doble y lleva foto; los demás van en filas con
   una regla. Cuatro cajas idénticas dirían que los cuatro servicios pesan lo
   mismo en el negocio, y no es verdad.
   =========================================================================== */

.servicios__reja {
  display: grid;
  gap: var(--sp-10);
}

@media (min-width: 60rem) {
  .servicios__reja {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: var(--sp-12);
    align-items: start;
  }
}

/* --- El que manda --------------------------------------------------------- */

.destacado__foto {
  margin-bottom: var(--sp-6);
}

.destacado__titulo {
  font-size: var(--fs-h2);
  font-weight: 700;
  margin: 0 0 var(--sp-3);
}

.destacado__texto {
  font-size: var(--fs-lead);
  margin: 0 0 var(--sp-5);
}

.destacado__lista {
  list-style: none;
  margin: 0 0 var(--sp-6);
  padding: 0;
}

.destacado__lista li {
  position: relative;
  padding-left: var(--sp-6);
  margin-bottom: var(--sp-2);
}

/* La marca de la lista es una raya, no un punto: se ve mejor de lejos. */
.destacado__lista li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.7em;
  width: var(--sp-4);
  height: 2px;
  background: var(--bullet-marca);
}

/* --- Los demás: filas con regla ------------------------------------------- */

.servicio-filas {
  list-style: none;
  margin: 0;
  padding: 0;
}

.servicio-fila {
  padding-block: var(--sp-5);
  border-top: 1px solid var(--border-hairline);
}

.servicio-fila:last-child {
  border-bottom: 1px solid var(--border-hairline);
}

.servicio-fila__titulo {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-2) var(--sp-3);
  font-size: var(--fs-h3);
  font-weight: 600;
  margin: 0 0 var(--sp-2);
}

/* El enlace del titulo medido en un movil daba 290x29: por debajo del minimo
   de 48px que se ha fijado para todo lo que se toca con el dedo. Se estira
   sobre la fila entera, asi que el objetivo pasa a ser el bloque completo y
   no solo el renglon de texto. Es la tecnica del ::after: sin JavaScript y
   sin anidar un enlace dentro de otro. */
.servicio-fila__titulo a {
  color: var(--text-body);
  text-decoration: none;
}

.servicio-fila {
  position: relative;
}

.servicio-fila__titulo a::after {
  content: "";
  position: absolute;
  inset: 0;
}

/* Cualquier otro enlace de la fila tiene que quedar POR ENCIMA de esa capa,
   o dejaria de poder pulsarse. */
.servicio-fila a:not(.servicio-fila__titulo a) {
  position: relative;
  z-index: 1;
}

.servicio-fila__titulo a:hover {
  color: var(--text-accent);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

/* El enlace de la fila cubre toda su altura, para que la zona de toque no sea
   solo el renglón del título. */
.servicio-fila__titulo a::after {
  content: "";
  position: absolute;
  inset: 0;
}

.servicio-fila {
  position: relative;
}

.servicio-fila__texto {
  margin: 0;
  color: var(--text-muted);
  max-width: 52ch;
}

.servicio-fila__campo {
  display: inline-block;
  flex: none;
  font-family: var(--font-body);
  font-size: var(--fs-meta);
  font-weight: 600;
  color: var(--text-brand);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-pill);
  padding: 0 var(--sp-3);
}

/* ===========================================================================
   FOTOGRAFÍA

   El contenedor que sustituye al hueco cuando la foto existe de verdad.
   Misma caja, misma proporción: al aparecer la imagen no se mueve nada.

   object-fit: cover recorta al contenedor en vez de deformar. Es lo que
   permite que la MISMA foto sirva para el hero panorámico de escritorio y
   para el 4:5 de móvil.
   =========================================================================== */

.foto {
  overflow: hidden;
  background: var(--slot-bg);
}

/* Las clases hueco--* declaran la proporción en --hueco-proporcion. */
.foto[class*="hueco--"] {
  aspect-ratio: var(--hueco-proporcion);
}

.foto picture,
.foto img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Por defecto se recorta por el centro. Cada foto puede decir otra cosa con
     --foto-encuadre; el hero lo hace, porque el rótulo de la nave está en el
     tercio superior y un recorte centrado se lo come. */
  object-position: var(--foto-encuadre, 50% 50%);
}

/* --- Tratamiento común -----------------------------------------------------

   Suave y uniforme. Desaturar un poco y subir el contraste lo justo hace que
   tres fotos hechas en días distintos parezcan del mismo sitio; el velo gris
   las acerca a la paleta sin teñirlas.

   Lo que NO hay aquí, y sigue sin haberlo: ni sombra DIFUSA, ni esquinas
   redondeadas. Son los recursos con los que se disimula una foto mal
   colocada, y ninguno arregla la colocación. La sombra que sí hay —abajo, en
   el papel— es corta, dura y desplazada, que es otra cosa: no disimula el
   borde, lo señala. */
.foto img {
  filter: saturate(0.85) contrast(1.05);
}

.foto {
  position: relative;

  /* Con el paralaje, la imagen es un 14 % más alta que su caja y se mueve
     dentro. Sin esto se saldría por arriba y por abajo. */
  overflow: hidden;
}

.foto::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--foto-velo);
  mix-blend-mode: multiply;
  opacity: 0.09;
  pointer-events: none;
}

/* --- Pie de foto -----------------------------------------------------------

   Toda fotografía lleva pie, en el mismo lenguaje de albarán que el resto del
   sitio: una línea corta con su regla fina encima.

   Con UNA excepción, y conviene dejarla escrita: la del hero no lo lleva. Ahí
   el pie sería una segunda voz compitiendo con la placa, que ya dice dónde
   está la nave y desde cuándo. Y en escritorio la placa cuelga por debajo de
   la foto, así que el pie caería detrás de ella.

   No es decoración: es lo que convierte la imagen en parte del documento en
   vez de un adorno. Y es más barato y más eficaz que cualquier efecto. */
.foto-pie {
  margin: var(--sp-3) 0 0;
  padding-top: var(--sp-2);
  border-top: 1px solid var(--border-hairline);
  font-size: var(--fs-meta);
  color: var(--text-muted);
}

/* ===========================================================================
   COPIAS SOBRE LA MESA

   Las fotos de ALVI son fotos de móvil hechas en la nave, no de estudio.
   Puestas planas y a escuadra, esa diferencia se lee como un defecto. Puestas
   como copias apoyadas encima de la mesa —papel alrededor, un grado de giro y
   una sombra corta— la misma imperfección pasa a ser el estilo, y encaja con
   el lenguaje de albarán que ya tiene el sitio.

   Son DOS elementos y tiene que serlo:

     .foto-marco   reserva el sitio y NO gira nunca.
     .foto-papel   es la copia: papel, sombra y giro.

   Si girase el marco, el hueco vacío y la foto real ocuparían cosas distintas
   y la página saltaría al cargar la imagen. Así el CLS se queda en 0.

   El giro sale de ImageService.giro(), del nombre del archivo: alterna de
   signo entre fotos y es estable —la misma foto se inclina siempre igual—.
   =========================================================================== */

.foto-marco {
  /* Sitio para que el giro y la sombra no se coman el borde del contenedor.
     Con 1,1° de giro, una copia de 1000px de ancho se sale 9,6px por arriba y
     por abajo; más los 4px de sombra. */
  padding: var(--sp-3) var(--sp-2) var(--sp-4);
}

.foto-papel {
  margin: 0;
  background: var(--foto-papel);

  /* El margen de papel: 13,5px. Menos de 10 no se lee como papel —parece un
     borde— y más de 14 empieza a parecer un passepartout de enmarcador. */
  padding: var(--sp-3);

  /* CORTA, DURA Y DESPLAZADA. Sin desenfoque a propósito. */
  box-shadow: var(--sp-1) var(--sp-1) 0 var(--foto-sombra);

  transform: rotate(var(--foto-giro, 0deg));
}

/* Menos de un grado y medio, y con los dos lados distintos: 0,9 y 1,1. Si las
   dos fueran 1,0 exacto se notaría el patrón. */
.foto-papel--izq { --foto-giro: -0.9deg; --foto-giro-entra: -1.8deg; }
.foto-papel--der { --foto-giro:  1.1deg; --foto-giro-entra:  1.8deg; }


/* --- La copia que se posa en la mesa ---------------------------------------

   Una sola vez, cuando la fotografía entra en pantalla: pasa de estar un poco
   grande y un poco más torcida a su sitio. 400ms y se acabó.

   El estado inicial SOLO existe si fotos.js ha marcado el documento. Si el
   JavaScript no carga, o si el ajuste de movimiento reducido está puesto, la
   marca no se pone y las fotos están en su sitio final desde el primer
   momento: no hay nada que deshacer ni nada que esperar.

   Y no hay desvanecido: la copia no aparece, se posa. Un fade-in por sección
   al desplazar es el sello de web generada y marea a quien lee despacio. */
[data-fotos-animadas] .foto-papel,
[data-fotos-animadas] .hueco-papel {
  transform: rotate(var(--foto-giro-entra, 1.8deg)) scale(1.04);
  transition: transform 400ms var(--ease);
}

[data-fotos-animadas] .foto-papel[data-posada],
[data-fotos-animadas] .hueco-papel[data-posada] {
  transform: rotate(var(--foto-giro, 0deg)) scale(1);
}

/* El hero y las fotos a sangre no se posan: son fondo, no piezas. */
[data-fotos-animadas] .hero__foto .foto-papel,
[data-fotos-animadas] .foto-sangre .foto-papel,
[data-fotos-animadas] .hero__foto .hueco-papel {
  transform: none;
  transition: none;
}

/* El paralaje necesita holgura que mover. La imagen es un 14 % más alta que
   su caja y va centrada: lo que se desplaza es esa holgura, así que nunca
   asoma un borde vacío. */
[data-fotos-animadas] .foto-sangre .foto img {
  position: relative;
  height: 114%;
  top: -7%;
}

/* Los huecos sin foto llevan lo mismo: mientras llegan las fotografías que
   faltan, el sitio tiene que verse igual de acabado con hueco que con foto. */
.hueco-marco {
  padding: var(--sp-3) var(--sp-2) var(--sp-4);
}

.hueco-papel {
  margin: 0;
  background: var(--foto-papel);
  padding: var(--sp-3);
  box-shadow: var(--sp-1) var(--sp-1) 0 var(--foto-sombra);
  transform: rotate(var(--foto-giro, 0deg));
}

/* --- Las dos excepciones ---------------------------------------------------

   El hero y las fotos a sangre son FONDO, no piezas puestas encima. Ahí el
   papel no pinta nada: una copia con margen blanco a lo ancho de la ventana
   sería un marco alrededor de la pantalla. El recurso es para las fotos
   incrustadas en el texto. */
.hero__foto .foto-marco,
.foto-sangre .foto-marco,
.hero__foto .hueco-marco {
  padding: 0;
}

.hero__foto .foto-papel,
.foto-sangre .foto-papel,
.hero__foto .hueco-papel {
  background: none;
  padding: 0;
  box-shadow: none;
  transform: none;
}
