/* ==========================================================================
   BRIGHTLOOP — COMPOSICIÓN DE LA WEB PÚBLICA
   --------------------------------------------------------------------------
   Sólo disposición. Ni un color literal: todo sale de tokens.css.
   La regla de oro de esta página: UNA sola rejilla simétrica en toda la home
   (la de los tres servicios). Todo lo demás —la ficha de la empresa, las
   cifras, la galería de citas— es asimétrico o de altura libre a propósito.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. MARCA — el lockup entra como máscara, no como <img>.
   Así hereda currentColor y funciona igual en papel y en tinta.
   -------------------------------------------------------------------------- */

.brandmark {
  display: block;
  background-color: currentColor;
  -webkit-mask: var(--brand-src) no-repeat center / contain;
          mask: var(--brand-src) no-repeat center / contain;
}
.brandmark--lockup {
  --brand-src: url('../assets/brand/brightloop-lockup.svg');
  height: var(--lockup-h, 1.15rem);
  width: calc(var(--lockup-h, 1.15rem) * 6.52547);   /* 1120.75 / 171.75 */
}
.brandmark--mark {
  --brand-src: url('../assets/brand/brightloop-mark.svg');
  height: var(--mark-h, 1.05rem);
  width: calc(var(--mark-h, 1.05rem) * 1.72611);     /* 271 / 157 */
}


/* --------------------------------------------------------------------------
   2. CABECERA
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: 40;
  background-color: var(--surface-page);
  border-block-end: 1px solid var(--border-hairline);
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-6);
  min-height: var(--header-h);
}

/* El lockup de la cabecera crece con la pantalla. El suelo es el tamaño de
   siempre: a 320 px el logo y el botón «Escribir» ya se reparten el ancho al
   milímetro, y cualquier píxel de más ahí desborda la barra. */
.site-header .brandmark--lockup { --lockup-h: clamp(1.15rem, 0.75rem + 1.3vw, 1.75rem); }

.site-nav { display: none; }
@media (min-width: 62rem) {
  .site-nav { display: flex; align-items: center; gap: var(--sp-7); }
}
.site-nav a {
  font-size: var(--fs-body-sm);
  color: var(--text-secondary);
  text-decoration: none;
  transition: color var(--dur-instant) var(--ease-in-out);
}
.site-nav a:hover { color: var(--text-primary); }

.site-header__actions { display: flex; align-items: center; gap: var(--sp-3); }


/* --------------------------------------------------------------------------
   3. HERO — asimétrico. Titular y entradilla se alinean a la izquierda y el
   aire queda a la derecha: es lo que rompe la simetría del render por defecto.
   -------------------------------------------------------------------------- */

.hero { position: relative; overflow: hidden; }
/* Un respiro real entre la barra y el titular: pegado a la cabecera, el
   titular se leía como parte de ella. Ese aire lo paga el propio titular,
   que baja de tamaño —de 136 px a 96 px arriba del todo—, así que el
   conjunto sigue cabiendo en el primer pantallazo. Abajo se conserva la
   separación grande: es la que despega el hero de la sección 01. */
.hero__inner {
  position: relative;
  padding-block-start: clamp(var(--sp-9), 7vw, var(--sp-13));
  padding-block-end: clamp(var(--sp-9), 6vw, var(--sp-12));
}

/* El titular no redefine `font-size`, sino el TOKEN con el que .t-display-1
   lo calcula. Así el deslizador de escala del panel de diseño lo sigue
   multiplicando: si se pisara la propiedad, el enganche --ui-type-scale
   dejaría de tener efecto justo aquí. */
.hero__title {
  --fs-display-1: clamp(2.625rem, 1.55rem + 4.6vw, 6rem);   /* 42 → 96 */
  position: relative;
  max-width: 16ch;
  margin-block-end: clamp(var(--sp-7), 4vw, var(--sp-10));
}

/* La entradilla arranca en la columna 1, alineada con el titular: la asimetría
   del hero la sostiene el hueco de la DERECHA, no un bloque desplazado. */
.hero__body { position: relative; display: grid; gap: var(--grid-gap); }
@media (min-width: 62rem) {
  .hero__body { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .hero__lead { grid-column: 1 / 7; }
}
.hero__lead { display: grid; gap: var(--sp-6); }

/* La cifra, en el primer pantallazo. Mono y pequeña, pero con el número en
   texto principal: es el dato que la gente viene a buscar y no debería estar
   a cuatro secciones de distancia. */
.hero__note {
  font-size: var(--fs-body-sm);
  line-height: var(--lh-ui);
  letter-spacing: var(--tr-small);
  color: var(--text-tertiary);
  /* Recorta el gap de .hero__lead: la nota pertenece a los botones, no es
     un tercer bloque suelto. */
  margin-block-start: calc(var(--sp-3) - var(--sp-6));
}
/* Sólo la cifra va en mono: es el dato, el resto es frase */
.hero__note b {
  font-family: var(--font-mono);
  color: var(--text-primary);
  font-weight: var(--fw-medium);
  font-variant-numeric: tabular-nums;
}


/* --------------------------------------------------------------------------
   4. SERVICIOS Y PRECIOS — filas, no tarjetas. Tres cajas iguales serían el tell.
   -------------------------------------------------------------------------- */

.rows { border-block-start: 1px solid var(--border-strong); }

.row-item {
  display: grid;
  gap: var(--sp-4);
  padding-block: clamp(var(--sp-6), 3vw, var(--sp-8));
  border-block-end: 1px solid var(--border-hairline);
}
@media (min-width: 54rem) {
  .row-item {
    grid-template-columns: 3fr 6fr 3fr;
    gap: var(--grid-gap);
    align-items: start;
  }
}
/* Regla de la página: la mono es para DATOS. Un «Desde cero» es prosa, así que
   va en la de texto; el plazo y el precio de la sección 02 sí son datos. */
.row-item__meta {
  font-size: var(--fs-body-sm);
  color: var(--text-tertiary);
  letter-spacing: var(--tr-small);
}
.rows--price .row-item__meta {
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  letter-spacing: 0;
}
/* El precio es el dato que se busca: sube a texto principal y se lleva la
   línea entera. Lo de debajo (plazo) se queda en terciario. */
.row-item__meta b {
  display: block;
  color: var(--text-primary);
  font-weight: var(--fw-medium);
  font-variant-numeric: tabular-nums;
}
@media (min-width: 54rem) { .row-item__meta { text-align: end; } }

/* Sección 02: la misma fila, con la cifra a tamaño de titular. No se abre una
   rejilla nueva —la home sigue teniendo una sola simétrica, la del método—:
   sólo cambia el peso tipográfico de la columna que importa. */
.rows--price .row-item__meta b {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  font-weight: var(--fw-medium);
  line-height: var(--lh-title);
  letter-spacing: var(--tr-h2);
  margin-block-end: var(--sp-2);
  /* El signo del euro y el punto de millar no deben partirse de la cifra */
  text-wrap: balance;
}
@media (min-width: 54rem) {
  /* La cifra pide más sitio que un «Diseño + código» */
  .rows--price .row-item { grid-template-columns: 3fr 5fr 4fr; }
}


/* --------------------------------------------------------------------------
   5. MÉTODO — la ÚNICA rejilla simétrica de la home (A5). Se gasta aquí.
   -------------------------------------------------------------------------- */

.steps {
  display: grid;
  gap: var(--grid-gap);
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}


/* --------------------------------------------------------------------------
   6. LISTA DE DOS COLUMNAS — planes, tablas de valores

   El espécimen tipográfico («Aa.» y el abecedario) vivía aquí, en la home.
   Se ha ido a styleguide.html, que es donde tiene sentido: la home la lee un
   cliente, no un diseñador.
   -------------------------------------------------------------------------- */
.readout { border-block-start: 1px solid var(--border-strong); }
.readout div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  padding-block: var(--sp-4);
  border-block-end: 1px solid var(--border-hairline);
  font-size: var(--fs-body-sm);
  letter-spacing: var(--tr-small);
}
.readout dt { color: var(--text-primary); font-weight: var(--fw-medium); }
.readout dd { color: var(--text-secondary); text-align: end; }
.readout .swatch {
  display: inline-block;
  width: 0.75rem; height: 0.75rem;
  border-radius: var(--r-xs);
  background-color: var(--accent);
  border: 1px solid var(--border-strong);
  transform: translateY(1px);
  margin-inline-end: var(--sp-2);
}


/* --------------------------------------------------------------------------
   7. LÍMITES — lista con marca propia de trazo, jamás un emoji (A13)
   -------------------------------------------------------------------------- */

.limits { border-block-start: 1px solid var(--border-strong); }
.limits li {
  display: grid;
  grid-template-columns: 1.25rem 1fr;
  gap: var(--sp-4);
  align-items: start;
  padding-block: var(--sp-5);
  border-block-end: 1px solid var(--border-hairline);
  color: var(--text-secondary);
  font-size: var(--fs-body-lg);
  line-height: 1.5;
}
.limits svg { color: var(--text-tertiary); margin-block-start: 0.3em; }
.limits b { color: var(--text-primary); font-weight: var(--fw-medium); }


/* --------------------------------------------------------------------------
   8. BLOQUE PENDIENTE — regla 3 del proyecto: nada inventado.
   Lo que falta se ve que falta. El borde discontinuo lo dice sin texto.
   -------------------------------------------------------------------------- */

.pending {
  display: grid;
  gap: var(--sp-3);
  padding: clamp(var(--sp-5), 2.5vw, var(--sp-7));
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-md);
  background-color: var(--surface-sunken);
}
.pending p { color: var(--text-secondary); font-size: var(--fs-body-sm); max-width: var(--measure-prose); }
/* .pending p (0-1-1) le ganaba a .t-accent (0-1-0), así que la etiqueta del
   bloque no llegaba a pintarse nunca con el acento. */
.pending .t-accent { color: var(--text-accent); }
.pending code {
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  color: var(--text-primary);
}
[data-pending='off'] .pending { display: none; }


/* --------------------------------------------------------------------------
   9. CONTACTO
   -------------------------------------------------------------------------- */

.contact__claim { max-width: 18ch; margin-block-end: clamp(var(--sp-7), 4vw, var(--sp-9)); }
.contact__grid { display: grid; gap: clamp(var(--sp-8), 5vw, var(--sp-11)); }
@media (min-width: 62rem) { .contact__grid { grid-template-columns: 5fr 6fr; } }


/* --------------------------------------------------------------------------
   10. PIE / COLOFÓN
   -------------------------------------------------------------------------- */

/* El pie cierra en tinta, y no por gusto: la firma en ascii trae el fondo
   negro pegado al archivo, así que o el pie es oscuro o la imagen se queda
   como un rectángulo posado encima del papel. En tinta ese negro deja de
   existir —lo funde `mix-blend-mode` unas líneas más abajo— y lo que se ve
   es sólo el dibujo de las letras. La hairline de arriba sobra: el cambio de
   superficie ya separa el pie de la sección anterior con más claridad de la
   que daba una línea de 1 px. */
.site-footer {
  isolation: isolate;      /* la fusión se queda dentro del pie */
}

/* La firma, a lo ancho del armazón y nunca más grande que el archivo
   —1536 px—: el armazón tope en 90rem menos los márgenes se queda por debajo,
   así que las letras no se interpolan ni se emborronan en un monitor ancho. */
.site-footer__art {
  display: block;
  padding-block-start: clamp(var(--sp-8), 5vw, var(--sp-10));
  border-radius: var(--r-xs);
}
.site-footer__art img {
  display: block;
  width: 100%;
  height: auto;
  /* El negro del archivo no se retoca en Photoshop: se funde. `lighten` deja
     pasar lo que es MÁS CLARO que el fondo —las letras— y sustituye el resto
     por la tinta del pie. Si mañana cambia el token de la tinta, la firma se
     adapta sola: no hay un negro escrito en ningún sitio. */
  mix-blend-mode: lighten;
}
/* Sin fusión (navegador antiguo, o modo de alto contraste) la imagen se ve
   con su negro original. Es el peor caso y sigue siendo legible: negro sobre
   tinta, no negro sobre papel. */
@supports not (mix-blend-mode: lighten) {
  .site-footer__art img { opacity: 0.92; }
}

.site-footer__grid {
  display: grid;
  gap: var(--sp-8);
  padding-block: clamp(var(--sp-8), 4vw, var(--sp-10));
}
@media (min-width: 54rem) {
  .site-footer__grid { grid-template-columns: 4fr 4fr 3fr; gap: var(--grid-gap); }
}
.site-footer p {
  font-size: var(--fs-body-sm);
  color: var(--text-tertiary);
  line-height: 1.6;
  max-width: 34ch;
}
.site-footer a { color: var(--text-secondary); }
.site-footer__links { display: grid; gap: var(--sp-3); justify-items: start; }
.site-footer__base {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  justify-content: space-between;
  padding-block: var(--sp-5);
  border-block-start: 1px solid var(--border-hairline);
}

/* Un valor que el panel de desarrollo actualiza en vivo */
.live { color: var(--text-primary); font-family: var(--font-mono); letter-spacing: 0; }


/* --------------------------------------------------------------------------
   11. ILUSTRACIÓN DEL HERO
   Una sola imagen, colocada por tokens. El ancla es el CENTRO —translate de
   -50%— porque así arrastrarla mueve lo que se ve: si el ancla fuese la
   esquina, al agrandar la imagen se desplazaría sola.

   El sitio se mide contra .hero, no contra .hero__inner: la caja interior
   está limitada por el ancho de la rejilla, y ahí la imagen no podría
   asomarse por el borde derecho.
   -------------------------------------------------------------------------- */

.hero__art {
  position: absolute;
  z-index: 0;
  /* El sitio que se pinta NO es siempre el del token: js/hero-art.js escribe
     --art-*-eff cuando hace falta echar la imagen para dentro para que no la
     corte el borde del hero. El token es la intención y no se toca; la
     corrección es de pintura y desaparece en cuanto vuelve a caber. */
  inset-block-start: var(--art-y-eff, var(--art-y));
  inset-inline-start: var(--art-x-eff, var(--art-x));
  /* Nunca por encima del tamaño del archivo: a partir de 1536 px no hay más
     detalle que enseñar, sólo interpolación —y esta ilustración es de trama
     fina, que es justo lo que peor aguanta que se estire—. */
  width: min(var(--art-w), 1536px);
  /* La proporción está en la caja y no sólo en el archivo: así el hueco ya
     tiene la forma correcta antes de que la imagen cargue, y nada salta. */
  aspect-ratio: 1536 / 1024;
  translate: -50% -50%;
  opacity: var(--art-op);
  pointer-events: none;      /* el modo de colocar lo vuelve a encender */
  user-select: none;
}

/* Ancho al 100 % y alto automático: la imagen conserva su proporción pase lo
   que pase con la ventana. Nunca se estira para rellenar. */
.hero__art img {
  display: block;
  width: 100%;
  height: auto;
}

/* El texto por delante de la imagen, siempre. Es la regla que hace que la
   ilustración se pueda colocar donde sea sin que nada quede ilegible. */
.hero__inner { z-index: 1; }

/* Por debajo de la rejilla de 12 columnas la entradilla ocupa todo el ancho
   y ya no queda hueco a la derecha: la imagen deja de flotar y pasa a ser un
   bloque más, después del texto. Ahí los tokens de sitio no pintan nada. */
@media (max-width: 61.999rem) {
  .hero { display: flex; flex-direction: column; }
  .hero__inner { order: 1; }
  .hero__art {
    order: 2;
    position: static;
    width: 100%;
    translate: none;
    margin-block-end: clamp(var(--sp-8), 6vw, var(--sp-10));
  }
}


/* --------------------------------------------------------------------------
   12. KICKER DE SECCIÓN
   El nombre de la sección, en Switzer y en caja baja. NO lleva número y NO
   lleva mono ni versalitas: la micro-etiqueta `01 SERVICIOS` está retirada de
   la web pública (regla 5 del README, listón A15). Aquí sólo hay una palabra
   y una regla horizontal que la acompaña hasta el borde.
   -------------------------------------------------------------------------- */

.section-kicker {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tr-small);
  color: var(--text-tertiary);
}
.section-kicker::after {
  content: '';
  flex: 1;
  height: 1px;
  background-color: var(--border-hairline);
}


/* --------------------------------------------------------------------------
   13. SERVICIOS · LA EMPRESA
   Texto largo a la izquierda y ficha de datos a la derecha: la asimetría la
   pone el reparto 7/4, no un bloque desplazado.
   -------------------------------------------------------------------------- */

.intro {
  display: grid;
  gap: clamp(var(--sp-7), 4vw, var(--sp-9));
  margin-block-end: clamp(var(--sp-9), 5vw, var(--sp-12));
}
@media (min-width: 62rem) {
  .intro {
    grid-template-columns: 7fr 4fr;
    gap: clamp(var(--sp-8), 6vw, var(--sp-12));
    align-items: start;
  }
}
.intro__text p { max-width: var(--measure-prose); }
/* La ficha se queda arriba aunque el texto de al lado siga bajando */
.intro__facts { position: sticky; inset-block-start: calc(var(--header-h) + var(--sp-6)); }
@media (max-width: 61.999rem) { .intro__facts { position: static; } }


/* --------------------------------------------------------------------------
   14. SERVICIOS · LOS TRES ENCARGOS
   Tres paneles, y el primero en tinta. Una tarjeta oscura entre dos claras
   dirige la mirada sin necesidad de una pegatina de «el más popular».
   Radio --r-lg porque son paneles, no tarjetas (components.css §4).
   -------------------------------------------------------------------------- */

.services {
  display: grid;
  gap: var(--grid-gap);
}
/* Tres tarjetas en dos columnas dejan una huérfana a media fila. En ese tramo
   la tercera ocupa la fila entera: deja de parecer un hueco y pasa a leerse
   como lo que es —el mantenimiento, que va después de las otras dos—. */
@media (min-width: 52rem) {
  .services { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .services .service:last-child { grid-column: 1 / -1; }
}
@media (min-width: 72rem) {
  .services { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .services .service:last-child { grid-column: auto; }
}
/* A fila completa la tarjeta no necesita estirar su contenido a lo ancho */
@media (min-width: 52rem) and (max-width: 71.999rem) {
  .services .service:last-child .service__body,
  .services .service:last-child .service__list { max-width: var(--measure-prose); }
}

.service {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding: clamp(var(--sp-6), 2.6vw, var(--sp-8));
  border: 1px solid var(--border-hairline);
  border-radius: var(--r-lg);
  background-color: var(--surface-raised);
  transition:
    border-color var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out);
}
.service:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-2);
}
/* La tarjeta en tinta se queda en la superficie ELEVADA de su propio modo, no
   en el fondo de página: dentro de una sección clara, un negro absoluto se lee
   como un agujero y no como una tarjeta. `.surface-ink` sigue haciendo su
   trabajo —cambiar el bloque de tokens—, sólo se le corrige el fondo. */
.service--feature {
  background-color: var(--surface-raised);
  box-shadow: var(--shadow-2);
}

/* La línea de apoyo del título: prosa corta en Switzer, nunca una etiqueta en
   versalitas. Recorta el gap de la tarjeta para pegarse a su titular. */
.service__tagline {
  font-size: var(--fs-body-sm);
  color: var(--text-tertiary);
  letter-spacing: var(--tr-small);
  margin-block-start: calc(var(--sp-3) - var(--sp-4));
}

/* El titular baja de tamaño dentro de la tarjeta: se toca el TOKEN, no la
   propiedad, para que el deslizador de escala del panel siga mandando. */
.service__title {
  --fs-h2: clamp(1.375rem, 1.15rem + 0.9vw, 1.75rem);
  margin: 0;
}
.service__body { color: var(--text-secondary); max-width: var(--measure-card); }

.service__list { margin-block-start: var(--sp-2); }

.service__price {
  display: grid;
  gap: var(--sp-1);
  margin-block-start: auto;          /* la cifra, siempre al pie */
  padding-block-start: var(--sp-5);
  border-block-start: 1px solid var(--border-hairline);
}
.service__price b {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2rem);
  font-weight: var(--fw-medium);
  line-height: var(--lh-title);
  letter-spacing: var(--tr-h2);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  text-wrap: balance;                /* el € no se separa de la cifra */
}
/* «/mes» y «sin permanencia» son palabras, no medidas: Switzer (listón A15).
   En mono sólo se queda la cifra de la línea de arriba. */
.service__per {
  font-size: 0.5em;
  font-weight: var(--fw-normal);
  letter-spacing: var(--tr-small);
  color: var(--text-tertiary);
}
.service__price span:not(.service__per) {
  font-size: var(--fs-caption);
  letter-spacing: var(--tr-small);
  color: var(--text-tertiary);
}

/* Nota al pie de la sección: la letra pequeña a la izquierda y el enlace a la
   derecha. En estrecho se apilan, y el enlace queda el último. */
.services-note {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4) var(--sp-8);
  margin-block-start: clamp(var(--sp-6), 3vw, var(--sp-8));
}
.services-note p { max-width: var(--measure-prose); flex: 1 1 24rem; }


/* --------------------------------------------------------------------------
   15. RESULTADOS · CIFRAS
   Cuatro datos y nada más. El número va delante de su etiqueta aunque en el
   marcado la etiqueta sea el <dt>: primero se lee la cifra, luego qué es.
   -------------------------------------------------------------------------- */

/* Dos columnas o cuatro, nunca tres y una suelta: con `auto-fit` el reparto
   cambia solo y a media ventana dejaba una cifra descolgada en su propia
   fila. Cuatro datos se leen en 2×2 igual de bien que en fila. */
.stats {
  display: grid;
  gap: var(--sp-6) var(--grid-gap);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border-block-start: 1px solid var(--border-strong);
}
@media (min-width: 64rem) { .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.stat {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding-block-start: clamp(var(--sp-5), 2.5vw, var(--sp-7));
}
.stats dd { margin: 0; }

.stat__num {
  order: 1;
  font-family: var(--font-display);
  font-size: var(--fs-h1);
  font-weight: var(--fw-medium);
  line-height: var(--lh-tight);
  letter-spacing: var(--tr-h1);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
/* La unidad acompaña a la cifra pero se lee como palabra: Switzer */
.stat__unit {
  font-size: 0.4em;
  font-weight: var(--fw-normal);
  letter-spacing: var(--tr-small);
  color: var(--text-tertiary);
  margin-inline-start: var(--sp-2);
}
.stat__label {
  order: 2;
  font-size: var(--fs-body-sm);
  color: var(--text-primary);
  letter-spacing: var(--tr-small);
}
.stat__note {
  order: 3;
  font-size: var(--fs-caption);
  color: var(--text-tertiary);
  margin-block-start: calc(var(--sp-1) * -1);
}


/* --------------------------------------------------------------------------
   16. BANDA DE LLAMADA — el paso a la galería, y el cierre de la galería
   -------------------------------------------------------------------------- */

.cta-band {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-6);
  margin-block-start: clamp(var(--sp-8), 4vw, var(--sp-11));
  padding: clamp(var(--sp-6), 3vw, var(--sp-8));
  border: 1px solid var(--border-strong);
  border-radius: var(--r-lg);
}
/* Sola en su sección no tiene de qué separarse */
.cta-band--solo { margin-block-start: 0; }
.cta-band__text { display: grid; gap: var(--sp-2); max-width: 46ch; }
.cta-band h3 { margin: 0; }


/* --------------------------------------------------------------------------
   17. TESTIMONIOS — galería en columnas de altura libre.
   `columns` y no `grid`: las citas no miden lo mismo y una rejilla las
   obligaría a fingir que sí, dejando huecos debajo de las cortas.
   -------------------------------------------------------------------------- */

.quotes { column-gap: var(--grid-gap); }
@media (min-width: 46rem) { .quotes { columns: 2; } }
@media (min-width: 76rem) { .quotes { columns: 3; } }
@media (min-width: 70rem) { .quotes--wide { columns: 2; } }

.quote {
  break-inside: avoid;
  margin: 0 0 var(--grid-gap);
  padding: clamp(var(--sp-5), 2.4vw, var(--sp-7));
  border: 1px solid var(--border-hairline);
  border-radius: var(--r-lg);
  background-color: var(--surface-raised);
  transition: border-color var(--dur-base) var(--ease-out);
}
.quote:hover { border-color: var(--border-strong); }

/* La comilla es del acento, y es de las pocas cosas que lo son: el
   presupuesto de color de la página es menos del 3% del área. */
.quote::before {
  content: '\201C';
  display: block;
  font-family: var(--font-display);
  font-size: 2.75rem;
  font-weight: var(--fw-medium);
  line-height: 0.7;
  color: var(--text-accent);
  margin-block-end: var(--sp-3);
}
.quote blockquote { margin: 0; }
.quote p {
  font-size: var(--fs-body-lg);
  line-height: 1.55;
  color: var(--text-primary);
  text-wrap: pretty;
}
/* La primera cita pesa más que las demás: es la que se lee seguro */
.quote--lead p {
  font-size: var(--fs-h3);
  line-height: var(--lh-h3);
  letter-spacing: var(--tr-h3);
}

.quote__who {
  display: grid;
  gap: 2px;
  margin-block-start: var(--sp-5);
  padding-block-start: var(--sp-4);
  border-block-start: 1px solid var(--border-hairline);
}
.quote__name {
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-medium);
  color: var(--text-primary);
}
.quote__role { font-size: var(--fs-caption); color: var(--text-tertiary); }


/* --------------------------------------------------------------------------
   18. CONTACTO
   -------------------------------------------------------------------------- */

/* Dentro de una cabecera de sección el reclamo ya no paga su propio hueco */
.section-head .contact__claim { margin-block-end: 0; }

.contact-list {
  display: grid;
  border-block-start: 1px solid var(--border-strong);
  margin-block-end: var(--sp-6);
}
.contact-list li {
  display: grid;
  grid-template-columns: 1.25rem 1fr;
  gap: var(--sp-4);
  align-items: center;
  padding-block: var(--sp-5);
  border-block-end: 1px solid var(--border-hairline);
}
.contact-list svg { color: var(--text-tertiary); }
.contact-list__pair { display: grid; gap: 2px; }
.contact-list__label { font-size: var(--fs-caption); color: var(--text-tertiary); }
/* Un correo y un teléfono son texto, no una medida: van en Switzer. La mono
   se reserva para cifras que se comparan entre sí (listón A15). */
.contact-list__value {
  font-size: var(--fs-body-lg);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tr-body);
  color: var(--text-primary);
  text-decoration: none;
  justify-self: start;
  transition: color var(--dur-instant) var(--ease-in-out);
}
.contact-list__value:hover { color: var(--text-accent); }

.contact__hours {
  max-width: var(--measure-lead);
  margin-block-end: clamp(var(--sp-6), 3vw, var(--sp-8));
}


/* --------------------------------------------------------------------------
   19. GALERÍA (trabajos.html) — cabecera de página
   -------------------------------------------------------------------------- */

.page-head {
  padding-block: clamp(var(--sp-8), 6vw, var(--sp-12)) clamp(var(--sp-7), 4vw, var(--sp-9));
  border-block-end: 1px solid var(--border-hairline);
}
.back-link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-body-sm);
  color: var(--text-tertiary);
  text-decoration: none;
  margin-block-end: clamp(var(--sp-6), 3vw, var(--sp-8));
  transition: color var(--dur-instant) var(--ease-in-out);
}
.back-link:hover { color: var(--text-primary); }
.page-head__title { max-width: 14ch; margin-block-end: var(--sp-6); }
.page-head__lead { max-width: var(--measure-lead); }
.page-head__pending { margin-block-start: clamp(var(--sp-7), 4vw, var(--sp-9)); max-width: 62ch; }


/* --------------------------------------------------------------------------
   20. GALERÍA — fichas de proyecto

   La miniatura es un dibujo de la página hecho con CSS, no una captura
   inventada. Cuando haya proyectos reales entra un <img> en su sitio y todo
   el bloque .mock se puede borrar de una vez.
   -------------------------------------------------------------------------- */

/* Seis fichas: 1, 2 o 3 columnas reparten exacto en los tres casos. Los
   saltos se declaran a mano en vez de dejarlos a `auto-fit`, que con este
   ancho mínimo colaba un tramo de cuatro columnas y dos huérfanas. */
.works {
  display: grid;
  gap: clamp(var(--sp-8), 4vw, var(--sp-10)) var(--grid-gap);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 36rem) { .works { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 72rem) { .works { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.work { display: flex; flex-direction: column; gap: var(--sp-3); }
.work__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-block-start: var(--sp-5);
}
.work__title { margin: 0; }
/* Qué encargo fue. Iba en una píldora en versalitas y ahora es lo que era: una
   palabra. El acento la distingue del año sin necesidad de una caja. */
.work__kind {
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tr-small);
  color: var(--text-accent);
}
.work__body { max-width: var(--measure-card); }
.work__stats {
  display: grid;
  gap: var(--sp-2);
  margin-block-start: auto;
  padding-block-start: var(--sp-4);
  border-block-start: 1px solid var(--border-hairline);
}
.work__stats div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  font-size: var(--fs-caption);
}
.work__stats dt { color: var(--text-tertiary); }
/* La columna derecha son medidas que se comparan de ficha a ficha: es el sitio
   donde la mono sigue teniendo trabajo (listón A15). */
.work__stats dd {
  margin: 0;
  font-family: var(--font-mono);
  letter-spacing: 0;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  text-align: end;
}

.mock {
  display: flex;
  flex-direction: column;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border: 1px solid var(--border-hairline);
  border-radius: var(--r-lg);
  background-color: var(--surface-sunken);
  transition:
    border-color var(--dur-base) var(--ease-out),
    transform var(--dur-base) var(--ease-out);
}
.work:hover .mock { border-color: var(--border-strong); transform: translateY(-3px); }

.mock__bar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: var(--sp-3) var(--sp-4);
  border-block-end: 1px solid var(--border-hairline);
  background-color: var(--surface-raised);
}
.mock__bar i { width: 7px; height: 7px; border-radius: var(--r-full); background-color: var(--border-strong); }

.mock__body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  flex: 1;
  padding: clamp(var(--sp-4), 2vw, var(--sp-6));
}
.mock__title {
  height: 0.875rem;
  width: 45%;
  border-radius: var(--r-xs);
  background-color: var(--text-tertiary);
}
.mock__title--wide { width: 68%; }
.mock__line { height: 0.5rem; border-radius: var(--r-xs); background-color: var(--border-strong); }
.mock__line--short { width: 58%; }
.mock__accent {
  height: 1.5rem;
  width: 38%;
  margin-block-start: auto;
  border-radius: var(--r-full);
  background-color: var(--accent);
}
.mock__grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-2); flex: 1; }
.mock__grid--two { grid-template-columns: repeat(2, 1fr); }
.mock__grid i { border-radius: var(--r-sm); background-color: var(--border-hairline); border: 1px solid var(--border-strong); }
.mock__split { display: grid; grid-template-columns: 3fr 2fr; gap: var(--sp-3); flex: 1; }
.mock__col { display: grid; gap: var(--sp-2); align-content: start; }
.mock__col i { height: 0.5rem; border-radius: var(--r-xs); background-color: var(--border-strong); }
.mock__col i:last-child { width: 60%; }
.mock__accent--tall { width: 100%; height: auto; margin: 0; border-radius: var(--r-sm); }

/* Cuatro variantes de densidad: si las seis miniaturas fuesen idénticas se
   leerían como un patrón de relleno, que es justo lo que no son. */
.mock[data-mock='b'] .mock__title { width: 34%; }
.mock[data-mock='c'] .mock__bar i:first-child { background-color: var(--accent); }
.mock[data-mock='e'] .mock__title { width: 56%; }
.mock[data-mock='f'] .mock__accent { width: 52%; }
