/* ═══════════════════════════════════════════════════════════════════════════
   Kitchen Remodeler Davie — identidad visual
   2026-08-10 · se carga ENCIMA de base.css

   DESIGN READ
   Un contratista licenciado que rehace cocinas de 1987 en un suburbio del sur
   de Florida, vendiéndole certeza a una pareja que paga con ahorros. Tiene que
   leerse SUSTANCIAL Y VERIFICABLE, no aspiracional.

   POR QUÉ ESTOS COLORES
   La casa mediana de Davie es de 1987, y en el sur de Florida eso es teja de
   barril y estuco. La terracota es el color del parque de viviendas del que
   habla todo el sitio: material, no decorativo. Y no es azul — que es lo que
   usan la referencia descartada y medio local pack.

   POR QUÉ ESTAS FUENTES
   Archivo es un grotesque americano de señalética: el cartel de la obra.
   IBM Plex Sans es humanista con ADN de ingeniería y aguanta las 1.600
   palabras de una página sin cansar. El contraste es de ANCHO Y PESO, no de
   serif contra sans — la marca no es editorial ni de lujo.

   Las dos son OFL y se sirven desde /assets/fonts/. Cero CDN.

   HEX Y NO OKLCH, a propósito: el parse_color de verificar.py lee hex y rgb().
   En OKLCH el bloque C queda ciego y deja de medir contraste.
   ═══════════════════════════════════════════════════════════════════════════ */

@font-face {
  font-family: "Archivo";
  src: url("/assets/fonts/archivo-variable.woff2") format("woff2-variations");
  font-weight: 400 900;
  font-stretch: 100% 125%;
  font-display: swap;
}

@font-face {
  font-family: "Plex";
  src: url("/assets/fonts/ibm-plex-sans-variable.woff2") format("woff2-variations");
  font-weight: 400 600;
  font-display: swap;
}

/* ── Tokens ────────────────────────────────────────────────────────────────
   UNA SOLA APARIENCIA, CLARA. El selector doble no es un capricho: base.css
   redefine sus tokens dentro de `@media (prefers-color-scheme: dark)` con
   `:root:not([data-theme="light"])`, que tiene MÁS especificidad que `:root`.
   Un `:root` pelado acá no lo pisaría y el sitio se daría vuelta solo. */
:root,
:root:not([data-theme="light"]) {
  /* superficies claras */
  --papel:      #f2f2f0;   /* el fondo. Neutro de verdad: el beige/crema es el
                              default de IA de 2026 y se reconoce al instante */
  --blanco:     #ffffff;
  --tinta:      #1a1714;
  --cuerpo:     #3e3a34;
  --mute:       #6b655b;
  --pelo:       #dfdcd5;

  /* superficies oscuras — el CTA y el pie van PEGADOS y se separan por VALOR */
  --profunda:   #221d17;
  --pie:        #15110d;
  --claro:      #ede8e0;
  --claro-mute: #b5aba0;
  --pelo-osc:   #3a332b;

  /* acento — terracota quemada. ÚNICO. */
  --acento:     #b4451f;
  --acento-osc: #8f3517;
  --acento-cl:  #e0673a;   /* el mismo tono, subido, para fondo oscuro */
  --acento-tin: #f3e2da;

  --foco:       #b4451f;
  --foco-osc:   #e0673a;

  /* estructura — REQUISITO 6 DEL OPERADOR: los márgenes anchos se controlan
     acá y en un solo lugar, no regla por regla */
  --ancho:      1400px;
  --ancho-texto: 68ch;
  /* El ancho del bloque que se centra cuando la sección no tiene foto: el
     mismo del hero, para que la página tenga un solo eje. Ver «SIN FOTO,
     CENTRADO». */
  --ancho-centrado: 62rem;
  --canaleta:   clamp(1.25rem, 5vw, 4.5rem);
  /* Ritmo vertical de TODA sección — el único lugar donde se decide. Lo
     consume `main > section { padding-block }` y nada más; `.hero` y
     `.site-footer` llevan el suyo propio a propósito.
     2.375rem = 38px · 3.75rem = 60px  →  60 a 1440, 43 a 1024, 38 en móvil.
     Decisión del operador 2026-08-10: se bajó de clamp(4rem,7vw,7rem)
     —100,8px a 1440— porque el sitio se leía demasiado aireado. El número
     sale de una sección medida en vivo y aprobada mirándola, no de una tabla.
     Nota: la referencia de la corrección #40 medía 90px. Esto se aparta de
     ella a propósito. */
  --seccion:    clamp(2.375rem, 4.2vw, 3.75rem);
  /* topbar + cabecera + franja de confianza. Es lo que se le descuenta a la
     altura de la ventana para que HERO + FRANJA ocupen la primera pantalla
     exacta y NO se asome la sección siguiente. */
  --tope:       15rem;
  --radio:      3px;

  --display: "Archivo", "Arial Narrow", system-ui, sans-serif;
  --texto:   "Plex", system-ui, -apple-system, sans-serif;

  /* base.css: se le pisan los tokens para que su modo oscuro no resucite */
  --b-tinta:  #1a1714;
  --b-cuerpo: #3e3a34;
  --b-mute:   #6b655b;
  --b-papel:  #ffffff;
  --b-hunde:  #f2f2f0;
  --b-pelo:   #dfdcd5;
  --b-enlace: #8f3517;
  --b-foco:   #b4451f;
}

/* ═══ BASE ═══════════════════════════════════════════════════════════════ */

body {
  background: var(--papel);
  color: var(--cuerpo);
  font-family: var(--texto);
  font-size: 1.0625rem;
  line-height: 1.7;
  font-synthesis-weight: none;
}

h1, h2, h3 {
  overflow-wrap: break-word;
  font-family: var(--display);
  color: var(--tinta);
  font-weight: 800;
  letter-spacing: -0.025em;   /* piso de impeccable: -0.04em. No se baja de ahí */
  line-height: 1.05;
  text-wrap: balance;
}

/* El H1 lleva el ancla entera y llega a 58 caracteres: se le da aire, no se
   lo aprieta. Techo de 6rem, que es el que impeccable fija para display. */
/* El ancla entera llega a 58 caracteres. A 4rem eso son SEIS líneas y el hero
   se come mil píxeles: el titular deja de ser titular y pasa a ser un muro.
   El techo real es el que lo deja en tres líneas. */
h1 {
  font-size: clamp(2.3rem, 3.9vw, 3.9rem);
  font-stretch: 110%;
  line-height: 1.06;
  margin: 0 0 1.5rem;
}

h2 {
  font-size: clamp(1.85rem, 3vw, 2.75rem);   /* 44px arriba */
  font-stretch: 108%;
  margin: 0 0 1.5rem;
  line-height: 1.1;
}

h3 {
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.3;
  margin: 0 0 0.5rem;
}

p { max-width: var(--ancho-texto); text-wrap: pretty; margin: 0 0 1.1rem; }
p:last-child { margin-bottom: 0; }

a { color: var(--acento-osc); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--acento); }

strong { font-weight: 600; color: var(--tinta); }

/* Foco visible en TODO lo navegable. No se saca nunca. */
:focus-visible {
  outline: 2px solid var(--foco);
  outline-offset: 3px;
  border-radius: 1px;
}

.skip {
  position: absolute; left: -9999px;
  background: var(--tinta); color: var(--claro);
  padding: 0.75rem 1.25rem; z-index: 100;
}
.skip:focus { left: 1rem; top: 1rem; }

/* ── El marcador de sección ────────────────────────────────────────────────
   Reemplaza al titular en dos tonos, que necesitaría un <span> dentro del H1
   y hoy el HTML no lo tiene (gancho #3 pendiente). Una regla corta en acento
   arriba del encabezado cumple la misma función: marca dónde empieza cada
   sección sin depender de que cambie el color del fondo. */
.cats__h2, .why__h2, .area__h2, .faq__h2, .about-resumen__h2,
.reseñas__h2, .form__h2, .cuando__h2, .proceso__h2, .costo__h2,
.criticos__h2, .bloque__h2, .local__h2, .galeria__h2,
.problemas__h2, .servicios-prosa__h2,
.hub-ciudad__h2, .geo__h2, .locations__h2,
/* las cuatro de /about/, que nunca estuvieron: sus H2 salían sin el filete de
   acento y la página se leía como si le faltara algo que las demás sí tienen */
.historia__h2, .propietario__h2, .credenciales__h2, .redes__h2 {
  position: relative;
  padding-top: 1.5rem;
}
.cats__h2::before, .why__h2::before, .area__h2::before, .faq__h2::before,
.about-resumen__h2::before, .reseñas__h2::before, .form__h2::before,
.cuando__h2::before, .variantes__h2::before, .proceso__h2::before, .costo__h2::before,
.criticos__h2::before, .bloque__h2::before, .local__h2::before,
.galeria__h2::before,
.problemas__h2::before, .servicios-prosa__h2::before,
.hub-ciudad__h2::before, .geo__h2::before, .locations__h2::before,
.historia__h2::before, .propietario__h2::before,
.credenciales__h2::before, .redes__h2::before {
  content: "";
  position: absolute; top: 0; left: 0;
  width: 3.5rem; height: 3px;
  background: var(--acento);
}

/* ── Ritmo de sección ─────────────────────────────────────────────────────
   CORRECCIÓN #40: cada sección lleva su PROPIO relleno. Una sección sin
   relleno no se lee como sección, y dos que comparten superficie necesitan un
   separador explícito.

   PRIMERO HAY QUE SOLTAR `main`. base.css lo deja en `max-width: 74rem` y
   centrado — sensato para leer texto sin piel, pero con eso NINGUNA franja
   llega a los bordes: la de confianza y el CTA quedan como cajas flotando en
   el medio de la página. Acá el ancho lo controla cada sección por dentro. */
main {
  max-width: none;
  margin-inline: 0;
  padding: 0;
}

/* El ancho se centra con el RELLENO de la sección, no poniéndole
   `margin-inline: auto` a cada hijo. Con `auto` en los hijos, un párrafo con
   medida corta —la apertura de una página de servicio— se va al centro de la
   página y queda flotando, desalineado con todo lo que tiene arriba y abajo. */
main > section {
  margin-block: 0;
  padding-block: var(--seccion);
  padding-inline: max(var(--canaleta), (100% - var(--ancho)) / 2);
}
/* Solo se saca el centrado. El tope de MEDIDA no se toca: sin él los párrafos
   corren a 1.360 px de ancho, que es el triple de lo legible. */
main > section > * { margin-inline: 0; }

/* ── ALTERNANCIA DE SUPERFICIE: PAPEL / BLANCO, POR NOMBRE ─────────────────
   `--papel` es el default y sólo se NOMBRAN las blancas. Es la mitad de las
   reglas y deja el default a la vista.

   POR QUÉ NO ES `:nth-of-type()` — la corrección #72, ahora en las trece
   plantillas. La versión anterior era `main > section:nth-of-type(even)`, o sea
   que el color de cada sección dependía de CUÁNTAS venían antes. El día que una
   plantilla suma una sección, todo lo que sigue cambia de color: pasó una vez,
   al insertar `variantes` en `gbp_service`, y dio vuelta seis fondos con los
   siete bloques en verde. Se arregló ahí, para un tipo. Acá se arregla para
   todos, y `verificar.py` C7 lo custodia en ERROR.

   `:where()` NO ES DECORATIVO. Aporta cero especificidad, así que cada regla
   pesa (0,1,2) — exactamente lo que pesaba el `:nth-of-type(even)` que
   reemplaza. Sin él, agregar la clase de tipo daría (0,2,2) y estas reglas le
   ganarían a los overrides por variante de más abajo, que hoy le ganan a la
   paridad: el CTA oscuro, las pieles planas de `ficha` y `contacto`, la banda
   de `mosaico`. Con `:where()` el cascade de abajo queda intacto.

   LOS VALORES SON LOS MEDIDOS, no los deducidos. Se leyó el fondo COMPUTADO de
   cada hijo de `main` en las 54 páginas publicadas, con navegador, antes de
   tocar nada. Ninguna página se mueve: lo único que cambia es de qué depende
   el color. */
main > section { background: var(--papel); }

:where(.t-homepage) main > section.cats,
:where(.t-homepage) main > section.costo,
:where(.t-homepage) main > section.reseñas,
:where(.t-homepage) main > section.area,
:where(.t-homepage) main > section.normativa,
:where(.t-homepage) main > section.faq          { background: var(--blanco); }

:where(.t-gbp_category) main > section.apertura,
:where(.t-gbp_category) main > section.servicios-prosa,
:where(.t-gbp_category) main > section.why,
:where(.t-gbp_category) main > section.servicios-grilla,
:where(.t-gbp_category) main > section.galeria  { background: var(--blanco); }

/* `gbp_service` tiene su propio mapa por nombre más abajo, donde vive la #72.
   Acá va sólo `galeria`, que ese mapa nunca declaró porque en su momento la
   sacaba de la paridad. */
:where(.t-gbp_service) main > section.galeria   { background: var(--blanco); }

:where(.t-location_page) main > section.apertura,
:where(.t-location_page) main > section.servicio-ahi,
:where(.t-location_page) main > section.normativa,
:where(.t-location_page) main > section.galeria { background: var(--blanco); }

:where(.t-supporting_content) main > section.faq,
:where(.t-supporting_content) main > section.cta { background: var(--blanco); }

:where(.t-utility.v-about) main > section.historia,
:where(.t-utility.v-about) main > section.area,
:where(.t-utility.v-about) main > section.redes,
:where(.t-utility.v-about) main > section.galeria { background: var(--blanco); }

:where(.t-utility.v-contacto) main > section.contacto,
:where(.t-utility.v-contacto) main > section.refuerzo,
:where(.t-utility.v-contacto) main > section.faq,
:where(.t-utility.v-contacto) main > section.cta { background: var(--blanco); }

/* `.t-utility.v-ficha` —la legal— no entra: sus once secciones ya son blancas
   por nombre en la piel de `ficha`, que es una superficie plana a propósito.
   Reproducirle una alternancia que nunca se pinta sería agregar el código
   muerto que este bloque vino a sacar. */

/* ── LAS SECCIONES QUE SE REPITEN, CON CADENAS DE HERMANOS ─────────────────
   Los tres hubs emiten N bloques iguales en un bucle, así que la clase no los
   distingue y el color TIENE que salir de la posición. La diferencia es de qué
   posición: `:nth-of-type()` cuenta todas las `section` de la página —sumar un
   hero corre el bucle entero—, y `.bloque + .bloque` cuenta sólo dentro de la
   corrida. Sumar una sección afuera no la toca.

   Se nombra el SEGUNDO de tres, que es el único blanco. `+ .bloque + .bloque`
   devuelve al tercero a papel, porque la regla de dos también lo alcanza. */
:where(.t-services_hub) main > section.bloque + section.bloque,
:where(.t-resources_hub) main > section.bloque + section.bloque {
  background: var(--blanco);
}
:where(.t-services_hub) main > section.bloque + section.bloque + section.bloque,
:where(.t-resources_hub) main > section.bloque + section.bloque + section.bloque {
  background: var(--papel);
}
:where(.t-services_hub) main > section.apertura,
:where(.t-services_hub) main > section.faq,
:where(.t-services_hub) main > section.cta      { background: var(--blanco); }

:where(.t-resources_hub) main > section.apertura,
:where(.t-resources_hub) main > section.why,
:where(.t-resources_hub) main > section.galeria { background: var(--blanco); }

:where(.t-locations_hub) main > section.geo + section.geo { background: var(--blanco); }
:where(.t-locations_hub) main > section.geo + section.geo + section.geo {
  background: var(--papel);
}
:where(.t-locations_hub) main > section.hub-intro,
:where(.t-locations_hub) main > section.hub-ciudad,
:where(.t-locations_hub) main > section.faq,
:where(.t-locations_hub) main > section.cta     { background: var(--blanco); }

main > section + section { border-top: 1px solid transparent; }
/* El filete de "dos seguidas comparten superficie" NO se reescribe: era CÓDIGO
   MUERTO y se borra. Decía `nth-of-type(even) + nth-of-type(even)`, y dos
   `<section>` adyacentes tienen paridad OPUESTA por definición, así que no
   coincidía nunca. Se midió: de 386 filetes declarados en las 54 páginas, los
   154 visibles los pintan las reglas por variante de más abajo
   —`ficha`, `contacto`, `legal`, `variantes + proceso`—, ninguno esta. */

/* ═══ BOTONES ════════════════════════════════════════════════════════════ */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 56px;                 /* > 44px, el mínimo táctil */
  padding: 1rem 2rem;
  font-family: var(--display);
  font-size: 1rem; font-weight: 700;
  letter-spacing: 0.02em;
  text-decoration: none;
  border: 2px solid transparent;
  border-radius: var(--radio);
  transition: background-color 160ms ease-out, color 160ms ease-out,
              border-color 160ms ease-out;
}

.btn--primario { background: var(--acento); color: #fff; }
.btn--primario:hover { background: var(--acento-osc); color: #fff; }

.btn--secundario {
  background: transparent; color: var(--tinta); border-color: var(--tinta);
}
.btn--secundario:hover { background: var(--tinta); color: var(--claro); }

.enlace-fuerte {
  font-family: var(--display); font-weight: 700; font-size: 0.98rem;
  letter-spacing: 0.01em; color: var(--acento-osc);
  text-decoration: none; border-bottom: 2px solid var(--acento);
  padding-bottom: 2px;
}
.enlace-fuerte:hover { color: var(--acento); border-bottom-color: var(--acento-osc); }

/* ═══ MARCO ══════════════════════════════════════════════════════════════ */

/* ── Barra superior: el teléfono es el CTA real del rubro ───────────────── */
.topbar {
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem;
  align-items: center; justify-content: center;
  /* MISMA fórmula que `main > section` y que la franja de confianza, no un
     `--canaleta` pelado: la canaleta tope a 72px, así que a 1440 coincidía por
     casualidad y a 1920 la barra arrancaba en x=72 mientras el contenido
     arrancaba en x=260 — 188px de desfase. La superficie sigue a sangre; lo
     que se acota es el CONTENIDO. */
  padding-block: 0.55rem;
  padding-inline: max(var(--canaleta), (100% - var(--ancho)) / 2);
  background: var(--pie); color: var(--claro-mute);
  font-size: 0.85rem;
}
/* ── EL ÁREA TÁCTIL DE LOS CONTROLES DEL CHROME: 44 px ─────────────────────
   Medido en navegador a 360 px sobre las 16 plantillas, 2026-08-17: de 28
   controles, 16 quedaban por debajo del mínimo táctil. Los cuatro que se
   arreglan acá son los del chrome que ya casi llegaban, y el peor de todos:

     topbar__phone        102 × 23   ← el teléfono ES la conversión del rubro
     site-header__cta     155 × 38   ← el botón "Call", 6 px corto
     site-header__logo    242 × 40
     site-nav__list a      88 × 40

   Los ocho enlaces del PIE quedan en 22 px por decisión del operador: llevarlos
   a 44 duplica la altura de ocho filas y es un cambio de diseño, no un ajuste.
   Queda anotado en `notes`, no disimulado.

   `min-height` y no `padding`: el padding hay que recalcularlo cada vez que
   cambia el cuerpo de la fuente, y el número que importa es la ALTURA de la
   caja. Con `align-items: center` el texto queda donde estaba y lo único que
   crece es el área de toque. */
.topbar__phone {
  font-family: var(--display); font-weight: 700; letter-spacing: 0.02em;
  color: var(--claro); text-decoration: none;
  display: inline-flex; align-items: center; min-height: 44px;
}
.topbar__phone:hover { color: var(--acento-cl); }
/* La licencia es el tercer ítem de la barra y el menos urgente de los tres:
   se lee cuando se la busca, no compite con el teléfono. Mismo cuerpo que la
   barra, un punto menos de opacidad. La barra ya es `flex-wrap`, así que en
   móvil baja a su propia línea sola. */
.topbar__licencia { opacity: 0.78; }
.topbar :focus-visible { outline-color: var(--foco-osc); }

/* ── Cabecera ──────────────────────────────────────────────────────────────
   REQUISITO 8 DEL OPERADOR: la nav se identifica como componente y lleva la
   forma del sistema. Los botones tienen radio 3px, así que la nav también:
   es una barra sobre superficie propia, no cinco palabras sueltas. */
.site-header {
  display: grid;
  /* 1fr auto 1fr y no `auto 1fr auto`: con columnas laterales de ancho
     distinto —el logo mide una cosa y el teléfono otra— la nav queda centrada
     respecto de la columna del medio, no de la PÁGINA. Con 1fr a cada lado,
     las dos laterales miden igual y el centro es el centro real. */
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 2rem;
  /* ídem topbar: el contenido de la cabecera se alinea con el de las
     secciones. La marca arranca donde arranca un H2 y el teléfono termina
     donde termina el texto. Ver convenciones §16. */
  padding-block: 1.1rem;
  padding-inline: max(var(--canaleta), (100% - var(--ancho)) / 2);
  background: var(--blanco);
  border-bottom: 1px solid var(--pelo);
}

.site-header__logo {
  font-family: var(--display);
  font-weight: 800; font-stretch: 112%;
  font-size: 1.15rem; letter-spacing: -0.02em; line-height: 1.1;
  color: var(--tinta); text-decoration: none;
  /* fila: símbolo + wordmark. Sin `max-width`: ahora el ancho lo fijan las dos
     piezas, y un tope en `ch` cortaba el nombre al entrar el símbolo. */
  display: flex; align-items: center; gap: 0.7rem;
  min-height: 44px;                 /* área táctil, ver el bloque del topbar */
}
.site-header__simbolo {
  display: block;
  width: 40px; height: 40px;
  flex: 0 0 auto;          /* que la columna de la nav no lo aplaste */
}
.site-header__logo:hover { color: var(--acento-osc); }
/* `:not(.site-header__simbolo)`: esta regla es para el LOGO completo, el que
   reemplaza al wordmark. Sin excluirlo le ganaba por especificidad al símbolo
   y lo estiraba a 44px cuando pide 40. */
.site-header__logo img:not(.site-header__simbolo) {
  display: block; height: 44px; width: auto;
}

/* ── El wordmark en dos líneas ──────────────────────────────────────────────
   "Kitchen Remodeler" arriba en Archivo pesado; "Davie" debajo, CENTRADO
   contra la línea de arriba y en la tipografía de TEXTO, que es la delgada.
   El contraste no es de tamaño sino de peso y ancho: 800 contra 400. */
.site-header__marca { display: block; }
.site-header__marca-nombre { display: block; white-space: nowrap; }
.site-header__marca-ciudad {
  display: block;
  text-align: center;
  font-family: var(--texto);
  font-weight: 400;
  font-size: 0.78rem;
  letter-spacing: 0.22em;
  /* SIN `text-indent`. El espaciado deja 0.22em de aire después de la última
     letra, así que centrar la caja deja los glifos 0.11em a la izquierda; y el
     Archivo de arriba tiene su propio lateral, que corre su centro óptico
     1,5px a la izquierda del de la caja. Los dos desvíos se cancelan: medido,
     quedan a 0,3px. Compensarlo a mano lo empujaba 3px a la derecha. */
  line-height: 1.5;
  color: var(--mute);
  text-transform: uppercase;
}
.site-header__logo:hover .site-header__marca-ciudad { color: var(--acento-osc); }

/* `min-width: 0` no es opcional: un hijo de grid no baja de su min-content y
   la lista de la nav mide ~600px. Sin esto la PÁGINA ENTERA se ensancha a 600
   y aparece scroll horizontal en móvil — con todo cortado a la derecha. */
.site-nav { justify-self: center; min-width: 0; }
.site-nav__list {
  display: flex; gap: 0.25rem;
  margin: 0; padding: 0.3rem; list-style: none;
  background: var(--papel);
  border: 1px solid var(--pelo);
  border-radius: var(--radio);
}
.site-nav__list a {
  /* `flex` y no `block` sólo para poder centrar el texto dentro de los 44 px
     del área táctil. Ver el bloque del topbar. */
  display: flex; align-items: center; min-height: 44px;
  padding: 0.5rem 0.95rem;
  font-family: var(--display); font-size: 0.9rem; font-weight: 600;
  color: var(--cuerpo); text-decoration: none;
  border-radius: 2px;
  transition: background-color 140ms ease-out, color 140ms ease-out;
}
.site-nav__list a:hover { background: var(--tinta); color: var(--claro); }

.site-header__cta {
  justify-self: end;
  display: flex; flex-direction: column; align-items: flex-end;
  /* `justify-content: center` porque es columna: acá el eje principal es el
     vertical, así que es esto y no `align-items` lo que centra en los 44 px.
     Ver el bloque del topbar. */
  justify-content: center; min-height: 44px;
  text-decoration: none; line-height: 1.2;
}
.site-header__cta-label {
  font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--mute);
}
.site-header__cta-num {
  font-family: var(--display); font-weight: 800; font-size: 1.3rem;
  letter-spacing: -0.01em; color: var(--acento-osc);
}
.site-header__cta:hover .site-header__cta-num { color: var(--acento); }

/* ═══ HERO ═══════════════════════════════════════════════════════════════ */

.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
  max-width: var(--ancho); margin-inline: auto;
  padding: clamp(2.5rem, 4vw, 4rem) var(--canaleta);
  /* HERO + FRANJA = la primera pantalla, exacta. Así el borde de abajo de la
     franja cae en el borde de la ventana y NO se asoma un pedazo de la sección
     siguiente, que es lo que dejaba ese blanco raro debajo. */
  min-height: calc(100svh - var(--tope));

  /* El fondo del hero. Ver diseno/convenciones.md §14. */
  position: relative;
  isolation: isolate;
}
/* Uno por TIPO de página, servido como --hero-fondo desde la plantilla.
   Si el tipo no tiene fondo, la variable no existe, `background-image` queda
   inválida y esto no dibuja nada: el hero se ve como antes. */
/* A SANGRE. El .hero está capado en --ancho (1400px) y centrado, así que un
   `inset: 0` deja el fondo corto: 40px a 1440 y 520px a 1920, con dos franjas
   lisas a los costados que delatan la caja. Se rompe la caja con 100vw.
   `overflow-x: clip` en main absorbe el ancho de la barra de scroll —que 100vw
   sí cuenta— sin crear un contenedor de scroll, que es lo que rompería un
   sticky. Medido a 1440 y 1920 el 2026-08-10. */
.hero::before {
  content: "";
  position: absolute;
  inset-block: 0;
  left: 50%;
  width: 100vw;
  transform: translateX(-50%);
  z-index: -1;
  background-image: var(--hero-fondo);
  background-size: cover;
  background-position: center;
  opacity: var(--hero-fondo-op, 0.10);
}
main { overflow-x: clip; }
.hero__texto { min-width: 0; align-self: center; }

.hero__h1 { position: relative; padding-top: 1.75rem; }
.hero__h1::before {
  content: ""; position: absolute; top: 0; left: 0;
  width: 5rem; height: 4px; background: var(--acento);
}

.hero__sub {
  font-size: clamp(1.1rem, 1.6vw, 1.45rem);
  line-height: 1.5;
  color: var(--cuerpo);
  max-width: 46ch;
  margin-bottom: 2.25rem;
}

.hero__acciones { display: flex; flex-wrap: wrap; gap: 0.85rem; }

.hero__figura { position: relative; margin: 0; min-width: 0; }
.hero__figura { align-self: center; display: flex; }
.hero__figura img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 5;
  max-height: calc(100svh - var(--tope) - 4rem);
  min-height: 460px;
  object-fit: cover;
  border-radius: var(--radio);
  animation: entrar 700ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
@keyframes entrar { from { transform: scale(1.03); } to { transform: none; } }

/* El dato del hero: ficha sólida montada sobre la foto. Es prueba, no adorno */
.hero__dato {
  position: absolute; left: -1px; bottom: 1.75rem;
  display: flex; flex-direction: column;
  padding: 1.1rem 1.5rem 1.15rem;
  background: var(--profunda); color: var(--claro);
  border-left: 4px solid var(--acento);
  max-width: 17rem;
}
.hero__dato b {
  font-family: var(--display); font-weight: 800; font-stretch: 112%;
  font-size: 2.1rem; line-height: 1; letter-spacing: -0.03em;
}
.hero__dato span {
  font-size: 0.85rem; line-height: 1.35; color: var(--claro-mute);
  margin-top: 0.35rem;
}

/* ── VARIANTES DE HERO POR TIPO DE PÁGINA ─────────────────────────────────
   Once tipos con el mismo hero hacen que el sitio se lea como una plantilla
   con la ciudad cambiada, que es justo lo que este modelo intenta no ser. El
   gancho es la clase `t-{tipo}` que `_base.html` pone en el <body>, así que no
   hace falta tocar el HTML de ninguna plantilla.

   homepage    texto ancho a la izquierda · foto vertical a la derecha
   servicio    ESPEJADO: foto cuadrada a la izquierda, texto a la derecha
   categoría   texto a la izquierda · foto apaisada, más baja
   hubs        BANNER: texto arriba a ancho completo, foto apaisada debajo
   utilitarias una sola columna, sin foto */

/* ── servicio: espejado ─────────────────────────────────────────────────── */
.t-gbp_service .hero,
.t-critical_gbp_service .hero {
  grid-template-columns: minmax(0, 0.88fr) minmax(0, 1.12fr);
}
.t-gbp_service .hero__figura,
.t-critical_gbp_service .hero__figura { grid-column: 1; grid-row: 1; }
.t-gbp_service .hero__texto,
.t-critical_gbp_service .hero__texto { grid-column: 2; grid-row: 1; }
.t-gbp_service .hero__figura img,
.t-critical_gbp_service .hero__figura img { min-height: 480px; }
.t-gbp_service .hero__dato,
.t-critical_gbp_service .hero__dato { left: auto; right: -1px; border-left: 0; border-right: 4px solid var(--acento); }

/* ── categoría: foto apaisada, texto con más peso ───────────────────────── */
/* ── categoría: EL MISMO HERO QUE EL HOMEPAGE ───────────────────────────────
   Tenía su propia variante —1.3fr/0.7fr con la foto en 3/4— y nunca se había
   visto, porque hasta el 2026-08-10 no se había renderizado ninguna página de
   categoría. Puesta al lado de las tres aprobadas se leía fuera de línea:
   hero de 674px contra 711, foto de 419x559 contra 479x596. Se saca, y hereda
   el hero base igual que los hubs. Mismo criterio que el bloque de acá abajo:
   la variedad entre tipos la dan el servicio (espejado) y las utilitarias (una
   columna); la categoría no necesita ser la rara. */

/* ── hubs: banner. El texto arriba, la foto apaisada debajo ─────────────── */
/* LOS HUBS USAN EL MISMO HERO QUE EL HOMEPAGE. Se probaron dos variantes —un
   banner a ancho de viewport y una foto apaisada— y las dos se leían rotas: una
   foto apaisada no tiene con qué llenar la altura al lado de un titular de dos
   líneas, y la franja oscura debajo la cortaba. La variedad entre tipos la dan
   el servicio (espejado) y las utilitarias (una columna); el hub no necesita
   ser el raro. */

/* ── location y supporting: la foto arriba, angosta y ancha ─────────────── */
.t-location_page .hero { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }
.t-location_page .hero__figura img { aspect-ratio: 5 / 6; }
.t-supporting_content .hero { grid-template-columns: minmax(0, 1fr); }
.t-supporting_content .hero__texto { max-width: 60ch; }

/* ── utilitarias: una columna, sin foto, y el texto respira ─────────────── */
.t-utility .hero { grid-template-columns: minmax(0, 1fr); }
.t-utility .hero__texto { max-width: 58ch; }

/* ═══ SEÑALES DE CONFIANZA ═══════════════════════════════════════════════
   Franja propia, fuera del hero. Las cuatro son hechos comprobables y están
   en las 37 páginas: es el mecanismo que mantiene coherente el sitio. */
.trust {
  background: var(--profunda);
  padding: 0 var(--canaleta);
}
.trust__lista {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 0; margin: 0 auto; padding: 0; list-style: none;
  max-width: var(--ancho);
}
.trust__item {
  /* El relleno de esta franja NO es decorativo: cierra la cuenta de la primera
     pantalla. topbar 41 + cabecera 88 + franja = --tope (240px). Con la franja
     a 90px sobraban 21 y quedaba una línea clara pegada al borde de abajo. */
  padding: 2.25rem 1.5rem 2.35rem;
  border-left: 1px solid var(--pelo-osc);
  font-family: var(--display); font-weight: 600;
  font-size: 0.92rem; line-height: 1.35;
  color: var(--claro);
}
.trust__item:first-child { border-left: 0; padding-left: 0; }
.trust__item::before {
  content: ""; display: block;
  width: 1.75rem; height: 3px; background: var(--acento-cl);
  margin-bottom: 0.9rem;
}

/* ═══ HOMEPAGE ═══════════════════════════════════════════════════════════ */

/* ── Categorías: grilla. NO son tarjetas flotantes con sombra — son fichas
      planas separadas por filete, que es lo que sostiene la lectura. ────── */
.cats__lista {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 0; margin: 0; padding: 0; list-style: none;
  border-top: 1px solid var(--pelo);
}
.cats__item {
  padding: 2rem 2rem 2.25rem;
  border-bottom: 1px solid var(--pelo);
  border-right: 1px solid var(--pelo);
  background: var(--blanco);
}
.cats__item:last-child { border-right: 0; }
.cats__img {
  display: block; width: 100%; height: auto; aspect-ratio: 4 / 3;
  object-fit: cover; margin-bottom: 1.5rem; border-radius: var(--radio);
}
.cats__item h3 { font-size: 1.5rem; font-stretch: 105%; }
.cats__item h3 a { color: var(--tinta); text-decoration: none; }
.cats__item h3 a:hover { color: var(--acento-osc); }
.cats__item p { color: var(--mute); font-size: 0.98rem; }

/* LA CABECERA DE LA SECCIÓN: título e intro de la categoría primaria a la
   izquierda, figura a la derecha centrada contra ellos. Mismo patrón que
   `.local` y `.servicios-prosa`, y por la misma razón: suelto, el texto ocupaba
   una medida de lectura y dejaba 674 px de blanco al lado — el cuadro exacto de
   la §16. `align-items: center` es la §5: el TEXTO manda la altura. */
.cats__cabecera {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
  margin-bottom: clamp(2rem, 3.5vw, 3rem);
}
.cats__cabecera:not(:has(.cats__figura)) { display: block; }
.cats__texto > *:first-child { margin-top: 0; }
.cats__texto p { color: var(--tinta); font-size: 1.02rem; margin-top: 1.1rem; }
.cats__figura { margin: 0; min-width: 0; }
.cats__figura img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--radio);
}
@media (max-width: 56rem) {
  .cats__cabecera { display: block; }
  .cats__figura { margin-top: 2rem; }
}

/* LA INTRO DE CADA CATEGORÍA. Cuando la tarjeta trae varios párrafos deja de ser
   un blurb y pasa a ser texto de lectura, así que va en tinta y no en gris: el
   `--mute` de arriba estaba pensado para una línea de resumen y a 200 palabras
   se lee lavado. El primer párrafo hace de entradilla. */
.cats__item p + p { margin-top: 1rem; }
.cats__item h3 + p {
  color: var(--tinta); font-size: 1.05rem;
  margin-top: 0.85rem;
}
.cats__item h3 ~ p { color: var(--tinta); }
.cats__item ul {
  margin: 1rem 0 0; padding-left: 1.1rem;
  color: var(--tinta); font-size: 0.98rem;
}
.cats__item li { margin-bottom: 0.35rem; }
/* El enlace de cierre se despega del texto y queda alineado con él: es la
   segunda arista hacia la categoría, además del H3. */
.cats__mas { margin-top: 1.35rem; }
.cats__mas a { font-size: 0.95rem; }

/* ── Why us: split asimétrico, foto a la izquierda ──────────────────────── */
/* `align-items: center` y no `start`: es la §5 —el TEXTO manda la altura y la
   columna de imágenes se centra contra él—. Con `start` la columna arrancaba
   arriba y terminaba mucho antes que el texto, y ese hueco era lo que el
   `sticky` venía a tapar. */
.why {
  display: grid;
  grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
  gap: clamp(2rem, 4vw, 4.5rem);
  align-items: center;
}
/* SIN `position: sticky`. Decisión del operador, 2026-08-10: una foto que se
   queda fija mientras el texto pasa al lado se lee como si se deslizara, y esta
   es la sección más larga del Homepage, así que el efecto duraba media pantalla
   de scroll. Se resuelve con contenido y no con posicionamiento: DOS fotos
   apiladas llenan la columna y la sección queda quieta. */
.why__figura {
  margin: 0; min-width: 0;
  display: grid; gap: 1.25rem;
}
.why__figura img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 3 / 4; object-fit: cover; border-radius: var(--radio);
}
/* LAS DOS SE QUEDAN EN 3:4, y esto se midió en vez de estimarse. La primera
   versión las bajó a 4:3 suponiendo que dos verticales se pasarían del texto:
   medido dieron 902 px contra 1.659 de texto, o sea la mitad. A 3:4 suman 1.588
   contra 1.659 — 71 px por debajo, que es el lado correcto de la §5: el texto
   manda y la figura queda un poco más corta. */
.why__texto h3 {
  font-size: 1.3rem; margin-top: 2.5rem;
  padding-left: 1rem; border-left: 3px solid var(--acento);
}
.why__texto h3:first-of-type { margin-top: 1.5rem; }

/* ── .why SIN figura ────────────────────────────────────────────────────────
   El grid de arriba es del Homepage, que trae [figura][texto]. En categoría y
   en servicio el .why no tiene figura: sus hijos son el H2 y el contenido
   sueltos, así que el H2 caía en una celda y el resto alternaba izquierda /
   derecha. Eso es lo que se veía desalineado. Sin figura: una sola columna. */
.why:not(:has(.why__figura)) { display: block; }
.why:not(:has(.why__figura)) .why__h2 { max-width: 22ch; }

/* Los motivos van POR PUNTOS y no en párrafos: son razones sueltas que se
   escanean, no un argumento que se lee de corrido. Dos columnas, con el filete
   de acento haciendo de viñeta. */
.why:not(:has(.why__figura)) ul {
  list-style: none;
  margin: 2.25rem 0 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr));
  gap: 1.75rem 3.5rem;
}
.why:not(:has(.why__figura)) li {
  padding-left: 1.15rem;
  border-left: 3px solid var(--acento);
  text-wrap: pretty;
}
.why:not(:has(.why__figura)) li strong {
  display: block;
  font-family: var(--display); font-weight: 700;
  font-size: 1.05rem; color: var(--tinta);
  margin-bottom: 0.4rem; letter-spacing: -0.01em;
}
/* la nota de permisos que cierra la sección, separada de la grilla */
.why:not(:has(.why__figura)) ul + p {
  margin-top: 2.5rem; max-width: 76ch;
  color: var(--mute); font-size: 0.95rem;
}

/* ── Reseñas ───────────────────────────────────────────────────────────── */
.reseñas__cabecera {
  /* El HTML trae [5.0] + [div: h2 + reseñas]. `display: contents` disuelve ese
     div y deja los tres como hermanos, y ahí sí se pueden ordenar: primero el
     título, después el par 5.0 / reseñas, todo apilado y centrado. */
  display: flex; flex-direction: column; align-items: center;
  gap: 0.75rem;
  text-align: center;
}
/* SIN FILETE DEBAJO. Decisión del operador, 2026-08-10: la sección se separa
   por superficie como todas las demás, y una línea acá partía el bloque en dos
   justo donde el título, el 5.0 y el conteo tienen que leerse como una unidad. */
.reseñas__cabecera > div { display: contents; }
.reseñas__h2      { order: 1; padding-top: 0; margin: 0; }
.reseñas__rating  { order: 2; }
.reseñas__resumen { order: 3; }
.reseñas__h2::before { display: none; }

/* EL 5.0 VUELVE A SU CUERPO GRANDE. Decisión del operador, 2026-08-10, mirando
   la sección: es el dato, y a 1,5rem no pesaba más que el conteo que lo
   acompaña. Revierte la igualación que había: el par ya no es "dos números del
   mismo tamaño" sino un número y su pie. */
.reseñas__rating, .reseñas__resumen {
  font-family: var(--display); font-weight: 700;
  line-height: 1.2; letter-spacing: -0.01em;
  margin: 0;
}
.reseñas__resumen { font-size: 1.5rem; }
.reseñas__rating {
  color: var(--acento);
  font-size: 3.5rem; font-stretch: 110%; letter-spacing: -0.03em;
}
.reseñas__resumen a { color: var(--cuerpo); text-decoration-thickness: 1px; }
.reseñas__resumen a:hover { color: var(--acento-osc); }
.reseñas__lista {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 2rem; margin-top: 2rem;
}
/* Hoy `reseñas` está vacío a propósito: el 5.0 y las 57 son reales y
   verificados, pero los TEXTOS hay que traerlos del perfil de Google y no se
   inventan. Sin esto la sección dibuja el encabezado y deja un pozo debajo.

   ⚠ SE MEDÍA CON `:empty` Y NUNCA DISPARABA. `:empty` exige CERO nodos hijos,
   y el renderer deja el salto de línea de la plantilla adentro del div: para el
   navegador eso es un nodo de texto, así que el elemento no está vacío. Se veía
   como una franja de aire debajo del conteo en el Homepage, y el filete que
   debía desaparecer con la lista tampoco desaparecía nunca.
   `:not(:has(.reseña))` pregunta lo que de verdad importa —si hay reseñas— y no
   depende de cómo la plantilla indente el HTML. */
.reseñas__lista:not(:has(.reseña)) { display: none; }
.reseña { margin: 0; padding-left: 1.25rem; border-left: 3px solid var(--acento-tin); }
.reseña p { font-size: 1.05rem; }
.reseña cite { font-style: normal; font-size: 0.9rem; color: var(--mute); }

/* ── Área de servicio: dos columnas ────────────────────────────────────── */
.area { }
.area__texto, .area__lista { }
.area > * { max-width: none; }
.area {
  display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
}
/* La columna derecha: foto arriba, filete, ciudades debajo. Las dos piezas
   centradas dentro de la columna y contra el texto de la izquierda, que es lo
   que las hace leer como un bloque y no como dos cosas apiladas. */
.area__col {
  display: grid; gap: 0;
  align-self: center;
  justify-items: center;
}
.area__figura { margin: 0 0 1.5rem; width: 100%; }
.area__figura img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--radio);
}
.area__lista {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 0; margin: 0; padding: 0; list-style: none;
  width: 100%;
  border-top: 2px solid var(--tinta);
  text-align: center;
}
.area__lista li {
  padding: 0.85rem 0.5rem;
  border-bottom: 1px solid var(--pelo);
  font-family: var(--display); font-weight: 600; font-size: 0.98rem;
  color: var(--tinta);
}
/* Con una cantidad impar de ciudades —nueve acá— la última quedaba sola en su
   fila y su filete cortaba a la mitad del ancho. Ocupando las dos columnas, el
   bloque cierra parejo con cualquier cantidad. */
.area__lista li:last-child:nth-child(odd) { grid-column: 1 / -1; }

/* ── LO QUE VA CENTRADO ────────────────────────────────────────────────────
   Se centra lo que es CIERRE O INVITACIÓN —FAQ, About, formulario, prueba
   social, área de cobertura—. Se alinea a la izquierda lo que es LECTURA O
   NAVEGACIÓN. El criterio completo está en diseno/convenciones.md. */
.faq, .about-resumen, .form, .reseñas { text-align: center; }
.faq > *, .form > *, .reseñas > * { margin-inline: auto; }
.faq__h2, .form__h2, .about-resumen__h2 { width: fit-content; margin-inline: auto; }
/* el de reseñas NO: su contenedor ya es un flex centrado y el `auto` lo
   empujaba lejos del 5.0 */
.reseñas__h2 { width: fit-content; }
/* el marcador de acento se recentra con el encabezado */
.faq__h2::before, .form__h2::before,
.about-resumen__h2::before, .reseñas__h2::before,
.problemas__h2::before { left: 50%; transform: translateX(-50%); }

/* ── PROBLEMAS ──────────────────────────────────────────────────────────────
   Es una pregunta al lector, no una sección de lectura: va centrada, como el
   FAQ y el formulario (§1). Y el cuerpo va a DOS columnas — centrar un título
   sobre una columna de texto de 694px en una caja de 1296 lo deja flotando
   lejos de lo que titula. Con las dos columnas el bloque ocupa el ancho y el
   centrado cae donde tiene que caer. */
.problemas__h2 { text-align: center; width: fit-content; margin-inline: auto; }
.problemas__cuerpo {
  columns: 2; column-gap: clamp(2rem, 4vw, 4rem);
  margin-top: 2.25rem;
}
.problemas__cuerpo > * { break-inside: avoid; }
.problemas__cuerpo h3 { break-after: avoid; margin-top: 0; }
.problemas__cuerpo p { margin-bottom: 1.75rem; }
.problemas__cuerpo > *:first-child { margin-top: 0; }
@media (max-width: 56rem) { .problemas__cuerpo { columns: 1; } }

/* ── SECCIONES CON COLUMNA DE IMÁGENES ──────────────────────────────────────
   `local` y `servicios-prosa` pasan a dos columnas SOLO si traen figura, con
   :has(). Sin imágenes se quedan a una columna, como estaban.
   `align-items: center` es la §5 en una línea: el TEXTO manda la altura y la
   columna de imágenes se centra contra él, nunca al revés.

   2026-08-13 · SE SUMAN `historia` y `credenciales`, las dos secciones de
   lectura de /about/. Se extiende esta lista en vez de escribirles un bloque
   propio: el patrón es idéntico y duplicarlo es garantizar que mañana se
   arregle uno y no el otro. Las dos clases existen SOLO en `about.html`
   —medido— así que esto no puede filtrarse a ninguna página viva.
   `propietario` queda fuera a propósito: no tiene slot de imagen genérico, así
   que la §16 la centra sola. */
.local:has(.local__figura),
.servicios-prosa:has(.servicios-prosa__figura),
.historia:has(.historia__figura),
.credenciales:has(.credenciales__figura) {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
}
.local__figura, .servicios-prosa__figura,
.historia__figura, .credenciales__figura {
  margin: 0; min-width: 0;
  display: grid; gap: 1.25rem;
}
.local__figura img, .servicios-prosa__figura img,
.historia__figura img, .credenciales__figura img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--radio);
}
/* Dos fotos en `historia` van 3:2 y no 4:3, por la misma medición que en
   `.apertura`: a 4:3 la columna de imágenes se pasa del texto y pasa a mandar
   ella la altura, que es lo contrario de la §5. */
/* ── LOS SELECTORES DE IMAGEN CUENTAN `<picture>`, NO SÓLO `<img>` ─────────
   Corregido el 2026-08-18, y no es cosmético: eran NUEVE selectores muertos.
   `build.py` envuelve en `<picture>` toda imagen que tenga derivados, así que
   desde que se generaron los `-480` no queda un solo `<img>` suelto en el
   sitio. Todo lo que contaba imágenes dejó de contar:

     · `:has(img:nth-of-type(2|3))`  →  siempre falso
     · `:has(img + img)`             →  siempre falso (dejaron de ser hermanas)
     · `.figura img:nth-of-type(2)`  →  nunca matchea: cada img es la 1ª de SU picture

   Lo que se publicó por eso: la tira de `variantes` a una sola columna y a
   sangre, o sea 1440x1080 por foto y una sección de 4.380 px en las nueve de
   la rama cabinet; las figuras de dos fotos de `cuando` en 3/4 en vez de 4/3,
   apiladas y estiradas; y el mosaico del hero de las location pages publicado
   como una grilla común, sin la foto alta a dos filas ni la cuadrada arriba.

   Ninguno dio síntoma en el CSS —un selector que no matchea no es un error—,
   y por eso hay que decirlo acá: al escribir una regla que cuente imágenes,
   contar `:is(img, picture)`. Pesa lo mismo que `img`, así que la
   especificidad no se mueve, y cubre también la imagen sin derivados, que
   sigue saliendo pelada. */
.historia__figura:has(:is(img, picture) + :is(img, picture)) img { aspect-ratio: 3 / 2; }
@media (max-width: 56rem) {
  .local:has(.local__figura),
  .servicios-prosa:has(.servicios-prosa__figura),
  .historia:has(.historia__figura),
  .credenciales:has(.credenciales__figura) { display: block; }
  .local__figura, .servicios-prosa__figura,
  .historia__figura, .credenciales__figura { margin-top: 2rem; }
}
.faq p, .form p, .about-resumen p, .reseñas p { margin-inline: auto; }

/* ── FAQ: pares, sin cajas. Solo filete entre ítems ─────────────────────── */
.faq__lista { margin: 0; max-width: 60rem; margin-inline: auto; }
.faq__item { border-bottom: 1px solid var(--pelo); }
.faq__item:first-child { border-top: 1px solid var(--pelo); }

/* La sección está centrada, pero el ACORDEÓN va alineado a la izquierda: una
   pregunta centrada con el signo a la derecha se lee torcida, y el ojo tiene
   que buscar dónde arranca cada una al abrirlas y cerrarlas. */
.faq__item { text-align: left; }

.faq__pregunta {
  display: flex; align-items: baseline; gap: 1rem;
  padding: 1.35rem 0;
  cursor: pointer;
  list-style: none;                     /* saca el triangulito de Safari/Firefox */
  font-family: var(--display); font-weight: 700; font-size: 1.15rem;
  color: var(--tinta); line-height: 1.35; letter-spacing: -0.01em;
}
.faq__pregunta::-webkit-details-marker { display: none; }
.faq__pregunta::after {
  content: "+";
  margin-left: auto;
  font-weight: 500; font-size: 1.5rem; line-height: 1;
  color: var(--acento);
  transition: transform 180ms ease;
}
.faq__item[open] .faq__pregunta::after { content: "−"; }
.faq__pregunta:hover { color: var(--acento-osc); }
.faq__pregunta:focus-visible { outline: 2px solid var(--foco); outline-offset: 3px; }

/* `margin-inline: 0` a mano: la regla `.faq p { margin-inline: auto }` de la
   sección centrada le metía la respuesta 110px adentro y la dejaba sin alinear
   con su propia pregunta. */
.faq p.faq__respuesta {
  margin: 0 0 1.5rem; margin-inline: 0; max-width: 72ch;
  color: var(--cuerpo);
}

/* ── About en el Home ──────────────────────────────────────────────────── */
.about-resumen {
  display: grid; grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  gap: clamp(2rem, 3vw, 3rem);
}
.about-resumen__texto { max-width: 62ch; }
.about-resumen__figura { margin: 0; max-width: 30rem; }
.about-resumen__figura img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 7 / 8; object-fit: cover; border-radius: var(--radio);
}

/* ── Formulario ────────────────────────────────────────────────────────── */
.form__nota { color: var(--mute); margin-bottom: 2rem; }
.form__campos {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.25rem 1.5rem; max-width: 44rem; margin-inline: auto;
  text-align: left;   /* las etiquetas y los campos NO se centran: se leen mal */
}
.form__campos label {
  display: flex; flex-direction: column; gap: 0.4rem;
  font-family: var(--display); font-weight: 600; font-size: 0.9rem;
  color: var(--tinta);
}
.form__campos label:nth-last-child(2),
.form__campos label:has(textarea) { grid-column: 1 / -1; }
.form__campos input, .form__campos textarea {
  font-family: var(--texto); font-size: 1rem;
  padding: 0.8rem 0.9rem;
  background: var(--blanco);
  color: var(--cuerpo);
  border: 1px solid var(--pelo);
  border-radius: var(--radio);
}
.form__campos input:hover, .form__campos textarea:hover { border-color: var(--mute); }
.form__opcional {
  font-weight: 400; font-size: 0.8rem; color: var(--mute);
  text-transform: none; letter-spacing: 0;
}
.form__campos button { grid-column: 1 / -1; justify-self: center; }
/* Validación sin JS: el mensaje es contenido, el estilo lo pone :user-invalid */
.form__campos label:has(:user-invalid) { color: var(--acento-osc); }
.form__campos :user-invalid { border-color: var(--acento); }
.form__campos label:has(:user-invalid)::after {
  content: attr(data-error);
  font-family: var(--texto); font-weight: 400; font-size: 0.85rem;
  color: var(--acento-osc);
}

/* ── Galería de trabajos: la piel del carrusel ────────────────────────────
   El mecanismo entero —radios, pista, breakpoint— vive en base.css y no se
   toca acá: esto es solo cómo se ve. Fichas planas sin sombra ni caja, igual
   que `.cats__item`: lo que separa una foto de la de al lado es el aire, no
   un borde.

   OJO CON EL BREAKPOINT. Las cuatro columnas y las flechas viven dentro de
   un `@media (min-width: 60rem)` en base.css. Cualquier regla de acá que
   toque el LAYOUT tiene que ir en la misma consulta o se aplica también en
   móvil, donde no hay flechas y la tira se desliza. Lo de afuera es color,
   tipografía y radio, que valen en los dos. */
.galeria__cabecera { margin-bottom: clamp(2rem, 3.5vw, 3rem); }
.galeria__texto > *:first-child { margin-top: 0; }
.galeria__texto p { color: var(--tinta); font-size: 1.02rem; margin-top: 1.1rem; }

.galeria__figura img { border-radius: var(--radio); }

.galeria__pie { margin-top: 1.25rem; }
.galeria__titulo {
  font-family: var(--display);
  font-size: 1.12rem; font-stretch: 105%; font-weight: 700;
  color: var(--tinta);
  line-height: 1.3;
}
.galeria__detalle {
  display: block;
  margin-top: 0.35rem;
  color: var(--mute);
  font-size: 0.92rem;
}

@media (min-width: 60rem) {
  .galeria__flecha {
    border-color: var(--pelo);
    border-radius: var(--radio);
    background: var(--blanco);
    color: var(--tinta);
    transition: background-color 160ms ease-out, border-color 160ms ease-out,
                color 160ms ease-out;
  }
  /* Solo el label reacciona. El `--off` es un <span>: no lleva hover porque
     no hace nada, y un control que se ilumina sin responder miente. */
  label.galeria__flecha:hover {
    background: var(--acento);
    border-color: var(--acento);
    color: #fff;
  }
  .galeria__flecha--off { border-color: var(--pelo); color: var(--claro-mute); opacity: 1; }
}

/* ═══ CTA + PIE ══════════════════════════════════════════════════════════
   Van PEGADOS, sin blanco entre ellos, y se separan por VALOR. Dos
   superficies oscuras contiguas leen como una sola pieza; un espacio en
   blanco entre el CTA y el pie los parte y el CTA queda huérfano. */
.cta {
  background: var(--profunda) !important;
  border-top: 0 !important;
  text-align: center;
}
.cta__h2 { color: var(--claro); padding-top: 0; max-width: 22ch; margin-inline: auto; }
.cta__h2::before { display: none; }
.cta__texto {
  color: var(--claro-mute); max-width: 52ch;
  margin: 0 auto 2rem; font-size: 1.08rem;
}
.cta .btn--primario { background: var(--acento-cl); color: #1a1714; }
.cta .btn--primario:hover { background: var(--claro); color: var(--profunda); }
.cta :focus-visible { outline-color: var(--foco-osc); }

/* REQUISITO 7 DEL OPERADOR: un pie completo, no una franja. Superficie propia
   a ancho completo, cada bloque en su fila, y el copyright separado abajo. */
/* base.css trae `footer { margin-top: 3rem }`. Son 48 px de BLANCO entre el
   CTA oscuro y el pie oscuro, y aparecen en toda página sin frase de vuelta al
   padre — el Homepage, sin ir más lejos. No se ven hasta mirar el final. */
.site-footer {
  margin-top: 0;
  text-align: center;
  background: var(--pie); color: var(--claro-mute);
  padding-block: clamp(3.5rem, 5vw, 5rem) 2rem;
  /* Columnas al ancho de su contenido y el conjunto CENTRADO. Con columnas
     fijas, los bloques vacíos —redes y legales, que hoy no existen— dejaban
     todo el pie corrido a la mitad izquierda. */
  /* FLEX y no grid: con `auto-fit` las pistas vacías no colapsan —el
     copyright, que abarca de 1 a -1, las mantiene ocupadas— y el pie quedaba
     corrido a la izquierda. En flex solo existen los bloques que se dibujan. */
  /* Centrado NO es amontonado en el medio. Cada bloque toma su parte del ancho
     —`flex: 1`— y centra su texto adentro: el pie se ve amplio y ninguna zona
     queda vacía. */
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  /* CENTRADO y simétrico. Con `space-evenly` y solo dos bloques el conjunto
     se corría a la izquierda: el reparto pesa distinto según el ancho de cada
     bloque. Centrados con una separación fija quedan a la misma distancia del
     medio, se vean dos bloques o cuatro. */
  justify-content: center;
  gap: 2.5rem clamp(3rem, 9vw, 9rem);
  /* La SUPERFICIE va a sangre y el CONTENIDO acotado. Con `max-width` sobre el
     pie, el fondo oscuro se recortaba y quedaban dos franjas claras a los
     costados. Se acota con el relleno, igual que las secciones. */
  max-width: none;
  padding-inline: max(var(--canaleta), (100% - var(--ancho)) / 2);
}
/* Bloques anchos y repartidos parejo. Con `flex: 1` y solo dos bloques, cada
   uno se queda con media página y el texto centrado adentro deja dos zanjas.
   Con un ancho base generoso y `space-evenly`, el pie se ve lleno de punta a
   punta sin que ninguna zona quede vacía. */
.site-footer > nav, .site-footer__datos { flex: 0 1 340px; min-width: 0; }
.site-footer > * { min-width: 0; }
.site-footer__negocio {
  font-family: var(--display); font-weight: 800; font-stretch: 112%;
  font-size: 1.35rem; letter-spacing: -0.02em;
  color: var(--claro); margin-bottom: 1rem;
}
.site-footer address { font-style: normal; margin-bottom: 1rem; line-height: 1.6; }
.site-footer p { max-width: none; margin-inline: auto; }
.site-footer__datos, .site-footer__links,
.site-footer__redes, .site-footer__legales { justify-self: center; }
.site-footer ul { display: flex; flex-direction: column; align-items: center; gap: 0; }
.site-footer a { color: var(--claro); text-decoration: none; }
.site-footer a:hover { color: var(--acento-cl); text-decoration: underline; }
.site-footer__horarios { color: var(--acento-cl); font-weight: 500; }
.site-footer__titulo {
  font-family: var(--display); font-size: 0.75rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--claro-mute); margin-bottom: 0.9rem;
}
.site-footer ul { margin: 0; padding: 0; list-style: none; }
.site-footer li { margin-bottom: 0.5rem; }
.site-footer :focus-visible { outline-color: var(--foco-osc); }
.site-footer__copy {
  flex: 0 0 100%;
  width: min(100%, 40rem); margin: 1.5rem auto 0; padding-top: 1.75rem;
  border-top: 1px solid var(--pelo-osc);
  font-size: 0.85rem; color: var(--claro-mute);
}

/* ═══ PÁGINA DE SERVICIO ═════════════════════════════════════════════════ */

/* La apertura arranca con el ancla y es la primera frase del cuerpo: se le da
   tamaño para que se lea como entrada, no como un párrafo más.

   El tamaño es EL MISMO clamp que `.hero__sub` —a propósito, y no un valor
   parecido—: la apertura y el subtítulo del hero son las dos entradas de la
   página y se leían con medio píxel de diferencia (22.4 contra 23.04 a 1440),
   que es peor que igualarlas. Compartiendo el clamp siguen iguales en todo el
   rango, no sólo en el ancho donde se midió. Se distinguen por color y leading,
   no por cuerpo. Si cambia uno, cambia el otro. */
.apertura p:first-child {
  font-size: clamp(1.1rem, 1.6vw, 1.45rem);
  line-height: 1.55; color: var(--tinta); max-width: 56ch;
}

/* ── Las secciones de prosa larga van a DOS COLUMNAS ──────────────────────
   Un H2 arriba y 600px de texto dentro de una caja de 1400 dejan medio ancho
   vacío: la página se lee desbalanceada, que es exactamente el defecto que
   hundió la piel anterior. El encabezado baja a la columna izquierda y queda
   fijo mientras se lee la derecha. Es composición, y no hace falta tocar el
   HTML para conseguirla. */
.t-gbp_service .cuando,
.t-gbp_service .variantes,
.t-gbp_service .proceso,
.t-gbp_service .costo,
.t-gbp_service .why {
  display: grid;
  grid-template-columns: minmax(0, 0.72fr) minmax(0, 1.28fr);
  /* FILAS EXPLÍCITAS. Con `span 100` sobre filas implícitas el encabezado
     estiraba la sección a 6.065 px de alto — un vacío enorme antes del CTA.
     Declaradas y en min-content, las filas que sobran miden cero. */
  grid-template-rows: repeat(24, min-content);
  column-gap: clamp(2rem, 5vw, 5rem);
  /* row-gap CERO y explícito: la regla `.why` del Homepage usa `gap`, que
     también fija el de filas, y acá eso se multiplica por las 21 filas vacías
     que sobran. Eran 1.500 px de aire fantasma. */
  row-gap: 0;
  align-items: start;
}
.t-gbp_service .cuando > h2,
.t-gbp_service .variantes > h2,
.t-gbp_service .proceso > h2,
.t-gbp_service .costo > h2,
.t-gbp_service .why > h2 {
  /* Abarca TODAS las filas: si se queda en la fila 1, esa fila toma la altura
     del encabezado y el primer párrafo queda separado del segundo por un hueco
     del tamaño del H2. */
  grid-column: 1; grid-row: 1 / -1;
  position: sticky; top: 2rem;
  margin-bottom: 0;
}
.t-gbp_service .cuando > *:not(h2),
.t-gbp_service .variantes > *:not(h2),
.t-gbp_service .proceso > *:not(h2),
.t-gbp_service .costo > *:not(h2),
.t-gbp_service .why > *:not(h2) { grid-column: 2; }

/* ── La apertura: texto a la izquierda, imagen a la derecha ────────────────
   La apertura es texto corto —lleva el ancla y es la primera frase del
   cuerpo— y dejaba la mitad derecha vacía. La imagen ocupa ese hueco y va
   CENTRADA VERTICALMENTE contra el alto del texto, no alineada arriba.
   El slot es opcional: sin `apertura_img` la sección vuelve a una columna. */
.apertura:has(.apertura__figura) {
  display: grid;
  /* La columna de imágenes es angosta a propósito. A 0.85fr mide 607 px, y dos
     fotos 4:3 ahí dan 934 de alto contra 844 de texto: la figura pasa a mandar
     la altura y el texto queda descolgado. A 0.72fr con 3:2 dan 760 y entran
     holgadas, así que se centran contra el texto en vez de estirarlo. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.72fr);
  /* Filas explícitas y row-gap cero, igual que en las secciones de prosa: sin
     esto el contenido se reparte SOLO entre las dos columnas y el texto queda
     zigzagueando en vez de leerse en orden. */
  grid-template-rows: repeat(24, min-content);
  column-gap: clamp(2rem, 5vw, 5rem);
  row-gap: 0;
  /* El texto manda la altura de la sección; la columna de imágenes se centra
     contra él. Al revés —imágenes estiradas— el texto queda descolgado. */
  align-items: start;
}
/* Todo el texto en la izquierda, en orden. La foto a la derecha, abarcando
   todas las filas y CENTRADA contra el alto del texto. */
.apertura:has(.apertura__figura) > *:not(.apertura__figura) { grid-column: 1; }
.apertura__figura {
  grid-column: 2; grid-row: 1 / -1;
  align-self: center;
  display: grid; gap: 1.5rem;
}
/* Dos imágenes con su proporción natural, y la COLUMNA CENTRADA contra el
   texto. Estirándolas para llenar el alto pasaba lo contrario de lo buscado:
   la figura abarca todas las filas del grid, así que al estirarse las estiraba
   a ellas y el texto quedaba arrancando arriba y terminando 102 px antes que
   las fotos — descolgado. Con alto propio, la figura es más baja que el texto
   y se centra contra él. */
.apertura__figura:has(:is(img, picture) + :is(img, picture)) {
  align-self: center;
  grid-template-rows: auto auto;
}
.apertura__figura:has(:is(img, picture) + :is(img, picture)) img { height: auto; aspect-ratio: 3 / 2; }
.apertura p:first-child { max-width: 46ch; }
.apertura__figura { margin: 0; }
.apertura:has(.apertura__figura) > h3 { margin-top: 1.75rem; }
.apertura__figura img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--radio);
}

/* ── Apertura de UN SOLO bloque de texto ───────────────────────────────────
   Cuando la apertura es un único párrafo, la imagen es MÁS ALTA que el texto
   y se invierte el supuesto de la regla de arriba. Medido en
   /small-kitchen-remodel-davie/: texto 208 px, imagen 384, y el texto quedaba pegado
   arriba con 176 px de vacío debajo.

   Ningún `align-*` lo arreglaba, y el motivo no se ve mirando: con
   `repeat(24, min-content)` la figura reparte su alto entre las 24 filas, así
   que la fila del texto medía 226 y las 23 filas VACÍAS se quedaban con 158 px.
   Pariente de la corrección #43 — filas fantasma que sí toman altura.

   Sin las filas explícitas el texto se centra contra la imagen. Pero eso NO se
   puede aplicar a toda apertura: en /services/ —8 bloques y 2 imágenes— la
   sección saltaba de 981 a 1480 px. Por eso el selector exige exactamente DOS
   hijos: un bloque de texto y la figura. Verificado: desfase 88 → 0 px acá,
   y /services/ sin moverse un píxel. */
.apertura:has(.apertura__figura):has(> :nth-child(2):last-child) {
  grid-template-rows: none;
  align-items: center;
}
/* El margen inferior del párrafo caía dentro de la caja centrada y dejaba los
   centros a 9 px. Con la figura al lado, ese margen no separa de nada. */
.apertura:has(.apertura__figura):has(> :nth-child(2):last-child) > p {
  margin-bottom: 0;
}

.proceso ol {
  counter-reset: paso; list-style: none; margin: 0; padding: 0;
  max-width: 60rem;
}
.proceso li {
  counter-increment: paso;
  position: relative;
  padding: 1.4rem 0 1.4rem 4.25rem;
  border-bottom: 1px solid var(--pelo);
}
.proceso li:first-child { border-top: 1px solid var(--pelo); }
.proceso li::before {
  content: counter(paso, decimal-leading-zero);
  position: absolute; left: 0; top: 1.35rem;
  font-family: var(--display); font-weight: 800; font-stretch: 115%;
  font-size: 1.5rem; line-height: 1; letter-spacing: -0.03em;
  color: var(--acento);
}
/* La entradilla de cada paso va en su propia línea, igual que en `why_us`: son
   pasos que se escanean, y un título en negrita a media frase no se escanea. */
.proceso li strong:first-child {
  display: block;
  font-family: var(--display); font-weight: 700;
  font-size: 1.05rem; color: var(--tinta);
  margin-bottom: 0.4rem; letter-spacing: -0.01em;
}

/* La sección que decide la llamada. Los tres párrafos que arrancan en negrita
   son una COMPARACIÓN de fuentes del mercado, no una tabla de precios. */
.costo p strong:first-child { display: block; margin-bottom: 0.25rem; }
.costo h3 { margin-top: 2.5rem; font-size: 1.25rem; }

/* ── PROCESO CON FIGURA ─────────────────────────────────────────────────────
   Mismo patrón que `local` y `servicios-prosa`: dos columnas SOLO si trae
   figura, con :has(). En `gbp_service` la sección no tiene `__texto` ni
   figura, así que esta regla no la toca y sigue igual que estaba.
   `align-items: center` es la §5: el TEXTO manda la altura. */
.proceso:has(.proceso__figura) {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
}
.proceso__figura {
  margin: 0; min-width: 0;
  display: grid; gap: 1.25rem;
}
.proceso__figura img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--radio);
}
/* Con la figura al lado la lista pierde el cap de 60rem: ya la capa la columna. */
.proceso:has(.proceso__figura) ol { max-width: none; }
@media (max-width: 56rem) {
  .proceso:has(.proceso__figura) { display: block; }
  .proceso__figura { margin-top: 2rem; }
}

/* ── LA TABLA DE TRAMOS DE PRECIO ───────────────────────────────────────────
   ACOTADA A `.costo` A PROPÓSITO. Una regla `table` global es exactamente la
   forma del bug del 2026-08-10: la regla de centrado se escribió global y movió
   el CTA de /services/ y /cabinet-maker-davie/ de 539 a 992 px sin que nadie lo
   pidiera. Si mañana otra sección necesita tabla, se promueve la regla ENTONCES
   y se mide antes y después contra las páginas ya aprobadas.

   POR QUÉ TABLA Y NO PROSA. El visitante compara tres rangos contra lo que mide
   cada uno. En prosa eso obliga a releer; en tabla se escanea. Es la única
   sección del sitio donde el contenido es una comparación de tres por tres.

   Sin bordes verticales y sin zebra: el filete horizontal alcanza para separar
   filas y la página no tiene una sola caja con reja en ningún otro lado. */
.costo table {
  width: 100%;
  margin: 2.25rem 0 0;
  border-collapse: collapse;
  font-size: 0.975rem;
  text-align: left;
}
.costo thead th {
  padding: 0 0 0.75rem;
  border-bottom: 2px solid var(--tinta);
  font-family: var(--display); font-weight: 700;
  font-size: 0.8rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--tinta);
  vertical-align: bottom;
}
.costo tbody td {
  padding: 1.15rem 0;
  border-bottom: 1px solid var(--pelo);
  vertical-align: top;
  line-height: 1.55;
}
/* La primera columna es el rango: es el dato que se busca, así que se lee como
   dato y no como prosa. */
.costo tbody td:first-child {
  font-family: var(--display); font-weight: 700;
  font-size: 1.05rem; color: var(--acento);
  letter-spacing: -0.01em;
  white-space: nowrap;
  padding-right: 2rem;
}
.costo th + th, .costo td + td { padding-left: 2rem; }

/* EN ANGOSTO LA TABLA SE APILA, no se encoge ni rueda de costado.

   Se probaron las dos alternativas y las dos fallan. Encogerla deja la segunda
   columna a UNA PALABRA POR LÍNEA y empuja la tercera fuera de la pantalla;
   medido a 390 px el 2026-08-10, con la columna «Where you run into it»
   cortada al medio. Y `display:block; overflow-x:auto` sobre el `<table>` no da
   scroll — al dejar de ser caja de tabla, las celdas se comprimen igual.

   Apilada, cada fila es un bloque: el rango de arriba como titular, qué mide
   debajo, y la fuente al pie en cuerpo chico. Los rótulos de columna se ocultan
   porque no sobreviven al apilado, y no hacen falta: las tres celdas se
   explican solas en ese orden. */
@media (max-width: 44rem) {
  .costo table, .costo tbody, .costo tr, .costo tbody td { display: block; width: auto; }
  .costo thead { display: none; }
  .costo tr { padding: 1.35rem 0; border-bottom: 1px solid var(--pelo); }
  .costo tr:first-child { border-top: 1px solid var(--pelo); }
  .costo tbody td { padding: 0; border: 0; }
  .costo tbody td:first-child {
    white-space: normal; padding-right: 0;
    font-size: 1.15rem; margin-bottom: 0.5rem;
  }
  .costo td + td { padding-left: 0; }
  .costo tbody td:last-child {
    margin-top: 0.6rem;
    font-size: 0.85rem; color: var(--mute);
  }
}

/* ── NORMATIVA Y CREDENCIALES ───────────────────────────────────────────────
   Familia 2 · franja ancha. Los hechos que respaldan el sitio: licencia,
   seguro, garantía, permisos y quién factura.

   NO LLEVA FIGURA, y por eso el `__texto` lo centra la regla de «SIN FOTO,
   CENTRADO» sin que haya que escribir nada acá. La grilla de datos queda a
   ancho completo debajo: es lo que la hace leer como franja y no como otra
   sección de prosa.

   Sin superficie propia: se distingue por ESTRUCTURA, no por color. Un fondo
   nuevo obliga a re-medir contraste (verificar.py bloque C) y a decidir la
   paleta, que es del design system y no de una sección. */
/* MISMO EJE QUE EL TEXTO. La regla de «SIN FOTO, CENTRADO» capa el `__texto` a
   62rem y lo centra; la grilla es su hermana, así que sin esto arranca en x=72
   mientras el H2 arranca en x=224. Dos ejes en una misma sección se ven
   torcidos aunque cada pieza esté bien. Medido el 2026-08-10. */
.normativa__datos {
  margin: 2.75rem auto 0;
  max-width: var(--ancho-centrado);
  display: grid;
  /* DOS columnas, no auto-fit. Con auto-fit y cinco datos quedaba una fila de
     cuatro y uno solo abajo con tres celdas vacías al lado — el mismo hueco que
     la §16 vino a resolver. A dos columnas, un número impar se resuelve con la
     regla de abajo y no queda hueco con ninguna cantidad. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2rem 3rem;
}
/* Si la cantidad es impar, el último ocupa la fila entera en vez de dejar media
   fila vacía. Es la pieza que hace que la franja no dependa de cuántos datos
   cargue datos.json. */
.normativa__dato:last-child:nth-child(odd) { grid-column: 1 / -1; }
@media (max-width: 46rem) {
  .normativa__datos { grid-template-columns: minmax(0, 1fr); }
}
.normativa__dato {
  padding-top: 1rem;
  border-top: 2px solid var(--acento);
}
.normativa__dato dt {
  font-family: var(--display); font-weight: 700;
  font-size: 0.78rem; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--mute);
  margin-bottom: 0.5rem;
}
.normativa__dato dd { margin: 0; font-size: 0.95rem; line-height: 1.55; }
.normativa__dato dd b {
  display: block;
  font-family: var(--display); font-weight: 700;
  font-size: 1.15rem; color: var(--tinta);
  letter-spacing: -0.01em;
  margin-bottom: 0.35rem;
}

/* La frase de vuelta al padre. Va en prosa, dentro del cuerpo. NO es un botón
   ni un breadcrumb: es el único enlace de esa arista del mapa. */
/* Va entre el CTA y el pie, que son las dos superficies oscuras. Centrada,
   porque es una sola frase suelta entre dos bloques a ancho completo: alineada
   a la izquierda se lee como un párrafo huérfano.
   Y SI NO HAY TEXTO NO HAY FRANJA: una banda clara vacía entre dos oscuras es
   una línea blanca que no significa nada. */
.vuelta {
  max-width: 68ch; margin: 0 auto;
  padding: 2.25rem var(--canaleta);
  background: var(--papel);
  color: var(--mute); font-size: 1rem;
  text-align: center; text-wrap: pretty;
}
.vuelta a { font-weight: 600; }
.vuelta > p { margin: 0; }          /* el <p> que trae md() no suma su propio margen */
.vuelta:empty, .vuelta:blank { display: none; }

/* ═══ HUB DE SERVICIOS ═══════════════════════════════════════════════════ */

.bloque { }
.bloque__h2 a { color: var(--tinta); text-decoration: none; }
.bloque__h2 a:hover { color: var(--acento-osc); }
.bloque__resumen { color: var(--mute); max-width: 62ch; margin-bottom: 2rem; }
.bloque__grilla {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 0; margin: 0; padding: 0; list-style: none;
  border-top: 1px solid var(--pelo);
}
.bloque__grilla li {
  padding: 1.35rem 1.5rem 1.5rem 0;
  border-bottom: 1px solid var(--pelo);
  min-width: 0;
}
.bloque__grilla a {
  display: block;
  font-family: var(--display); font-weight: 700; font-size: 1.08rem;
  letter-spacing: -0.01em;
  color: var(--tinta); text-decoration: none; margin-bottom: 0.3rem;
}
.bloque__grilla a:hover { color: var(--acento-osc); }
.bloque__grilla span { display: block; font-size: 0.93rem; color: var(--mute); line-height: 1.55; }

/* ═══ CRÍTICOS ═══════════════════════════════════════════════════════════ */
.criticos { background: var(--profunda) !important; }
.criticos__h2, .criticos h3 a { color: var(--claro); }
.criticos p { color: var(--claro-mute); }
.criticos__lista {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 0; margin: 2rem 0 0; padding: 0; list-style: none;
  border-top: 1px solid var(--pelo-osc);
}
.criticos__item { padding: 1.75rem 1.5rem 1.75rem 0; border-bottom: 1px solid var(--pelo-osc); }
.criticos :focus-visible { outline-color: var(--foco-osc); }

/* ═══ SIN FOTO, CENTRADO — REGLA DEL SITIO ═══════════════════════════════
   Decisión del operador, 2026-08-10. Una sección sin slot de imagen NO se
   deja alineada a la izquierda: su columna de texto se centra en la caja.

   Por qué. El tope de medida legible son ~694 px y la caja mide 1.440: sin
   foto al lado quedan 674 px de blanco a la derecha, y cuatro secciones así
   seguidas se leen como una página a la que le faltan las imágenes. Centrada,
   el mismo texto se lee como una decisión.

   El TEXTO sigue alineado a la izquierda dentro de su columna: lo que se
   centra es el BLOQUE. Prosa larga centrada línea por línea es ilegible —
   eso queda para el CTA y la frase de vuelta, que son cierre (§1).

   Se resuelve con :has() y no con una clase, así que una sección nueva la
   hereda sola: si le llega imagen va a dos columnas, si no, se centra.

   EL ANCHO ES EL DEL HERO —62rem— por decisión del operador, mirando los dos
   al lado: con el tope de lectura de 68ch el bloque queda angosto y flotando
   en el medio, que se lee peor que pegado a la izquierda. Es el mismo número
   en las dos superficies, así que la página tiene un solo eje.

   No alcanza con `margin-inline: auto` a secas: el `__texto` es un bloque de
   ancho completo y el cap de 68ch vive en el `<p>`, así que sin max-width
   propio el div ocupa los 1.296 y el párrafo queda igual de pegado a la
   izquierda. Medido: 694 px de texto en una caja de 1.440.

   EL CTA QUEDA FUERA. Ya estaba resuelto como cierre —texto centrado a 539 px
   (§1)— y la regla global se lo llevó puesto en /services/ y /cabinet-maker-davie/,
   dos páginas ya aprobadas. Esto es para secciones de LECTURA sin foto, no
   para el cierre. Delatado y revertido el 2026-08-10. */
main > section:not(.cta):not(:has(figure)) > [class$="__texto"] {
  max-width: var(--ancho-centrado);
  margin-inline: auto;
}
main > section:not(.cta):not(:has(figure)) > [class$="__texto"] > * { max-width: none; }

/* El hero sigue la misma regla. Sin `hero_img` la columna derecha queda
   vacía —479 px medidos el 2026-08-10 en /locations/— así que pasa a una
   columna.

   SE CENTRA EN POSICIÓN, NO EN AMPLITUD (operador, 2026-08-10). El bloque va
   al centro de la caja; el titular, el subtítulo y los dos CTA siguen
   alineados a la izquierda dentro de él. Centrar línea por línea parte el
   titular en escalera y desarma el filete de acento, que nace en el borde
   izquierdo del texto.

   Y va ANCHO: sin foto que lo empuje, el titular tiene todo el espacio
   horizontal, así que sube de cuerpo y baja a dos líneas en vez de tres. */
.hero:not(:has(.hero__figura)) {
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
}
.hero:not(:has(.hero__figura)) .hero__texto { max-width: var(--ancho-centrado); width: 100%; }
.hero:not(:has(.hero__figura)) .hero__h1 { font-size: clamp(2.6rem, 5.2vw, 5.2rem); }
.hero:not(:has(.hero__figura)) .hero__sub { max-width: 52ch; }

/* ═══ HUB DE UBICACIONES ═════════════════════════════════════════════════
   El área de cobertura es CIERRE O INVITACIÓN, no lectura: va centrada (§1),
   igual que el bloque `.area` del Homepage. Y se resuelve con el MISMO
   tratamiento que ahí —rejilla con filete, tipografía de display— porque es
   literalmente la misma información en otra página: dos tratamientos
   distintos para la misma lista se leen como dos sitios.

   Sin esta regla la lista salía como nueve viñetas apiladas: 469 px de alto
   para nueve nombres de ciudad, medido el 2026-08-10 al estrenar el tipo. */
/* Los cuatro bloques de prosa: TEXTO A LA IZQUIERDA, FIGURA AL LADO, y el
   CONJUNTO centrado en la sección (operador, 2026-08-10).

   Las columnas van en px y no en fr, con `justify-content: center`. Es lo que
   hace que el par texto+figura mida los mismos 992 px del hero y quede sobre
   el mismo eje, en vez de estirarse a los 1.296 disponibles.

   Y es lo que cierra la §5: estos textos miden ~263 px. Una figura 4:3 sobre
   una columna de 543 px daría 407 px de alto y se pasaría del texto por 144,
   que es exactamente lo que la §5 prohíbe. Sobre 352 px da 264 y el
   desbalance queda en 1 px. El texto manda la altura; la figura se acomoda. */
.hub-intro, .hub-ciudad, .hub-cobertura {
  display: grid;
  grid-template-columns: minmax(0, 600px) minmax(0, 352px);
  justify-content: center;
  gap: 2.5rem; align-items: center;
}
/* Sin figura cae al bloque centrado de «SIN FOTO, CENTRADO». Es el ÚLTIMO
   recurso —una sección de este hub va CON foto—, no el plan. */
:is(.hub-intro, .hub-ciudad, .hub-cobertura):not(:has(figure)) {
  display: block;
}
/* LA INTRO SE LEE COMO UNA APERTURA, PORQUE LO ES: es la primera frase del
   cuerpo y lleva el ancla. Toma el MISMO clamp que `.apertura p:first-child`
   —medido: 23,04 px a 1440 contra los 17 que tenía— y el mismo color de
   tinta. Si cambia uno, cambia el otro: el comentario de `.apertura` ya
   advierte que dos entradas de página con medio píxel de diferencia se leen
   peor que iguales. */
/* La apertura del hub de recursos se lee como las demás: el texto CENTRADO
   contra la altura de la figura, no alineado arriba. `.apertura` general va a
   `align-items: start` a propósito —en una página de servicio el texto es
   largo y arrancar arriba es correcto—, pero acá son dos párrafos cortos
   contra dos imágenes, y alineados arriba quedan colgando de la esquina.
   Se acota al tipo con `t-resources_hub` para no tocar /services/ ni las
   categorías, que ya estaban aprobadas. */
/* `align-items: center` NO alcanza: la apertura tiene FILAS EXPLÍCITAS y la
   figura abarca 1/-1, así que `align-items` centra cada párrafo dentro de SU
   fila y el bloque de texto sigue pegado arriba. Lo que centra el conjunto de
   filas contra la altura del contenedor es `align-content`. Medido: texto en
   y=0 con align-items, centrado con align-content. */
.t-resources_hub .apertura:has(.apertura__figura) { align-items: center; }
.t-resources_hub .apertura__texto > p:last-child { margin-bottom: 0; }
.t-resources_hub .apertura p { font-size: clamp(1.1rem, 1.6vw, 1.45rem); line-height: 1.55; }
.t-resources_hub .apertura p:not(:first-child) { color: var(--cuerpo); }

.hub-intro__texto p:first-child {
  font-size: clamp(1.1rem, 1.6vw, 1.45rem);
  line-height: 1.55; color: var(--tinta);
}
:is(.hub-intro, .hub-ciudad, .hub-cobertura) figure {
  margin: 0; display: grid; gap: 1rem;
}
:is(.hub-intro, .hub-ciudad, .hub-cobertura) figure img {
  width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover;
}

/* ── EL ÍNDICE GEOGRÁFICO POR CATEGORÍA ────────────────────────────────────
   Un bloque por página de dinero, y dentro una card por ancla. Es el corazón
   del hub: la referencia del rubro publica 17 cards y nosotros publicábamos
   una lista plana de 9 nombres sin enlazar.

   Las cards NO son tarjetas flotantes con sombra: son fichas con filete,
   igual que `.bloque__grilla` de /services/ y `.cats__item` del Homepage. Un
   sitio con tres tratamientos distintos para la misma idea se lee como tres
   sitios. */
.geo__h2 a { color: var(--tinta); text-decoration: none; }
.geo__h2 a:hover { color: var(--acento-osc); }
.geo__grilla {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 0; margin: 2rem 0 0; padding: 0; list-style: none;
  border-top: 1px solid var(--pelo);
}
.geo__card {
  padding: 1.15rem 1.5rem 1.15rem 0;
  border-bottom: 1px solid var(--pelo);
  min-width: 0;
}
.geo__card a {
  font-family: var(--display); font-weight: 700; font-size: 1.02rem;
  color: var(--tinta); text-decoration: none;
}
.geo__card a:hover { color: var(--acento-osc); }
/* Un ancla todavía SIN página. Se dibuja apagada y sin enlace: muestra la
   arquitectura sin mentir que hay algo del otro lado. Desaparece sola en
   cuanto el rank map de la Fase 3 crea la location page. */
.geo__pendiente {
  font-family: var(--display); font-weight: 600; font-size: 1.02rem;
  color: var(--mute);
}

.locations { text-align: center; }
.locations__h2 { width: fit-content; margin-inline: auto; }
.locations__h2::before { left: 50%; transform: translateX(-50%); }
.locations__grilla {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0; margin: 2.25rem 0 0; padding: 0; list-style: none;
  border-top: 2px solid var(--tinta);
}
.locations__grilla li {
  padding: 0.85rem 0.5rem;
  border-bottom: 1px solid var(--pelo);
  font-family: var(--display); font-weight: 600; font-size: 0.98rem;
  color: var(--tinta); min-width: 0;
}
/* Con location pages (Fase 3) cada ítem trae enlace + resumen. Hereda el
   tratamiento de `.bloque__grilla`, que ya está probado con ese contenido.
   NO SE VIO RENDERIZADO todavía: no hay location pages hasta el rank map. */
.locations__grilla a {
  font-family: var(--display); font-weight: 700;
  color: var(--tinta); text-decoration: none;
}
.locations__grilla a:hover { color: var(--acento-osc); }
.locations__grilla span {
  display: block; font-weight: 400;
  font-size: 0.93rem; color: var(--mute); line-height: 1.55;
}

/* ═══ RESPONSIVE ═════════════════════════════════════════════════════════ */

@media (max-width: 1080px) {
  .site-header { grid-template-columns: minmax(0, 1fr) auto; gap: 1rem 1.5rem; }
  /* La nav ENVUELVE, no se desplaza. Un carrusel horizontal sin indicador
     esconde dos de los cinco enlaces y nadie descubre que están ahí. */
  .site-nav { grid-column: 1 / -1; justify-self: stretch; min-width: 0; }
  .site-nav__list { flex-wrap: wrap; width: auto; justify-content: center; }
  .trust__lista { grid-template-columns: repeat(2, 1fr); }
  .trust__item:nth-child(3) { border-left: 0; padding-left: 0; }
  .trust__item { border-top: 1px solid var(--pelo-osc); }
  .trust__item:nth-child(-n+2) { border-top: 0; }
  .site-footer { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 860px) {
  .hero, .why, .area, .about-resumen,
  .t-gbp_service .hero, .t-critical_gbp_service .hero,
  .t-gbp_category .hero, .t-location_page .hero,
  .apertura:has(.apertura__figura) {
    grid-template-columns: minmax(0, 1fr);
  }

  /* ── LAS TRES SECCIONES DE PROSA DEL HUB DE UBICACIONES ───────────────────
     Faltaban en esta lista desde que se estrenó el tipo, y no era un valor mal
     elegido: NO EXISTÍA el bloque angosto. La regla de la línea 1580 declara
     `minmax(0, 600px) minmax(0, 352px)` sin corte, así que las dos columnas
     sobreviven a cualquier ancho: a 360 px quedan 320 útiles, menos los 40 del
     `gap`, repartidos proporcionalmente entre las dos → 140 y 140.

     O sea que TODO el cuerpo de /locations/ —la intro que lleva el ancla, el
     bloque de ciudad y el de cobertura— se leía en una columna de 140 px.
     Medido el 2026-08-14 al cerrar las tres location pages; la página estaba
     cerrada desde el 2026-08-11 y esto no se había visto porque el cierre de
     entonces difirió las medidas de navegador al deploy.

     Colapsan en el orden del documento, que ya es el correcto: en la plantilla
     `hub-intro__texto` viene ANTES que `hub-intro__figura`, así que el texto
     queda arriba y la foto debajo. Es la misma regla que el `.hero` de acá
     arriba: la foto no va primero. */
  .hub-intro, .hub-ciudad, .hub-cobertura {
    grid-template-columns: minmax(0, 1fr);
  }

  /* ── EL CHROME DEL HEADER, CENTRADO EN MÓVIL ──────────────────────────────
     Pedido del operador, 2026-08-11, y estaba medido mal de tres formas.

     1 · EL HEADER. A 390 la grilla de 1080px daba `326px 0px`: la segunda
         columna colapsaba a 0 y el CTA se salía de ella. Centro del CTA en
         268 contra 195 de la página — 73 px corrido a la derecha. Va a una
         sola columna con los tres bloques centrados.

     2 · EL TELÉFONO. `text-align: start` heredado: el rótulo y el número
         quedaban alineados a la izquierda DENTRO de un bloque ya corrido.

     LA NAV NO SE TOCA. Hubo una versión con `grid-template-columns:
     repeat(3, …)` que alineaba About y Contact bajo Services y Locations;
     el operador la revirtió el 2026-08-11. Los cinco enlaces se quedan con
     el `flex-wrap` centrado que ya tenían. No rehacerlo. */
  .site-header {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    text-align: center;
  }
  .site-header__logo { justify-content: center; }
  /* NO alcanza con `text-align`: el bloque es un flex column con
     `align-items: flex-end` y `justify-self: end`. Lo que alinea las dos
     líneas es el flex, no el texto. Van las tres. */
  .site-header__cta {
    justify-self: center;
    align-items: center;
    text-align: center;
  }
  /* el espejado del servicio se deshace: en una columna el texto va primero */
  .t-gbp_service .hero__texto, .t-critical_gbp_service .hero__texto,
  .t-gbp_service .hero__figura, .t-critical_gbp_service .hero__figura {
    grid-column: 1; grid-row: auto;
  }
  .t-gbp_service .hero__figura, .t-critical_gbp_service .hero__figura { order: 1; }
  /* La foto NO va primero. El H1 lleva el ancla y el botón de llamar es la
     conversión del rubro: los dos tienen que entrar en la primera pantalla. */
  .hero { gap: 2rem; }
  .hero__figura { order: 0; }
  .hero__dato { left: 0; bottom: 1rem; }
  .why__figura { position: static; }
  .cats__item { border-right: 0; }
  .area__lista { grid-template-columns: 1fr; }
  .locations__grilla { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .form__campos { grid-template-columns: minmax(0, 1fr); }
  /* LAS CINCO SECCIONES EN GRID, Y SON CINCO. La lista de escritorio (línea
     1076) enumera `cuando · variantes · proceso · costo · why`; acá faltaba
     `variantes` en las TRES reglas. Nadie lo vio porque hasta el 2026-08-11
     ninguna página tenía esa sección: medido a 390 px, era la única que no
     colapsaba —114 px de H2 contra 203 px de texto, "Kitchen" partido— y las
     otras cuatro daban 350 px. Si mañana entra una sección más al grid de
     arriba, entra también acá o repite el mismo agujero. */
  .t-gbp_service .cuando, .t-gbp_service .variantes, .t-gbp_service .proceso,
  .t-gbp_service .costo, .t-gbp_service .why {
    grid-template-columns: minmax(0, 1fr);
  }
  .t-gbp_service .cuando > h2, .t-gbp_service .variantes > h2,
  .t-gbp_service .proceso > h2,
  .t-gbp_service .costo > h2, .t-gbp_service .why > h2 {
    position: static; margin-bottom: 1.5rem;
  }
  .t-gbp_service .cuando > *:not(h2), .t-gbp_service .variantes > *:not(h2),
  .t-gbp_service .proceso > *:not(h2),
  .t-gbp_service .costo > *:not(h2), .t-gbp_service .why > *:not(h2) {
    grid-column: 1;
  }
  .reseñas__cabecera { flex-direction: column; align-items: flex-start; gap: 0.5rem; }
}

@media (max-width: 560px) {
  .trust__lista { grid-template-columns: 1fr; }
  .trust__item { border-left: 0; padding-left: 0; border-top: 1px solid var(--pelo-osc); }
  .trust__item:first-child { border-top: 0; }
  .site-footer { grid-template-columns: minmax(0, 1fr); }
  .hero__acciones .btn { width: 100%; }
  .proceso li { padding-left: 3.25rem; }
}

/* ═══ MOVIMIENTO REDUCIDO ════════════════════════════════════════════════
   No es opcional. Toda animación necesita su alternativa. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ═══ IMPRESIÓN ══════════════════════════════════════════════════════════ */
@media print {
  .topbar, .site-nav, .site-header__cta, .cta, .form { display: none; }
  body { background: #fff; color: #000; }
}

/* ── VARIANTES · "¿cuál de todas?" ─────────────────────────────────────────
   UNA sola ejecución, IDÉNTICA en las cuatro pieles de página de servicio.
   Es la sección donde más tentaría diferenciarlas, y es justo la que no
   conviene: el visitante que compara está haciendo la misma tarea mental en
   las 28 páginas, y cambiarle la forma de la comparación de una a otra le
   cuesta a él, no al sitio. Las pieles se diferencian en el hero, la grilla
   de servicios y el tratamiento de foto — acá no.

   La sección ya hereda de `.t-gbp_service .variantes` el grid de dos
   columnas con el H2 a la izquierda. Lo de abajo es solo su contenido.

   FORMA: cada opción es un `### Nombre` seguido de su párrafo, que es lo
   único que `md()` sabe emitir — no hay tarjetas porque no hay envoltorio
   por opción, y forzarlo pediría tocar el motor. El peso visual lo carga el
   filete de acento del h3, que alcanza para leerlas como bloques distintos. */
.variantes h3 {
  font-family: var(--display);
  font-size: clamp(1.05rem, 1.3vw, 1.25rem);
  margin-block: 2rem 0.4rem;
  padding-left: 0.9rem;
  border-left: 3px solid var(--acento);
  line-height: 1.25;
}
.variantes h3:first-of-type { margin-top: 0; }
.variantes h3 + p { margin-top: 0; max-width: 62ch; }

/* La tabla es la otra forma legítima de esta sección — en las páginas de
   material la comparación ES una tabla. Hereda la del costo y no se
   redefine: dos tablas distintas en el mismo sitio se leen como un error. */

/* TIRA DE MINIATURAS — pieza A35. Hasta tres, cuadradas.
   `auto-fit` y no `repeat(3, …)`: con dos fotos, dos columnas que ocupan el
   ancho, no dos tercios y un hueco. Una variante sin foto no deja agujero.

   ⚠ SE CONTABA CON `auto-fit` Y NO FUNCIONA ACÁ. La regla decía
   `repeat(auto-fit, minmax(0, 1fr))`, que además es degenerado: sin un mínimo
   con el que acotar, el navegador llena pistas hasta donde le da el gap.
   Medido el 2026-08-11 sobre la página de quartz: **77 columnas de 1,03 px**,
   las tres miniaturas dibujadas a 1×1 px. En `/small-kitchen-remodel-davie/` daba
   47 columnas y NO se notó —las dos fotos desbordaban su pista y se veían a
   384 px por el `min-width: auto` del ítem de grid—, así que la regla estuvo
   mal desde que se escribió y el caso de dos fotos la tapó.
   Con un mínimo real siguió mal: 3 fotos en 6 columnas de 203 px, porque las
   pistas vacías tampoco colapsaron.

   ASÍ QUE SE CUENTA, NO SE ESTIMA. Son una, dos o tres —lo que emite la
   plantilla— y `:has()` lo resuelve exacto. `minmax(0, 1fr)` es seguro acá
   porque la cantidad de pistas ya no la deduce el navegador. */
.variantes__tira {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1rem;
  margin-top: 2.5rem;
}
/* `:is(img, picture)` Y NO `img` PELADO — medido el 2026-08-18.
   `build.py` envuelve en `<picture>` toda imagen que TENGA derivados, así que
   los hijos de la tira dejaron de ser `<img>` en cuanto se generaron los `-480`.
   `:has(img:nth-of-type(2))` pasó a dar SIEMPRE falso, la tira se quedó en una
   sola columna y, como en `.v-galeria` va a sangre, cada foto se publicó a
   1440x1080: la sección medía 4.380 px de alto en las nueve páginas de la rama
   cabinet. La regla nunca dejó de existir, dejó de matchear, y por eso no hubo
   ningún síntoma en el CSS. `:is()` pesa lo mismo que `img`, así que la
   especificidad no se mueve, y cubre las dos formas: la envuelta y la pelada
   de una imagen sin derivados. */
.variantes__tira:has(:is(img, picture):nth-of-type(2)) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.variantes__tira:has(:is(img, picture):nth-of-type(3)) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.variantes__tira img {
  width: 100%; height: auto;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radio);
}
.variantes__tira figcaption {
  grid-column: 1 / -1;
  margin-top: 0.75rem;
  font-size: 0.85rem;
  color: var(--mute);
}
@media (max-width: 640px) {
  /* En móvil la tira baja a dos columnas: tres miniaturas en 360 px de ancho
     dan 100 px cada una y dejan de mostrar nada. Con UNA foto sigue a ancho
     completo — media foto y medio hueco es peor que la foto sola.

     Y CON TRES, UNA DEBAJO DE OTRA — operador 2026-08-18. Dos columnas y tres
     fotos dan una fila de dos y una tercera sola contra el borde izquierdo:
     no es una grilla, es una grilla rota. Esta regla estuvo MUERTA hasta hoy
     porque su `:has(img…)` nunca matcheaba, así que la tira caía en la única
     columna que pedía la regla de `.v-galeria` de más abajo —la de «tres fotos
     de 130 px no son una galería, son tres estampillas»— y nadie vio el
     conflicto. Al revivirla ganó por peso: (0,2,1) contra (0,2,0). Se resuelve
     acotándola a EXACTAMENTE dos fotos y declarando el caso de tres, en vez de
     bajarle el peso a la otra, que es lo mismo pero adivinando. */
  .variantes__tira:has(:is(img, picture):nth-of-type(2)):not(:has(:is(img, picture):nth-of-type(3))) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .variantes__tira:has(:is(img, picture):nth-of-type(3)) {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ── EL FONDO DE LAS SECCIONES SE FIJA POR NOMBRE, NO POR POSICIÓN ─────────
   Solo en `gbp_service`, que es el único tipo con una sección OPCIONAL en el
   medio (`variantes`). Los demás tipos siguen con la alternancia general de
   más arriba y no se tocan.

   EL PROBLEMA QUE RESUELVE. La alternancia usa `:nth-of-type()`, o sea que
   cuenta posiciones. Al insertar `variantes` entre `cuando` y `proceso`,
   TODO lo de abajo se corre un lugar y cambia de color: medido el
   2026-08-11, seis secciones invertidas. Con 28 servicios donde unas llevan
   la sección y otras no, dos páginas hermanas publican los mismos bloques
   con los colores al revés. No lo caza ningún gate —los cuatro bloques dan
   verde— y se lee como descuido.

   LOS VALORES SON LOS DE HOY. A cada sección se le asigna el color que ya
   tenía por posición en una página sin `variantes`, así las 7 páginas
   publicadas no se mueven. Lo único que cambia es de qué depende. */
.t-gbp_service main > section.apertura,
.t-gbp_service main > section.variantes,
.t-gbp_service main > section.proceso,
.t-gbp_service main > section.why,
.t-gbp_service main > section.faq   { background: var(--blanco); }

.t-gbp_service main > section.hero,
.t-gbp_service main > section.cuando,
.t-gbp_service main > section.costo,
.t-gbp_service main > section.normativa { background: var(--papel); }

/* La regla de filete por paridad de más arriba ahora mentiría: cuenta
   posiciones y los colores ya no dependen de eso. Se apaga acá y el separador
   lo pone la regla siguiente, que sabe de verdad qué par comparte fondo. */
.t-gbp_service main > section + section { border-top-color: transparent; }

/* ── SEPARADOR ENTRE DOS SECCIONES DEL MISMO FONDO ────────────────────────
   `variantes` y `proceso` son las dos blancas y sin esto se leen como una
   sola sección larga.

   EL FILETE QUE YA EXISTE, no uno nuevo. La primera versión de esta regla
   dibujaba una barra de acento de 5rem × 4px, con el argumento de repetir el
   gesto del H1 del hero. Medido el 2026-08-11 sobre el HTML publicado: caía a
   61 px de `.proceso__h2::before`, que es la MISMA barra en 3.5rem × 3px y el
   mismo terracota, alineada al mismo borde izquierdo. Dos barras casi iguales
   a 61 px no se leen como un gesto repetido: se leen como un render duplicado.

   La piel ya tenía resuelto este caso exacto —línea 241, "cuando dos seguidas
   comparten superficie, entra un filete"—, un pelo de 1px a todo el ancho. Lo
   único que hacía falta era volver a encenderlo para el par que de verdad
   comparte fondo, después de haberlo apagado para todos arriba.

   Va SOLO en este par. `apertura + variantes` no existe: por #65 `variantes`
   se inserta entre `cuando` y `proceso`, y `cuando` es papel. */
.t-gbp_service main > .variantes + .proceso { border-top-color: var(--pelo); }


/* ══════════════════════════════════════════════════════════════════════════
   PIEL · FICHA TÉCNICA          `variante: ficha` en el front matter del .md
   ══════════════════════════════════════════════════════════════════════════

   PARA QUÉ ESTÁ. Es la piel de lo que se decide COMPARANDO: los ocho
   materiales de encimera, donde el visitante ya sabe que quiere una encimera
   y está eligiendo cuál. Esa tarea es escanear, no leer seguido, y el layout
   la tiene que servir: superficie plana, secciones numeradas, etiquetas en
   mono, y la medida de texto un poco más ancha porque casi todo son datos.

   DE DÓNDE SALE. `diseno/servicio/02-ficha-tecnica.html`, la maqueta que el
   usuario trajo. Traslada su tratamiento a tokens: los 35 KB de `style=`
   inline de la maqueta no viajan, y ningún color nuevo entra al sitio — los
   siete que usa (`--tinta --cuerpo --mute --pelo --acento --papel --blanco`)
   ya viven en `:root` y ya están medidos en `diseno/contraste.md`.

   QUÉ NO TRAE, Y POR QUÉ. La maqueta tiene tres piezas que NO son CSS: el
   rótulo `SERVICE SHEET · 03 / …` sobre el H1, la fila de cuatro specs del
   hero (SCOPE · IN-HOUSE · WARRANTY · LICENSE) y el índice lateral pegajoso
   01–06. Las tres piden HTML nuevo en `plantillas/`, que es del modelo y se
   propaga a todas las copias. Quedan pendientes de decisión y la piel se
   sostiene sin ellas: de las cuatro señas que el README de las maquetas le
   atribuye a la ficha —índice lateral, secciones numeradas, mono en las
   etiquetas, tabla de costos a tres columnas—, tres se consiguen acá.

   LA REGLA QUE LA HACE SEGURA. Todo cuelga de `.v-ficha`, que solo existe si
   el .md lo pidió. Una página sin `variante:` no puede ver ninguna de estas
   reglas, así que esto NO se filtra a las siete páginas publicadas. Medido
   contra HEAD antes de commitear, como toda regla global. */

/* La mono es de esta piel y de ninguna otra, así que se declara acá y no
   arriba con `Archivo` y `Plex`. El archivo ya estaba en el repo: era una de
   las tres fuentes que `verificar.py` delataba como peso muerto en cada
   corrida. Son 10 KB y `swap`, así que no bloquea el primer pintado. */
@font-face {
  font-family: "Plex Mono";
  src: url("/assets/fonts/ibm-plex-mono-latin.woff2") format("woff2");
  font-weight: 400 600;
  font-display: swap;
}
:root { --mono: "Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace; }

/* ── 1 · SUPERFICIE PLANA ──────────────────────────────────────────────────
   La alternancia papel/blanco es lo que le da ritmo a las otras pieles. Acá
   estorba: en una página que se escanea, el cambio de fondo cada dos pantallas
   compite con la única jerarquía que importa, que es la numeración. Todo
   blanco, y el corte lo hace el filete — el mismo `--pelo` de la línea 241,
   no un gesto nuevo.

   `:not(.cta)` porque el CTA de cierre es oscuro a propósito: va pegado al pie
   y los dos se separan por VALOR. Y el `--pelo` explícito en vez de heredar la
   regla de paridad, que arriba cuenta posiciones y acá no aplica. */
.t-gbp_service.v-ficha main > section:not(.cta) { background: var(--blanco); }
.t-gbp_service.v-ficha main > section:not(.cta) + section:not(.cta) {
  border-top-color: var(--pelo);
}

/* ── 2 · UNA SOLA COLUMNA ──────────────────────────────────────────────────
   Las otras pieles dejan el H2 pegajoso en una columna de 0.72fr y el cuerpo
   en 1.28fr. Acá no: el H2 numerado va arriba, a todo el ancho, y el texto
   corre debajo. Es lo que permite la tabla de tres columnas del costo y la
   lista de definiciones de la normativa, que a 783 px se aprietan.

   Se apaga el `position: sticky` a propósito. Con las secciones numeradas, el
   encabezado pegado deja de ser la referencia de "dónde estoy" —lo es el
   número— y un H2 flotando sobre una tabla que se scrollea se lee mal. */
/* SIGUE SIENDO GRID, de una sola columna — no `display: block`.
   Con `block` los hijos conservan `grid-column: 2` y el H2 su
   `grid-row: 1 / -1`, propiedades que el flujo normal ignora sin quitarlas: el
   resultado medido contra el fixture fue un hueco de −4 px entre el H2 y el
   párrafo siguiente, o sea el texto encima del encabezado, con los 28 px de
   `margin-bottom` declarados y sin efecto. Grid de una columna es además el
   camino que el bloque de 860 px ya usa para lo mismo desde hace semanas. */
.t-gbp_service.v-ficha .cuando,
.t-gbp_service.v-ficha .variantes,
.t-gbp_service.v-ficha .proceso,
.t-gbp_service.v-ficha .costo,
.t-gbp_service.v-ficha .why {
  grid-template-columns: minmax(0, 1fr);
}
/* `relative` y NO `static`. Los dos apagan el sticky, pero el ordinal de la
   sección 3 es un `::before` ABSOLUTO: con el H2 en `static` deja de tener
   bloque contenedor, se cuelga del ancestro posicionado que encuentre y
   aterriza fuera de la caja. Medido contra el fixture el 2026-08-11: los cinco
   H2 quedaron con 3.5rem de sangría y nada adentro, que se lee como si
   estuvieran centrados. */
.t-gbp_service.v-ficha .cuando > h2,
.t-gbp_service.v-ficha .variantes > h2,
.t-gbp_service.v-ficha .proceso > h2,
.t-gbp_service.v-ficha .costo > h2,
.t-gbp_service.v-ficha .why > h2 {
  position: relative;
  /* Y `top: auto`. El sticky venía con `top: 2rem` y `relative` NO lo ignora:
     lo aplica como desplazamiento. El H2 bajaba 32 px sobre su posición de
     layout y se montaba encima del párrafo — hueco medido de −4 px con
     28 px de `margin-bottom` declarados, que es exactamente 27,5 − 32.
     Apagar `position` sin apagar `top` es media corrección. */
  top: auto;
  grid-column: 1; grid-row: auto;
  margin-bottom: 1.75rem;
}
.t-gbp_service.v-ficha .cuando > *:not(h2),
.t-gbp_service.v-ficha .variantes > *:not(h2),
.t-gbp_service.v-ficha .proceso > *:not(h2),
.t-gbp_service.v-ficha .costo > *:not(h2),
.t-gbp_service.v-ficha .why > *:not(h2) { grid-column: 1; }
/* La medida sube de 68ch a 74ch: en una ficha la línea larga trabaja a favor
   porque casi ningún párrafo pasa de cuatro líneas. */
.v-ficha main > section > p,
.v-ficha main > section > ul,
.v-ficha main > section > ol,
.v-ficha .normativa__texto > p { max-width: 74ch; }

/* ── 3 · EL NÚMERO EN LUGAR DE LA BARRA ────────────────────────────────────
   Los 19 H2 de sección del sitio llevan un filete de acento de 3.5rem × 3px
   (línea 197). En esta piel ese mismo `::before` se convierte en el ordinal
   mono: es el gesto de la maqueta y no hay que tocar una sola etiqueta del
   HTML para conseguirlo.

   El contador cuenta SECCIONES DEL CUERPO, no posiciones del DOM: `apertura`
   no entra —es la bajada del H1, no un capítulo— y `hero`, `vuelta` y `cta`
   tampoco. Con `variantes` presente la página numera 01–07 en vez de 01–06, y
   eso es correcto: son siete capítulos. Es la misma trampa de la corrección
   #72 resuelta al revés — acá el número SÍ tiene que correrse. */
.v-ficha main { counter-reset: ficha; }
.v-ficha .cuando, .v-ficha .variantes, .v-ficha .proceso,
.v-ficha .costo, .v-ficha .why, .v-ficha .normativa,
.v-ficha .faq { counter-increment: ficha; }

.v-ficha .cuando__h2, .v-ficha .variantes__h2, .v-ficha .proceso__h2,
.v-ficha .costo__h2, .v-ficha .why__h2, .v-ficha .normativa__h2,
.v-ficha .faq__h2 {
  padding-top: 0;
  padding-left: 3.5rem;
  /* El ordinal cuelga en la canaleta izquierda. Colgado y no en línea: si va
     inline el H2 de dos líneas alinea la segunda contra el borde y el número
     deja de leerse como índice. */
}
.v-ficha .cuando__h2::before, .v-ficha .variantes__h2::before,
.v-ficha .proceso__h2::before, .v-ficha .costo__h2::before,
.v-ficha .why__h2::before, .v-ficha .normativa__h2::before,
.v-ficha .faq__h2::before {
  content: counter(ficha, decimal-leading-zero);
  /* `absolute` EXPLÍCITO. Cinco de los siete lo heredan de la lista de filetes
     de la línea 197; `normativa__h2` no está en esa lista —es el H2 que no
     tenía barra— así que su `::before` era una caja INLINE y el ordinal se
     imprimía pegado al texto: "06Licensed, Insured…". Poner `relative` en el
     H2 no alcanza si el pseudo no es absoluto: son las dos mitades. */
  position: absolute;
  top: 0.45em; left: 0;
  width: auto; height: auto; background: none;
  font-family: var(--mono);
  font-size: 0.75rem; font-weight: 400; letter-spacing: 0.06em;
  color: var(--acento);
}

/* ── 4 · LA APERTURA ES UNA BAJADA, NO UN CAPÍTULO ─────────────────────────
   Sin número y con filete lateral: se lee como el sumario que es, y de paso
   queda claro que la numeración empieza abajo. */
.t-gbp_service.v-ficha .apertura > p:first-of-type {
  font-size: 1.15rem;
  line-height: 1.55;
  color: var(--tinta);
  border-left: 3px solid var(--acento);
  padding-left: 1.25rem;
  max-width: 74ch;
}

/* ── 5 · LOS DATOS SE VEN COMO DATOS ───────────────────────────────────────
   Mono para todo lo que es rótulo y no prosa: encabezados de la tabla del
   costo, rótulos de la normativa, numerales del proceso. Es la seña que el
   README le atribuye a esta piel, y es la que la separa de `revista` sin
   cambiar una palabra del copy. */

/* La tabla del costo. Tres columnas —rango · fuente · qué mide— las escribe
   el .md; acá se le da el tratamiento. La primera columna en acento y sin
   partir: un rango de precio cortado en dos líneas deja de leerse como un
   número. */
.v-ficha .costo table {
  width: 100%; border-collapse: collapse;
  margin: 1.5rem 0 1.75rem;
  font-size: 0.9rem;
}
.v-ficha .costo th {
  text-align: left; padding: 0.65rem 0.75rem 0.65rem 0;
  border-bottom: 2px solid var(--tinta);
  font-family: var(--mono); font-weight: 400;
  font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--tinta);
}
.v-ficha .costo td {
  padding: 0.75rem 0.75rem 0.75rem 0;
  border-bottom: 1px solid var(--pelo);
  vertical-align: top;
  color: var(--mute);
}
.v-ficha .costo tbody td:first-child {
  font-family: var(--display); font-weight: 700;
  color: var(--acento); white-space: nowrap;
}
.v-ficha .costo tbody td:last-child { padding-right: 0; }
/* Una tabla nunca desborda la página: se scrollea dentro de su caja. */
.v-ficha .costo table { display: block; overflow-x: auto; }

/* El proceso: numerales mono en su propia columna, con filete por paso. */
.v-ficha .proceso ol { list-style: none; padding: 0; margin: 0;
  border-top: 1px solid var(--pelo); counter-reset: paso; }
/* SANGRÍA FRANCESA, NO GRID. Un `<li>` de este sitio es `**negrita.** y después
   el texto`: en el DOM eso es un `<strong>` más un NODO DE TEXTO suelto. Con
   `display: grid` el navegador arma dos ítems —el elemento y el texto anónimo—
   y `> *` solo alcanza al primero: el texto se cae a la columna del ordinal.
   Medido el 2026-08-11 sobre la página de quartz: 52 px de ancho y 878 px de
   alto para un paso, o sea una palabra por línea. Contra el fixture no se veía
   porque sus pasos no llevan negrita.
   Con `padding-left` y el ordinal absoluto el texto sigue siendo flujo normal
   y no hay ítems que repartir. */
.v-ficha .proceso ol > li {
  counter-increment: paso;
  position: relative;
  padding: 1rem 0 1rem 4.25rem;
  border-bottom: 1px solid var(--pelo);
  max-width: none;
}
.v-ficha .proceso ol > li::before {
  content: counter(paso, decimal-leading-zero);
  position: absolute; top: 1.3rem; left: 0;
  font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.06em;
  color: var(--acento);
  /* se apaga lo que hereda de `.proceso li::before` de la línea 1199 */
  background: none; width: auto; height: auto; border-radius: 0;
}
.v-ficha .proceso ol > li strong { font-family: var(--display); color: var(--tinta); }

/* La normativa ya viene como <dl> del parcial: acá se le pone el rótulo mono
   en una columna fija, que es exactamente la sección 05 de la maqueta.
   TODO centrado, filas incluidas — decisión del operador, segunda pasada del
   2026-08-11. Hubo una versión que dejaba las filas alineadas a la izquierda
   con el argumento de que una etiqueta mono centrada deja de leerse como
   ficha; el operador lo revirtió. La columna de rótulos deja de ser una
   columna fija y pasa a apilarse: rótulo arriba, valor debajo, los dos al eje.
   Centrar el texto de una grilla de dos columnas sin sacarle las columnas deja
   cada celda centrada en su propia mitad, que no es centrar nada. */
.t-gbp_service.v-ficha .normativa__datos { text-align: center; }
.t-gbp_service.v-ficha .normativa__dato {
  grid-template-columns: minmax(0, 1fr);
  gap: 0.35rem;
  padding-block: 1.1rem;
}
.t-gbp_service.v-ficha .normativa__dato dt { padding-top: 0; }
.t-gbp_service.v-ficha .normativa__dato dd { margin-inline: auto; }
.v-ficha .normativa__datos { display: block; border-top: 1px solid var(--pelo); }
.v-ficha .normativa__dato {
  display: grid; grid-template-columns: 11rem minmax(0, 1fr); gap: 1.25rem;
  padding: 0.9rem 0; border-bottom: 1px solid var(--pelo);
}
.v-ficha .normativa__dato dt {
  font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--mute); padding-top: 0.2em;
}
.v-ficha .normativa__dato dd { margin: 0; max-width: 70ch; }
.v-ficha .normativa__dato dd b { font-family: var(--display); color: var(--tinta); }

/* El FAQ: mismo filete, sin caja. Sigue siendo <details> y sigue cerrado —
   eso no se toca, es la regla de contenido invisible contra el schema.

   El FAQ queda CENTRADO, como en el resto del sitio. Hubo una versión de esta
   hoja que lo alineaba a la izquierda para que su ordinal hiciera columna con
   los otros; el operador lo revirtió el 2026-08-11 junto con el resto del eje
   centrado. Lo único que se toca es la medida de la lista. */
.t-gbp_service.v-ficha .faq__lista { max-width: 74ch; }
.v-ficha .faq__lista { border-top: 1px solid var(--pelo); }
.v-ficha .faq__item {
  border-bottom: 1px solid var(--pelo); border-top: 0;
  border-left: 0; border-right: 0;
  padding: 1rem 0; margin: 0; background: none;
}
.v-ficha .faq__respuesta { max-width: 74ch; }

/* ── 6 · EL HERO SE DESESPEJA ──────────────────────────────────────────────
   `gbp_service` publica el hero espejado —foto a la izquierda—. La ficha lo
   pone como el resto del sitio: el H1 primero en orden de lectura y la foto a
   la derecha, en 4:5. Es lo único de la maqueta que cambia el hero sin pedir
   HTML nuevo.

   ⚠ Y SE DESHACE EN MÓVIL, abajo. Acá decía que no hacía falta porque el
   bloque de 860px ya manda el texto primero, y era falso: ese bloque es
   `.t-gbp_service .hero__figura` (0,2,0) y esto es (0,3,0), así que gana esto
   y la figura se queda en la columna 2 de una grilla de una sola columna. El
   H1 salió UNA LETRA POR LÍNEA en 390px. Toda regla de columnas que se
   escriba acá necesita su contraparte en el media query — es el hallazgo A de
   hoy repetido dentro de la corrección del hallazgo A. */
.t-gbp_service.v-ficha .hero__texto { grid-column: 1; grid-row: 1; }
.t-gbp_service.v-ficha .hero__figura { grid-column: 2; grid-row: 1; }
.t-gbp_service.v-ficha .hero__figura img { aspect-ratio: 4 / 5; min-height: 0; }

/* ── 7 · MÓVIL ─────────────────────────────────────────────────────────────
   El ordinal colgado no entra en 350px: 3.5rem de sangría se comen el 16% de
   la medida. Baja a bloque, arriba del H2. Y las dos rejillas de dos columnas
   —normativa y proceso— se apilan.

   Esta sección existe porque el 2026-08-11 `variantes` entró a la lista de
   grid de escritorio y no a la de 860px, y publicó una sección sin colapsar
   durante semanas sin que ningún gate lo viera. Toda piel nueva se mide a
   390px antes de darse por hecha. */
@media (max-width: 860px) {
  .v-ficha .cuando__h2, .v-ficha .variantes__h2, .v-ficha .proceso__h2,
  .v-ficha .costo__h2, .v-ficha .why__h2, .v-ficha .normativa__h2,
  .v-ficha .faq__h2 { padding-left: 0; padding-top: 1.5rem; }
  .v-ficha .cuando__h2::before, .v-ficha .variantes__h2::before,
  .v-ficha .proceso__h2::before, .v-ficha .costo__h2::before,
  .v-ficha .why__h2::before, .v-ficha .normativa__h2::before,
  .v-ficha .faq__h2::before { top: 0; }
  .v-ficha .normativa__dato { grid-template-columns: minmax(0, 1fr); gap: 0.35rem; }
  .v-ficha .proceso ol > li { padding-left: 3rem; }
  /* El hero vuelve a una columna. Sin esto la figura se queda en la columna 2
     y el H1 se parte carácter por carácter. Ver el ⚠ del bloque 6. */
  .t-gbp_service.v-ficha .hero__texto,
  .t-gbp_service.v-ficha .hero__figura { grid-column: 1; grid-row: auto; }
  .t-gbp_service.v-ficha .hero__figura { order: 1; }
}

/* ── 8 · LA FILA DE SPECS DEL HERO ─────────────────────────────────────────
   La cuarta seña de la maqueta, y la única de las tres que piden HTML que se
   hizo. El parcial la dibuja solo si el .md declaró `spec_1`, así que ninguna
   página sin specs ve una sola de estas reglas.

   `auto-fit` y no `repeat(4, …)`: con dos specs se reparten el ancho en vez
   de dejar medio hero vacío. El filete separa columnas y NO se dibuja en la
   última — `:last-child` y no `:not(:first-child)`, porque con auto-fit la
   cantidad de columnas cambia con el ancho y el borde derecho del último es
   el único que siempre sobra. */
.v-ficha .hero__specs,
.v-contacto .hero__specs {
  margin: 1.5rem 0 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
}
/* CUATRO COLUMNAS FIJAS, no `auto-fit`. En `ficha` el hero es texto solo y el
   auto-fit acierta; acá la columna comparte ancho con el formulario y el
   cálculo le daba dos, así que los cuatro specs salían en dos filas y la
   fila dejaba de leerse como una fila. Son siempre cuatro datos declarados.
   Debajo de 62rem el hero ya es de una columna y vuelve el auto-fit. */
.v-contacto .hero__specs {
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  border-top: 1px solid var(--pelo);
}
.v-ficha .hero__spec,
.v-contacto .hero__spec {
  padding: 0.85rem 1rem 0.85rem 0;
  border-right: 1px solid var(--pelo);
}
.v-ficha .hero__spec:not(:first-child) { padding-left: 1rem; }
.v-ficha .hero__spec:last-child,
.v-contacto .hero__spec:last-child { border-right: 0; padding-right: 0; }
.v-ficha .hero__spec dt,
.v-contacto .hero__spec dt {
  font-family: var(--mono);
  font-size: 0.68rem; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--mute);
}
.v-ficha .hero__spec dd,
.v-contacto .hero__spec dd {
  margin: 0.25rem 0 0;
  font-family: var(--display); font-weight: 700;
  font-size: 1.05rem; color: var(--tinta);
}
@media (max-width: 860px) {
  /* Dos y dos. Cuatro columnas en 350px dan 87px cada una y el valor se parte.
     El filete derecho de la primera de cada fila se queda; el de la segunda
     se va, y por eso se apaga por posición par y no solo en el último. */
  .v-ficha .hero__specs,
.v-contacto .hero__specs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .v-ficha .hero__spec:nth-child(even) { border-right: 0; padding-right: 0; }
  .v-ficha .hero__spec:nth-child(odd) { padding-left: 0; }
}


/* ══════════════════════════════════════════════════════════════════════════
   FICHA · EL EJE DE LA PÁGINA         decisión del operador, 2026-08-11
   ══════════════════════════════════════════════════════════════════════════

   UNA SOLA SECCIÓN CON FOTOS, EL RESTO CENTRADO. La 01 —`cuando`, la más
   larga y la única que argumenta sin estructura propia— lleva su columna de
   imágenes a la derecha, alineada con el texto que tiene a su izquierda. Las
   otras seis se centran.

   Esto NO es el fallback de la §16 de convenciones ("sección sin foto, se
   centra") usado por falta de foto: es la composición elegida. La página tiene
   un solo eje, la 01 lo rompe a propósito y por eso se lee como la sección que
   sostiene el argumento. Vale para las 28 páginas de servicio, no solo para
   esta — está anotado en `diseno/convenciones.md`.

   LO QUE NO SE CENTRA, Y POR QUÉ: la tabla del costo, la lista numerada del
   proceso, las filas del <dl> de normativa y las preguntas del FAQ. Son datos
   tabulados, y una etiqueta mono centrada arriba de su valor deja de leerse
   como ficha. Se centra el BLOQUE; adentro, la estructura queda alineada. */

.t-gbp_service.v-ficha .variantes,
.t-gbp_service.v-ficha .proceso,
.t-gbp_service.v-ficha .costo,
.t-gbp_service.v-ficha .why,
.t-gbp_service.v-ficha .normativa,
.t-gbp_service.v-ficha .faq { text-align: center; }

/* El contenido se centra contra el MISMO ancho que el hero — `--ancho-centrado`
   es el token que existe para esto y evita que cada sección invente el suyo. */
.t-gbp_service.v-ficha .variantes > *,
.t-gbp_service.v-ficha .proceso > *,
.t-gbp_service.v-ficha .costo > *,
.t-gbp_service.v-ficha .why > * {
  max-width: var(--ancho-centrado);
  margin-inline: auto;
}

/* El ordinal se va ARRIBA del H2 y centrado. Colgado a la izquierda de un H2
   centrado queda flotando en el medio de la nada. Es el mismo tratamiento que
   ya usaba el bloque de móvil, subido acá para las seis secciones centradas.
   La 01 NO entra: conserva el ordinal colgado, que es parte de lo que la
   distingue. */
.v-ficha .variantes__h2, .v-ficha .proceso__h2, .v-ficha .costo__h2,
.v-ficha .why__h2, .v-ficha .normativa__h2, .v-ficha .faq__h2 {
  padding-left: 0; padding-top: 1.75rem;
  /* `relative` explícito. Cinco de estos seis ya lo traían de la lista de H2
     con filete de la línea 197, pero `normativa__h2` NUNCA estuvo en esa lista
     —es el H2 que no tenía barra— y quedó en `static`: su ordinal absoluto se
     colgó del ancestro posicionado y aterrizó encima de la palabra "Licensed".
     Es el mismo mecanismo que ya me pasó con el H2 sticky esta mañana. */
  position: relative;
}
.v-ficha .variantes__h2::before, .v-ficha .proceso__h2::before,
.v-ficha .costo__h2::before, .v-ficha .why__h2::before,
.v-ficha .normativa__h2::before, .v-ficha .faq__h2::before {
  top: 0; left: 50%; transform: translateX(-50%);
}

/* Las estructuras tabuladas vuelven a la izquierda adentro del bloque —
   MENOS LA TABLA DEL COSTO, que va centrada por decisión del operador
   (2026-08-11, segunda pasada). Tres columnas cortas de ancho parejo se leen
   como una ficha igual centradas, y alineadas a la izquierda dentro de un
   bloque centrado quedaban peleando con el eje de toda la sección. La lista
   del proceso y el <dl> de normativa NO: ahí el texto es prosa de largo
   desparejo y centrarla sí rompe la lectura. */
.t-gbp_service.v-ficha .proceso ol,
.t-gbp_service.v-ficha .faq__lista { text-align: left; }

/* Y la tabla se centra COMO BLOQUE, además de su texto. Es `display: block`
   —así se lleva el `overflow-x` que la hace scrollear en vez de desbordar—, y
   un bloque al 100% ocupa los 992 px del contenedor mientras su contenido real
   mide 545: el texto quedaba centrado adentro de una caja pegada a la
   izquierda, o sea a 220 px del eje de la sección. `fit-content` + `auto` la
   encoge a lo que mide y la centra, y el `max-width` conserva el scroll. */
.t-gbp_service.v-ficha .costo table {
  text-align: center;
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
}
.t-gbp_service.v-ficha .costo th,
.t-gbp_service.v-ficha .costo td { text-align: center; }
/* El padding lateral se empareja: venía asimétrico —cero a la izquierda en la
   primera celda y cero a la derecha en la última— porque la tabla se alineaba
   al borde del texto. Centrada, esa asimetría corre el contenido medio grado
   a la derecha y se nota en la fila de encabezados. */
.t-gbp_service.v-ficha .costo th,
.t-gbp_service.v-ficha .costo td { padding-inline: 0.75rem; }

/* ── SECCIÓN 01 · TEXTO A LA IZQUIERDA, FIGURAS A SU DERECHA ───────────────
   El H2 cruza las dos columnas para que el ordinal colgado siga alineado con
   el borde del texto. Las figuras arrancan en la fila 2 y bajan: `align-self:
   start` las pega al tope del texto en vez de centrarlas contra él, que es lo
   que pide "alineadas con el texto a su mano izquierda". */
.t-gbp_service.v-ficha .cuando {
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  column-gap: clamp(2rem, 4vw, 4rem);
}
.t-gbp_service.v-ficha .cuando > h2 { grid-column: 1 / -1; }
.t-gbp_service.v-ficha .cuando > *:not(h2):not(.cuando__figura) { grid-column: 1; }
/* El bloque de texto se centra contra las figuras. Existe solo cuando hay
   figuras —el envoltorio es condicional en la plantilla— y por eso puede
   llevarse el `align-self` sin tocar las páginas sin foto. Los párrafos
   recuperan acá el tope de medida que perdieron al dejar de ser hijos
   directos de la sección. */
.t-gbp_service.v-ficha .cuando__texto {
  grid-column: 1; grid-row: 2 / -1;
  align-self: center;
}
.t-gbp_service.v-ficha .cuando__texto > * { max-width: 74ch; }
.t-gbp_service.v-ficha .cuando__texto > *:first-child { margin-top: 0; }
.t-gbp_service.v-ficha .cuando__texto > *:last-child { margin-bottom: 0; }
/* CUATRO clases y cero elementos. La regla general de la piel es
   `.t-gbp_service.v-ficha .cuando > *:not(h2)`, que con el `:not(h2)` suma un
   elemento y pesa (0,3,1): le ganaba a un selector de tres clases y mandaba la
   figura a la columna 1. Medido: x=72, ancho 712, apilada arriba del texto. */
.t-gbp_service.v-ficha .cuando > .cuando__figura {
  grid-column: 2; grid-row: 2 / -1;
  /* CENTRADA CONTRA EL TEXTO, no pegada al tope. Es la §5 —"el TEXTO manda la
     altura; la columna de imágenes se centra contra él"— y es lo que hay que
     hacer para que la diferencia que quede se reparta arriba y abajo en vez de
     acumularse de un lado. Hubo una versión con `align-self: start` y con las
     fotos en 4:3 sobrando 82 px: el texto se leía empujado hacia arriba. */
  align-self: center;
  margin: 0;
  display: flex; flex-direction: column; gap: 1rem;
}
/* 3:2 CON DOS FOTOS Y 4:3 CON UNA — el número sale de la §13 bis, que dice que
   la columna de imágenes se mide contra la altura del TEXTO y no al revés.
   Medido acá: el texto de la 01 da 724 px; dos fotos en 4:3 sobre una columna
   de 526 daban 805 y se pasaban 82. En 3:2 dan 717 y entran con 7 de sobra.
   Con una sola foto no hay nada que igualar y 4:3 es la del resto del sitio. */
.t-gbp_service.v-ficha .cuando__figura img {
  width: 100%; height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: var(--radio);
}
/* Mismo arreglo que la tira de `variantes`: con `img` pelado el `:has()` daba
   siempre falso, o sea que el `:not()` daba siempre VERDADERO y el 4/3 se
   aplicaba también a las figuras de DOS fotos, que estaban escritas para 3/2. */
.t-gbp_service.v-ficha .cuando__figura:not(:has(:is(img, picture):nth-of-type(2))) img {
  aspect-ratio: 4 / 3;
}

/* ── LA APERTURA SE LEE COMO EL SUBTÍTULO DEL HERO ─────────────────────────
   Medido: el `.hero__sub` va a 23,04 px y la apertura iba a 18,4 — la bajada
   de la página se leía más chica que la del hero, que dice lo mismo en menos
   palabras. Se igualan. El `1.44rem` es exactamente esos 23,04 px. */
.t-gbp_service.v-ficha .apertura > p:first-of-type {
  font-size: 1.44rem;
  line-height: 1.5;
}

/* ── EL HERO Y SU FRANJA ENTRAN EN UNA PANTALLA ────────────────────────────
   Medido antes: hero 824 px, franja terminando en 1.064 sobre una ventana de
   900 — 164 px pasados. El token no estaba mal: 129 px de chrome + 111 de
   franja = 240 = las `--tope: 15rem` exactas, y `.hero` ya pide
   `min-height: calc(100svh - var(--tope))` = 660.

   EL QUE SE PASABA ERA LA FIGURA. Con `aspect-ratio: 4/5` sobre una columna
   de 671 px la foto pide 839 px de alto y arrastra al hero con ella. La foto
   no puede decidir la altura de la primera pantalla: la decide la ventana.
   Así que la figura ESTIRA hasta el alto del hero y recorta, en vez de dictar.

   Y LA COLUMNA DE TEXTO SE ENSANCHA, que es la mitad que faltaba. Con 527 px
   el H1 salía en TRES líneas —266 px— y el subtítulo en tres más. La maqueta
   pone el texto a `1fr` y la foto a 380 px fijos, y por algo: con el texto
   ancho el H1 entra en dos líneas y el hero baja de 736 a caber en los 660
   que deja `--tope`. Achicar el padding hubiera tapado el síntoma.

   LA FOTO PASÓ DE 380 A 424 px — 2026-08-11, pedido del operador sobre quartz
   y granite. A 380 la caja daba 380×545 = ratio 0,697 contra el 0,778 del
   archivo (896×1152): con `object-fit: cover` la imagen se renderiza a 424 de
   ancho y la caja le RECORTABA 44 px, 22 por lado. 424 = 545 × 0,778, o sea el
   ancho exacto al que deja de recortar a 1440×900. Los 44 px salen de la
   columna de texto (818 → 774) y el H1 sigue en dos líneas: medido. */
.t-gbp_service.v-ficha .hero {
  grid-template-columns: minmax(0, 1fr) minmax(0, 424px);
}
.t-gbp_service.v-ficha .hero__figura { align-self: stretch; }
.t-gbp_service.v-ficha .hero__figura img {
  aspect-ratio: auto;
  height: 100%;
  min-height: 0;
  object-fit: cover;
}

/* ── LOS CUATRO SPECS, EN UNA SOLA LÍNEA ───────────────────────────────────
   `minmax(9rem, …)` daba 3 columnas en los 527 px de la columna de texto y el
   cuarto se caía a una segunda fila, que además es la altura que empujaba la
   franja fuera de la pantalla. Son CUATRO y son siempre cuatro: se declaran
   cuatro. El rótulo baja de tamaño y pierde el `uppercase`, que es lo que lo
   hacía largo. */
.v-ficha .hero__specs,
.v-contacto .hero__specs { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.v-ficha .hero__spec,
.v-contacto .hero__spec { padding: 0.7rem 0.6rem 0.7rem 0; }
.v-ficha .hero__spec:not(:first-child) { padding-left: 0.6rem; }
.v-ficha .hero__spec dt,
.v-contacto .hero__spec dt { font-size: 0.6rem; letter-spacing: 0.04em; }
.v-ficha .hero__spec dd,
.v-contacto .hero__spec dd { font-size: 0.95rem; white-space: nowrap; }

@media (max-width: 860px) {
  /* EL HERO VUELVE A UNA COLUMNA. Tercera vez en el día que una regla de
     columnas de esta piel —(0,3,0)— le gana al bloque general de 860px
     —(0,2,0)— y publica el H1 partido carácter por carácter: 1.510 px de alto
     medidos a 390. Regla de la casa: NINGUNA declaración de
     `grid-template-columns` bajo `.v-ficha` sale de acá sin su contraparte
     en este bloque, en el mismo commit. */
  .t-gbp_service.v-ficha .hero { grid-template-columns: minmax(0, 1fr); }
  /* La 01 vuelve a una columna y las figuras van abajo del texto. */
  .t-gbp_service.v-ficha .cuando { grid-template-columns: minmax(0, 1fr); }
  .t-gbp_service.v-ficha .cuando > h2,
  .t-gbp_service.v-ficha .cuando__figura { grid-column: 1; grid-row: auto; }
  .t-gbp_service.v-ficha .cuando__figura { flex-direction: row; }

  /* ── LA SÉPTIMA TRAMPA DE LA §18.6, AL REVÉS ─────────────────────────────
     Devolver la sección a UNA columna no alcanza: la FIGURA conserva su
     `grid-column: 2` de escritorio, el navegador le fabrica una columna
     implícita para alojarla, y la explícita —`minmax(0, 1fr)`— se queda con
     0 px. El texto sale UNA LETRA POR LÍNEA.

     Medido a 390 el 2026-08-11, y la parte cara: `/quartz-…/` estaba
     PUBLICADA así. Su `apertura` daba `0px 318px` con el texto en 23 px, y su
     `cuando` daba `318px 0px`, o sea las dos fotos invisibles en móvil.

     Por qué el reset de `.cuando__figura` que ya estaba tres líneas más
     arriba no alcanzaba: la regla de escritorio es
     `.t-gbp_service.v-ficha .cuando > .cuando__figura` —(0,4,0)— y el reset
     era `.t-gbp_service.v-ficha .cuando__figura` —(0,3,0)—. Gana la de
     escritorio esté donde esté, porque esto no lo decide el orden.

     REGLA: un reset de móvil se escribe con la MISMA FORMA DE SELECTOR que la
     regla que pisa, y resetea `grid-row` además de `grid-column`. */
  .apertura:has(.apertura__figura) > .apertura__figura,
  .t-gbp_service.v-ficha .cuando > .cuando__figura {
    grid-column: 1;
    grid-row: auto;
  }
  /* Los specs vuelven a dos y dos: cuatro en 350 px dan 87 px cada uno. */
  .v-ficha .hero__specs,
.v-contacto .hero__specs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ── LAS OPCIONES DE `variantes`, EN TARJETAS ──────────────────────────────
   Pedido del operador, 2026-08-11.

   LA REGLA DEL MODELO NO LO IMPIDE ACÁ, Y CONVIENE SABER POR QUÉ. Lo prohibido
   es convertir en tarjeta un párrafo QUE LLEVA ENLACES adentro: encajonado, el
   enlace se lee como navegación y deja de contar como contextual — es la
   restricción de las piezas A15 y A19 del catálogo, y la razón de que
   `.servicios-prosa` y `.opciones` sean párrafos y no tarjetas. Las opciones de
   `variantes` NO llevan enlaces: son las variantes internas del servicio, y
   por #65 la comparación con enlaces vive en el PADRE. Si alguna vez una
   opción necesita un enlace, sale de la tarjeta y no al revés.

   SIN ENVOLTORIO POR OPCIÓN. `md()` emite `<h3>` y `<p>` como HERMANOS: no hay
   un elemento por opción que encajonar, y fabricarlo pediría tocar el motor.
   La tarjeta se arma partiendo el borde entre los dos —el h3 se lleva arriba e
   izquierda y derecha, el párrafo abajo— con cero separación entre ellos. Se
   lee como una caja sola porque lo es, ópticamente.

   ⚠ ESTO ASUME UN PÁRRAFO POR `###`. Con dos, el segundo queda fuera de la
   caja. Es el contrato de escritura de la sección: una opción, un párrafo. */
/* LOS DOS AL MISMO ANCHO, EXPLÍCITO. Sin esto el `h3` se encoge al ancho de su
   texto —medidos 271, 364 y 152 px para las tres opciones— y la mitad de
   arriba de la tarjeta queda flotando como una etiqueta sobre la caja del
   párrafo. Con el borde partido en dos elementos, que midan igual no es
   estético: es lo que hace que se lea como UNA caja. */
.v-ficha .variantes h3,
.v-ficha .variantes h3 + p {
  width: 100%;
  max-width: 46rem;
  margin-inline: auto;
  box-sizing: border-box;
}
.v-ficha .variantes h3 {
  margin: 0 auto;
  padding: 1.1rem 1.35rem 0.6rem;
  border: 1px solid var(--pelo);
  border-bottom: 0;
  border-left: 3px solid var(--acento);
  border-radius: var(--radio) var(--radio) 0 0;
  background: var(--blanco);
}
.v-ficha .variantes h3 + p {
  margin: 0 auto 1.15rem;
  padding: 0 1.35rem 1.35rem;
  border: 1px solid var(--pelo);
  border-top: 0;
  border-left: 3px solid var(--acento);
  border-radius: 0 0 var(--radio) var(--radio);
  background: var(--blanco);
}
.v-ficha .variantes h3:first-of-type { margin-top: 0; }
/* La última no arrastra su margen contra la tira de miniaturas. */
.v-ficha .variantes h3 + p:last-of-type { margin-bottom: 0; }


/* ═══════════════════════════════════════════════════════════════════════════
   PIEL «GALERÍA» — .v-galeria
   2026-08-12 · traslado de diseno/servicio/03-galeria.html

   PARA QUÉ EXISTE. `diseno/servicio/README.md` la describe como *"la que más
   depende de tener fotos buenas. Sin fotos reales se cae"*, y el reparto de
   la bitácora del 2026-08-11 se la asigna a **lo que se decide MIRANDO**:
   refacing, refinishing, islas, backsplash. Son las páginas donde el visitante
   no compara una tabla de materiales — mira una puerta y decide si le gusta.

   POR QUÉ NO ALCANZABA CON `.v-ficha`. La ficha está construida para
   escanear: numera las secciones, aplana la superficie y centra el texto para
   que la jerarquía la lleve el ordinal. Eso es correcto para quartz contra
   granite. Para refacing es lo contrario de lo que hace falta: la foto tiene
   que mandar, y una foto dentro de una caja de 1400 px con canaleta a los
   costados no manda nada. De ahí las tres decisiones de esta piel — hero
   partido a sangre, tira de tres a sangre, y cierre partido.

   LA REGLA QUE LA HACE SEGURA — la misma que la ficha. Todo cuelga de
   `.v-galeria`, que solo existe si el `.md` lo pidió. Las diez hermanas de
   countertop están en `.v-ficha` y NO pueden ver ninguna de estas reglas.
   Medido contra el fixture antes de dar por buena la piel.

   LO QUE NO SE TRASLADÓ, Y POR QUÉ:
     · El CTA de la maqueta es partido — foto a la izquierda, texto a la
       derecha. `cta_final` no tiene slot de imagen, y agregárselo es tocar
       `plantillas/` , que es del modelo y se propaga a todas las copias. Acá
       el CTA queda oscuro a todo el ancho y alineado a la izquierda, que es
       el resto del gesto. Pendiente de decisión.
     · El kicker en mono terracota sobre el H1 —"DAVIE, FL · BROWARD
       COUNTY"— tampoco tiene slot. Se conserva el filete del `.hero__h1`,
       subido a `--acento-cl` para que se lea sobre el panel oscuro.
     · Las barras de sitio y el pie NO se tocan. Son chrome compartido: una
       cabecera distinta según la página se lee como otro sitio, no como otra
       sección.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1 · EL HERO PARTIDO A MEDIA PANTALLA ──────────────────────────────────
   Panel oscuro a la izquierda, foto a sangre a la derecha, mitad y mitad.

   HAY QUE ROMPER LA CAJA. `.hero` es `main > section`, o sea que llega con
   `max-width: var(--ancho)`, `margin-inline: auto` y la canaleta. Con eso la
   foto termina 40 px antes del borde a 1440 y 520 antes a 1920 — el mismo
   cálculo que la línea 437 hace para el fondo. Se sueltan las tres.

   `align-items: stretch` pisa el `center` del hero base: las dos mitades
   tienen que medir lo mismo o el panel oscuro flota. */
.t-gbp_service.v-galeria .hero {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0;
  align-items: stretch;
  max-width: none;
  margin-inline: 0;
  padding: 0;
  background: var(--profunda);
}
/* El fondo al 10% queda tapado por el panel y por la foto: dibujarlo es pagar
   una imagen que nadie ve. Y en el borde entre las dos mitades asomaba. */
.t-gbp_service.v-galeria .hero::before { display: none; }

/* Se deshace el espejado del tipo (línea 517): en galería el texto va a la
   IZQUIERDA y la foto a la derecha. */
.t-gbp_service.v-galeria .hero__texto {
  grid-column: 1; grid-row: 1;
  align-self: stretch;
  display: flex; flex-direction: column; justify-content: center;
  /* El relleno vertical entra en la cuenta de la primera pantalla (§7): con
     4,5rem el panel medía 144 px de aire y empujaba la franja fuera. */
  padding: clamp(1.5rem, 2.6vw, 4rem) clamp(1.5rem, 4vw, 4.5rem);
  /* El texto no puede pegarse al borde de la ventana en pantallas anchas: se
     alinea con la canaleta del resto de la página. */
  padding-left: max(var(--canaleta), (100vw - var(--ancho)) / 2);
}
/* LA FOTO NO PUEDE MANDAR LA ALTURA, Y CON `height: 100%` LA MANDA.
   Primera versión: `display: block` en la figura y `height: 100%` en la img.
   Medido a 1440 dio un hero de 926 px contra los 660 que pide `--tope`, o sea
   la franja de confianza 266 px por debajo del borde de la ventana — la §7 de
   `convenciones.md` rota. El motivo: `height: 100%` dentro de un track cuya
   altura depende del contenido es circular, y el navegador cae al alto
   INTRÍNSECO — 1152 px de la imagen escalados al ancho de la mitad dan 926.
   Sacar la foto del flujo con `absolute` corta la circularidad: la figura
   deja de tener alto propio y la fila la fija el texto contra el min-height. */
.t-gbp_service.v-galeria .hero__figura {
  grid-column: 2; grid-row: 1;
  align-self: stretch;
  position: relative;
  overflow: hidden;
}
/* La foto llena su mitad, sin proporción propia y sin radio: es superficie,
   no una imagen apoyada sobre el fondo. */
.t-gbp_service.v-galeria .hero__figura img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  aspect-ratio: auto;
  min-height: 0; max-height: none;
  object-fit: cover;
  border-radius: 0;
}

/* El texto sobre superficie oscura. Los tres tonos son los que ya usa
   `.hero__dato` desde el 2026-08-10, así que el bloque C ya los mide. */
.t-gbp_service.v-galeria .hero__h1 { color: var(--claro); }
.t-gbp_service.v-galeria .hero__h1::before { background: var(--acento-cl); }
/* El margen bajo el subtítulo y el de arriba de la ficha de datos entran los
   dos en la cuenta de la §7. En el panel oscuro hay menos alto disponible que
   en el hero base, así que se aprietan. */
.t-gbp_service.v-galeria .hero__sub { color: var(--claro-mute); margin-bottom: 1.6rem; }
/* LA FICHA DE DATOS HAY QUE REPETIRLA, NO HEREDARLA. `.hero__specs` existe
   desde el 2026-08-11 y está escrita entera bajo `.v-ficha` (línea 2187): una
   página en otra variante recibe el `<dl>` crudo del navegador, con el `<dd>`
   sangrado y un par por línea. Se vio mirando; ningún gate lo mide.
   Lo correcto de fondo sería subir el layout a la piel compartida y dejar en
   cada variante solo el color — pero eso toca la cascada de diez páginas
   publicadas, así que acá se repite y queda anotado como deuda. */
.t-gbp_service.v-galeria .hero__specs {
  margin: 1.25rem 0 0;
  display: grid;
  /* CUATRO Y SIEMPRE CUATRO, declaradas. Con `auto-fit, minmax(8.5rem,…)` a
     1280 la columna de texto da para tres y el cuarto par se cae a una
     segunda fila, que además es la altura que empuja la franja fuera de la
     pantalla. Es textual la corrección que la ficha ya tenía en su línea
     2405, y la volví a cometer. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-top: 1px solid var(--pelo-osc);
}
.t-gbp_service.v-galeria .hero__spec {
  padding: 0.85rem 0.9rem 0.85rem 0;
  border-right: 1px solid var(--pelo-osc);
}
.t-gbp_service.v-galeria .hero__spec:not(:first-child) { padding-left: 0.9rem; }
.t-gbp_service.v-galeria .hero__spec:last-child { border-right: 0; padding-right: 0; }
.t-gbp_service.v-galeria .hero__spec dt {
  font-family: var(--mono);
  font-size: 0.65rem; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--claro-mute);
}
.t-gbp_service.v-galeria .hero__spec dd {
  margin: 0.3rem 0 0;
  font-family: var(--display); font-weight: 700;
  font-size: 1rem; color: var(--claro); white-space: nowrap;
}
/* El botón secundario es un contorno claro sobre oscuro, no tinta sobre papel */
.t-gbp_service.v-galeria .hero .btn--secundario {
  color: var(--claro); border-color: var(--claro-mute);
}
.t-gbp_service.v-galeria .hero .btn--secundario:hover {
  background: var(--claro); color: var(--profunda); border-color: var(--claro);
}
.t-gbp_service.v-galeria .hero :focus-visible { outline-color: var(--foco-osc); }

/* ── 2 · LA FRANJA DE CONFIANZA, EN TERRACOTA ──────────────────────────────
   Es la seña que el README le atribuye a esta maqueta. Y resuelve de paso el
   problema que crea el hero oscuro: con la franja también oscura, hero y
   franja se funden en un solo bloque negro de una pantalla entera.

   Blanco sobre `--acento` mide 5,51:1 — arriba del 4,5 de texto. Declarado en
   `diseno/contraste.md`. El relleno NO se toca: cierra la cuenta de --tope. */
.v-galeria .trust { background: var(--acento); }
.v-galeria .trust__item { color: #fff; border-left-color: var(--acento-osc); }
.v-galeria .trust__item::before { background: var(--acento-tin); }

/* ── 3 · NINGÚN TÍTULO SE DESLIZA, Y EL BLOQUE VA CENTRADO ─────────────────
   Decisión del operador, 2026-08-12, mirando la página armada.

   EL H2 PEGAJOSO SE VA. El grid base (línea 1076) deja el encabezado en una
   columna de 0.72fr con `position: sticky`, así que acompaña al cuerpo
   mientras se scrollea. En la ficha eso funciona porque las secciones están
   numeradas y el H2 hace de índice. Acá no hay numeración: un título que se
   desliza al costado de una prosa que no lo necesita distrae, y deja media
   página vacía debajo de él durante toda la sección.

   Y EL BLOQUE SE CENTRA. Sin la columna del H2, el cuerpo conserva su medida
   de lectura —~630 px— dentro de una caja de 1.400, y quedan 700 px de papel
   a la derecha. Es exactamente el caso que resuelve la regla del sitio
   «SIN FOTO, CENTRADO» (línea 1429, operador 2026-08-10): el bloque se centra
   en la caja al mismo ancho que el hero, `--ancho-centrado`.

   ⚠ SE CENTRA EL BLOQUE, NO LAS LÍNEAS. La prosa sigue alineada a la
   izquierda dentro de su columna. Centrar línea por línea 1.600 palabras es
   ilegible y esa misma regla lo dice con todas las letras; el centrado por
   línea queda para el cierre y la frase de vuelta, que son §1.

   `proceso` queda FUERA del centrado: su contenido es una grilla de tres
   fichas que necesita el ancho entero. Y `cuando` tiene su propio layout. */
.t-gbp_service.v-galeria .cuando,
.t-gbp_service.v-galeria .variantes,
.t-gbp_service.v-galeria .proceso,
.t-gbp_service.v-galeria .costo,
.t-gbp_service.v-galeria .why {
  grid-template-columns: minmax(0, 1fr);
}
.t-gbp_service.v-galeria .cuando > h2,
.t-gbp_service.v-galeria .variantes > h2,
.t-gbp_service.v-galeria .proceso > h2,
.t-gbp_service.v-galeria .costo > h2,
.t-gbp_service.v-galeria .why > h2 {
  grid-column: 1; grid-row: auto;
  position: static;
  margin-bottom: 1.75rem;
}
.t-gbp_service.v-galeria .cuando > *:not(h2),
.t-gbp_service.v-galeria .variantes > *:not(h2),
.t-gbp_service.v-galeria .proceso > *:not(h2),
.t-gbp_service.v-galeria .costo > *:not(h2),
.t-gbp_service.v-galeria .why > *:not(h2) { grid-column: 1; }

/* El bloque centrado. `--ancho-centrado` es el mismo 62rem del hero, así que
   la página entera tiene UN eje y no dos. La tira a sangre se excluye a mano:
   su trabajo es justamente romper la caja. */
.t-gbp_service.v-galeria .variantes > *,
.t-gbp_service.v-galeria .costo > *,
.t-gbp_service.v-galeria .why > * {
  max-width: var(--ancho-centrado);
  margin-inline: auto;
}
.t-gbp_service.v-galeria .variantes > * > * { max-width: none; }

/* ── 3 bis · CADA VARIANTE, EN SU TARJETA ──────────────────────────────────
   Pedido del operador, 2026-08-12.

   NO SE PUEDE ENVOLVER: el CSS no agrupa dos hermanos en una caja, y en el
   DOM cada variante son dos nodos sueltos —`<h3>` y el `<p>` de al lado—
   porque `md()` no envuelve por opción. Es la misma restricción que la ficha
   resolvió en su día: el H3 se lleva los bordes de ARRIBA y el párrafo los de
   ABAJO, sin borde entre ellos, y los dos con el mismo ancho y el mismo
   fondo. Pegados, se leen como una sola caja.

   ⚠ POR ESO LA CORRECCIÓN #95 IMPORTA ACÁ MÁS QUE EN NINGÚN LADO: el
   selector es `h3 + p`, o sea el párrafo ADYACENTE. Una variante escrita en
   dos párrafos deja el segundo fuera de la tarjeta, a ancho completo y sin
   borde. Un `###` de esta sección lleva UN párrafo. */
.t-gbp_service.v-galeria .variantes h3,
.t-gbp_service.v-galeria .variantes h3 + p {
  width: 100%;
  max-width: var(--ancho-centrado);
  margin-inline: auto;
  box-sizing: border-box;
  background: var(--blanco);
  border: 1px solid var(--pelo);
  border-left: 3px solid var(--acento);
}
.t-gbp_service.v-galeria .variantes h3 {
  margin: 1.6rem auto 0;
  padding: 1.15rem 1.5rem 0.65rem;
  border-bottom: 0;
  border-radius: var(--radio) var(--radio) 0 0;
}
.t-gbp_service.v-galeria .variantes h3 + p {
  margin: 0 auto;
  padding: 0 1.5rem 1.4rem;
  border-top: 0;
  border-radius: 0 0 var(--radio) var(--radio);
}
.t-gbp_service.v-galeria .variantes h3:first-of-type { margin-top: 0.5rem; }
/* La última no arrastra margen contra la tira: la tira ya pega a sangre. */
.t-gbp_service.v-galeria .variantes h3 + p:last-of-type { margin-bottom: 0; }

/* ── 4 · LA APERTURA ENTRA EN DISPLAY ──────────────────────────────────────
   En la maqueta la apertura es un párrafo grande y en negrita que ocupa la
   pantalla entero. Es la bisagra entre el hero y el cuerpo: dice de qué trata
   la página en voz alta antes de que empiece la prosa.

   Acá se conserva la figura al lado —esta piel tiene fotos y desperdiciarlas
   sería raro—, así que el gesto se aplica al primer párrafo y nada más. */
.v-galeria .apertura > p:first-of-type {
  font-family: var(--display);
  font-weight: 700; font-stretch: 105%;
  font-size: clamp(1.25rem, 1.9vw, 1.7rem);
  line-height: 1.32;
  letter-spacing: -0.015em;
  color: var(--tinta);
  max-width: 34ch;
}

/* ── 5 · «CUANDO»: TEXTO A LA IZQUIERDA, FOTOS A LA DERECHA Y CENTRADAS ────
   La primera versión daba vuelta las columnas —fotos a la izquierda— y el
   operador la corrigió el 2026-08-12: van a la derecha, y **centradas contra
   el texto**, que es la §5 de `convenciones.md` textual — *"el TEXTO manda la
   altura y la columna de imágenes se centra contra él, nunca al revés"*.

   El H2 abarca las dos columnas y va arriba: dentro de la columna de texto
   quedaba angosto y partido en cuatro líneas.

   `align-items: center` es lo que pide *"que todo se vea alineado"*: con las
   fotos al tope, la columna derecha terminaba 200 px antes que la izquierda y
   la sección se leía descolgada por abajo. */
.t-gbp_service.v-galeria .cuando:has(.cuando__figura) {
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  grid-template-rows: min-content 1fr;
  column-gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
}
.t-gbp_service.v-galeria .cuando:has(.cuando__figura) > h2 {
  grid-column: 1 / -1; grid-row: 1;
}
.t-gbp_service.v-galeria .cuando:has(.cuando__figura) .cuando__texto {
  grid-column: 1; grid-row: 2;
  align-self: center;
}
/* `:has()` EN EL SELECTOR NO ES ADORNO: sin él esta regla pesa (0,3,0) y la
   de columna única de la sección 3 —`.cuando > *:not(h2)`— pesa (0,3,1) y
   gana, así que la figura se quedaba en la columna 1 ENCIMA del texto. Se vio
   mirando: las dos fotos tapaban los párrafos. Con `:has()` sube a (0,4,0). */
.t-gbp_service.v-galeria .cuando:has(.cuando__figura) .cuando__figura {
  grid-column: 2; grid-row: 2;
  margin: 0; align-self: center;
  display: grid; gap: 1.25rem;
}
.t-gbp_service.v-galeria .cuando__figura img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 3 / 4; object-fit: cover;
  border-radius: var(--radio);
}
/* Con dos fotos, 3:4 cada una mide más que el texto y la sección se estira.
   Con dos van apaisadas; el retrato es para la foto sola. */
.t-gbp_service.v-galeria .cuando__figura:has(:is(img, picture) + :is(img, picture)) img { aspect-ratio: 4 / 3; }

/* ── 6 · LA TIRA DE TRES, A SANGRE ─────────────────────────────────────────
   La pieza que le da nombre a la piel. Tres fotos de borde a borde, sin
   canaleta y sin espacio entre ellas: se leen como una sola banda.

   ROMPER LA CAJA desde dentro de una sección que tiene relleno: `left: 50%`
   más `margin-left: -50vw` sobre `width: 100vw`. Es el mismo recurso que
   `.hero::before`, y `main { overflow-x: clip }` de la línea 448 absorbe el
   ancho de la barra de scroll que 100vw sí cuenta. Sin ese clip esto agrega
   scroll horizontal en Windows.

   El relleno vertical de la sección se anula por abajo para que la tira pegue
   con el borde: una banda a sangre con 60 px de papel debajo no es una banda. */
/* `.t-gbp_service` DELANTE, y no por costumbre: la regla base de la línea
   1106 es `.t-gbp_service .variantes > *:not(h2)` y pesa (0,2,1) por el
   `:not(h2)`. Un `.v-galeria .variantes__tira` pelado pesa (0,2,0) y PIERDE:
   la tira se quedaba en la columna 2 con el `grid-column: 2` heredado, y la
   cuenta de abajo daba x=256 en vez de 0. Medido antes de escribir esto. */
.t-gbp_service.v-galeria .variantes__tira {
  /* ABARCAR LAS DOS COLUMNAS ES PARTE DEL TRUCO, no cosmética. La cuenta
     `left: 50% + margin-left: -50vw` solo da 0 si el contenedor está CENTRADO
     en la ventana. Dentro de la columna 2 del grid no lo está: medido, la
     tira arrancaba en x=254 y se iba por la derecha. Con `1 / -1` el
     contenedor pasa a ser la caja de contenido de la sección, que sí está
     centrada, y la cuenta cierra en 0. */
  grid-column: 1 / -1;
  position: relative;
  left: 50%; margin-left: -50vw;
  width: 100vw; max-width: 100vw;
  gap: 0;
  margin-top: clamp(2.375rem, 4.2vw, 3.75rem);
  margin-bottom: calc(-1 * var(--seccion));
}
.v-galeria .variantes__tira img {
  width: 100%; height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 0;
}
/* El pie vuelve adentro de la caja: es prosa, y a 100vw se leería a 1900 px */
.v-galeria .variantes__tira figcaption {
  grid-column: 1 / -1;
  max-width: var(--ancho);
  margin-inline: auto;
  padding: 1.1rem max(var(--canaleta), (100vw - var(--ancho)) / 2) 0;
  text-align: left;
}

/* ── 7 · EL PROCESO EN TRES COLUMNAS ───────────────────────────────────────
   La lista de pasos deja de ser una lista y pasa a ser una grilla de fichas
   con filete. En la ficha los pasos se leen en vertical porque esa piel es un
   índice; acá el proceso es tranquilizador, no operativo — se mira entero de
   una y se ve que son ocho pasos y no veinte.

   `display: grid` sobre el `<ol>` es seguro; sobre el `<li>` NO lo es, y eso
   está documentado en el punto de la ficha de la línea 2063: un `<li>` de este
   sitio es `<strong>` + nodo de texto suelto, y en grid el navegador arma dos
   ítems y el texto se cae a la columna del ordinal. Acá el `<li>` sigue en
   flujo normal, con el ordinal arriba y no colgando al costado. */
.v-galeria .proceso ol {
  list-style: none; margin: 0; padding: 0;
  max-width: none;
  counter-reset: paso;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0;
  border-top: 1px solid var(--pelo);
  border-left: 1px solid var(--pelo);
}
/* LA CARD BAJA DE CUERPO — decisión del operador, 2026-08-18. El texto del
   proceso venía al mismo tamaño que la prosa de la página, 17 px, y en una
   grilla de tres columnas eso no se lee igual: la prosa corre a 65 caracteres
   por línea y acá la columna da 34, o sea el doble de líneas para el mismo
   texto, y la fila entera se estira hasta la card más larga. A 15,2 px con
   interlínea 1,55 la card ocupa menos sin que el paso deje de leerse: sigue
   por encima del pie de foto (13,6 px), que es el piso de este sitio.

   El padding baja con la tipografía. Si no, el aire alrededor queda calculado
   para un cuerpo que ya no está y la card se ve vacía en vez de compacta. */
.v-galeria .proceso ol > li {
  counter-increment: paso;
  position: static;
  padding: 1.35rem 1.45rem 1.6rem;
  border: 0;
  border-right: 1px solid var(--pelo);
  border-bottom: 1px solid var(--pelo);
  font-size: 0.95rem;
  line-height: 1.55;
}
.v-galeria .proceso ol > li::before {
  content: counter(paso, decimal-leading-zero);
  position: static;
  display: block;
  margin-bottom: 0.85rem;
  font-family: var(--mono);
  font-size: 0.78rem; font-weight: 600; letter-spacing: 0.08em;
  color: var(--acento);
}

/* EL PASO QUE ROMPE SU FILA. En una grilla la fila entera mide lo que mide su
   card más alta, así que un paso que dobla en texto a sus hermanos deja a las
   otras dos medio vacías. Medido a 1440 el 2026-08-13 en /pantry-cabinets-davie/:
   el paso 6 tiene 826 caracteres contra 257 de mediana y dejaba su fila en
   638 px contra los 320 px de la fila de arriba.

   La marca la pone `build.py` (`_clase_paso`) porque el CSS no puede medir
   texto, y el umbral es relativo a los hermanos: una página donde todos los
   pasos son largos no se toca.

   Con esto la fila baja a 430 px y la desproporción pasa de 2,0x a 1,34x.
   NO alinea del todo, y no puede: bajando el paso 6 hasta 11 px la fila se
   planta en 378 px, que es lo que mide el paso 4. Lo que queda de diferencia
   ya no es tipografía, es largo de copy. */
.v-galeria .proceso ol > li.paso--largo {
  font-size: 0.9rem;
  line-height: 1.45;
}

/* ── 8 · EL COSTO EN COLUMNA ANGOSTA ───────────────────────────────────────
   El H2 a todo el ancho y la prosa en una medida de lectura. En la ficha el
   costo es una tabla de tres columnas que necesita el ancho; acá es un
   argumento y se lee como tal. La tabla, si la hay, conserva el ancho. */
.v-galeria .costo > p,
.v-galeria .costo > h3,
.v-galeria .costo > ul,
.v-galeria .costo > ol { max-width: 46rem; }

/* ── 9 · LA NORMATIVA EN DOS COLUMNAS ──────────────────────────────────────
   Texto a la izquierda, credenciales apiladas a la derecha con filete entre
   ellas. En la ficha van centradas y en grilla; acá la lista es una columna
   de hechos que se recorre de arriba abajo, al lado del párrafo que los
   encuadra. */
.v-galeria .normativa {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  column-gap: clamp(2rem, 5vw, 5rem);
  /* CENTRADAS UNA CONTRA OTRA — pedido del operador, 2026-08-12. Con
     `align-items: start` el párrafo terminaba ~110 px antes que la última
     credencial y la sección quedaba descolgada por abajo. Es la misma §5 que
     gobierna `cuando`: dos columnas de distinto alto se centran entre sí. */
  align-items: center;
  text-align: left;
}
.v-galeria .normativa__texto > * { margin-inline: 0; }
.v-galeria .normativa__datos {
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
  border-top: 2px solid var(--tinta);
}
.v-galeria .normativa__dato {
  padding: 1.15rem 0 1.2rem;
  border-bottom: 1px solid var(--pelo);
}

/* ── 10 · LA FAQ, CENTRADA COMO MANDA LA §1 ────────────────────────────────
   La primera versión la alineaba a la izquierda y argumentaba que galería no
   tiene el eje centrado de la ficha. El operador lo corrigió el 2026-08-12, y
   la corrección se sostiene sola: ahora que `variantes`, `costo` y `why` van
   en bloque centrado, el eje SÍ existe, y una FAQ a la izquierda sería la
   pieza descolgada. `convenciones.md` §1 vale entera también acá — se
   revirtió la nota que decía lo contrario. */
.v-galeria .faq__lista { max-width: var(--ancho-centrado); }

/* ── 10 bis · LA FRANJA DE CIFRAS ──────────────────────────────────────────
   Tres números sobre superficie oscura, a sangre, entre el costo y el porqué.
   Es un `<aside>` y no una `<section>` a propósito: la paridad de fondos la
   cuenta `:nth-of-type(section)`, y meter una sección acá correría el fondo
   de todo lo que sigue — la corrección #73.

   A sangre con la misma cuenta que la tira: el `<aside>` es hijo directo de
   `main`, que no tiene relleno propio, así que acá alcanza con el ancho. */
.v-galeria .cifras {
  background: var(--profunda);
  padding: clamp(2.25rem, 3.5vw, 3.25rem) var(--canaleta);
}
.v-galeria .cifras__lista {
  max-width: var(--ancho); margin-inline: auto;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
}
.v-galeria .cifra { padding-inline: clamp(1rem, 3vw, 3rem); }
.v-galeria .cifra:first-child { padding-left: 0; }
.v-galeria .cifra + .cifra { border-left: 1px solid var(--pelo-osc); }
.v-galeria .cifra b {
  display: block;
  font-family: var(--display); font-weight: 800; font-stretch: 112%;
  font-size: clamp(2rem, 3.4vw, 3.1rem); line-height: 1;
  letter-spacing: -0.03em;
  color: var(--claro);
}
/* La PRIMERA en acento. Es la cifra que la sección de costo acaba de
   defender; las otras dos la enmarcan. Sobre oscuro va `--acento-cl`, que es
   el tono subido — `--acento` a secas cae a 3:1 y no se lee (contraste.md). */
.v-galeria .cifra:first-child b { color: var(--acento-cl); }

/* LA CIFRA SUELTA DE `costo`, sólo en esta piel. Un párrafo cuyo único
   contenido es la banda de precio: la regla genérica de arriba
   —`.costo p strong:first-child`— ya lo pone en bloque, y acá se centra y se
   sube de cuerpo.

   VA ACOTADA A `.v-galeria` A PROPÓSITO. Esa regla genérica está activa en
   `small-kitchen-remodel` (3 párrafos) y en `luxury-kitchen-remodeling` (1),
   las dos ya cerradas: centrarla ahí les movería el copy sin que nadie lo
   pidiera. Medido el 2026-08-12: `.v-galeria` la usa UNA sola página, y el
   párrafo de apertura de `costo` NO abre en negrita, así que no se centra. */
.v-galeria .costo p strong:first-child {
  text-align: center;
  margin: clamp(2rem, 3.5vw, 2.75rem) 0;
  font-family: var(--display); font-weight: 800; font-stretch: 112%;
  font-size: clamp(1.75rem, 3vw, 2.6rem); line-height: 1;
  letter-spacing: -0.03em;
  color: var(--acento);
}
.v-galeria .cifra span {
  display: block; margin-top: 0.7rem;
  font-family: var(--display); font-weight: 600;
  font-size: 0.9rem; line-height: 1.35;
  color: var(--claro-mute);
}

/* ── 11 · EL CIERRE PARTIDO ────────────────────────────────────────────────
   Foto a la izquierda, panel oscuro con el titular a la derecha, mitad y
   mitad y a sangre. El slot `cta_img` se agregó al parcial el 2026-08-12
   —pedido del operador— y es OPCIONAL: sin él este bloque no dispara y el CTA
   sale como siempre, que es lo que hace que las diecisiete páginas escritas
   no se enteren.

   Mismo recurso que el hero: se sueltan `max-width`, `margin-inline` y el
   relleno de `main > section`, y la foto va `absolute` para que no arrastre
   la altura. Sigue siendo el último bloque y sigue pegando con el pie —
   `convenciones.md` §6, hueco 0 medido. */
.v-galeria .cta:has(.cta__figura) {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0;
  align-items: stretch;
  max-width: none; margin-inline: 0;
  padding: 0;
  text-align: left;
}
.v-galeria .cta__figura {
  grid-column: 1; grid-row: 1;
  margin: 0; position: relative; overflow: hidden;
  min-height: 18rem;
}
.v-galeria .cta__figura img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; border-radius: 0;
}
.v-galeria .cta__texto-caja {
  grid-column: 2; grid-row: 1;
  display: flex; flex-direction: column; justify-content: center;
  padding: clamp(2rem, 3vw, 3.25rem) clamp(1.5rem, 4vw, 4.5rem);
  /* El texto se alinea con la canaleta del resto de la página, no con el
     borde de la ventana. Espejo de lo que hace el panel del hero. */
  padding-right: max(var(--canaleta), (100vw - var(--ancho)) / 2);
}
/* LA MEDIDA DEL TITULAR DECIDE EL ALTO DE TODA LA SECCIÓN, y eso no se ve
   escribiendo el CSS: se ve midiendo. El operador señaló el cierre como
   demasiado alto el 2026-08-12 — medía 571 px.

   Y EL `max-width` NO ERA LA PALANCA. Con `18ch` el titular caía en cuatro
   líneas; se subió a `28ch` y siguió en cuatro, porque a 43,2 px el H2 ya
   medía 590 de los 596 disponibles: **lo que lo limitaba era el ancho del
   panel, no el cap**. La palanca es el CUERPO. El tamaño del `.cta__h2` está
   calibrado para un cierre a todo el ancho y centrado; en media pantalla hay
   que bajarlo, y con eso el titular pasa a tres líneas.

   Ojo al escribir un `cta_titulo` largo: acá cada línea cuesta ~42 px de
   sección. El de esta página tiene 87 caracteres. */
.v-galeria .cta:has(.cta__figura) .cta__h2 {
  margin-inline: 0; max-width: 28ch;
  font-size: clamp(1.75rem, 2.6vw, 2.35rem);
}
.v-galeria .cta:has(.cta__figura) .cta__texto { margin-inline: 0; max-width: 56ch; }
.v-galeria .cta:has(.cta__figura) .btn { align-self: start; }

/* ── 12 · MÓVIL ────────────────────────────────────────────────────────────
   Las tres piezas partidas se apilan. El hero pone el texto ARRIBA y la foto
   debajo —al revés que la piel base, que en servicio manda la foto primero—
   porque acá el panel oscuro arranca la página y cortarlo con una foto en el
   medio deja una franja negra flotando entre dos claras. */
@media (max-width: 56rem) {
  .t-gbp_service.v-galeria .hero {
    grid-template-columns: minmax(0, 1fr);
  }
  .t-gbp_service.v-galeria .hero__texto {
    grid-column: 1; grid-row: 1; order: 0;
    padding-left: var(--canaleta); padding-right: var(--canaleta);
  }
  .t-gbp_service.v-galeria .hero__figura {
    grid-column: 1; grid-row: 2; order: 1;
  }
  .t-gbp_service.v-galeria .hero__figura img { aspect-ratio: 4 / 3; min-height: 0; }
  /* Dos y dos, igual que la ficha: cuatro columnas en 350 px parten el valor */
  .t-gbp_service.v-galeria .hero__specs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .t-gbp_service.v-galeria .hero__spec:nth-child(even) { border-right: 0; padding-right: 0; }
  .t-gbp_service.v-galeria .hero__spec:nth-child(odd) { padding-left: 0; }

  .t-gbp_service.v-galeria .cuando:has(.cuando__figura) {
    grid-template-columns: minmax(0, 1fr);
  }
  .t-gbp_service.v-galeria .cuando:has(.cuando__figura) > h2,
  .t-gbp_service.v-galeria .cuando:has(.cuando__figura) .cuando__texto {
    grid-column: 1;
  }
  .t-gbp_service.v-galeria .cuando:has(.cuando__figura) .cuando__figura {
    grid-column: 1; grid-row: auto; margin-top: 2rem;
  }
  .t-gbp_service.v-galeria .cuando__figura img,
  .t-gbp_service.v-galeria .cuando__figura:has(:is(img, picture) + :is(img, picture)) img { aspect-ratio: 4 / 3; }

  /* La tira a sangre pasa a una sola columna: tres fotos de 130 px de ancho
     no son una galería, son tres estampillas. */
  .v-galeria .variantes__tira { grid-template-columns: minmax(0, 1fr); }

  .v-galeria .proceso ol { grid-template-columns: minmax(0, 1fr); }

  .v-galeria .normativa { grid-template-columns: minmax(0, 1fr); row-gap: 2rem; }

  /* Las tres cifras en columna: a 390 px, tres de 110 px parten "A third to
     a half" en cuatro líneas y el número deja de ser un número grande. */
  .v-galeria .cifras__lista { grid-template-columns: minmax(0, 1fr); }
  .v-galeria .cifra { padding-inline: 0; }
  .v-galeria .cifra + .cifra {
    border-left: 0; border-top: 1px solid var(--pelo-osc);
    margin-top: 1.5rem; padding-top: 1.5rem;
  }

  /* El cierre se apila con el texto ARRIBA, igual que el hero: el panel
     oscuro tiene que pegar con el pie, y con la foto abajo quedaría una
     franja clara entre dos oscuras — `convenciones.md` §2. */
  .v-galeria .cta:has(.cta__figura) { grid-template-columns: minmax(0, 1fr); }
  .v-galeria .cta__texto-caja {
    grid-column: 1; grid-row: 2;
    padding-inline: var(--canaleta);
  }
  .v-galeria .cta__figura {
    grid-column: 1; grid-row: 1;
    min-height: 0; aspect-ratio: 4 / 3;
  }
}


/* ═══════════════════════════════════════════════════════════════════════════
   PIEL «REVISTA» — .v-revista
   2026-08-12 · traslado de diseno/servicio/04-revista.html

   PARA QUÉ EXISTE. `diseno/servicio/README.md` la describe como *"la más
   editorial. La que mejor se lee si el copy es fuerte"*, y el reparto de
   `ESTADO.md` §7b se la asigna a **lo que se EXPLICA**: los argumentos largos.
   Son las páginas donde el visitante no compara una tabla ni mira una puerta —
   lee por qué una cosa cuesta lo que cuesta y por qué la otra no le sirve.

   POR QUÉ NO ALCANZABA CON LAS OTRAS DOS. La ficha numera y aplana para que se
   escanee; la galería manda la foto al frente. Las dos le sacan peso al texto,
   que es justo lo único que esta página tiene para dar. Acá el orden se
   invierte: la foto es el fondo sobre el que se apoya el titular, la prosa
   conserva el título colgado que hace de índice, y el dato duro —la tabla de
   mercado— acompaña al argumento al costado en vez de interrumpirlo.

   LA REGLA QUE LA HACE SEGURA — la misma de las otras dos. Todo cuelga de
   `.v-revista`, que solo existe si el `.md` lo pidió. Las diez de countertop
   están en `.v-ficha`, `/cabinet-refacing-davie/` en `.v-galeria` y ninguna puede
   ver una sola de estas reglas.

   LO QUE NO SE TRASLADÓ, Y POR QUÉ:
     · LA PROSA A DOS COLUMNAS de la sección *Right call*. Es la regla 3 de las
       cuatro que `diseno/servicio/README.md` marca como rotas: un párrafo con
       enlaces contextuales adentro, partido en dos columnas, rompe la lectura
       del enlace — y el enlace contextual es la única arista que sostiene el
       mapa del sitio. Se reemplaza por lo que la maqueta ya insinúa en el
       resto: título colgado a la izquierda, prosa a la derecha en una sola
       columna de medida larga.
     · EL ASIDE PEGAJOSO DEL COSTO con el número grande, la tabla y una foto
       3:4. No hay slot para ese bloque y agregarlo sería tocar `plantillas/`,
       que es del modelo — la deuda que `galeria` ya abrió con `cta_img` y las
       cifras. Lo que sí viaja es el GESTO: la tabla de mercado, que la página
       ya escribe en su markdown, se va a la columna derecha y queda pegajosa
       al lado de la prosa que la explica. El número grande ya tiene su pieza
       propia y es la franja de cifras, que está más abajo.
     · EL FAQ EN `<details open>`. Es la regla 2 del README y no es de piel:
       las respuestas van al schema y marcar en JSON-LD algo que no se ve es
       contenido invisible. El acordeón del sitio ya resuelve eso y no se toca.
     · Las barras de sitio y el pie, igual que en galería: son chrome
       compartido y una cabecera distinta por página se lee como otro sitio.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1 · EL HERO: FOTO A SANGRE Y LA FICHA MONTADA ENCIMA ──────────────────
   La seña de esta maqueta. La foto ocupa la pantalla entera y el titular vive
   en un panel de papel apoyado abajo a la izquierda, con el filete de acento
   arriba.

   HAY QUE ROMPER LA CAJA, igual que en galería: `.hero` es `main > section` y
   llega con `max-width: var(--ancho)` y la canaleta, así que sin soltarlo la
   foto termina 40 px antes del borde a 1440. Se sueltan las tres y el relleno
   se recalcula para que el PANEL siga alineado con la canaleta del resto.

   ⚠ LA FOTO NO PUEDE IR `position: absolute` DENTRO DE ESTE GRID, y esto
   costó dos pasadas de medir. La primera versión la sacaba del flujo con
   `inset: 0` sobre el `.hero`, que es la receta de galería. Medido acá con una
   sonda en el HTML publicado: **la figura salía de 1440 × 0 px, con el borde
   de arriba en 503 — el centro exacto del hero**, y los cuatro offsets
   resueltos en `0px`. El ancho estiraba y el alto no. El motivo es la
   combinación que galería no tiene: un absoluto hijo de un GRID, con las
   propiedades de colocación en `auto` y `align-self: center` heredado del
   `.hero__figura` base. El bloque contenedor resuelve con alto cero y el
   `align-self` centra la caja vacía. El hero se publicaba de color plano y la
   foto no aparecía en ningún lado.

   SE RESUELVE CON LA CELDA, NO CONTRA ELLA. La figura vuelve al flujo como
   ítem del grid, estirada en su única celda, y el `<img>` va absoluto ADENTRO
   de ella — que es donde el truco sí funciona, porque ahí el bloque contenedor
   es una caja con alto propio. Lo que hace falta para que la celda mida el
   hero entero es soltarle el relleno al `.hero`: con relleno, la celda mide el
   contenido y quedan dos franjas lisas arriba y abajo. El relleno pasa al
   panel, como margen. */
.t-gbp_service.v-revista .hero {
  grid-template-columns: minmax(0, 1fr);
  align-items: end;
  max-width: none;
  margin-inline: 0;
  padding: 0;
  background: var(--profunda);
}
/* El fondo al 10% queda tapado por la foto entera: dibujarlo es pagar una
   imagen que nadie ve. Mismo criterio que galería. */
.t-gbp_service.v-revista .hero::before { display: none; }

/* La figura ocupa la única celda y se estira en los dos ejes. El `z-index: -1`
   es lo que la deja DEBAJO del panel: en el parcial `.hero__texto` viene ANTES
   que `.hero__figura`, así que sin esto la foto se pinta encima del titular.
   Es el mismo recurso que ya usa `.hero::before`, y funciona por el
   `isolation: isolate` del hero. */
.t-gbp_service.v-revista .hero__figura {
  grid-column: 1; grid-row: 1;
  align-self: stretch; justify-self: stretch;
  position: relative;
  z-index: -1;
  margin: 0;
  display: block;
  overflow: hidden;
}
.t-gbp_service.v-revista .hero__figura img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  aspect-ratio: auto;
  min-height: 0; max-height: none;
  object-fit: cover;
  border-radius: 0;
}
/* El dato del hero cuelga del borde IZQUIERDO de la foto, que ahora es el
   borde de la ventana. Se lo manda arriba y alineado con la canaleta, que es
   donde no pelea con el panel. Ninguna página de esta piel lo declara todavía;
   la regla existe para que el día que lo declare no salga pegado al vidrio. */
.t-gbp_service.v-revista .hero__dato {
  left: auto; bottom: auto;
  top: clamp(1.5rem, 3vw, 2.5rem);
  right: max(var(--canaleta), (100vw - var(--ancho)) / 2);
}

/* EL PANEL. Papel sólido sobre la foto: el texto no se lee sobre una imagen
   —ningún par de contraste sobrevive a una foto— y por eso la maqueta pone
   caja y no degradado. Todos los colores de adentro son los del cuerpo del
   sitio, así que el bloque C no estrena un solo par. */
.t-gbp_service.v-revista .hero__texto {
  grid-column: 1; grid-row: 1;
  align-self: end;
  /* CENTRADO EN HORIZONTAL, ABAJO EN VERTICAL — pedido del operador,
     2026-08-12. Se centra el panel; NO se sube. Por eso `align-self` sigue en
     `end` y lo único que cambia es el eje horizontal. Con `justify-self:
     center` el margen izquierdo que alineaba el panel con la canaleta pasa a
     sobrar: empujaría el bloque a la derecha del centro. */
  justify-self: center;
  /* 56rem Y NO 46, Y LA PALANCA ES EL H1 — §18.3 textual: «achicar el relleno
     tapa el síntoma; ensanchar el texto arregla la causa». Medido en el HTML
     publicado: a 46rem el titular caía en TRES líneas y hero + franja cerraban
     en 989 contra los 900 de la ventana, o sea 89 px por debajo del borde y la
     §7 rota. A 56rem el ancla entra en dos líneas. */
  max-width: 56rem;
  box-sizing: border-box;
  background: var(--papel);
  border-top: 5px solid var(--acento);
  padding: clamp(1.75rem, 2.4vw, 2.25rem) clamp(1.5rem, 2.6vw, 3rem)
           clamp(1.75rem, 2.4vw, 2rem);
  /* El relleno que se le sacó al `.hero` para que la foto llegue a los cuatro
     bordes vuelve acá como MARGEN. El de la izquierda es el que alinea el
     panel con la canaleta del resto de la página, y los verticales son los
     otros 43 px que hacían falta para cerrar la primera pantalla. */
  margin: clamp(1.5rem, 2.5vw, 2.5rem) var(--canaleta);
}
/* EL FILETE DEL H1 SE APAGA, y no por gusto: mide 5rem × 4px en el mismo
   terracota y quedaría a 40 px del borde de 5px del panel. Dos barras casi
   iguales tan cerca no se leen como un gesto repetido — es textual la lección
   del separador de `variantes + proceso` (línea 1839). El borde del panel ES
   el filete de esta piel. */
.t-gbp_service.v-revista .hero__h1 { padding-top: 0; }
.t-gbp_service.v-revista .hero__h1::before { display: none; }
.t-gbp_service.v-revista .hero__sub { margin-bottom: 1.5rem; }

/* LA FICHA DE DATOS HAY QUE REPETIRLA, NO HEREDARLA — la misma deuda que
   anotó galería: `.hero__specs` está escrita entera bajo `.v-ficha`, así que
   otra variante recibe el `<dl>` crudo del navegador. Acá va sobre papel, con
   los mismos valores que la ficha. CUATRO Y SIEMPRE CUATRO, declaradas: con
   `auto-fit` el cuarto par se cae a una segunda fila y esa altura es la que
   empuja la franja de confianza fuera de la primera pantalla. */
.t-gbp_service.v-revista .hero__specs {
  margin: 1.5rem 0 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-top: 1px solid var(--pelo);
}
.t-gbp_service.v-revista .hero__spec {
  padding: 0.8rem 0.9rem 0 0;
  border-right: 1px solid var(--pelo);
}
.t-gbp_service.v-revista .hero__spec:not(:first-child) { padding-left: 0.9rem; }
.t-gbp_service.v-revista .hero__spec:last-child { border-right: 0; padding-right: 0; }
.t-gbp_service.v-revista .hero__spec dt {
  font-family: var(--mono);
  font-size: 0.68rem; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--mute);
}
.t-gbp_service.v-revista .hero__spec dd {
  margin: 0.25rem 0 0;
  font-family: var(--display); font-weight: 700;
  font-size: 1.05rem; color: var(--tinta);
}

/* ── 2 · LA FRANJA DE CONFIANZA NO SE TOCA ─────────────────────────────────
   Galería la pasó a terracota porque su hero es oscuro y los dos bloques se
   fundían. Acá el hero termina en un panel de papel, así que la franja oscura
   de siempre hace de corte y no hay nada que resolver. Una piel que cambia
   colores sin un problema que arreglar es footprint, no diseño. */

/* ── 3 · LA APERTURA ENTRA EN VOZ ALTA ─────────────────────────────────────
   En la maqueta la apertura es un párrafo grande en display, a mitad de
   pantalla, con la foto al lado y las dos piezas centradas entre sí. Es la
   bisagra: dice de qué trata la página antes de que empiece la prosa.

   Mitad y mitad NO: 0.8fr para la foto. Pedido del operador el 2026-08-12 —
   *"centrá el texto con la imagen para que esté alineado"*— y lo que lo
   resuelve es la §5 de `convenciones.md`, no un `align-*` más: **el TEXTO
   manda la altura y la columna de imágenes se centra contra él, nunca al
   revés**. A 1fr y 4:3 la foto medía 459 px contra ~330 de texto, así que la
   más alta era ella y el texto se quedaba pegado arriba con el hueco abajo.
   Con la columna en 0.8fr y la foto en 16:10 la foto baja de la altura del
   texto y `align-items: center` la centra contra él, que es lo que se ve
   alineado. */
.t-gbp_service.v-revista .apertura:has(.apertura__figura) {
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr);
  align-items: center;
}
.v-revista .apertura > p:first-of-type {
  font-family: var(--display);
  font-weight: 700; font-stretch: 105%;
  font-size: clamp(1.3rem, 2vw, 1.75rem);
  line-height: 1.32;
  letter-spacing: -0.02em;
  color: var(--tinta);
  max-width: none;
}
.v-revista .apertura__figura img { aspect-ratio: 16 / 10; }

/* ── 4 · «CUANDO»: TEXTO A LA IZQUIERDA, FOTOS A LA DERECHA ────────────────
   Reescrita por pedido del operador, 2026-08-12: *"el texto y el título del
   lado izquierdo y las imágenes del lado derecho; las imágenes tienen que ser
   del largo del texto y estar centradas y alineadas una con otra"*.

   La primera versión conservaba el grid base —H2 pegajoso solo en la columna
   izquierda, prosa a la derecha— y colgaba el mosaico DEBAJO del texto. Ahora
   el H2 baja a la columna del texto y la columna derecha es entera de fotos.

   `align-self: stretch` en la figura es lo que cumple *"del largo del texto"*:
   la figura abarca de la primera fila a la última —o sea el alto completo de la
   columna izquierda— y las dos fotos se reparten ese alto en dos pistas
   iguales, así que quedan alineadas entre sí arriba y abajo. Sin `stretch`,
   cada foto dibuja su propia proporción y la columna termina antes que la
   prosa.

   El H2 pierde el `sticky`: dentro de la columna de texto, un título que se
   desliza deja la prosa corriendo sola debajo de un hueco. */
.t-gbp_service.v-revista .cuando:has(.cuando__figura) {
  /* 1.15/0.85 y no 1.3/0.7: con la columna de fotos en 300 px, dos imágenes
     apaisadas recortadas a 300×370 pierden la cocina y se leen como texturas.
     A 0.85fr la pista da ~380 px y cada foto queda casi cuadrada. */
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  column-gap: clamp(2rem, 4vw, 3.5rem);
}
.t-gbp_service.v-revista .cuando:has(.cuando__figura) > h2 {
  grid-column: 1; grid-row: auto;
  position: static;
  max-width: 22ch;
  margin-bottom: 1.5rem;
}
.t-gbp_service.v-revista .cuando:has(.cuando__figura) .cuando__texto {
  grid-column: 1;
}
.t-gbp_service.v-revista .cuando__texto > * { max-width: 68ch; }
.t-gbp_service.v-revista .cuando__texto > *:first-child { margin-top: 0; }

/* H2 de `costo` centrado — pedido del operador, 2026-08-13.
   Alcance: la piel galería, que son las 9 de la rama cabinet. No hay clase por
   página en el `<body>`, así que plantilla + piel es lo más angosto que existe. */
.t-gbp_service.v-galeria .costo__h2 {
  text-align: center;
}
.t-gbp_service.v-galeria .costo__h2::before {
  left: 50%;
  transform: translateX(-50%);
}

/* H2 de `cuando` centrado — pedido del operador, 2026-08-13.
   Alcance elegido: la piel revista y nada más. `.cuando__h2` a secas renderiza
   en 29 páginas, 26 de ellas ya cerradas, y el `<body>` no lleva clase por
   página: plantilla y piel es lo más angosto que hay. */
.t-gbp_service.v-revista .cuando__h2 {
  text-align: center;
  margin-inline: auto;
}
/* La barrita del filete se centra con él. Sin esto queda anclada a `left: 0`
   y cuelga a la izquierda de un título centrado, que se ve roto y no centrado.
   `position: relative` hay que devolvérselo: la regla de la figura lo pasa a
   `static` y ahí el `::before` absoluto se va a buscar otro ancestro. */
.t-gbp_service.v-revista .cuando:has(.cuando__figura) > h2 {
  position: relative;
  /* Devolverle `relative` hace que el filete vuelva a dibujarse DENTRO de la
     caja, y el H2 crece por encima de su fila del grid: medido, se comía 8px
     del primer párrafo. El margen inferior sube de 1.5 a 3rem para despejarlo. */
  margin-bottom: 3rem;
}
.t-gbp_service.v-revista .cuando__h2::before {
  left: 50%;
  transform: translateX(-50%);
}

/* `:has()` EN EL SELECTOR NO ES ADORNO — es la misma lección que ya está
   anotada en la galería (línea 2811): sin él esta regla pesa (0,3,0), la de la
   piel base `.t-gbp_service .cuando > *:not(h2)` pesa (0,2,1) y gana por el
   `:not()`, así que la figura se quedaría en la columna que le da la base. */
.t-gbp_service.v-revista .cuando:has(.cuando__figura) .cuando__figura {
  grid-column: 2; grid-row: 1 / -1;
  align-self: stretch;
  margin: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: 1fr 1fr;
  gap: 1rem;
}
.t-gbp_service.v-revista .cuando__figura:not(:has(:is(img, picture) + :is(img, picture))) {
  grid-template-rows: 1fr;
}
.v-revista .cuando__figura img {
  display: block;
  width: 100%; height: 100%;
  aspect-ratio: auto;
  object-fit: cover;
  border-radius: var(--radio);
}

/* ── 5 · EL PROCESO EN FICHAS CON EL ORDINAL GRANDE ────────────────────────
   La maqueta convierte la lista en fichas: filete de acento arriba, el número
   en display grande y el paso debajo. En la ficha los pasos son una lista
   vertical numerada porque esa piel ES un índice; acá el proceso tranquiliza —
   se ve de una que son ocho pasos y no veinte.

   ⚠ `display: grid` va en el `<ol>` y NUNCA en el `<li>`. Está medido en la
   línea 2882: un `<li>` de este sitio es `<strong>` + un nodo de texto suelto,
   y en grid el navegador arma dos ítems y el texto se cae a otra celda. El
   `<li>` se queda en flujo normal y el ordinal pasa de absoluto a bloque. */
.v-revista .proceso ol {
  list-style: none; margin: 0; padding: 0;
  max-width: none;
  counter-reset: paso;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: clamp(1.5rem, 2.4vw, 2.25rem);
}
.v-revista .proceso ol > li {
  counter-increment: paso;
  position: static;
  padding: 1.1rem 0 0;
  border: 0;
  border-top: 2px solid var(--acento);
}
.v-revista .proceso ol > li:first-child { border-top: 2px solid var(--acento); }
.v-revista .proceso ol > li::before {
  content: counter(paso, decimal-leading-zero);
  position: static;
  display: block;
  margin-bottom: 0.5rem;
  font-family: var(--display); font-weight: 800; font-stretch: 112%;
  font-size: 1.65rem; line-height: 1; letter-spacing: -0.03em;
  color: var(--acento);
}

/* ── 6 · EL COSTO, CENTRADO Y SIN NADA QUE SE DESLICE ──────────────────────
   Pedido del operador, 2026-08-12: *"esta sección va sin sliding, centrala"*.

   La versión anterior mandaba la tabla a una columna derecha PEGAJOSA, para
   traer el gesto del aside de la maqueta sin tocar `plantillas/`. Se revirtió
   entera: la sección vuelve a una columna y el bloque se centra contra
   `--ancho-centrado`, que es el mismo eje del hero y del resto de la página.

   La tabla NO se centra línea por línea: se centra el BLOQUE. Centrar el texto
   de una tabla no la centra —es `display: block` para llevarse el `overflow-x`,
   y un bloque al 100% ocupa el contenedor entero—, así que van las dos cosas,
   `width: fit-content` y `margin-inline: auto`. Está medido en la §18.1 de
   `convenciones.md`. */
.t-gbp_service.v-revista .costo {
  grid-template-columns: minmax(0, 1fr);
}
.t-gbp_service.v-revista .costo > h2 {
  grid-column: 1; grid-row: auto;
  position: static;
  margin-bottom: 1.75rem;
}
.t-gbp_service.v-revista .costo > *:not(h2) { grid-column: 1; }
.t-gbp_service.v-revista .costo > * {
  max-width: var(--ancho-centrado);
  margin-inline: auto;
}
/* LA TABLA VA ANCHA — pedido del operador, 2026-08-12: centrada con
   `fit-content` medía 495 px dentro de una sección de 992 y se leía como una
   ficha suelta en el medio del texto. Ocupa el ancho del bloque, que es el
   mismo `--ancho-centrado` que el resto de la sección, así que sigue habiendo
   un solo eje. */
.v-revista .costo > table {
  width: 100%;
  max-width: var(--ancho-centrado);
  margin-inline: auto;
}
/* La primera columna se acota para que el segundo dato no se vaya al otro
   extremo de la sección: a ancho completo y sin cap, el rango quedaba a 600 px
   de lo que mide, y leer la fila obligaba a barrer la pantalla entera. */
.v-revista .costo > table th:first-child,
.v-revista .costo > table td:first-child { width: 34%; }

/* ── 6 bis · LA FRANJA DE CIFRAS ───────────────────────────────────────────
   El número grande del aside de la maqueta, en la pieza que el modelo ya tiene
   para eso. Es un `<aside>` y no una `<section>`: la paridad de fondos la
   cuenta `:nth-of-type(section)` y meter una sección acá correría el fondo de
   todo lo que sigue — corrección #73.

   No va a sangre. En galería la banda oscura corta una página de fotos a
   sangre; acá la página es una caja de texto de punta a punta y una banda que
   se escapa de la caja rompe el único eje que tiene. */
/* ── EL ORDEN VISUAL DE `main`, Y POR QUÉ SE HACE CON CSS ──────────────────
   Pedido del operador, 2026-08-12: la franja de cifras sube y queda ENTRE
   `cuando` y `variantes`, no después del costo.

   En el DOM la emite `gbp_service.html` después de `costo`, y moverla ahí es
   tocar `plantillas/`, que es del modelo y se propaga a las 37 páginas y a las
   demás copias. Acá se resuelve con `order`: CSS puro, que muere con la piel.
   `main` pasa a ser una columna flex y cada hijo declara su lugar.

   ES SEGURO POR UNA RAZÓN CONCRETA: en `gbp_service` el fondo de cada sección
   se fija POR NOMBRE y no por posición (línea 1819, corrección #72). Si
   dependiera de `:nth-of-type()`, reordenar daría vuelta seis colores. El
   separador de `variantes + proceso` también sigue en pie: el selector
   adyacente mira el DOM, y el DOM no cambió.

   Los catorce hijos se enumeran completos a propósito. Con `order` alcanzaría con
   declarar el que se mueve, pero entonces el orden de los otros doce viviría en
   un archivo y el de la piel en otro, y el día que la plantilla sume una
   sección nadie se entera. */
.v-revista main { display: flex; flex-direction: column; }
.v-revista main > .hero      { order: 1; }
.v-revista main > .trust     { order: 2; }
.v-revista main > .apertura  { order: 3; }
.v-revista main > .cuando    { order: 4; }
.v-revista main > .cifras    { order: 5; }
.v-revista main > .variantes { order: 6; }
.v-revista main > .proceso   { order: 7; }
.v-revista main > .costo     { order: 8; }
.v-revista main > .why       { order: 9; }
.v-revista main > .normativa { order: 10; }
.v-revista main > .faq       { order: 11; }
/* La galería entró el 2026-08-13 y sin esta línea caía a `order: 0` —el valor
   por defecto— o sea ARRIBA DEL HERO, en las nueve páginas con esta piel. Es
   textualmente lo que avisa el párrafo de arriba: acá se enumeran los trece
   hijos completos justamente para que sumar una sección se note, y se notó
   MIRANDO, no midiendo. Ningún bloque de verificar.py mira el orden pintado. */
.v-revista main > .galeria   { order: 12; }
.v-revista main > .vuelta    { order: 13; }
.v-revista main > .cta       { order: 14; }

/* A SANGRE, LOS DOS BORDES — pedido del operador, 2026-08-12. La primera
   versión dejaba la banda oscura DENTRO de la caja de 1400 px, con papel a los
   costados. Acá el oscuro llega al vidrio.

   No hace falta el truco de `100vw` que usa el hero: `.cifras` es un `<aside>`,
   y el relleno de `main > section` no lo toca, así que ya nace a ancho completo.
   Alcanza con moverle el color al contenedor y el relleno horizontal con él —
   el contenido sigue alineado con la canaleta del resto de la página. */
.v-revista .cifras {
  background: var(--profunda);
  padding: clamp(1.75rem, 3vw, 2.75rem) max(var(--canaleta), (100% - var(--ancho)) / 2);
}
.v-revista .cifras__lista {
  max-width: var(--ancho); margin-inline: auto;
  background: none;
  padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 3rem);
}
.v-revista .cifra b {
  display: block;
  font-family: var(--display); font-weight: 800; font-stretch: 112%;
  font-size: clamp(2rem, 3.4vw, 3.1rem); line-height: 1;
  letter-spacing: -0.03em;
  color: var(--claro);
}
/* La PRIMERA en acento subido: `--acento` a secas cae a 3:1 sobre oscuro y no
   se lee. Está en diseno/contraste.md. */
.v-revista .cifra:first-child b { color: var(--acento-cl); }
.v-revista .cifra span {
  display: block; margin-top: 0.65rem;
  font-family: var(--display); font-weight: 600;
  font-size: 0.9rem; line-height: 1.35;
  color: var(--claro-mute);
}

/* ── 7 · EL PORQUÉ SOBRE TINTE ─────────────────────────────────────────────
   La única superficie nueva de esta piel, y es la que trae la maqueta: el
   bloque *Why us* sobre `--acento-tin`, el rosado del acento que ya está en la
   paleta. Con la franja de cifras oscura arriba y la normativa en papel abajo,
   la página tiene tres valores seguidos y deja de leerse plana.

   LOS PARES NUEVOS ESTÁN DECLARADOS en `diseno/contraste.md`: el bloque C solo
   mide los colores que conviven en una misma regla, y estos no conviven en
   ninguna. */
.t-gbp_service.v-revista main > section.why { background: var(--acento-tin); }
.t-gbp_service.v-revista main > section.why + section { border-top-color: transparent; }
.v-revista .why__h2 { max-width: 20ch; }

/* ── 8 · LA NORMATIVA: LAS CINCO CREDENCIALES EN UNA SOLA FILA ─────────────
   Pedido del operador, 2026-08-12. Antes iban en `auto-fit` sobre
   `--ancho-centrado`, que con un mínimo de 14rem entregaba cuatro arriba y una
   sola abajo — media fila vacía, que es justo lo que la §16 vino a resolver.

   SON CINCO Y SE DECLARAN CINCO. `auto-fit` deduce la cantidad del ancho
   disponible y por eso no sirve acá: la cantidad la sabe el sitio, no el
   navegador —son las credenciales de `datos.json`— y la lección de la tira de
   miniaturas (línea 1762) es la misma, «se cuenta, no se estima».

   Y LA GRILLA SE VA A 76rem MIENTRAS EL TEXTO SE QUEDA EN 62. A 62rem cada
   tarjeta mide 189 px y `CGC1524886` sale al borde. Son dos anchos, pero
   CENTRADOS SOBRE EL MISMO EJE, que es lo que la sección ya hacía. */
.v-revista .normativa__datos {
  max-width: min(100%, 76rem);
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 0.85rem;
}
.v-revista .normativa__dato {
  background: var(--blanco);
  border-top: 3px solid var(--acento);
  padding: 1.1rem 1rem 1.25rem;
}
.v-revista .normativa__dato dt { font-size: 0.7rem; letter-spacing: 0.06em; }
.v-revista .normativa__dato dd { font-size: 0.9rem; }
.v-revista .normativa__dato dd b { font-size: 1rem; }
/* El impar deja de abarcar la fila entera: con cinco columnas declaradas, una
   tarjeta estirada al doble se lee como un error de maquetado. */
.v-revista .normativa__dato:last-child:nth-child(odd) { grid-column: auto; }

/* ── 9 · EL FAQ, CENTRADO Y SIN NADA PEGAJOSO ─────────────────────────────
   Pedido del operador, 2026-08-12: *"centrá esta sección sin sliding menu"*.
   La versión anterior dejaba el H2 quieto en una columna de 19rem mientras las
   preguntas corrían al lado. Se revirtió: el FAQ es CIERRE O INVITACIÓN y por
   la §1 de `convenciones.md` va centrado, igual que en las otras dos pieles.

   Se centra el BLOQUE. El acordeón por dentro sigue alineado a la izquierda —
   una pregunta centrada con el signo a la derecha se lee torcida y el ojo
   pierde dónde arranca cada una al abrirlas. Eso ya lo hace la piel base. */
.t-gbp_service.v-revista .faq {
  display: block;
  text-align: center;
}
.v-revista .faq__h2 {
  position: static;
  max-width: none;
  margin-inline: auto;
  margin-bottom: 1.75rem;
}
.v-revista .faq__lista {
  max-width: var(--ancho-centrado);
  margin-inline: auto;
  border-top: 2px solid var(--tinta);
}
.v-revista .faq__item:first-child { border-top: 0; }

/* ── 10 · EL CIERRE, CENTRADO ─────────────────────────────────────────────
   Pedido del operador, 2026-08-12: *"centrala, sin aumentar el tamaño de la
   sección"*. La versión anterior lo armaba en dos columnas —titular y bajada a
   la izquierda, botón a la derecha— siguiendo la maqueta. Vuelve al cierre
   centrado de la piel base, que ya es §1.

   LO QUE EVITA QUE CREZCA es el cap del titular. Centrado y a 22ch, el
   `cta_titulo` de esta página —75 caracteres— cae en cuatro líneas y la sección
   se estira. A 34ch entra en dos, que es el mismo alto que tenía partido en dos
   columnas. Al escribir un `cta_titulo` para esta piel, cada línea cuesta ~46 px
   de sección. */
.v-revista .cta:not(:has(.cta__figura)) .cta__h2 { max-width: 34ch; }

/* ── 11 · MÓVIL ────────────────────────────────────────────────────────────
   LA REGLA QUE UNE A LAS SEIS TRAMPAS (línea 593): ninguna declaración de
   `grid-template-columns` bajo `.v-*` sale sin su contraparte acá, en el mismo
   commit. Arriba quedan cinco —hero, apertura, cuando, proceso y normativa—
   más la grilla interna de la figura de `cuando` y la de las cifras. */
@media (max-width: 56rem) {
  /* El hero deja de ser foto de fondo: en 390 px una foto recortada a la
     altura del panel no muestra una cocina, muestra un pedazo de mesada. Se
     apila —texto arriba, foto debajo— igual que el resto del sitio, y el panel
     pierde la caja porque a ancho completo ya no hay nada sobre lo que montar.

     EL FONDO VUELVE A PAPEL, Y ES UN BLOQUEANTE, NO UN DETALLE. En escritorio
     el `--profunda` del hero es lo que se ve por detrás de la foto a sangre;
     en móvil la foto baja y el panel de papel se disuelve, así que sin esto el
     titular —que es `--tinta`— queda casi negro sobre casi negro. Se vio
     mirando a 390 y no lo caza ningún gate: el bloque C mide los pares que
     conviven en una regla, y estos dos nunca se declararon juntos. */
  .t-gbp_service.v-revista .hero {
    padding: clamp(2.5rem, 4vw, 4rem) var(--canaleta);
    background: var(--papel);
  }
  .t-gbp_service.v-revista .hero__figura {
    grid-column: 1; grid-row: 2; order: 1;
    align-self: auto;
    z-index: auto;
    margin-top: 2rem;
  }
  .t-gbp_service.v-revista .hero__figura img {
    position: relative; inset: auto;
    height: auto; aspect-ratio: 4 / 3;
    border-radius: var(--radio);
  }
  .t-gbp_service.v-revista .hero__texto {
    grid-column: 1; grid-row: 1; order: 0;
    justify-self: stretch;
    max-width: none;
    background: none;
    border-top: 0;
    padding: 0;
    margin: 0;
  }
  /* Sin panel vuelve el filete del H1, que es el que marca dónde arranca. */
  .t-gbp_service.v-revista .hero__h1 { padding-top: 1.75rem; }
  .t-gbp_service.v-revista .hero__h1::before { display: block; }
  .t-gbp_service.v-revista .hero__dato { position: static; margin-top: 1rem; }
  /* Dos y dos: cuatro columnas en 350 px dan 87 px y el valor se parte. */
  .t-gbp_service.v-revista .hero__specs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .t-gbp_service.v-revista .hero__spec:nth-child(even) { border-right: 0; padding-right: 0; }
  .t-gbp_service.v-revista .hero__spec:nth-child(odd) { padding-left: 0; }

  .t-gbp_service.v-revista .apertura:has(.apertura__figura) {
    grid-template-columns: minmax(0, 1fr);
  }

  /* `cuando` apila: el texto arriba y las dos fotos debajo, una sobre otra y a
     4:3. En una columna, «del largo del texto» deja de querer decir nada. */
  .t-gbp_service.v-revista .cuando:has(.cuando__figura) {
    grid-template-columns: minmax(0, 1fr);
  }
  .t-gbp_service.v-revista .cuando:has(.cuando__figura) > h2,
  .t-gbp_service.v-revista .cuando:has(.cuando__figura) .cuando__texto {
    grid-column: 1;
  }
  .t-gbp_service.v-revista .cuando:has(.cuando__figura) .cuando__figura {
    grid-column: 1; grid-row: auto;
    align-self: auto;
    margin-top: 2rem;
    grid-template-rows: auto auto;
  }
  .v-revista .cuando__figura img { aspect-ratio: 4 / 3; height: auto; }

  .v-revista .proceso ol { grid-template-columns: minmax(0, 1fr); }

  /* Las cinco credenciales en una fila son de escritorio. A 390 px cada una
     mediría 60 px: vuelven a una columna, que es lo que hace la piel base. */
  .v-revista .normativa__datos { grid-template-columns: minmax(0, 1fr); }

  /* Tres cifras de 110 px parten el pie en cuatro líneas y el número deja de
     ser un número grande. */
  .v-revista .cifras__lista { grid-template-columns: minmax(0, 1fr); }
  .v-revista .cifra + .cifra {
    border-top: 1px solid var(--pelo-osc);
    padding-top: 1.5rem;
  }
}


/* ══════════════════════════════════════════════════════════════════════════
   LAS TRES PIELES DE LOCATION PAGE — 2026-08-13
   ══════════════════════════════════════════════════════════════════════════

   Vienen de `diseno/location/0{1,2,3}-*.html`, las tres maquetas importadas
   el 2026-08-13. Se traslada la COMPOSICIÓN y nada más: ni una palabra de su
   copy —es del fixture, un plomero inventado en Fairbrook— ni un dato del
   negocio, que sale de brief/datos.json.

   POR QUÉ TRES Y NO UNA. Decisión del operador del 2026-08-13: una piel por
   categoría de GBP. Es el mismo argumento que ya sostiene las cuatro pieles de
   `gbp_service` y que está escrito en `_base.html` §LA VARIANTE — un tipo con
   muchas páginas publicado con una sola piel es footprint de plantilla—, pero
   llevado un paso más lejos: acá la piel además AGRUPA. Las geográficas de
   cabinet se parecen entre ellas y no a las de countertop, que es como se lee
   un sitio con tres líneas de negocio y no una red de páginas puerta.

     zigzag    kitchen remodeling   editorial, aguanta la lectura larga
     mosaico   cabinet maker        la más fotográfica, reparte 7 fotos
     ficha     countertop           índice numerado, datos duros

   LA REGLA QUE LAS HACE SEGURAS. Todo cuelga de `.t-location_page.v-*`, con
   el TIPO en el selector y no solo la variante. Sin el tipo, `.v-ficha` ya
   existe para `gbp_service` y estas reglas se le filtrarían a diez páginas
   publicadas. Medido contra HEAD antes de commitear.

   SIN FOTOS TODAVÍA. Las tres páginas se publican con los seis slots de
   imagen vacíos, así que todo lo que dependa de una figura va detrás de
   `:has(figure)` y degrada a una columna. Cuando entren las imágenes, la
   composición de la maqueta aparece sola y sin tocar CSS. */


/* ── LA FAQ: EL RELLENO LO PONE LA CAJA, NO LA PREGUNTA ────────────────────
   Vale para las tres, y por eso vive acá arriba y no repetido en cada una.

   `.faq__pregunta` de la piel base trae `padding: 1.35rem 0`, y ahí está bien:
   en una FAQ sin caja, ese relleno ES la separación entre preguntas. Las tres
   maquetas de location, en cambio, envuelven cada pregunta en algo que ya
   rellena —la tarjeta de la 02 con 22/24, el `details` de la 01 con 16 y el de
   la 03 con 20—, así que los dos rellenos se suman y cada ficha crece 43,2 px.

   Medido a 1440 el 2026-08-13, `summary` cerrado:

     maqueta   ficha 28 · mosaico 24 · zigzag 24
     sitio     ficha 71 · mosaico 69 a 94 · zigzag 70

   El operador lo vio en la de cabinet: *"los cards están muy grandes"*. Lo
   estaban, y en las tres. */
.t-location_page .faq__pregunta { padding-block: 0; }


/* ══ 01 · ZIGZAG — kitchen remodeling ═══════════════════════════════════════
   Trasladada 1 a 1 de `diseno/location/03-zigzag.html` el 2026-08-13, después
   de que la primera versión se quedara en la franja terracota y un H2 corrido:
   el zigzag de esa maqueta lo dibujan LAS FOTOS alternando de lado, así que sin
   los seis slots llenos no había nada que alternar. Con las 18 imágenes puestas,
   esto es la composición medida sobre la maqueta.

   El mapeo salió limpio porque la maqueta y la plantilla tienen la misma
   estructura: `.hero__texto` es el panel oscuro y `.hero__figura` la foto a
   sangre; cada sección es su H2, su prosa y su `figure`. No hace falta una
   etiqueta nueva en `plantillas/`, que es del modelo y se propaga a todas las
   copias.

   LO ÚNICO QUE NO SE TRAJO: la foto del CTA de cierre. La maqueta la tiene
   —`grid 1fr 1fr`, foto a la izquierda y panel oscuro a la derecha— pero el CTA
   es un parcial COMPARTIDO por las 40 páginas del sitio y darle un slot ahí es
   una decisión de modelo, no de piel. Es el punto 1 de la tabla de conflictos
   de `diseno/location/README.md` y sigue abierto. */

/* ── EL HERO PARTIDO ───────────────────────────────────────────────────────
   `1.05fr 1fr`, medido en la maqueta. A sangre y sin `gap`: el panel oscuro
   nace en el borde izquierdo de la ventana y la foto muere en el derecho, que
   es lo que le da el corte. Por eso se suelta el `max-width` y el relleno del
   hero base, y el aire pasa a vivir adentro del panel. */
.t-location_page.v-zigzag .hero {
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: 0;
  max-width: none;
  padding: 0;
  align-items: stretch;
  /* HERO + FRANJA = UNA PANTALLA EXACTA. Pedido del operador el 2026-08-13, y
     se aparta de la maqueta a propósito: ahí el hero mide 602 y la franja 64,
     que a 900 de alto deja la página cortada a media pantalla.

     El `--tope` de 15rem ya ES topbar 41 + cabecera 88 + franja 111 = 240, así
     que restarlo deja exactamente el hueco que la franja necesita debajo:
     129 + 660 + 111 = 900. El `min(560px, …)` de antes lo capaba a 560 y el
     contenido lo empujaba a 635, que no llegaba ni a una cosa ni a la otra. */
  min-height: calc(100svh - var(--tope));
}
.t-location_page.v-zigzag .hero__texto {
  background: var(--profunda);
  color: var(--claro);
  align-self: stretch;
  display: flex; flex-direction: column; justify-content: center;
  gap: 1.15rem;
  padding: clamp(2.5rem, 4.5vw, 4.5rem)
           clamp(1.5rem, 4vw, 4rem)
           clamp(2.5rem, 4.5vw, 4.5rem)
           max(var(--canaleta), (100vw - var(--ancho)) / 2);
}
.t-location_page.v-zigzag .hero__h1 { color: var(--claro); }
.t-location_page.v-zigzag .hero__sub { color: var(--claro-mute); max-width: 46ch; }
/* El botón secundario del hero es de borde oscuro sobre claro: sobre el panel
   se volvía invisible. Pasa a claro, que es el par ya declarado. */
.t-location_page.v-zigzag .hero__texto .btn--secundario {
  color: var(--claro); border-color: var(--claro);
}
.t-location_page.v-zigzag .hero__dato b { color: var(--claro); }
.t-location_page.v-zigzag .hero__dato span { color: var(--claro-mute); }

/* La foto a sangre. `align-self: stretch` y no `center`, que es lo que el hero
   base le pone: centrada dejaba una banda de papel arriba y abajo y el corte
   se perdía. La imagen cubre la celda entera. */
.t-location_page.v-zigzag .hero__figura {
  align-self: stretch;
  margin: 0;
  min-height: 380px;
}
.t-location_page.v-zigzag .hero__figura img {
  width: 100%; height: 100%;
  aspect-ratio: auto;
  object-fit: cover;
  object-position: center;
}

/* ── LA FRANJA EN TERRACOTA ────────────────────────────────────────────────
   Es la seña más fuerte de la maqueta y ya estaba resuelta en el sitio:
   `v-galeria` hace esto desde el 2026-08-11 y sus tres pares están declarados
   en `diseno/contraste.md` (`--acento`/#ffffff 4.5, `--acento`/`--acento-tin`
   3.0 para el filete, `--acento`/`--acento-osc` 1.0 para el divisor). Se reusa
   tal cual en vez de traer el #c96741 de la maqueta, que sería un token nuevo
   sin medir. */
.t-location_page.v-zigzag .trust { background: var(--acento); }
.t-location_page.v-zigzag .trust__item {
  color: #fff;
  border-left-color: var(--acento-osc);
}
.t-location_page.v-zigzag .trust__item::before { background: var(--acento-tin); }

/* ── EL ZIGZAG DEL CUERPO ──────────────────────────────────────────────────
   Cuatro secciones y la foto cambia de lado en cada una:

     apertura      texto 1.25fr  ·  foto 1fr        foto DERECHA
     ángulo        par de fotos  ·  texto           fotos IZQUIERDA, pegajosas
     servicio      texto         ·  foto            foto DERECHA
     direcciones   foto          ·  texto + NAP     foto IZQUIERDA

   Se mueven columnas declaradas, nunca `direction`, que invierte la
   puntuación.

   ⚠ `grid-row: 1 / -1` NO SIRVE ACÁ, y costó una vuelta entera. El `-1`
   apunta a la última línea de la grilla EXPLÍCITA, y estas secciones no
   declaran `grid-template-rows`: sus filas son implícitas, una por hijo. Con
   la grilla explícita vacía, `1 / -1` colapsa a un tramo de una sola fila, y
   esa fila se estira a la altura de la foto. Medido el 2026-08-13 con
   `getBoundingClientRect`: en `servicio-ahi` la fila 1 daba 464 px —la altura
   exacta de la figura— con un H2 de 95 px adentro, o sea 369 px de hueco
   debajo del título. Se usa `span 99`, que cuenta filas implícitas. */
/* ⚠⚠ Y `span 99` PIDE `row-gap: 0`, que es la segunda mitad de la trampa de
   arriba y costó la sesión siguiente. El `span` crea 99 filas implícitas de
   verdad, y entre filas implícitas el `row-gap` se dibuja igual que entre
   filas con contenido: 98 huecos × 20 px = **1.960 px de aire muerto adentro
   del tramo**, en cada una de las cuatro secciones. Medido el 2026-08-13 con
   `getBoundingClientRect` sobre esta misma página ya publicada:
   `servicio-ahi` daba **2.773 px** para 240 palabras y una foto de 464.

   NO SE VE MIRANDO, y por eso pasó el ojo de ayer: en la captura es una
   sección larga con mucho blanco, que es exactamente lo que un diseño
   aireado parece. Y la medición de ayer fue la correcta para el bug de ayer
   —el offset del H2 contra la figura— pero nadie midió el ALTO de la sección.

   El ritmo vertical no se pierde: `h2` trae `margin-bottom: 1.5rem` y `p`
   `1.1rem`, y en una grilla los márgenes no colapsan. */
.t-location_page.v-zigzag .apertura,
.t-location_page.v-zigzag .angulo,
.t-location_page.v-zigzag .servicio-ahi,
.t-location_page.v-zigzag .direcciones {
  display: grid;
  column-gap: clamp(2rem, 4vw, 4rem);
  row-gap: 0;
  align-items: start;
}

/* apertura — sin H2, así que la prosa ocupa la primera columna entera */
.t-location_page.v-zigzag .apertura { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); }
.t-location_page.v-zigzag .apertura > *:not(.apertura__figura) { grid-column: 1; }
.t-location_page.v-zigzag .apertura__figura {
  grid-column: 2; grid-row: 1 / span 99; align-self: center; margin: 0;
}

/* ángulo — el par pegajoso. Es la sección más larga de la página, y en la
   maqueta las dos fotos acompañan el scroll del argumento en vez de quedarse
   arriba. Arranca en la fila 2: la 1 es del separador. */
.t-location_page.v-zigzag .angulo { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.t-location_page.v-zigzag .angulo > *:not(.angulo__figura) { grid-column: 2; }
/* CENTRADA, y SIN `sticky`. La maqueta la deja pegajosa y arrancando arriba, y
   así estaba; el operador pidió tres veces que las fotos quedaran centradas con
   el texto de al lado, y ésta era la que faltaba: el par arrancaba 104 px por
   debajo del H2 y quedaba 77 descentrado contra el bloque de texto completo.

   El `sticky` sale porque es lo que la ata al borde de arriba: con él, cualquier
   `align-self` distinto de `start` deja de tener efecto en cuanto se scrollea.
   Se pierde el efecto de la maqueta —las dos fotos acompañando el argumento— y
   es un cambio deliberado sobre la referencia, no un descuido. */
/* ⚠ ARRANCA EN LA FILA 1, NO EN LA 2. Con `2 / span 99` el tramo que la figura
   ocupa empieza DEBAJO del H2, así que `center` la centraba contra los párrafos
   y no contra el bloque completo: quedaban 60 px. El comentario viejo decía que
   la fila 1 era del separador; medido sobre el HTML publicado, esta sección no
   emite separador —sus hijos son `h2`, los `p` y la `figure`— así que la fila 1
   es la del título y la figura la comparte sin pisar nada: están en columnas
   distintas. */
.t-location_page.v-zigzag .angulo__figura {
  grid-column: 1; grid-row: 1 / span 99;
  align-self: center;
  margin: 0;
  display: grid; gap: 1rem;
}

/* servicio — vuelve la foto a la derecha */
.t-location_page.v-zigzag .servicio-ahi { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.t-location_page.v-zigzag .servicio-ahi > *:not(.servicio-ahi__figura) { grid-column: 1; }
/* CENTRADA contra el texto, no arrancando arriba: es lo que hace la maqueta
   —`ai=center` en las tres secciones de foto al costado, medido— y lo que pidió
   el operador el 2026-08-13. El `ángulo` es la excepción y se queda en `start`,
   porque ahí la figura es pegajosa y acompaña el scroll. */
.t-location_page.v-zigzag .servicio-ahi__figura {
  grid-column: 2; grid-row: 1 / span 99; align-self: center; margin: 0;
}

/* direcciones — foto a la izquierda, y el NAP en tarjeta de tinte, como la
   maqueta. El par `--acento-tin`/`--cuerpo` y `/--tinta` ya están declarados
   (los usa la piel revista). */
.t-location_page.v-zigzag .direcciones { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.t-location_page.v-zigzag .direcciones > *:not(.direcciones__figura) { grid-column: 2; }
.t-location_page.v-zigzag .direcciones__figura {
  grid-column: 1; grid-row: 1 / span 99; align-self: center; margin: 0;
}
.t-location_page.v-zigzag .direcciones__nap {
  background: var(--acento-tin);
  padding: 1.5rem 1.75rem;
  border-left: 3px solid var(--acento);
}

/* Las fotos del cuerpo llenan su celda con el ratio que declara la plantilla. */
.t-location_page.v-zigzag .apertura__figura img,
.t-location_page.v-zigzag .angulo__figura img,
.t-location_page.v-zigzag .servicio-ahi__figura img,
.t-location_page.v-zigzag .direcciones__figura img {
  width: 100%; height: auto; display: block;
}

/* ── LA NORMATIVA EN OSCURO, A DOS COLUMNAS ────────────────────────────────
   En la maqueta es la única sección de valor invertido del cuerpo, y funciona:
   licencia, seguro y permisos son el bloque que se consulta, no el que se lee
   de corrido, y el cambio de superficie lo separa de la argumentación sin
   necesitar un título más grande. */
.t-location_page.v-zigzag .normativa {
  background: var(--profunda);
  color: var(--claro);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: clamp(2rem, 4vw, 4rem);
  /* ARRIBA, no centrado. Se probó centrado primero, porque es lo que hace la
     maqueta —`ai=center`, medido—, y acá no funciona por una razón de
     CONTENIDO: la maqueta no tiene la lista de cinco datos y su normativa mide
     153 de alto, mientras que la de esta página mide 544 contra 347 de prosa.
     Centrando dos columnas tan dispares, la derecha sobresale 99 px por arriba
     y otros 99 por abajo, y eso se lee como desalineado, no como centrado.
     Con `start` las dos arrancan en la misma línea. Decisión del operador,
     2026-08-13, mirándolo. */
  align-items: start;
}
.t-location_page.v-zigzag .normativa__texto { grid-column: 1; }
/* ⚠ SOLO LA IZQUIERDA SE CENTRA, y NO contradice la decisión de arriba.
   Lo que se probó y se rechazó el 2026-08-13 fue `align-items: center` en la
   GRILLA, o sea las dos columnas a la vez: ahí la lista de cinco datos —544 de
   alto contra 385 de prosa— sobresalía 99px por arriba y 99 por abajo, y se
   leía desalineada. Centrando SOLO la prosa, la lista se queda anclada arriba
   con el título y el bloque corto queda a la misma altura visual que el largo.
   Pedido del operador el 2026-08-14 sobre las cuatro páginas servidas:
   "debe seguir del lado izquierdo pero en el centro de la sección para que se
   vea alineado con el texto que tiene del lado derecho".
   Si una sesión futura ve `center` acá y lo lee como la reversión del 13:
   no lo es. `align-items` de la grilla sigue en `start`, a propósito. */
.t-location_page.v-zigzag .normativa__texto { align-self: center; }
.t-location_page.v-zigzag .normativa__datos { grid-column: 2; }
/* El margen de arriba servía para despegar la lista del título cuando las dos
   columnas arrancaban juntas; con el centrado, lo único que hace es correr la
   columna 44px hacia abajo y descentrarla. */
.t-location_page.v-zigzag .normativa__datos { margin-top: 0; }
/* ⚠ LA GRILLA DE ADENTRO NO SABE QUE SE ANGOSTÓ. Su colapso a una columna vive
   en `@media (max-width: 46rem)` (línea 1573) y mide el VIEWPORT, pero acá el
   contenedor es la MITAD del viewport: entre 861 —donde la sección deja de
   estar partida— y 1.120, el viewport es demasiado ancho para que colapse y la
   lista corre a dos columnas dentro de media página. Son dos grillas anidadas
   y sólo una se enteró.

   Medido el 2026-08-27 sobre /kitchen-remodeling-near-flamingo-gardens/:
       861px  → columna de 307, cada dato 129px → ~17 caracteres por línea
       890px  → columna de 321, cada dato 137px → ~18
      1024px  → columna de 388, cada dato 170px → ~22
   y el `dd` de permisos son 160 caracteres, o sea nueve renglones de tres
   palabras. Lo caza `layout.py` en 890 —el ancho que mide— en las CINCO
   location pages del zigzag, con el mismo número en las cinco porque el dato
   sale de datos.json. Es el mismo defecto del `0px 318px` del 2026-08-13: un
   breakpoint de viewport gobernando un contenedor de media página se lee
   perfecto y no hace nada.

   LAS DOS PUNTAS DE LA BANDA SON MEDIDAS, no elegidas. Por debajo de 861 la
   sección es de una columna y la lista tiene el ancho entero, donde dos
   columnas dan ~44 por línea y están bien —forzar una sola ahí da 95 y sería
   cambiar un aviso por otro—. Por encima de 1.120 las dos columnas ya dan 26
   y suben. El techo va en 1.120 y no en 1.088, donde da exactamente 24, que es
   el umbral del bloque: no se apoya en el borde.

   Cuesta alto: la sección crece entre 31px (861) y 76px (1024). Es aire.
   Fuera de la banda no cambia un píxel — comprobado en 390, 800, 1200 y 1440.

   No hace falta tocar `:last-child:nth-child(odd)`: en una grilla de una
   columna, `grid-column: 1 / -1` ES esa columna. Medido, no supuesto. */
@media (min-width: 861px) and (max-width: 1120px) {
  .t-location_page.v-zigzag .normativa__datos {
    grid-template-columns: minmax(0, 1fr);
  }
}
.t-location_page.v-zigzag .normativa h2 { color: var(--claro); }
.t-location_page.v-zigzag .normativa a { color: var(--acento-cl); }
.t-location_page.v-zigzag .normativa__texto > p { color: var(--claro-mute); }
.t-location_page.v-zigzag .normativa__dato { border-top-color: var(--pelo-osc); }
.t-location_page.v-zigzag .normativa__dato dt { color: var(--claro-mute); }
.t-location_page.v-zigzag .normativa__dato dd { color: var(--claro-mute); }
/* El VALOR del dato va en un `<b>` con color propio (línea 1366, `--tinta`),
   así que heredar el color del `dd` no alcanza: sobre `--profunda` el número
   de licencia, los "2 years" y el nombre de la empresa quedaban en tinta sobre
   tinta, o sea invisibles. Se vio en la captura del 2026-08-13. */
.t-location_page.v-zigzag .normativa__dato dd b { color: var(--claro); }
/* La sección que sigue arranca en claro otra vez: sin esto el filete de
   paridad de la línea 242 dibuja un pelo claro sobre fondo oscuro. */
.t-location_page.v-zigzag .normativa + section { border-top-color: transparent; }

/* ── LA FAQ CON EL H2 AL COSTADO ───────────────────────────────────────────
   `320px 1fr` y el encabezado pegajoso, medido en la maqueta. Acá el sticky sí
   vale —al revés que en la ficha, donde el número es la referencia—: la FAQ es
   la sección más larga de scroll y el H2 al costado dice dónde estás. */
.t-location_page.v-zigzag .faq {
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr);
  column-gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
  text-align: left;
}
.t-location_page.v-zigzag .faq__h2 {
  grid-column: 1;
  position: sticky; top: 2rem;
  width: auto; margin-inline: 0; text-align: left;
}
.t-location_page.v-zigzag .faq__h2::before { left: 0; transform: none; }
.t-location_page.v-zigzag .faq__lista { grid-column: 2; }
/* El `details` de esta maqueta rellena 20 arriba y abajo — el equivalente a la
   tarjeta de la 02, pero sin caja dibujada. Va acá porque ahora que la pregunta
   no rellena (ver arriba), sin esto los ítems quedan pegados uno al otro. */
.t-location_page.v-zigzag .faq__item { padding-block: 20px; }
.t-location_page.v-zigzag .faq__pregunta { font-size: 18px; line-height: 1.35; }

/* ── EL CIERRE PARTIDO ─────────────────────────────────────────────────────
   FOTO A LA IZQUIERDA Y PANEL OSCURO A LA DERECHA, que es como lo dibuja la
   maqueta y el espejo de lo que hace la 02.

   ESTO ES LO QUE AYER QUEDÓ AFUERA, y no por CSS: la duda era si darle un slot
   de imagen al CTA, que es un parcial COMPARTIDO por las 40 páginas. Resultó
   que el slot ya existía —`cta_img`, agregado el 2026-08-12 para la piel
   `galeria`— así que el punto 1 de la tabla de conflictos de
   `diseno/location/README.md` se cierra sin tocar el modelo: alcanza con
   declarar la clave en el .md y escribir estas reglas.

   La foto va `absolute` dentro de su celda para que no arrastre la altura de
   la sección. Sin eso —medido el 2026-08-13, antes de escribir esto— el CTA
   de esta página daba 1.338 px: la imagen se dibujaba a los 1.440 del ancho
   completo debajo del texto. */
.t-location_page.v-zigzag .cta:has(.cta__figura) {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0;
  align-items: stretch;
  max-width: none; margin-inline: 0;
  padding: 0;
  text-align: left;
}
.t-location_page.v-zigzag .cta__figura {
  grid-column: 1; grid-row: 1;
  margin: 0; position: relative; overflow: hidden;
  min-height: 18rem;
}
.t-location_page.v-zigzag .cta__figura img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; border-radius: 0;
}
.t-location_page.v-zigzag .cta__texto-caja {
  grid-column: 2; grid-row: 1;
  display: flex; flex-direction: column; justify-content: center;
  padding: clamp(2rem, 3vw, 3.25rem) clamp(1.5rem, 4vw, 4.5rem);
  padding-right: max(var(--canaleta), (100vw - var(--ancho)) / 2);
}
.t-location_page.v-zigzag .cta:has(.cta__figura) .cta__h2 {
  margin-inline: 0; max-width: 28ch;
  font-size: 36px;              /* medido en la maqueta; el clamp daba 37,4 */
  line-height: 1.12;
  letter-spacing: -0.025em;
}
.t-location_page.v-zigzag .cta:has(.cta__figura) .cta__texto {
  margin-inline: 0; max-width: 56ch;
}
.t-location_page.v-zigzag .cta:has(.cta__figura) .btn { align-self: start; }

/* ── LA GEOMETRÍA, EL RITMO Y LA ESCALA DE LA MAQUETA ──────────────────────
   Lo mismo que se le hizo a la 02 el 2026-08-13 y que a esta piel le faltaba:
   la composición estaba bien —el hero partido, la alternancia, el par pegajoso,
   el H2 lateral de la FAQ— y aun así la página no se leía como la referencia,
   porque tomaba del sitio las otras tres cosas. Medido a 1440:

     GEOMETRÍA   maqueta 1.240 de contenido con canaleta de 100
                 sitio   1.400 con canaleta de hasta 72
     RITMO       maqueta 72 arriba y 0 abajo; el aire lo da la sección siguiente
                 sitio   `--seccion`, 60 arriba Y 60 abajo en todas
     TIPO        maqueta H1 54 · H2 38, con 34 en normativa y 36 en el cierre
                 sitio   H1 56,2 y un solo H2 que escala a 43,2

   Los valores van en píxeles y no en `rem` por lo mismo que en la 02: el `rem`
   sigue atado al root de 16 y lo que se replica es un absoluto de la maqueta. */
.t-location_page.v-zigzag {
  --z-ancho: 1240px;
  --z-canaleta: 100px;
  --z-sangre: max(var(--z-canaleta), (100% - var(--z-ancho)) / 2);
}

/* El relleno lateral y el ritmo vertical, para las secciones del cuerpo. El
   hero y el cierre quedan afuera: los dos van partidos a sangre y traen el
   suyo. */
/* Las TRES que traen ritmo propio se EXCLUYEN acá en vez de intentar pisarlas
   más abajo. Cada `:not()` vale una clase, así que esta regla pesa (0,6,2) y
   le gana a cualquier `.t-location_page.v-zigzag .normativa` por más abajo que
   esté escrita: con `padding-block: 72px 0` heredado, la lista de datos de la
   normativa terminaba tocando el filete inferior.
   ⚠ `.apertura` se sumó a la lista el 2026-08-14 POR LA MISMA RAZÓN, y se
   intentó primero el atajo que este comentario ya desaconsejaba —escribir
   `padding-block-end` más abajo en la regla propia de `.apertura`, que pesa
   (0,3,0)— y no tomó. El `0` de acá sólo es correcto cuando la sección de
   abajo comparte color y pone el aire con su 72; `.apertura` es blanca y
   `.angulo` es gris, así que el borde del color caía en la última línea del
   texto. Si mañana otra sección cambia de fondo, va a esta lista también. */
.t-location_page.v-zigzag main > section:not(.hero):not(.cta):not(.normativa):not(.servicio-ahi):not(.apertura) {
  padding-inline: var(--z-sangre);
  padding-block: 72px 0;
}
.t-location_page.v-zigzag main > section.normativa,
.t-location_page.v-zigzag main > section.servicio-ahi {
  padding-inline: var(--z-sangre);
}
/* Las dos secciones que la maqueta pinta con fondo propio cierran su caja
   abajo y se separan de la anterior con margen, no con relleno.

   ⚠ VAN CON `main > section.x` Y NO CON `.x` A SECAS. La regla de arriba pesa
   (0,4,1) —los dos `:not()` cuentan como clase— y `.t-location_page.v-zigzag
   .normativa` pesa (0,3,0), así que el `padding-block: 72px 0` le ganaba y
   estas dos secciones quedaban con relleno CERO abajo: la lista de datos
   terminaba tocando el filete inferior. Lo vio el operador el 2026-08-13.
   Tercera vez que esta hoja se cobra la misma trampa, y las tres veces el CSS
   se leía correcto.

   Los valores son los de la maqueta y NO son el mismo: 72 en el servicio, 56
   en la normativa. */
.t-location_page.v-zigzag main > section.servicio-ahi {
  padding-block: 72px;
  margin-top: 72px;
}
.t-location_page.v-zigzag main > section.normativa {
  padding-block: 56px;
  margin-top: 72px;
}

/* Las canaletas internas: 56 en el cuerpo, 48 en la apertura y la normativa. */
.t-location_page.v-zigzag .angulo,
.t-location_page.v-zigzag .servicio-ahi,
.t-location_page.v-zigzag .direcciones,
.t-location_page.v-zigzag .faq { column-gap: 56px; }
.t-location_page.v-zigzag .apertura,
.t-location_page.v-zigzag .normativa { column-gap: 48px; }

/* La apertura corre en una caja MÁS ANGOSTA que el resto: 1.100 contra 1.240,
   o sea canaleta de 170. Es la bajada del H1 y la maqueta la mete hacia adentro
   a propósito, para que el ojo baje del hero al texto y no al borde. */
.t-location_page.v-zigzag .apertura {
  padding-inline: max(170px, (100% - 1100px) / 2);
  /* ⚠ EL FONDO CAMBIA JUSTO ACÁ, y por eso el 0 de abajo se veía.
     La regla de arriba —`main > section:not(.hero):not(.cta)…`— da
     `padding-block: 72px 0`, y ese 0 funciona mientras las dos secciones
     compartan color: el aire lo pone el 72 de la de abajo. Pero `.apertura`
     es BLANCA y `.angulo` es gris (#f2f2f0), así que el borde del color cae
     exactamente en la última línea del texto: medido el 2026-08-14, texto
     972→1433 y sección 900→1433. La figura no lo delataba porque va
     centrada y cerraba 32px antes.
     Se empareja con el 72 de arriba. Decisión del operador, 2026-08-14,
     mirándolo en las cuatro páginas servidas. */
  padding-block: 72px;
}

/* ── LA ESCALA ─────────────────────────────────────────────────────────────*/
.t-location_page.v-zigzag .hero__h1 {
  font-size: 54px;
  line-height: 1.02;
  letter-spacing: -0.035em;
}
.t-location_page.v-zigzag .angulo__h2,
.t-location_page.v-zigzag .servicio-ahi__h2,
.t-location_page.v-zigzag .direcciones__h2,
.t-location_page.v-zigzag .faq__h2,
/* La galería no está en la maqueta: esta página publica una. Entra a la escala
   de la piel para no quedar como el único titular de otro tamaño. */
.t-location_page.v-zigzag .galeria__h2 {
  font-size: 38px;
  line-height: 1.08;
  letter-spacing: -0.03em;
  margin-bottom: 22px;
}
/* La normativa baja a 34 en la maqueta, y no es un descuido: es la sección de
   letra chica y el titular acompaña. */
.t-location_page.v-zigzag .normativa__h2 {
  font-size: 34px;
  line-height: 1.1;
  letter-spacing: -0.025em;
  margin-bottom: 22px;
}
.t-location_page.v-zigzag .cta__h2 {
  font-size: 36px;
  line-height: 1.12;
  letter-spacing: -0.025em;
}

/* ⚑ LA APERTURA NO ES PROSA Y NO VA CON LA PROSA. Es la bajada del H1, y la
   maqueta la publica a 25 en peso 700 — medido, `fs=25 fw=700 lh=35,5`. En la
   primera vuelta entró al grupo de los 16 de abajo y quedó del tamaño del
   cuerpo, que es lo que el operador vio: pidió que midiera como el texto del
   hero. Mide un poco más, y así está en la referencia.

   ⚠ BAJA DE 25 A 21 EL 2026-08-14. Es un cambio de criterio del operador
   mirándolo servido, y conviene no adornarlo: **los 25 nunca se vieron con un
   texto largo al lado**. Contado, no recordado: Pine Island Ridge mide 114
   palabras y las cuatro nuevas 109, 111, 114 y 138, así que el largo casi no
   cambió y NO es la explicación. Lo que pasó es que a 25 en peso 700 el bloque
   llegaba a 462px de alto y competía con el H1 en vez de leerse como su bajada.
   A 21 sigue midiendo por encima del cuerpo (16) y del subtítulo del hero (17),
   que es lo que protegía el pedido anterior de subirla.
   El `line-height` sube de 1.42 a 1.5 a propósito: al achicar el cuerpo de
   letra, la misma proporción de interlínea aprieta el párrafo.
   Pedido del operador, 2026-08-14, mirándolo servido. */
.t-location_page.v-zigzag .apertura p {
  font-size: 21px;
  font-weight: 700;
  line-height: 1.5;
  letter-spacing: -0.015em;
  margin: 0 0 16px;
}

/* El subtítulo del hero: 17, no los 23 que traía la piel base. */
.t-location_page.v-zigzag .hero__sub {
  font-size: 17px;
  line-height: 1.6;
  max-width: 557px;
}

/* El último párrafo de una columna no lleva separación abajo: con ella, el
   bloque de texto mide 16 px más de lo que se ve y la foto de al lado queda 8
   descentrada. Es la misma corrección que ya tiene la 02.

   ⚠ `last-of-type` Y NO `last-child` EN EL SERVICIO: ahí el último hijo de la
   sección es la `<figure>`, así que ningún `<p>` es `:last-child` y la regla no
   hacía nada. En direcciones se usa `last-child` a propósito: después del
   último párrafo viene la tarjeta del NAP, y ahí la separación sí hace falta. */
.t-location_page.v-zigzag .apertura p:last-child,
.t-location_page.v-zigzag .direcciones p:last-child,
.t-location_page.v-zigzag .angulo p:last-of-type,
.t-location_page.v-zigzag .servicio-ahi p:last-of-type { margin-bottom: 0; }

/* La prosa de toda la piel: 16 a 1,7 con 16 de separación. */
.t-location_page.v-zigzag .angulo p,
.t-location_page.v-zigzag .servicio-ahi p,
.t-location_page.v-zigzag .direcciones p,
.t-location_page.v-zigzag .normativa p,
.t-location_page.v-zigzag .faq p {
  font-size: 16px;
  line-height: 1.7;
  margin: 0 0 16px;
}


/* ══ 02 · MOSAICO — cabinet maker ═══════════════════════════════════════════
   REESCRITA 1 A 1 el 2026-08-13, contra la maqueta MEDIDA y no leída.

   POR QUÉ SE REESCRIBIÓ. La primera versión se escribió LEYENDO los `style=`
   de `diseno/location/02-mosaico.html` y se verificó midiendo la página contra
   sí misma. Eso comprueba que el CSS hace lo que uno quiso, no que se parezca
   a la referencia. El operador lo cazó de una: *"no son los diseños exactos"*.
   Tenía razón, y la diferencia más grande no era ninguna de las composiciones:
   era que la piel usaba **la escala tipográfica y la geometría del sitio** en
   vez de las de la maqueta.

     GEOMETRÍA   maqueta 1.280 de contenido con canaleta de 32
                 sitio   1.400 con canaleta de hasta 72
     RITMO       maqueta padding propio por sección (64 · 56 · 45 · 32)
                 sitio   `--seccion`, el mismo clamp para todas
     TIPO        maqueta H2 de sección a 40px, 36px y 34px según la sección
                 sitio   un solo `h2` que escala hasta 44px

   Con la misma composición y esas tres cosas cambiadas, la página se lee como
   otra cosa. Acá los tres se toman de la maqueta.

   LOS COLORES NO SE TOCARON Y NO HACÍA FALTA: los doce de la maqueta YA son
   los tokens del sitio, medidos uno por uno —#221d17 `--profunda`, #1a1714
   `--tinta`, #ede8e0 `--claro`, #b5aba0 `--claro-mute`, #e0673a `--acento-cl`,
   #b4451f `--acento`, #f3e2da `--acento-tin`, #3e3a34 `--cuerpo`, #6b655b
   `--mute`, #dfdcd5 `--pelo`, #3a332b `--pelo-osc`, #f2f2f0 `--papel`—. Salen
   del mismo sistema. Por eso el bloque C de `verificar.py` sigue valiendo: no
   entra un color sin par de contraste declarado.

   LA REFERENCIA ESTÁ MEDIDA Y GUARDADA, no recordada: 146 nodos con 30
   propiedades cada uno, extraídos con `chrome-headless-shell` a 1440. El
   arnés y el volcado quedaron en el scratchpad de la sesión.

   LO ÚNICO QUE NO SE PUDO TRASLADAR DESDE EL CSS es el ángulo en dos columnas
   de flujo independiente: eso pide dos `<div>` en el HTML y se agregó a
   `location_page.html` detrás de `angulo_cuerpo2`. El porqué está ahí.

   ⚑ UNA DIFERENCIA QUE QUEDA, Y ES DE CONTENIDO, NO DE DISEÑO: la maqueta no
   tiene sección `normativa` con lista de datos y esta página publica cinco.
   Van a todo el ancho debajo del par h2/párrafo, que es lo más cerca que se
   puede estar de una maqueta que no previó el bloque. */

/* ── LA GEOMETRÍA DE LA MAQUETA ────────────────────────────────────────────
   1.280 de contenido, canaleta de 32. Se declara una vez acá y la consumen
   todas las secciones; el `--ancho` de 1.400 del sitio no entra en esta piel. */
.t-location_page.v-mosaico {
  --m-ancho: 1280px;
  --m-canaleta: 32px;
  /* La fórmula de sangre completa: el fondo llega al borde de la ventana y el
     contenido se para en 1.280. Misma que usa `main > section`, con otros dos
     números. */
  --m-sangre: max(var(--m-canaleta), (100% - var(--m-ancho)) / 2);
  /* La caja de las secciones que NO van a sangre: su borde exterior mide
     1.280 + las dos canaletas. */
  --m-caja: calc(var(--m-ancho) + var(--m-canaleta) * 2);
}

/* El ritmo vertical del sitio no se aplica: cada sección de la maqueta trae el
   suyo. Y la alternancia papel/blanco tampoco — la maqueta pinta tres secciones
   y deja el resto sobre papel. */
.t-location_page.v-mosaico main > section {
  padding-block: 0;
  background: transparent;
  border-top-color: transparent;
}

/* ── EL HERO ───────────────────────────────────────────────────────────────
   Medido: sección 1440×623 con relleno 64/32, adentro una grilla de 1.280
   partida en `616 616` con hueco de 48 y centrada. NO es un hero de pantalla
   completa: se le suelta el `min-height` de `100svh − --tope` de la piel base,
   que es lo que lo estiraba a 660 y más. */
.t-location_page.v-mosaico .hero {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 48px;
  align-items: center;
  max-width: none;
  min-height: 0;
  padding: 64px var(--m-sangre);
  background: var(--profunda);
}
.t-location_page.v-mosaico .hero__texto {
  display: flex; flex-direction: column; gap: 18px;
}
/* El rótulo en mono arriba del H1. Existe en las dos maquetas y en la vuelta
   anterior no se puso; el gancho `hero_rotulo` se agregó al parcial el mismo
   día por la piel `ficha` de servicio. Medido: 11px, peso 700, `letter-spacing`
   2,2px —o sea 0.2em—, en versalitas y en acento claro. */
.t-location_page.v-mosaico .hero__rotulo {
  margin: 0;
  font-family: var(--display);
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--acento-cl);
}
/* SIN EL FILETE DE ACENTO SOBRE EL H1. `.hero__h1::before` lo dibuja absoluto en
   `top: 0`, y esta piel le saca el `padding-top` al H1, así que la barrita caía
   justo encima del texto: se veía pegada al titular. La maqueta no la tiene
   —medida, entre el rótulo y el H1 no hay ningún nodo— porque acá el rótulo en
   mono cumple esa función. Mismo criterio y misma solución que `.v-contacto`,
   que ya lo resolvía así cuando la página publica rótulo. */
.t-location_page.v-mosaico .hero:has(.hero__rotulo) .hero__h1::before { content: none; }

.t-location_page.v-mosaico .hero__h1 {
  margin: 0; padding-top: 0;
  font-size: clamp(32px, 4.2vw, 54px);
  line-height: 1.02; letter-spacing: -0.035em;
  color: var(--claro);
}
.t-location_page.v-mosaico .hero__sub {
  margin: 0;
  font-size: 17px; line-height: 1.6;
  max-width: 54ch;
  color: var(--claro-mute);
}
.t-location_page.v-mosaico .hero__acciones { gap: 12px; margin-top: 4px; }
.t-location_page.v-mosaico .hero__texto .btn--secundario {
  color: var(--claro); border-color: var(--pelo-osc);
}

/* EL MOSAICO. Medido: `371.7 304.5` con hueco de 12 — o sea `1.6fr 1fr`. La
   foto alta ocupa las dos filas, la cuadrada la de arriba y el dato cierra
   abajo.

   LAS FILAS VAN `auto 1fr` Y NO `auto auto`: la alta manda el alto total, y
   con las dos en `auto` el sobrante se repartiría entre ambas y estiraría la
   cuadrada, que con `aspect-ratio` declarado significa recortarla. Con `1fr`
   abajo, todo el sobrante se lo lleva la caja del dato, a la que estirarse no
   le hace nada.

   Hay que soltar `min-height` y `max-height` de la imagen base —valen 460px y
   la altura de la ventana— porque acá el que manda es el ratio. */
.t-location_page.v-mosaico .hero__figura {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  gap: 12px;
  align-self: center;
}
.t-location_page.v-mosaico .hero__figura img { min-height: 0; max-height: none; }
/* EL ÍTEM DE LA GRILLA ES EL `<picture>`, NO EL `<img>` — medido el 2026-08-18.
   `build.py` envuelve toda imagen con derivados, así que `img:nth-of-type(2)`
   dejó de matchear —cada `img` es la primera de SU picture— y el mosaico se
   publicó como una grilla de dos columnas comunes: las dos fotos en 3/4 y en
   `grid-column: auto`, sin la alta a dos filas ni la cuadrada arriba. Cinco
   páginas. La colocación va sobre el ítem; el `aspect-ratio` tiene que llegar
   al `img`, así que se separa en dos reglas en vez de dejarlo en una que ya no
   alcanza a ninguno de los dos. */
.t-location_page.v-mosaico .hero__figura > picture { display: block; }
.t-location_page.v-mosaico .hero__figura > :is(img, picture):first-of-type {
  grid-column: 1; grid-row: 1 / span 2;
}
.t-location_page.v-mosaico .hero__figura > :is(img, picture):nth-of-type(2) {
  grid-column: 2; grid-row: 1;
}
.t-location_page.v-mosaico .hero__figura > :is(img, picture):first-of-type,
.t-location_page.v-mosaico .hero__figura > picture:first-of-type img {
  aspect-ratio: 3 / 4;
}
.t-location_page.v-mosaico .hero__figura > :is(img, picture):nth-of-type(2),
.t-location_page.v-mosaico .hero__figura > picture:nth-of-type(2) img {
  aspect-ratio: 1;
}
.t-location_page.v-mosaico .hero__figura > picture img {
  width: 100%; height: 100%; object-fit: cover;
}
/* El dato deja de estar MONTADO sobre la foto —`position: absolute` sobre la
   esquina, que es lo que hace la piel base— y pasa a ser la tercera pieza del
   mosaico: caja calada sobre el panel. */
.t-location_page.v-mosaico .hero__dato {
  position: static;
  grid-column: 2; grid-row: 2;
  align-self: stretch;
  display: flex; flex-direction: column; justify-content: center; gap: 2px;
  max-width: none;
  padding: 16px;
  background: transparent;
  border: 1px solid var(--pelo-osc); border-left-width: 1px;
}
.t-location_page.v-mosaico .hero__dato b {
  font-size: 26px; line-height: 1; letter-spacing: -0.03em;
  color: var(--acento-cl);
}
.t-location_page.v-mosaico .hero__dato span {
  font-size: 13px; color: var(--claro-mute);
}

/* ── LA FRANJA DE CONFIANZA ────────────────────────────────────────────────
   Medida: 64px de alto, fondo `--tinta`, cuatro celdas de 360 con relleno
   20/28. La piel base la dibuja a 110px —su relleno cierra la cuenta de la
   primera pantalla del hero de `100svh`, que acá ya no existe— y con el filete
   de acento arriba de cada ítem, que la maqueta no tiene. */
.t-location_page.v-mosaico .trust { background: var(--tinta); padding: 0; }
.t-location_page.v-mosaico .trust__lista {
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  max-width: none;
}
.t-location_page.v-mosaico .trust__item {
  padding: 20px 28px;
  border-left: 0;
  border-right: 1px solid var(--pelo-osc);
  font-size: 14px; font-weight: 600; line-height: 1.7;
  color: var(--claro);
}
.t-location_page.v-mosaico .trust__item:last-child { border-right: 0; }
.t-location_page.v-mosaico .trust__item::before { display: none; }

/* ── LA APERTURA: LA TARJETA, SOLA ─────────────────────────────────────────
   Medida: sección de 1.344 con relleno 64/32/0, y adentro una tarjeta blanca
   de 1.280 con relleno 36/40 y filete. El párrafo va en Archivo a 25px y peso
   700: es una BAJADA, no cuerpo de texto, y ese contraste de peso es lo que
   la separa de la prosa que viene abajo.

   ⚑ Y NO LLEVA FOTO. La maqueta reparte SIETE slots —hero ×2, ángulo ×2,
   servicio, direcciones y cierre— y ninguno cae acá. La vuelta anterior le
   metió la de apertura al costado porque la plantilla tiene el slot, y eso
   partía la tarjeta en dos. La foto se sacó del `.md` y quedó guardada en
   `diseno/imagenes-sin-usar/`, con el mismo criterio que las dos de
   `gbp_category`: fuera de `assets/` para que el bloque D no la marque como
   peso muerto. */
.t-location_page.v-mosaico .apertura {
  display: block;
  max-width: var(--m-caja); margin-inline: auto;
  padding: 64px var(--m-canaleta) 0;
}
.t-location_page.v-mosaico .apertura > p {
  max-width: none;
  margin: 0;
  padding: 36px 40px;
  background: var(--blanco);
  border: 1px solid var(--pelo);
  font-family: var(--display);
  font-size: clamp(19px, 2.2vw, 25px);
  font-weight: 700; line-height: 1.42; letter-spacing: -0.018em;
  color: var(--tinta);
  text-wrap: pretty;
}

/* ── EL SEPARADOR DE TRES CUADRADOS ────────────────────────────────────────
   Medido: 22px de alto, 48 de aire arriba, dos filetes de 2px que llegan hasta
   24px antes del grupo, y tres cuadrados de 18 separados por 12 — terracota
   lleno, terracota calado, tinta. La vuelta anterior lo dibujó a 9px y sin los
   filetes, que son la mitad del gesto.

   VA COMO `::before` DE LA SECCIÓN SIGUIENTE para no pedir una etiqueta nueva
   en la plantilla, que es del modelo y viaja a todas las copias.

   ⚠ UN `::before` DENTRO DE UN GRID ES UN ÍTEM DEL GRID, no un adorno del
   fondo: sin `grid-column: 1 / -1` y `grid-row: 1` se auto-coloca en la primera
   celda libre y empuja el H2 una fila abajo.

   El grupo mide 18×3 + 12×2 = 78, así que arranca en `50% − 39px`. Los filetes
   van de borde a `50% − 63px`, que son los 24 de aire que mide la maqueta.
   ⚠ `background-position` NO acepta `calc(left + N)` —`left` es palabra clave,
   no longitud— pero SÍ acepta `calc(50% − 39px)`. */
.t-location_page.v-mosaico .angulo::before {
  content: "";
  display: block;
  grid-column: 1 / -1; grid-row: 1;
  width: 100%; height: 22px;
  margin-bottom: 32px;
  background-image:
    linear-gradient(var(--tinta), var(--tinta)),
    linear-gradient(var(--tinta), var(--tinta)),
    linear-gradient(var(--acento), var(--acento)),
    linear-gradient(var(--acento), var(--acento)),
    linear-gradient(var(--tinta), var(--tinta));
  background-size:
    calc(50% - 63px) 2px, calc(50% - 63px) 2px,
    18px 18px, 18px 18px, 18px 18px;
  background-position:
    left center, right center,
    calc(50% - 39px) center, calc(50% - 9px) center, calc(50% + 21px) center;
  background-repeat: no-repeat;
}
/* El del medio es CALADO: se dibuja el marco de 2px con un gradiente encima
   del lleno, en el color del papel. Un `border` no existe en un background. */
.t-location_page.v-mosaico .angulo::after {
  content: "";
  display: block;
  grid-column: 1 / -1; grid-row: 1;
  width: 100%; height: 22px;
  margin-bottom: 32px;
  background-image: linear-gradient(var(--papel), var(--papel));
  background-size: 14px 14px;
  background-position: calc(50% - 7px) center;
  background-repeat: no-repeat;
  pointer-events: none;
}

/* ── EL ÁNGULO, EN DOS COLUMNAS ────────────────────────────────────────────
   Medido: sección de 1.344 con relleno 32/32/0; H2 con tope de 24ch y 28 de
   margen abajo; y dos columnas de 628 con hueco de 24, cada una con su propio
   flujo. Izquierda: dos párrafos y la foto del hammock. Derecha: la foto del
   panel hinchado y dos párrafos.

   Las dos columnas vienen del HTML —`angulo_cuerpo` y `angulo_cuerpo2`— porque
   una grilla comparte las filas y la foto de la derecha empujaría al primer
   párrafo de la izquierda. El comentario largo está en la plantilla. */
.t-location_page.v-mosaico .angulo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 24px; row-gap: 0;
  align-items: start;
  max-width: var(--m-caja); margin-inline: auto;
  padding: 32px var(--m-canaleta) 0;
}
/* LAS DOS COLUMNAS SE CENTRAN ENTRE SÍ. Tienen flujo propio y alturas distintas
   —938 la izquierda, 829 la derecha, medido—, así que con `start` la foto de la
   izquierda y los párrafos que quedan a su derecha arrancan desparejos: 44 px.
   Centrando la más corta dentro de la alta, los dos pares se emparejan.
   Va con `align-self` en las columnas y no con `align-items` en la sección, para
   no mover el H2 ni el separador, que viven en sus propias filas. */
.t-location_page.v-mosaico .angulo__col { align-self: center; }

.t-location_page.v-mosaico .angulo__h2 {
  grid-column: 1 / -1; grid-row: 2;
  max-width: 24ch;
  margin: 0 0 28px;
  font-size: clamp(28px, 3.4vw, 40px);
  line-height: 1.08; letter-spacing: -0.03em;
}
.t-location_page.v-mosaico .angulo__col { grid-row: 3; }
.t-location_page.v-mosaico .angulo__col--izq { grid-column: 1; }
.t-location_page.v-mosaico .angulo__col--der { grid-column: 2; }
.t-location_page.v-mosaico .angulo__figura,
.t-location_page.v-mosaico .angulo__figura2 { margin: 0; }
.t-location_page.v-mosaico .angulo__figura2 { margin-bottom: 16px; }
.t-location_page.v-mosaico .angulo__figura img,
.t-location_page.v-mosaico .angulo__figura2 img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 3; object-fit: cover;
}

/* ── EL SERVICIO AHÍ ───────────────────────────────────────────────────────
   Medido: sección a sangre en blanco, 64 de aire arriba, relleno 64/32, y
   adentro `573 659` con hueco de 48 y centrado en vertical — o sea `1fr 1.15fr`
   con la FOTO A LA IZQUIERDA, cuadrada. */
.t-location_page.v-mosaico .servicio-ahi {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  column-gap: 48px; row-gap: 0;
  align-items: center;
  max-width: none;
  margin-top: 64px;
  padding: 64px var(--m-sangre);
  background: var(--blanco);
}
.t-location_page.v-mosaico .servicio-ahi > *:not(.servicio-ahi__figura) { grid-column: 2; }
.t-location_page.v-mosaico .servicio-ahi__figura {
  grid-column: 1; grid-row: 1 / span 99;
  align-self: center; margin: 0;
}
.t-location_page.v-mosaico .servicio-ahi__figura img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 1; object-fit: cover;
}
.t-location_page.v-mosaico .servicio-ahi__h2 {
  max-width: 22ch; margin: 0 0 22px;
  font-size: clamp(28px, 3.4vw, 40px);
  line-height: 1.08; letter-spacing: -0.03em;
}
.t-location_page.v-mosaico .servicio-ahi p { max-width: 62ch; }

/* ── DIRECCIONES: LA TARJETA EN TINTE ──────────────────────────────────────
   Medida: la tarjeta mide 1.280 de borde a borde con relleno 36/40, y adentro
   `605.5 550.5` con hueco de 44, centrado. Acá la SECCIÓN es la tarjeta: la
   plantilla no emite un envoltorio, y poniéndole a la sección un borde exterior
   de 1.280 la caja queda exactamente donde la maqueta la tiene.
   El par `--acento-tin`/`--cuerpo` ya está declarado en `diseno/contraste.md`. */
.t-location_page.v-mosaico .direcciones {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  column-gap: 44px; row-gap: 0;
  align-items: center;
  max-width: var(--m-ancho); margin: 64px auto 0;
  padding: 36px 40px;
  background: var(--acento-tin);
}
.t-location_page.v-mosaico .direcciones > *:not(.direcciones__figura) { grid-column: 1; }
.t-location_page.v-mosaico .direcciones__figura {
  grid-column: 2; grid-row: 1 / span 99;
  align-self: center; margin: 0;
}
.t-location_page.v-mosaico .direcciones__figura img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 3 / 2; object-fit: cover;
}
.t-location_page.v-mosaico .direcciones__h2 {
  margin: 0 0 20px;
  font-size: clamp(26px, 3vw, 36px);
  line-height: 1.1; letter-spacing: -0.028em;
}
.t-location_page.v-mosaico .direcciones__texto > p { max-width: 60ch; margin-bottom: 24px; }
.t-location_page.v-mosaico .direcciones__nap {
  background: var(--blanco);
  border-left: 0;
  padding: 20px 22px;
  font-size: 15px;
}
.t-location_page.v-mosaico .direcciones__linea { margin: 0 0 2px; }
.t-location_page.v-mosaico .direcciones__linea strong {
  font-family: var(--display); font-weight: 700; font-size: 17px;
  color: var(--tinta);
}

/* ── LA NORMATIVA, INVERTIDA ───────────────────────────────────────────────
   Medida: sección a sangre en `--profunda`, 56 de aire arriba, relleno 56/32,
   y adentro `618 618` con hueco de 44 — el H2 a la izquierda y el párrafo a la
   derecha, no un bloque de texto con la lista al lado.

   Para eso `normativa__texto` se disuelve con `display: contents`: sus dos
   hijos pasan a ser ítems de la grilla y se reparten uno por columna.

   ⚑ LA LISTA DE DATOS NO ESTÁ EN LA MAQUETA. Esta página publica cinco y va a
   todo el ancho debajo, que es lo más cerca que se puede estar de una
   referencia que no previó el bloque. Se deja anotado, no disimulado. */
.t-location_page.v-mosaico .normativa {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 44px; row-gap: 0;
  /* CENTRADO, igual que en la 01 y por lo mismo: la maqueta lo tiene así
     —medido, `ai=center`— y con `start` el H2 de la primera columna quedaba
     pegado arriba contra un párrafo bastante más alto a su derecha. */
  align-items: center;
  max-width: none;
  margin-top: 56px;
  padding: 56px var(--m-sangre);
  background: var(--profunda);
  color: var(--claro);
}
.t-location_page.v-mosaico .normativa__texto { display: contents; }
.t-location_page.v-mosaico .normativa__h2 {
  grid-column: 1; grid-row: 1;
  max-width: 20ch; margin: 0;
  font-size: clamp(24px, 2.8vw, 34px);
  line-height: 1.1; letter-spacing: -0.025em;
  color: var(--claro);
}
.t-location_page.v-mosaico .normativa__texto > p {
  grid-column: 2; grid-row: 1;
  margin: 0;
  font-size: 15px; line-height: 1.7;
  color: var(--claro-mute);
}
.t-location_page.v-mosaico .normativa a { color: var(--acento-cl); }
/* ⚑ SIN EL `max-width` DE LA PIEL BASE. `.normativa__datos` viene capado a 992 y
   centrado, y en esta sección eso producía TRES alineaciones distintas en la
   misma caja: el H2 arrancaba en 80, el párrafo de la derecha en 744 y la lista
   en 224. El tope tiene sentido en la piel base, donde la lista va sola a lo
   ancho de la página; acá la lista ya está contenida por la grilla de la
   sección, así que el tope sólo la desalinea. Con `none`, la lista ocupa las dos
   columnas de 80 a 1.360: "License" arranca donde arranca el título, y el filete
   de "Who contracts the work" cierra donde cierra el párrafo de arriba.
   Lo pidió el operador el 2026-08-13, mirándolo. */
.t-location_page.v-mosaico .normativa__datos {
  grid-column: 1 / -1; grid-row: 2;
  margin-top: 32px;
  max-width: none;
}
.t-location_page.v-mosaico .normativa__dato { border-top-color: var(--pelo-osc); }
.t-location_page.v-mosaico .normativa__dato dt,
.t-location_page.v-mosaico .normativa__dato dd { color: var(--claro-mute); }
/* El VALOR va en un `<b>` con color propio: sin esto queda tinta sobre tinta. */
.t-location_page.v-mosaico .normativa__dato dd b { color: var(--claro); }

/* ── LA FAQ, EN DOS COLUMNAS ───────────────────────────────────────────────
   Medida: sección de 1.344 con relleno 64/32/0, H2 centrado a 40px, y la lista
   en `630 630` con hueco de 20.

   Grid y no `columns` porque cada ítem es un `<details>` y un acordeón partido
   por un salto de columna se abre roto. Y trae un beneficio: el grid llena por
   FILAS, así que se lee 1-2 / 3-4 / 5, que es el orden que publica el
   `FAQPage`. La maqueta usa dos columnas de flex y se lee 1-3-5 / 2-4, que es
   el punto 7 de su tabla de conflictos. Acá la referencia se aparta a
   propósito, y es la única vez en toda la piel. */
.t-location_page.v-mosaico .faq {
  display: block;
  max-width: var(--m-caja); margin-inline: auto;
  padding: 64px var(--m-canaleta) 0;
  text-align: center;
}
.t-location_page.v-mosaico .faq__h2 {
  width: auto; margin: 0 0 28px; padding-top: 0;
  font-size: clamp(28px, 3.4vw, 40px);
  line-height: 1.08; letter-spacing: -0.03em;
}
.t-location_page.v-mosaico .faq__lista {
  max-width: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
  align-items: start;
  text-align: left;
}
.t-location_page.v-mosaico .faq__item {
  background: var(--blanco);
  border: 1px solid var(--pelo);
  padding: 22px 24px;
}
.t-location_page.v-mosaico .faq__item summary {
  font-family: var(--display); font-weight: 700;
  font-size: 18px; line-height: 1.35;
  color: var(--tinta);
}
.t-location_page.v-mosaico .faq__respuesta {
  margin: 12px 0 0; font-size: 15px; max-width: none;
}

/* ── LA NOTA DE VUELTA ─────────────────────────────────────────────────────
   Medida: caja de 1.280 con relleno 22/24, blanca, con filete y centrada, a 48
   de la FAQ. La piel base la dibuja como una línea de pie con tope de 68ch. */
.t-location_page.v-mosaico .vuelta {
  max-width: var(--m-ancho);
  margin: 48px auto 0;
  padding: 22px 24px;
  background: var(--blanco);
  border: 1px solid var(--pelo);
  color: var(--cuerpo); font-size: 16px;
}

/* ── EL CIERRE PARTIDO ─────────────────────────────────────────────────────
   Medido: sección a sangre en `--profunda`, 64 de aire arriba, relleno 45/32,
   y adentro una caja de **900** —no de 1.280— partida en `1fr 1fr` con hueco de
   34 y centrada. La foto va DENTRO de esa caja, no a sangre.

   La vuelta anterior la copió del cierre de la piel `galeria`, que sí es a
   sangre y mitad y mitad de ventana. No es lo que hace esta maqueta. */
.t-location_page.v-mosaico .cta:has(.cta__figura) {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 34px;
  align-items: center;
  max-width: none; margin-top: 64px;
  padding: 45px max(var(--m-canaleta), (100% - 900px) / 2);
  text-align: left;
}
.t-location_page.v-mosaico .cta__texto-caja {
  grid-column: 1; grid-row: 1;
  display: flex; flex-direction: column; align-items: flex-start; gap: 9px;
  padding: 0;
}
.t-location_page.v-mosaico .cta:has(.cta__figura) .cta__h2 {
  margin: 0; max-width: none;
  font-size: clamp(19px, 2.1vw, 25px);
  line-height: 1.12; letter-spacing: -0.025em;
}
.t-location_page.v-mosaico .cta:has(.cta__figura) .cta__texto {
  margin: 0; max-width: 50ch; font-size: 14px;
}
.t-location_page.v-mosaico .cta:has(.cta__figura) .btn { margin-top: 6px; }
.t-location_page.v-mosaico .cta__figura {
  grid-column: 2; grid-row: 1;
  margin: 0; position: static; min-height: 0;
}
.t-location_page.v-mosaico .cta__figura img {
  position: static; display: block;
  width: 100%; height: auto;
  aspect-ratio: 4 / 3; object-fit: cover; border-radius: 0;
}

/* La galería no está en la maqueta: la emite `location_page.html` desde el
   2026-08-13 y le llega a las tres pieles por parcial. Entra a la escala del
   H2 de esta piel —el mismo clamp que el ángulo— para no ser el único titular
   con la escala del sitio en una página que ya no la usa. */
.t-location_page.v-mosaico .galeria__h2 {
  margin: 0 0 28px;
  font-size: clamp(28px, 3.4vw, 40px);
  line-height: 1.08; letter-spacing: -0.03em;
}

/* El cuerpo de texto de toda la piel: 16px a 1.7, con 16 de separación entre
   párrafos. Es el de la maqueta y no el del sitio. */
.t-location_page.v-mosaico .angulo__col p,
.t-location_page.v-mosaico .servicio-ahi p,
.t-location_page.v-mosaico .direcciones__texto p {
  font-size: 16px; line-height: 1.7; margin: 0 0 16px;
}
.t-location_page.v-mosaico .angulo__col p:last-child,
.t-location_page.v-mosaico .servicio-ahi p:last-child,
.t-location_page.v-mosaico .direcciones__texto p:last-child { margin-bottom: 0; }


/* ══ 03 · FICHA — countertop contractor ═════════════════════════════════════
   Hermana declarada de la `02 · Ficha técnica` de servicio, así que reusa el
   nombre de variante a propósito: la mono, la medida de 74ch y la maquinaria
   del contador ya cuelgan de `.v-ficha` pelado (líneas 1964 y 1980) y se
   heredan solas.

   LO QUE FALTABA. Esa maquinaria enumera las secciones de un SERVICIO, así
   que en una geográfica solo incrementaba en `.normativa` y `.faq` y la
   página numeraba 01 y 02 en vez de 01–05. Se agregan las tres que faltan.
   El contador incrementa en orden de documento, así que quedan:
   ángulo 01 · servicio 02 · direcciones 03 · normativa 04 · FAQ 05. */
:is(.t-location_page, .t-utility).v-ficha .angulo,
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi,
:is(.t-location_page, .t-utility).v-ficha .direcciones { counter-increment: ficha; }

:is(.t-location_page, .t-utility).v-ficha .angulo__h2,
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi__h2,
:is(.t-location_page, .t-utility).v-ficha .direcciones__h2 {
  position: relative;
  padding-top: 0;
  padding-left: 3.5rem;
}
:is(.t-location_page, .t-utility).v-ficha .angulo__h2::before,
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi__h2::before,
:is(.t-location_page, .t-utility).v-ficha .direcciones__h2::before {
  content: counter(ficha, decimal-leading-zero);
  position: absolute;
  top: 0.45em; left: 0;
  width: auto; height: auto; background: none;
  font-family: var(--mono);
  font-size: 0.75rem; font-weight: 400; letter-spacing: 0.06em;
  color: var(--acento);
}

/* Superficie plana, igual que la ficha de servicio: en una página que se
   escanea, el cambio de fondo cada dos pantallas compite con la numeración,
   que es la única jerarquía que importa. El corte lo hace el filete. */
:is(.t-location_page, .t-utility).v-ficha main > section:not(.cta) { background: var(--blanco); }
:is(.t-location_page, .t-utility).v-ficha main > section:not(.cta) + section:not(.cta) {
  border-top-color: var(--pelo);
}

/* ── EL ÍNDICE LATERAL, Y LA GRILLA QUE LO SOSTIENE ────────────────────────
   Es lo que la README llama el distintivo de esta maqueta, y lo que faltaba
   para el 1 a 1. Necesita dos cosas que el CSS no puede inventar y que se
   agregaron al modelo el 2026-08-13: el `<nav>` con sus cinco etiquetas y los
   `id` de las cinco secciones. Las dos son OPCIONALES y viajan al template.

   EL PROPIO `<main>` ES LA GRILLA, y no un `<aside>` hermano. Un hermano de
   `<main>` pide tocar `_base.html`, que lo comparten las 40 páginas del sitio;
   el nav adentro de main lo resuelve una plantilla sola.

   LAS COLUMNAS SON DE SANGRE COMPLETA, con líneas nombradas. Hace falta porque
   esta página mezcla las dos cosas: el hero, la franja y el cierre siguen
   yendo de borde a borde de la ventana, y el cuerpo se mete en la columna de
   la derecha. Con una grilla de dos columnas a secas habría que elegir una de
   las dos y la otra se rompe.

   ⚠ `grid-row: 3 / span 99` OTRA VEZ, y por lo mismo que en la 01: `-1` apunta
   a la última línea de la grilla EXPLÍCITA y acá las filas son implícitas, una
   por sección, así que `3 / -1` colapsaría a una fila sola. La fila 3 es la
   primera del cuerpo: la 1 es el hero y la 2 la franja de confianza. Con
   `row-gap: 0` las 90 y pico de filas sobrantes no ocupan un píxel. */
/* ── LA GEOMETRÍA DE LA MAQUETA ────────────────────────────────────────────
   Igual que en la 02, y por el mismo motivo: la primera vuelta usó `--ancho`
   (1.400) y `--canaleta` (72) del sitio, y con eso la composición podía estar
   bien y la página leerse como otra cosa. Medido en la maqueta a 1440:

     caja        1.368 de borde exterior (margen 36 + relleno 24 por lado)
     contenido   1.320 = índice 220 + canaleta 48 + columna 1.052
     canaleta    60 efectivos hasta el borde de la ventana

   Los 1.052 de la columna de texto NO se declaran: salen de restar, y por eso
   dan clavados los 1.052 de la maqueta. */
:is(.t-location_page, .t-utility).v-ficha {
  --f-ancho: 1320px;
  --f-canaleta: 60px;
  --f-indice: 220px;
  --f-hueco: 48px;
  /* Sangre completa: el fondo llega al borde y el contenido se para en 1.320. */
  --f-sangre: max(var(--f-canaleta), (100% - var(--f-ancho)) / 2);
}

:is(.t-location_page, .t-utility).v-ficha main {
  --indice: var(--f-indice);
  --indice-hueco: var(--f-hueco);
  display: grid;
  grid-template-columns:
    [full-start] minmax(var(--f-canaleta), 1fr)
    [ind-start] var(--indice) [ind-end]
    var(--indice-hueco)
    [cont-start] minmax(0, calc(var(--f-ancho) - var(--indice) - var(--indice-hueco))) [cont-end]
    minmax(var(--f-canaleta), 1fr) [full-end];
  row-gap: 0;
  background: var(--blanco);
}
/* ⚠ LOS 32 DE LA MAQUETA VAN EN LA APERTURA, NO EN EL `main`. En la maqueta el
   `<main>` empieza DESPUÉS de la franja de confianza y su `padding-top: 32` es
   el aire entre las dos. Acá el `main` ES la grilla y la franja vive adentro,
   así que ese mismo padding empujaba el HERO 32 px hacia abajo y dejaba la
   apertura pegada al borde inferior de la franja, sin nada de aire. Medido: el
   `trust` cerraba en 793 y la apertura arrancaba en 793.

   La apertura se EXCLUYE de la regla de ritmo con un `:not()` en vez de pelear
   con ella: esa regla pesa (0,4,2) —cada `:not()` cuenta como clase— y ningún
   `.apertura` razonable le gana. Es la tercera vez que esta hoja se cobra lo
   mismo; el patrón que funciona es excluir, no pisar. */
:is(.t-location_page, .t-utility).v-ficha main > :is(section.apertura, section.legal__apertura) {
  padding-block: 32px 40px;
}
:is(.t-location_page, .t-utility).v-ficha main > * { grid-column: cont-start / cont-end; }
:is(.t-location_page, .t-utility).v-ficha main > .hero,
:is(.t-location_page, .t-utility).v-ficha main > .trust,
:is(.t-location_page, .t-utility).v-ficha main > .cta { grid-column: full-start / full-end; }
/* El relleno lateral lo pone ahora la grilla. Se lo saca a las secciones del
   CUERPO y sólo a ellas: el hero, la franja y el cierre siguen a sangre y
   llevan el suyo propio, con más especificidad que esta regla. */
:is(.t-location_page, .t-utility).v-ficha main > section:not(.hero):not(.cta) { padding-inline: 0; }

/* ── EL RITMO VERTICAL DE LA MAQUETA ───────────────────────────────────────
   El `--seccion` del sitio pone 60 arriba Y 60 abajo: 120 entre dos secciones.
   La maqueta pone 40, y sólo abajo — el aire de arriba lo da el relleno de la
   cabecera numerada. Con el clamp del sitio, esta página medía 6.139 de alto
   contra los 4.324 de la maqueta. Medido el 2026-08-13. */
:is(.t-location_page, .t-utility).v-ficha main > section:not(.hero):not(.cta):not(.apertura):not(.legal__apertura) {
  padding-block: 0 40px;
}
/* La cabecera de la sección numerada: 20 arriba y 14 hasta la prosa.
   ⚠ VA CON LOS SELECTORES `__h2` Y NO CON `> h2`. Los tres numerados ya se
   tocan arriba por clase —(0,3,0)— y ahí se les fija `padding-top: 0`;
   `.angulo > h2` pesa (0,2,1) y perdía en silencio. Es la misma trampa de
   especificidad que la media query de la 01, y tampoco se ve leyendo el CSS. */
:is(.t-location_page, .t-utility).v-ficha .angulo__h2,
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi__h2,
:is(.t-location_page, .t-utility).v-ficha .direcciones__h2,
:is(.t-location_page, .t-utility).v-ficha .normativa__h2,
:is(.t-location_page, .t-utility).v-ficha .faq__h2 {
  padding-top: 20px;
  margin-bottom: 14px;
}

:is(.t-location_page, .t-utility).v-ficha .indice {
  grid-column: ind-start / ind-end;
  grid-row: 3 / span 99;
  align-self: start;
  position: sticky; top: 1.5rem;
  padding-block: 32px;        /* la maqueta, medida — no el `--seccion` de 60 */
  display: flex; flex-direction: column; gap: 1.25rem;
}
:is(.t-location_page, .t-utility).v-ficha .indice__rotulo {
  margin: 0 0 0.25rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--pelo);
  font-family: var(--mono);
  font-size: 0.68rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--mute);
}
:is(.t-location_page, .t-utility).v-ficha .indice__lista {
  counter-reset: idx;
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column;
}
:is(.t-location_page, .t-utility).v-ficha .indice__item { counter-increment: idx; }
:is(.t-location_page, .t-utility).v-ficha .indice__item a {
  display: block; padding: 0.3rem 0;
  font-family: var(--mono); font-size: 0.76rem; line-height: 1.4;
  color: var(--cuerpo); text-decoration: none;
}
/* El ordinal sale de un contador y no del texto: si mañana una sección no se
   escribe, la numeración se recalcula sola y no queda un 04 sin un 03. */
:is(.t-location_page, .t-utility).v-ficha .indice__item a::before {
  content: counter(idx, decimal-leading-zero) " · ";
  color: var(--acento);
}
:is(.t-location_page, .t-utility).v-ficha .indice__item a:hover { color: var(--tinta); text-decoration: underline; }
:is(.t-location_page, .t-utility).v-ficha .indice__tarjeta {
  background: var(--papel);
  border: 1px solid var(--pelo);
  padding: 0.9rem 1rem;
  display: flex; flex-direction: column; gap: 0.2rem;
}
:is(.t-location_page, .t-utility).v-ficha .indice__telefono {
  font-family: var(--display); font-weight: 800;
  font-size: 1.05rem; letter-spacing: -0.01em;
  color: var(--tinta); text-decoration: none;
}
:is(.t-location_page, .t-utility).v-ficha .indice__horario {
  font-family: var(--mono); font-size: 0.66rem; line-height: 1.4;
  color: var(--mute);
}

/* ── EL HERO DE LA FICHA ───────────────────────────────────────────────────
   Compacto y a `1fr 400px`, medido en la maqueta. NO es un hero de pantalla
   completa: acá la primera pantalla la ganan los datos duros, no la foto, así
   que se le suelta el `min-height` de `100svh - --tope` que trae la piel base.
   Con eso, además, deja de importar que la franja de confianza cambie de alto
   más abajo. */
/* EL RELLENO ES EL DE LA GRILLA DE `main`, no el `max-width` + `margin: auto`
   que trae el hero base. Con el de la piel base, el H1 arrancaba en x=92 y el
   cuerpo de la página en x=315: 223 px de desfase entre el titular y el índice
   que tiene justo debajo. Medido el 2026-08-13. La fórmula es la misma que ya
   usan la topbar y `main > section`, y por el mismo motivo. */
:is(.t-location_page, .t-utility).v-ficha .hero {
  grid-template-columns: minmax(0, 1fr) minmax(0, 400px);
  align-items: center;
  min-height: 0;
  max-width: none;
  /* ⚠ Y `margin-inline: 0`, que faltaba. Sacarle el `max-width` al hero base no
     alcanza: la línea 424 le pone además `margin-inline: auto`, y UN MARGEN
     AUTO IMPIDE QUE UN ÍTEM DE GRILLA ESTIRE — se queda del tamaño de su
     contenido y se centra en su área. `justify-self: stretch` no lo revierte;
     lo único que lo revierte es matar el margen.

     La location page zafaba de casualidad: su contenido mide justo 1.320 más
     el relleno, así que los márgenes auto resolvían a 0 y no se veía. La
     legal, sin foto, mide menos: el hero salía de 1.136 centrado y el H1
     arrancaba en x=212 contra los 60 del índice que tiene justo debajo.
     Medido el 2026-08-14, y es el mismo desfase que este bloque dice haber
     arreglado el 2026-08-13. Estaba arreglado a medias. */
  margin-inline: 0;
  /* Medido: caja de 1.320 con relleno 40 arriba y abajo, y la grilla partida en
     `872 400` con hueco de 48 — que es exactamente 1.320. La columna de texto no
     se declara: sale de `1fr`. */
  padding-inline: var(--f-sangre);
  padding-block: 40px;
  gap: 48px;
  border-bottom: 1px solid var(--pelo);
}
:is(.t-location_page, .t-utility).v-ficha .hero__figura {
  display: flex; flex-direction: column; gap: 0.6rem;
  align-self: center;
}
:is(.t-location_page, .t-utility).v-ficha .hero__figura img {
  aspect-ratio: 8 / 9;
  min-height: 0; max-height: none;
}
/* El dato baja de la foto y se vuelve un pie de foto de una línea, que es lo
   que la maqueta hace con él. */
:is(.t-location_page, .t-utility).v-ficha .hero__dato {
  position: static;
  flex-direction: row; align-items: baseline; gap: 0.5rem;
  max-width: none; padding: 0;
  background: transparent; border-left: 0;
  color: var(--mute); font-size: 0.85rem;
}
:is(.t-location_page, .t-utility).v-ficha .hero__dato b { color: var(--tinta); font-size: 1.15rem; }
/* La fila de datos duros de `.v-ficha` está calibrada para CUATRO pares y esta
   página declara DOS: los únicos con fuente en el brief. Con `repeat(4)` los
   dos quedaban apretados contra el borde izquierdo y sobraban dos columnas
   vacías. `auto-fit` reparte los que haya. */
:is(.t-location_page, .t-utility).v-ficha .hero__specs,
.v-contacto .hero__specs {
  grid-template-columns: repeat(auto-fit, minmax(140px, 220px));
  justify-content: start;
}

/* ── LA FRANJA DE CONFIANZA, EN CLARO ──────────────────────────────────────
   En la maqueta la ficha es la única de las tres que NO la pone en oscuro:
   son cuatro datos de registro y van en mono, centrados, sobre papel. El par
   `--tinta`/`--papel` es el del cuerpo del sitio y está declarado. */
:is(.t-location_page, .t-utility).v-ficha .trust {
  background: var(--papel);
  border-bottom: 1px solid var(--pelo);
}
:is(.t-location_page, .t-utility).v-ficha .trust__item {
  color: var(--tinta);
  border-left-color: var(--pelo);
  font-family: var(--mono); font-weight: 400;
  font-size: 0.72rem; letter-spacing: 0.04em; text-transform: uppercase;
  text-align: center;
  padding: 1.1rem 1.25rem;
}
:is(.t-location_page, .t-utility).v-ficha .trust__item::before { display: none; }

/* ── EL CUERPO: TEXTO A LA IZQUIERDA, FOTO EN UN RIEL ANGOSTO ──────────────
   Las tres secciones numeradas reparten igual: el H2 con su ordinal a todo el
   ancho y debajo dos columnas, la prosa y una columna de foto más angosta.
   Lo que cambia es el ratio del riel, y cambia por lo que muestra:

     ángulo        300px   DOS fotos apiladas, separadas por un pelo
     servicio      280px   una, 3:4
     direcciones   1fr     una, 3:2 — apaisada, que es un recorrido

   Esto reemplaza a la versión de una sola columna que había acá, escrita
   cuando la página no tenía fotos: con las seis puestas, una columna deja las
   imágenes a todo el ancho del texto y la ficha se lee como cualquier otra. */
:is(.t-location_page, .t-utility).v-ficha .angulo,
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi,
:is(.t-location_page, .t-utility).v-ficha .direcciones {
  display: grid;
  column-gap: clamp(1.5rem, 3vw, 2rem);
  row-gap: 0;                 /* ⚠ obligatorio con `span 99` — ver la 01 */
  align-items: start;
}
:is(.t-location_page, .t-utility).v-ficha .angulo { grid-template-columns: minmax(0, 1fr) minmax(0, 300px); }
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi { grid-template-columns: minmax(0, 1fr) minmax(0, 280px); }
:is(.t-location_page, .t-utility).v-ficha .direcciones {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;        /* la maqueta centra esta y sólo esta */
}

:is(.t-location_page, .t-utility).v-ficha .angulo > h2,
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi > h2,
:is(.t-location_page, .t-utility).v-ficha .direcciones > h2 {
  position: relative; top: auto;
  grid-column: 1 / -1; grid-row: 1;
  margin-bottom: 1.25rem;
}
:is(.t-location_page, .t-utility).v-ficha .angulo > *:not(h2):not(.angulo__figura),
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi > *:not(h2):not(.servicio-ahi__figura),
:is(.t-location_page, .t-utility).v-ficha .direcciones > *:not(h2):not(.direcciones__figura) {
  grid-column: 1;
}
:is(.t-location_page, .t-utility).v-ficha .angulo__figura,
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi__figura,
:is(.t-location_page, .t-utility).v-ficha .direcciones__figura {
  grid-column: 2; grid-row: 2 / span 99;
  align-self: start; margin: 0;
}
:is(.t-location_page, .t-utility).v-ficha .angulo__figura img,
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi__figura img,
:is(.t-location_page, .t-utility).v-ficha .direcciones__figura img {
  width: 100%; height: auto; display: block;
}
/* Las dos del ángulo apiladas, separadas por un pelo y con filete alrededor:
   es una lámina de dos viñetas, no dos fotos sueltas.

   Y LA LÁMINA MIDE LO QUE EL TEXTO. En la maqueta el par ocupa 512 de alto y la
   columna de prosa también 512: es una sola lámina al costado del argumento, no
   dos fotos que terminan antes. Acá quedaban en 450 contra 587 de texto, porque
   la figura tomaba su altura natural. Se estira al tramo y las dos filas se
   reparten en partes iguales; el recorte lo absorbe `object-fit`. */
:is(.t-location_page, .t-utility).v-ficha .angulo__figura {
  display: grid; gap: 1px;
  grid-template-rows: 1fr 1fr;
  align-self: stretch;
  background: var(--pelo);
  border: 1px solid var(--pelo);
}
:is(.t-location_page, .t-utility).v-ficha .angulo__figura img {
  height: 100%; object-fit: cover;
}
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi__figura img { aspect-ratio: 3 / 4; object-fit: cover; }
:is(.t-location_page, .t-utility).v-ficha .direcciones__figura { align-self: center; }
:is(.t-location_page, .t-utility).v-ficha .direcciones__figura img { aspect-ratio: 3 / 2; object-fit: cover; }
/* El NAP se separa del texto con un filete y no con una caja de color: en una
   ficha, un bloque tintado compite con la numeración. */
:is(.t-location_page, .t-utility).v-ficha .direcciones__nap {
  border-top: 1px solid var(--pelo);
  padding-top: 1rem;
}

/* La normativa y la FAQ vienen CENTRADAS de la piel base, y en una ficha eso
   rompe lo único que la sostiene: si 01, 02 y 03 alinean a la izquierda y 04 y
   05 al centro, el ordinal deja de leerse como índice y pasa a leerse como
   adorno. Se vio en la captura del 2026-08-13. Van a la izquierda como las
   otras tres, y el ordinal vuelve a colgar de la misma canaleta. */
:is(.t-location_page, .t-utility).v-ficha .normativa,
:is(.t-location_page, .t-utility).v-ficha .faq { text-align: left; }
:is(.t-location_page, .t-utility).v-ficha .normativa__h2,
:is(.t-location_page, .t-utility).v-ficha .faq__h2 {
  width: auto;
  margin-inline: 0;
  text-align: left;
}
:is(.t-location_page, .t-utility).v-ficha .normativa__h2::before,
:is(.t-location_page, .t-utility).v-ficha .faq__h2::before {
  left: 0;
  transform: none;
}
:is(.t-location_page, .t-utility).v-ficha .normativa__texto { margin-inline: 0; }

/* La apertura es la bajada del H1, no un capítulo: sin número y con filete
   lateral, igual que en la ficha de servicio. Con la foto al costado en una
   columna de 19rem, que es lo que mide la maqueta. */
:is(.t-location_page, .t-utility).v-ficha .apertura {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 300px);
  column-gap: 32px;
  row-gap: 0;                 /* ⚠ obligatorio con `span 99` — ver la 01 */
  align-items: center;
  margin-bottom: 40px;        /* medido en la maqueta */
}
:is(.t-location_page, .t-utility).v-ficha .apertura > *:not(.apertura__figura) { grid-column: 1; }
:is(.t-location_page, .t-utility).v-ficha .apertura__figura {
  grid-column: 2; grid-row: 1 / span 99;
  align-self: center; margin: 0;
}
:is(.t-location_page, .t-utility).v-ficha .apertura__figura img { width: 100%; height: auto; display: block; }
:is(.t-location_page, .t-utility).v-ficha .apertura > p:first-of-type {
  border-left: 3px solid var(--acento);
  padding-left: 20px;
  font-size: 18px;
  line-height: 1.6;
  /* Ocupa su columna entera, como en la maqueta: la bajada del H1 ya está
     acotada por la grilla de 720 y un `ch` encima la partía en 521. */
  max-width: none;
}


/* ── LA ESCALA TIPOGRÁFICA DE LA MAQUETA ───────────────────────────────────
   La tercera de las cuatro cosas del 1 a 1, y en esta piel era la peor: el H2
   de sección medía 43,2 contra los 26 de la maqueta — no una desviación, otra
   jerarquía. Con el H2 al 166% el ordinal de la ficha deja de leerse como
   índice. Todos los valores están MEDIDOS sobre la maqueta a 1440, no elegidos.

   VA EN PÍXELES Y NO EN `rem`, igual que la 02: el `rem` sigue atado al root de
   16 y lo que hay que replicar es un número absoluto de la referencia.

   ⚑ EL `max-width` DE LA PROSA NO SE DECLARA Y NO HAY QUE DECLARARLO. Los `p`
   heredan `--ancho-texto: 68ch` y el `ch` escala con el tamaño de letra: a 17px
   el sitio medía 792,4 y a 15px da 699,2, que es el número de la maqueta al
   décimo. Fijarlo a mano sería romperlo en el próximo cambio de fuente. */
:is(.t-location_page, .t-utility).v-ficha .hero__h1 {
  font-size: 48px;
  line-height: 1.03;
  letter-spacing: -0.03em;
}
:is(.t-location_page, .t-utility).v-ficha .hero__sub {
  font-size: 17px;
  line-height: 1.55;
  margin-bottom: 36px;
  /* El `46ch` de la piel base estaba calibrado para el sub a 23px; a 17 deja la
     línea en 493 y la maqueta la lleva a 664. Va en `ch` y no en píxeles para
     que siga siendo una medida de lectura y no un número suelto. */
  max-width: 62ch;
}
:is(.t-location_page, .t-utility).v-ficha .hero .btn { font-size: 14px; padding: 14px 24px; }
:is(.t-location_page, .t-utility).v-ficha .hero__specs dt { font-size: 11px; letter-spacing: 0.05em; }
:is(.t-location_page, .t-utility).v-ficha .hero__specs dd { font-size: 17px; line-height: 1.65; }
:is(.t-location_page, .t-utility).v-ficha .hero__dato { font-size: 13px; }
:is(.t-location_page, .t-utility).v-ficha .hero__dato b { font-size: 18px; }
:is(.t-location_page, .t-utility).v-ficha .trust__item { font-size: 12px; padding: 16px 20px; }

/* El H2 de las cinco secciones. 26 a 1,65 — el mismo interlineado que la prosa,
   que es lo que lo mantiene atado al bloque y no flotando encima. */
:is(.t-location_page, .t-utility).v-ficha .angulo__h2,
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi__h2,
:is(.t-location_page, .t-utility).v-ficha .direcciones__h2,
:is(.t-location_page, .t-utility).v-ficha .normativa__h2,
:is(.t-location_page, .t-utility).v-ficha .faq__h2,
/* La galería no existe en la maqueta —esta página publica una y aquella no—,
   pero un H2 a 43 entre cinco a 26 rompe justo lo que la ficha sostiene, que
   es la jerarquía del índice. Entra a la escala de la piel. */
:is(.t-location_page, .t-utility).v-ficha .galeria__h2 {
  font-size: 26px;
  line-height: 1.65;
  letter-spacing: -0.02em;
}
/* El ordinal cuelga de una canaleta proporcional al H2 nuevo: con 3,5rem sobre
   un titular de 26 quedaba un hueco de casi el doble del número. Medido en la
   maqueta: el `span` del ordinal ocupa 14 y separa 14. */
:is(.t-location_page, .t-utility).v-ficha .angulo__h2,
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi__h2,
:is(.t-location_page, .t-utility).v-ficha .direcciones__h2 { padding-left: 28px; }
:is(.t-location_page, .t-utility).v-ficha .angulo__h2::before,
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi__h2::before,
:is(.t-location_page, .t-utility).v-ficha .direcciones__h2::before { top: 0.65em; }

/* La prosa de toda la piel: 15 a 1,653 con 14 de separación. */
:is(.t-location_page, .t-utility).v-ficha .angulo p,
:is(.t-location_page, .t-utility).v-ficha .servicio-ahi p,
:is(.t-location_page, .t-utility).v-ficha .direcciones p,
:is(.t-location_page, .t-utility).v-ficha .normativa p,
:is(.t-location_page, .t-utility).v-ficha .faq p {
  font-size: 15px;
  line-height: 1.653;
  margin: 0 0 14px;
}
:is(.t-location_page, .t-utility).v-ficha .faq__item summary { font-size: 17px; line-height: 1.65; }
:is(.t-location_page, .t-utility).v-ficha .faq__item p { margin: 12px 0 0; }
/* La FAQ arranca en la canaleta del texto, no indentada: medida, la maqueta la
   lleva a los 1.052 completos y acá entraba a 960 con 47 de sangría. */
:is(.t-location_page, .t-utility).v-ficha .faq__item { margin-inline: 0; padding: 16px 0; }

/* ── EL CIERRE, EN PAPEL ───────────────────────────────────────────────────
   La ficha es la única de las tres que NO cierra en oscuro: la maqueta la pone
   sobre `--papel` con el titular en tinta, centrado, y el botón en acento. Es
   coherente con su franja de confianza, que también es la única clara. El par
   tinta/papel es el del cuerpo del sitio y ya está declarado en `contraste.md`,
   así que el bloque C lo mide sin agregar nada.

   ⚠ VA CON `!important`, Y NO ES CAPRICHO. `.cta` de la piel base declara
   `background: var(--profunda) !important` y `border-top: 0 !important` (línea
   1046). Sin repetir el `!important` acá, esta regla se aplicaba a medias: el
   fondo seguía OSCURO y los colores de texto de abajo sí entraban, así que el
   cierre quedaba tinta sobre tinta y no se leía. Lo cazó el operador —"el cta
   no se lee"— y el bloque C no lo ve: mide pares declarados, y tinta/papel está
   declarado; lo que falla es que el fondo real no era el declarado. */
:is(.t-location_page, .t-utility).v-ficha .cta {
  background: var(--papel) !important;
  border-top: 1px solid var(--pelo) !important;
  padding: 52px var(--f-sangre);
  text-align: center;
}
/* El botón sobre papel va en acento pleno con texto blanco, como en la maqueta:
   el `--acento-cl` de la piel base está calibrado contra el CTA oscuro. */
:is(.t-location_page, .t-utility).v-ficha .cta .btn--primario {
  background: var(--acento); color: #fff;
}
:is(.t-location_page, .t-utility).v-ficha .cta .btn--primario:hover {
  background: var(--acento-osc); color: #fff;
}

/* LA NOTA DE VUELTA, SIN FONDO PROPIO. Va justo encima del cierre y las dos
   superficies son claras: con el `--papel` que trae de la piel base, la nota y
   el CTA se funden en una sola mancha y el borde entre ambos desaparece.
   Medido: la nota cerraba en 4624 y el CTA abría en 4624, sin nada en el medio.
   En la maqueta la nota no declara fondo —se apoya en el blanco del cuerpo— y
   el relleno es 20 arriba y 40 abajo. El filete del CTA hace el corte. */
:is(.t-location_page, .t-utility).v-ficha .vuelta {
  background: transparent;
  padding: 20px 0 40px;
}
:is(.t-location_page, .t-utility).v-ficha .cta__h2 {
  font-size: 32px;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--tinta);
}
:is(.t-location_page, .t-utility).v-ficha .cta p { font-size: 15px; color: var(--cuerpo); margin-inline: auto; }
:is(.t-location_page, .t-utility).v-ficha .cta .btn { font-size: 15px; padding: 16px 30px; }


/* ══ LAS TRES, EN ANGOSTO ═══════════════════════════════════════════════════
   Todo lo que sea de dos columnas se cae a una, y las fotos vuelven al flujo.
   El corte es el mismo que usa el resto de la hoja para las grillas de cuerpo. */
@media (max-width: 860px) {
  /* ⚠ LA CANALETA DE ESCRITORIO NO SE ACHICA SOLA. Medido a 360 px el
     2026-08-14, cerrando las tres location pages. `--z-canaleta` vale 100 y
     `--f-canaleta` 60, y las dos SOBREVIVEN al corte angosto: la sangre es un
     `max()` y, cuando `(100% - ancho) / 2` se vuelve negativo en móvil, el
     `max()` elige justamente la canaleta de escritorio. En 360 eso deja 160 px
     de caja útil en zigzag y 240 en ficha.

     Y lo que se rompe no es el margen, que sería cosmético: en ficha el H1
     parte la palabra al medio —"Countert / op", "Contract / or"— porque a 48 px
     "Countertop" mide 260 y la caja quedó en 240; en zigzag la galería queda en
     una tira de 160 con ítems de 281, que `main { overflow-x: clip }` recorta
     dejando la foto cortada y el pie ilegible.

     Se corrige en la canaleta y NO en cada caja: las dos sangres la leen por
     `var()`, así que se recalculan solas y ninguna otra regla se toca. */
  .t-location_page.v-zigzag { --z-canaleta: var(--canaleta); }
  :is(.t-location_page, .t-utility).v-ficha  { --f-canaleta: var(--canaleta); }

  /* zigzag — el hero deja de estar partido: el panel oscuro arriba, la foto
     debajo. Se le devuelve el relleno lateral que el split le había sacado. */
  .t-location_page.v-zigzag .hero {
    grid-template-columns: minmax(0, 1fr);
    min-height: 0;
  }
  .t-location_page.v-zigzag .hero__texto {
    padding: clamp(2rem, 7vw, 3rem) var(--canaleta);
  }
  .t-location_page.v-zigzag .hero__figura { min-height: 0; }
  .t-location_page.v-zigzag .hero__figura img { aspect-ratio: 4 / 3; }

  .t-location_page.v-zigzag .apertura,
  .t-location_page.v-zigzag .angulo,
  .t-location_page.v-zigzag .servicio-ahi,
  .t-location_page.v-zigzag .direcciones,
  .t-location_page.v-zigzag .normativa,
  .t-location_page.v-zigzag .faq {
    grid-template-columns: minmax(0, 1fr);
  }
  /* ⚠ LOS SELECTORES SE REPITEN CLAVADOS, NO SE ACORTAN A `> *`. Una media
     query NO suma especificidad: adentro compite exactamente igual que afuera.
     `.angulo > *:not(.angulo__figura)` pesa (0,4,0) y `.angulo > *` pesa
     (0,3,0), así que el `grid-column: 2` de escritorio le ganaba acá adentro y
     las secciones seguían a DOS columnas en 390 px. Medido el 2026-08-13 sobre
     esta página ya publicada: `.angulo` daba `0px 318px` —la primera columna
     colapsada a cero— y en la piel 02 la misma causa daba una sección de
     12.835 px de alto.

     No se ve mirando el CSS: el bloque angosto está escrito, se lee correcto y
     no hace nada. Sale midiendo `gridTemplateColumns` a 390. */
  .t-location_page.v-zigzag .apertura > *:not(.apertura__figura),
  .t-location_page.v-zigzag .angulo > *:not(.angulo__figura),
  .t-location_page.v-zigzag .servicio-ahi > *:not(.servicio-ahi__figura),
  .t-location_page.v-zigzag .direcciones > *:not(.direcciones__figura),
  .t-location_page.v-zigzag .apertura__figura,
  .t-location_page.v-zigzag .angulo__figura,
  .t-location_page.v-zigzag .servicio-ahi__figura,
  .t-location_page.v-zigzag .direcciones__figura,
  .t-location_page.v-zigzag .normativa__texto,
  .t-location_page.v-zigzag .normativa__datos,
  .t-location_page.v-zigzag .faq__h2,
  .t-location_page.v-zigzag .faq__lista { grid-column: 1; grid-row: auto; }
  /* El par del ángulo deja de ser pegajoso: en una columna, un bloque pegado
     tapa el texto que viene a explicar. */
  .t-location_page.v-zigzag .angulo__figura,
  .t-location_page.v-zigzag .faq__h2 { position: static; }
  .t-location_page.v-zigzag .angulo__figura { grid-template-columns: repeat(2, 1fr); }
  /* El cierre partido se apila con el TEXTO arriba: con la foto primero, el
     titular queda fuera de pantalla justo cuando la página pide la llamada. */
  .t-location_page.v-zigzag .cta:has(.cta__figura) {
    grid-template-columns: minmax(0, 1fr);
  }
  .t-location_page.v-zigzag .cta__texto-caja {
    grid-column: 1; grid-row: 1;
    padding: clamp(2rem, 7vw, 3rem) var(--canaleta);
  }
  .t-location_page.v-zigzag .cta__figura {
    grid-column: 1; grid-row: 2;
    position: static; min-height: 0;
  }
  .t-location_page.v-zigzag .cta__figura img { position: static; aspect-ratio: 4 / 3; }

  /* ── mosaico, en angosto ─────────────────────────────────────────────────
     El mosaico del hero deja de ser mosaico: las dos fotos una al lado de la
     otra y el dato debajo a todo el ancho. Un 3:4 y un 1:1 apilados en 390 px
     son dos pantallas de foto antes del primer párrafo.

     ⚠ LOS SELECTORES SE REPITEN CLAVADOS, NO SE ACORTAN A `> *`: una media
     query no suma especificidad, y `> *:not(.figura)` pesa más que `> *`. */
  .t-location_page.v-mosaico .hero {
    grid-template-columns: minmax(0, 1fr);
    padding: clamp(2rem, 7vw, 3rem) var(--m-canaleta);
  }
  .t-location_page.v-mosaico .hero__figura {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: auto auto;
  }
  .t-location_page.v-mosaico .hero__figura > :is(img, picture):first-of-type { grid-column: 1; grid-row: 1; }
  .t-location_page.v-mosaico .hero__figura > :is(img, picture):nth-of-type(2) { grid-column: 2; grid-row: 1; }
  .t-location_page.v-mosaico .hero__dato { grid-column: 1 / -1; grid-row: 2; }

  .t-location_page.v-mosaico .angulo,
  .t-location_page.v-mosaico .servicio-ahi,
  .t-location_page.v-mosaico .direcciones,
  .t-location_page.v-mosaico .normativa {
    grid-template-columns: minmax(0, 1fr);
  }
  .t-location_page.v-mosaico .angulo__col--izq,
  .t-location_page.v-mosaico .angulo__col--der,
  .t-location_page.v-mosaico .servicio-ahi > *:not(.servicio-ahi__figura),
  .t-location_page.v-mosaico .servicio-ahi__figura,
  .t-location_page.v-mosaico .direcciones > *:not(.direcciones__figura),
  .t-location_page.v-mosaico .direcciones__figura,
  .t-location_page.v-mosaico .normativa__h2,
  .t-location_page.v-mosaico .normativa__texto > p,
  .t-location_page.v-mosaico .normativa__datos { grid-column: 1; grid-row: auto; }
  /* La columna derecha del ángulo va DESPUÉS de la izquierda, no intercalada:
     en una sola columna el orden de lectura es el del documento. */
  .t-location_page.v-mosaico .angulo__col--der { margin-top: 16px; }
  .t-location_page.v-mosaico .servicio-ahi,
  .t-location_page.v-mosaico .normativa {
    padding-left: var(--m-canaleta); padding-right: var(--m-canaleta);
  }
  .t-location_page.v-mosaico .faq__lista { grid-template-columns: minmax(0, 1fr); }
  /* El cierre partido se apila con el texto arriba: con la foto primero, el
     titular queda fuera de pantalla justo cuando la página pide la llamada. */
  .t-location_page.v-mosaico .cta:has(.cta__figura) {
    grid-template-columns: minmax(0, 1fr);
    padding-left: var(--m-canaleta); padding-right: var(--m-canaleta);
  }
  .t-location_page.v-mosaico .cta__texto-caja { grid-column: 1; grid-row: 1; }
  .t-location_page.v-mosaico .cta__figura { grid-column: 1; grid-row: 2; }

  /* ficha — se cae el índice y con él la grilla de tres columnas del <main>.
     Un índice pegajoso en 390 px de ancho es una barra que tapa el texto que
     viene a explicar, y no hay dónde ponerlo al costado porque costado no hay.
     El nav se oculta: sus cinco destinos son las cinco secciones que siguen a
     continuación, así que no se pierde ningún contenido, sólo un atajo. */
  :is(.t-location_page, .t-utility).v-ficha main {
    display: block;
    background: transparent;
  }
  :is(.t-location_page, .t-utility).v-ficha main > section:not(.hero):not(.cta) {
    padding-inline: max(var(--canaleta), (100% - var(--ancho)) / 2);
  }
  :is(.t-location_page, .t-utility).v-ficha .indice { display: none; }

  :is(.t-location_page, .t-utility).v-ficha .hero,
  :is(.t-location_page, .t-utility).v-ficha .apertura,
  :is(.t-location_page, .t-utility).v-ficha .angulo,
  :is(.t-location_page, .t-utility).v-ficha .servicio-ahi,
  :is(.t-location_page, .t-utility).v-ficha .direcciones {
    grid-template-columns: minmax(0, 1fr);
  }
  :is(.t-location_page, .t-utility).v-ficha .apertura > *,
  :is(.t-location_page, .t-utility).v-ficha .angulo > *,
  :is(.t-location_page, .t-utility).v-ficha .servicio-ahi > *,
  :is(.t-location_page, .t-utility).v-ficha .direcciones > * { grid-column: 1; grid-row: auto; }
  /* Las dos del ángulo dejan de estar apiladas: lado a lado ocupan la mitad
     de pantalla en vez de dos tercios. */
  :is(.t-location_page, .t-utility).v-ficha .angulo__figura { grid-template-columns: repeat(2, 1fr); }
}


/* ══════════════════════════════════════════════════════════════════════════
   /about/ — LAS TRES CORRECCIONES DEL 2026-08-13, PEDIDAS MIRANDO LA PÁGINA
   ══════════════════════════════════════════════════════════════════════════

   `historia`, `propietario`, `credenciales` y `redes` existen SOLO en
   `about.html` — medido con grep sobre plantillas/ — así que se estilan sin
   scope y no pueden filtrarse a ninguna página viva.

   `.area` NO: la comparten `homepage.html` y `contact.html`, y el Homepage
   está construido y aprobado. Todo lo de `.area` va bajo `.v-about`, que sale
   del `variante: about` del front matter y del `<body class="t-… v-…">`. */

/* ── 1 · CREDENCIALES: EL H2 EN UNA SOLA LÍNEA ─────────────────────────────
   Medido a 1440: la columna de texto daba 712 px y "Licensed, Insured, and
   Guaranteed" a 43,2 px pide ~785, así que partía en dos por unos 70 px.
   Se ensancha la columna de TEXTO en vez de achicar el titular: la sección son
   seis viñetas cortas y su foto no necesita los 526 px que tenía. 1.35/0.65
   deja 836 px de texto, que entra con margen, y 402 de foto, que para una
   imagen 4:3 al lado de una lista sigue siendo holgado. */
.credenciales:has(.credenciales__figura) {
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 0.65fr);
}

/* ── 2 · CONNECT WITH US: CENTRADA ─────────────────────────────────────────
   Es un CIERRE, no una lectura: un H2 y los perfiles vivos. Cae del lado de
   "cierre o invitación" del criterio de §1, igual que la FAQ y el formulario,
   así que usa exactamente el mismo patrón que ya tienen `.faq` y `.form`:
   texto centrado, H2 a `fit-content` con `margin-inline: auto`, y el filete de
   acento recentrado — sin eso el filete queda colgado a la izquierda del
   titular centrado, que es peor que no centrar nada. */
.redes { text-align: center; }
.redes__h2 { width: fit-content; margin-inline: auto; }
.redes__h2::before { left: 50%; transform: translateX(-50%); }
.redes ul {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 0.75rem 2rem;
}

/* ── 3 · ÁREA DE SERVICIO: LA COLUMNA DERECHA, PROPORCIONAL AL TEXTO ───────
   Medido a 1440: el texto de la izquierda daba 485 px de alto y la columna
   derecha 672 —foto 372 + lista 276—, o sea la foto y la lista mandaban la
   altura de la sección y el texto quedaba flotando centrado contra ellas. Es
   exactamente lo que convenciones §5 prohíbe: el TEXTO manda la altura.

   Se corrige por los dos lados, sin tocar el ancho de las columnas:
     · la foto pasa de 4:3 a 16:9  → de 372 a ~278 px
     · la lista pasa de 2 a 3 columnas → de 5 filas a 3, de 276 a ~166 px
   Total ~468 contra 485 del texto: la derecha ya no empuja.

   VA EN UN `min-width` Y NO SUELTO: el bloque responsive de más arriba colapsa
   `.area` a una columna y `.area__lista` a 1 columna en ≤56rem. Una regla
   `.v-about .area__lista` sin media query tiene MÁS especificidad que la del
   bloque responsive y le ganaría también en móvil, dejando tres columnas de
   ciudades en 390 px. */
@media (min-width: 56.01rem) {
  .v-about .area__figura img { aspect-ratio: 16 / 9; }
  .v-about .area__lista { grid-template-columns: repeat(3, 1fr); }
  /* La regla de "el último impar ocupa toda la fila" está pensada para DOS
     columnas. Con tres y nueve ciudades la grilla cierra sola, y dejarla haría
     que la novena se estirara a lo ancho sin motivo. */
  .v-about .area__lista li:last-child:nth-child(odd) { grid-column: auto; }
}


/* ══════════════════════════════════════════════════════════════════════════
   PIEL · CONTACTO FICHA        `variante: contacto` en el front matter del .md
   ══════════════════════════════════════════════════════════════════════════

   DE DÓNDE SALE. `Contacto Ficha.dc.html` del proyecto de Claude Design
   3b9fe333-5f02-43fa-b10a-fe43b5cbd582, traído por MCP el 2026-08-13. Ver
   `diseno/contacto/README.md`: ahí están las coordenadas para volver a
   bajarla y la lista de lo que se trasladó y lo que no.

   NINGÚN COLOR NUEVO. La maqueta se dibujó sobre los tokens de este sitio
   —#b4451f, #1a1714, #f2f2f0, #dfdcd5, #6b655b son `--acento --tinta --papel
   --pelo --mute`—, así que trasladarla es cambiar los literales por las
   variables. `diseno/contraste.md` sigue valiendo sin medir nada nuevo.

   LA REGLA QUE LA HACE SEGURA. Todo cuelga de `.v-contacto`, que solo existe
   si el .md lo pidió. `/contact/` es la única página que lo declara, así que
   esto no puede alcanzar a las 39 restantes. Es el mismo contrato con el que
   entraron `v-ficha`, `v-galeria` y `v-revista`.

   LO QUE LA MAQUETA TRAE Y ACÁ NO ESTÁ, a propósito:
     · la nav en minúsculas y mono, y el botón "Call Now" en la cabecera: eso
       es chrome de `_base.html` y lo comparten las 40 páginas. Cambiarlo es
       un rediseño del sitio, no de esta página.
     · el `max-width:1320px` de la maqueta: acá manda `--ancho`, que es el
       mismo eje de las otras 39. */

/* ── 0 · SUPERFICIE PLANA ──────────────────────────────────────────────────
   Igual que en `ficha` y por el mismo motivo: la alternancia papel/blanco da
   ritmo cuando se LEE, y acá se ESCANEA. El corte lo hace el filete. */
.v-contacto main > section:not(.cta) { background: var(--blanco); }
.v-contacto main > section:not(.cta) + section:not(.cta) { border-top-color: var(--pelo); }

/* ── 1 · EL HERO: RÓTULO, SPECS Y EL FORMULARIO AL LADO ────────────────────
   El formulario ocupa la columna de la figura. En una página de conversión
   bajarlo a media página es esconderlo: acá entra en la primera pantalla, al
   lado del H1, que es lo que la maqueta resuelve y las otras doce plantillas
   no necesitan. */
.v-contacto .hero__rotulo {
  font-family: var(--mono, "Plex Mono", ui-monospace, monospace);
  font-size: 0.75rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--acento); margin: 0 0 0.25rem;
}
/* El filete de acento del H1 sobra cuando arriba ya hay un rótulo en acento:
   son dos gestos del mismo color a 20 px, que se leen como un render doble.
   Es la misma corrección que la piel `ficha` hizo con su par de barras. */
.v-contacto .hero:has(.hero__rotulo) .hero__h1 { padding-top: 0; }
.v-contacto .hero:has(.hero__rotulo) .hero__h1::before { content: none; }
/* EL HERO VUELVE A DOS COLUMNAS. La regla §16 lo colapsa a una sola cuando no
   encuentra `.hero__figura`, y acá la columna derecha no es una figura: es el
   formulario. Sin esto el panel caía debajo del H1, a ancho completo y
   centrado, que es exactamente lo que la maqueta viene a evitar. */
/* VA EN UN `min-width`, y esto no es opcional: `.v-contacto .hero:has(…)` tiene
   más especificidad que la regla del bloque responsive que colapsa el hero a
   una columna, así que sin la media query ganaba también a 500 px y el
   formulario quedaba en una columna de 200 px al lado del H1. Medido el
   2026-08-13, mismo error que ya se había atajado en `.area__lista`. */
@media (min-width: 62rem) {
  .v-contacto .hero:has(.hero__form) {
    /* Mitad y mitad, como la maqueta: su hero es `auto-fit` con mínimo de 400,
       que a 1440 resuelve en dos columnas iguales. El 1.05/0.95 de la primera
       vuelta dejaba el panel en 569 contra los 636 de allá, y un formulario de
       cinco campos es lo último que se angosta. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    justify-items: stretch;
  }
  .v-contacto .hero:has(.hero__form) .hero__texto { max-width: none; }
}
/* El H1 baja de cuerpo SOLO en esta piel. La escala del sitio está calculada
   para un hero de texto a ancho casi completo; con el formulario al lado la
   columna es la mitad y el mismo titular parte en tres líneas y empuja los
   specs fuera de la primera pantalla. Es la misma decisión que la maqueta ya
   había tomado con su `clamp(30px, 3.8vw, 48px)`. */
.v-contacto .hero:has(.hero__form) .hero__h1 { font-size: clamp(2rem, 3.6vw, 3.4rem); }
.v-contacto .hero:has(.hero__form) .hero__sub { max-width: 42ch; }
.v-contacto .hero__form {
  min-width: 0; align-self: center;
  background: var(--blanco);
  border: 1px solid var(--pelo);
  border-top: 3px solid var(--acento);
}
.v-contacto .hero__form .form { padding: clamp(1.5rem, 2.5vw, 2rem); }
/* El formulario del sitio va centrado —es cierre— y acá es un panel de
   trabajo: vuelve a la izquierda, que es como se llena un formulario. */
.v-contacto .hero__form .form,
.v-contacto .hero__form .form__h2 { text-align: left; margin-inline: 0; width: auto; }
.v-contacto .hero__form .form__h2::before { left: 0; transform: none; }
.v-contacto .hero__form .form__campos { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.9rem; }
.v-contacto .hero__form .form__campos > label:nth-child(n+3),
.v-contacto .hero__form .form__campos > button { grid-column: 1 / -1; }
.v-contacto .hero__form .form__campos > button { justify-self: start; }

/* ── 2 · MAIN A DOS COLUMNAS, CON EL ÍNDICE PEGAJOSO EN LA CANALETA ────────
   El aside es hijo directo de `main` y las secciones NO se envuelven: envolver
   las habría sacado de `main > section`, que es de donde cuelgan el padding,
   el ritmo, los fondos y la regla §16. Acá `main` pasa a grilla y el aside
   ocupa la primera columna abarcando todas las filas.

   LA PRIMERA COLUMNA INCLUYE LA CANALETA —`calc(var(--canaleta) + 14rem)`— y
   las secciones pierden SOLO su padding izquierdo. Así el índice arranca en el
   mismo x que arranca el texto en el resto del sitio, y el cuerpo no queda con
   la canaleta contada dos veces.

   El hero, la franja de confianza y el CTA abarcan las dos columnas: son de
   ancho completo y su fondo se rompe a sangre. */
@media (min-width: 62rem) {
  .v-contacto main {
    display: grid;
    grid-template-columns: calc(var(--canaleta) + 14rem) minmax(0, 1fr);
    align-items: start;
  }
  .v-contacto main > * { grid-column: 2; }
  .v-contacto main > .hero,
  .v-contacto main > .trust,
  .v-contacto main > .cta { grid-column: 1 / -1; }
  /* `:not(.hero):not(.cta)` — las dos que abarcan las dos columnas conservan
     su canaleta, que es la que las alinea con la cabecera y con el pie. Sin
     esa exclusión el H1 arrancaba en x=20 contra los 72 del resto del sitio,
     y el hero se leía descolgado de su propia página. */
  .v-contacto main > section:not(.hero):not(.cta),
  .v-contacto main > .vuelta { padding-left: 0; }
  .v-contacto main > .indice {
    grid-column: 1;
    /* `3 / span 50` y NO `3 / -1`. El −1 cuenta desde el final del grid
       EXPLÍCITO, y acá todas las filas son implícitas: resolvía a una línea
       anterior a la 3, el navegador lo daba vuelta y el índice terminaba
       encima del hero. Medido el 2026-08-13. El span sobra a propósito —hay
       6 filas de contenido— y las implícitas de más miden 0 porque no hay
       contenido ni `row-gap`. */
    grid-row: 3 / span 50;
    position: sticky; top: calc(var(--tope) + 1.5rem);
    padding: 3rem var(--canaleta) 3rem var(--canaleta);
  }
}
.indice { min-width: 0; }
.indice__rotulo {
  font-family: var(--mono, "Plex Mono", ui-monospace, monospace);
  font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--mute); margin: 0 0 0.75rem;
  border-bottom: 1px solid var(--pelo); padding-bottom: 0.5rem;
}
.indice__lista {
  list-style: none; margin: 0 0 1.5rem; padding: 0;
  counter-reset: idx;
  display: grid; gap: 0.15rem;
}
.indice__lista li { counter-increment: idx; }
.indice__lista a {
  font-family: var(--mono, "Plex Mono", ui-monospace, monospace);
  font-size: 0.78rem; line-height: 1.4;
  color: var(--cuerpo); text-decoration: none;
  display: block; padding: 0.3rem 0;
}
.indice__lista a::before {
  content: counter(idx, decimal-leading-zero) " · ";
  color: var(--acento);
}
.indice__lista a:hover { color: var(--acento); }
.indice__tel {
  margin: 0; padding: 0.9rem 1rem;
  background: var(--papel); border: 1px solid var(--pelo);
  display: grid; gap: 0.2rem;
}
.indice__tel span {
  font-family: var(--mono, "Plex Mono", ui-monospace, monospace);
  font-size: 0.68rem; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--mute);
}
.indice__tel a {
  font-family: var(--display); font-weight: 800; font-size: 1.15rem;
  letter-spacing: -0.01em; color: var(--tinta); text-decoration: none;
}
.indice__tel a:hover { color: var(--acento); }
/* En angosto el índice deja de ser índice: la página entra en dos pantallas y
   un menú de cinco anclas arriba del contenido es un obstáculo, no una ayuda. */
@media (max-width: 61.99rem) { .indice { display: none; } }

/* ── 3 · LAS SECCIONES SE NUMERAN ──────────────────────────────────────────
   Mismo mecanismo que `ficha`: el contador convierte el `::before` del H2 en
   el ordinal, sin tocar una etiqueta del HTML. `position: absolute` explícito
   porque tres de estos cinco H2 no están en la lista de filetes de la línea
   197, y sin eso el número sale inline pegado al texto. */
.v-contacto main { counter-reset: cficha; }
.v-contacto .contacto, .v-contacto .areas, .v-contacto .refuerzo,
.v-contacto .normativa, .v-contacto .faq { counter-increment: cficha; }
.v-contacto .contacto__h2, .v-contacto .areas__h2, .v-contacto .refuerzo__h2,
.v-contacto .normativa__h2, .v-contacto .faq__h2 {
  position: relative;
  padding-top: 0; padding-left: 3.5rem;
}
.v-contacto .contacto__h2::before, .v-contacto .areas__h2::before,
.v-contacto .refuerzo__h2::before, .v-contacto .normativa__h2::before,
.v-contacto .faq__h2::before {
  content: counter(cficha, decimal-leading-zero);
  position: absolute; top: 0.35em; left: 0;
  width: auto; height: auto; background: none;
  font-family: var(--mono, "Plex Mono", ui-monospace, monospace);
  font-size: 0.75rem; font-weight: 500; letter-spacing: 0.04em;
  color: var(--acento);
}
/* La FAQ es la única centrada del sitio, y su ordinal colgado a la izquierda
   la descentraba: acá el número va arriba, centrado con el título. */
.v-contacto .faq__h2 { padding-left: 0; }
.v-contacto .faq__h2::before { position: static; display: block; margin-bottom: 0.4rem; }

/* ── 4 · LOS TRES DATOS, EN CELDAS ─────────────────────────────────────────
   Un solo filete entre celdas y no una caja por celda: la maqueta usa el
   borde compartido, que es lo que las hace leer como una ficha y no como tres
   tarjetas sueltas. */
.contacto__grilla {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  border: 1px solid var(--pelo);
  margin-top: 1.75rem;
}
.contacto__dato {
  display: grid; gap: 0.25rem; align-content: start;
  padding: 1.5rem 1.6rem;
  border-right: 1px solid var(--pelo);
  text-decoration: none;
}
.contacto__dato:last-child { border-right: 0; }
a.contacto__dato:hover { background: var(--papel); }
.contacto__rotulo {
  font-family: var(--mono, "Plex Mono", ui-monospace, monospace);
  font-size: 0.68rem; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--mute);
}
.contacto__valor {
  font-family: var(--display); font-weight: 800; font-size: 1.5rem;
  letter-spacing: -0.02em; color: var(--tinta); font-style: normal;
}
/* El correo es largo y con el cuerpo del teléfono desborda la celda. */
.contacto__valor--email { font-weight: 700; font-size: 1rem; word-break: break-word; }
.contacto__direccion { font-size: 1rem; font-weight: 700; line-height: 1.45; }
.contacto__pie { font-size: 0.9rem; color: var(--mute); }

/* ── 5 · LAS CIUDADES, EN PÍLDORAS ─────────────────────────────────────────
   En la About la misma lista va en tabla, porque ahí acompaña a una foto y
   tiene que cerrar un bloque rectangular. Acá es una fila suelta y la píldora
   la deja respirar. La regla vive bajo `.v-contacto` para no tocar la tabla
   del Homepage ni la de la About, que comparten `.areas__lista`. */
.v-contacto .areas__lista {
  display: flex; flex-wrap: wrap; gap: 0.5rem;
  list-style: none; margin: 1.5rem 0 0; padding: 0;
  border-top: 0; text-align: left; width: auto;
}
.v-contacto .areas__lista li {
  background: var(--papel); border: 1px solid var(--pelo); border-bottom: 1px solid var(--pelo);
  padding: 0.5rem 1rem; border-radius: 100px;
  font-family: var(--display); font-weight: 600; font-size: 0.85rem;
  color: var(--tinta);
}

/* ── 6 · EL REFUERZO, CON SU FOTO VERTICAL ─────────────────────────────────
   3:4 y angosta: es la única foto de la página y compite con el formulario del
   hero, así que no puede pesar más que él. Sin `refuerzo_img` la §16 centra el
   bloque de texto y la sección queda como estaba. */
.refuerzo:has(.refuerzo__figura) {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 0.34fr);
  gap: clamp(2rem, 4vw, 3rem);
  align-items: start;
}
.refuerzo__figura { margin: 0; min-width: 0; }
.refuerzo__figura img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 3 / 4; object-fit: cover;
  border-radius: var(--radio);
}
@media (max-width: 56rem) {
  .refuerzo:has(.refuerzo__figura) { display: block; }
  .refuerzo__figura { margin-top: 2rem; }
}

/* ── 7 · LA FRANJA DE NORMATIVA, EN FILAS ETIQUETADAS ──────────────────────
   La grilla de dos columnas del sitio pasa a lista de filas con la etiqueta en
   mono a la izquierda: es lo que la maqueta hace y lo que deja leer los cinco
   hechos como una tabla de datos y no como cinco párrafos. */
.v-contacto .normativa__datos {
  display: block; max-width: none; margin-top: 2rem;
  border-top: 1px solid var(--pelo);
}
.v-contacto .normativa__dato {
  display: grid; grid-template-columns: 12.5rem minmax(0, 1fr);
  gap: 1.5rem; padding: 1.1rem 0;
  border-bottom: 1px solid var(--pelo);
}
.v-contacto .normativa__dato dt {
  font-family: var(--mono, "Plex Mono", ui-monospace, monospace);
  font-size: 0.68rem; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--mute);
}
.v-contacto .normativa__dato dd b { display: block; margin-bottom: 0.2rem; }
@media (max-width: 46rem) {
  .v-contacto .normativa__dato { grid-template-columns: 1fr; gap: 0.35rem; }
}

/* ── CIERRE DE LA PIEL `contacto` ──────────────────────────────────────────
   Esta media query va AL FINAL y no junto a la regla que corrige, y el motivo
   es orden de cascada: la primera versión la puso ARRIBA de la declaración
   base de `.hero__specs`, misma especificidad, así que la base la pisaba y los
   cuatro specs seguían saliendo en dos filas aunque la regla existiera y se
   leyera correcta. Un `@media` no gana por estar en un `@media`. */
@media (min-width: 62rem) {
  .v-contacto .hero__specs { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ══════════════════════════════════════════════════════════════════════════
   PIEL `contacto` · LA ESCALA — corregida el 2026-08-13 mirando la maqueta
   ══════════════════════════════════════════════════════════════════════════

   LA PRIMERA VERSIÓN TRASLADÓ EL LAYOUT Y NO LA ESCALA, y una ficha con la
   tipografía de una página de lectura deja de ser una ficha. Medido contra la
   maqueta a 1440, antes de tocar nada:

     H2 de sección    43,2 px  →  la maqueta pide 26     +66%
     H2 del formulario 43,2 px  →  24                     +80%
     subtítulo         23,0 px  →  17                     +35%
     párrafo y body    17,0 px  →  15                     +13%
     alto del hero     1.148 px →  sin alto mínimo        estirado una pantalla

   El teléfono (24), la píldora (13,6) y la pregunta de FAQ (18,4) ya estaban
   bien: no se tocan. Va al FINAL del archivo a propósito, por la trampa 2 del
   README de `diseno/contacto/`: un `@media` no gana por ser un `@media`, y una
   regla de escala tiene que ir después de la que corrige.

   LA CANALETA NO BAJA A LOS 24 px DE LA MAQUETA. Allá la cabecera también va a
   24; acá la comparten las 40 páginas y quedan a 72. Bajar solo el cuerpo
   dejaría el H1 desalineado de su propio logo y de su propio pie, que se ve
   peor que la diferencia de densidad. Es la única medida de la maqueta que no
   se copia, y es una decisión, no un olvido. */

/* ── El hero deja de ocupar la pantalla entera ─────────────────────────────
   `min-height: calc(100svh - var(--tope))` es la §7 del sitio: hero + franja
   de confianza = exactamente la primera pantalla. En una ficha de contacto eso
   estira 1.148 px de aire alrededor de un formulario que ya entra, y empuja la
   sección 01 abajo del pliegue. Acá el alto lo da el contenido. */
.v-contacto .hero { min-height: 0; padding-block: clamp(2rem, 3.5vw, 3rem); }

/* ── La escala de la maqueta ───────────────────────────────────────────────
   En px de la maqueta, escritos en rem sobre la raíz de 16: 15→0.9375,
   17→1.0625, 24→1.5, 26→1.625, 48→3. */
.v-contacto main { font-size: 0.9375rem; line-height: 1.65; }
.v-contacto main p,
.v-contacto main li,
.v-contacto main dd { font-size: 0.9375rem; }

.v-contacto .hero:has(.hero__form) .hero__h1 { font-size: clamp(1.875rem, 3.4vw, 3rem); }
.v-contacto .hero__sub { font-size: 1.0625rem; line-height: 1.55; }
.v-contacto .hero__spec dd { font-size: 1.0625rem; }

/* Los cinco H2 de sección, y el del formulario, que es el que más se pasaba. */
.v-contacto .contacto__h2, .v-contacto .areas__h2, .v-contacto .refuerzo__h2,
.v-contacto .normativa__h2, .v-contacto .faq__h2 { font-size: 1.625rem; }
.v-contacto .form__h2 { font-size: 1.5rem; }
/* El ordinal cuelga a 3.5rem del borde, que era la medida contra un H2 de 43.
   Con 26 px el número queda lejos y se despega del título. */
.v-contacto .contacto__h2, .v-contacto .areas__h2,
.v-contacto .refuerzo__h2, .v-contacto .normativa__h2 { padding-left: 2.5rem; }

/* El teléfono de las celdas y el del índice bajan con el resto: a 24 px contra
   un cuerpo de 15 la celda se lee como un cartel y no como un dato. */
.v-contacto .contacto__valor { font-size: 1.375rem; }
.v-contacto .contacto__pie,
.v-contacto .contacto__direccion { font-size: 0.9375rem; }

/* ── El ritmo vertical, también de la maqueta ──────────────────────────────
   Allá cada sección son 20 px arriba y 40 abajo, con el filete haciendo el
   corte. El ritmo del sitio es del doble porque está calculado para páginas de
   2.000 palabras, y ésta tiene 700. */
.v-contacto main > section { padding-block: 1.5rem 2.5rem; }
.v-contacto main > section > h2:first-child,
.v-contacto main > section > .refuerzo__texto > h2:first-child { margin-top: 0; }
/* El correo se pasó a 22 px con la regla de escala de arriba —`.v-contacto
   .contacto__valor` tiene más especificidad que `.contacto__valor--email`— y a
   ese cuerpo no entra en la celda: se partía en "…davie." / "com". Vuelve al
   cuerpo de texto y rompe por donde no deja una sílaba suelta. */
.v-contacto .contacto__valor--email { font-size: 0.95rem; overflow-wrap: anywhere; }

/* ══════════════════════════════════════════════════════════════════════════
   PIEL `contacto` · EL PASE 1 A 1 — 2026-08-13, segunda vuelta
   ══════════════════════════════════════════════════════════════════════════

   LA PRIMERA VUELTA TRASLADÓ EL LAYOUT, LA SEGUNDA LA ESCALA, Y ÉSTA LAS
   SUPERFICIES. Renderizadas la maqueta y la página una al lado de la otra a
   1440, lo que seguía distinto no era el tamaño de nada: era de qué color es
   cada franja y cuánto mide la canaleta del índice. Ocho diferencias, todas
   medidas contra el render y no contra el recuerdo:

     franja de confianza   oscura con filete de acento  →  papel, mono, centrada
     canaleta del índice   152 px de contenido          →  220, y el teléfono
                                                           dejaba de entrar
     columna del índice    fondo papel                  →  blanco
     filas de normativa    filete superior de acento    →  filete gris abajo
     frase de vuelta       franja papel a ancho completo→  blanco, dentro del
                                                           cuerpo, con su filete
     CIERRE                NO EXISTÍA                   →  ver contact.html
     FAQ                   pregunta a la izquierda      →  centrada
     hero                  foto de fondo                →  blanco

   VA AL FINAL DEL ARCHIVO, como los dos bloques de arriba y por el mismo
   motivo: corrige reglas que ya existen y un `@media` no gana por ser un
   `@media`. Ver la trampa 2 del README de `diseno/contacto/`.

   LO QUE SIGUE SIN COPIARSE, y ahora por pedido explícito del operador: la
   cabecera, la nav y el pie son los de este sitio. La maqueta trae los suyos
   —nav en minúsculas, botón "Call Now", pie a la izquierda— y son chrome de
   `_base.html`, compartido por las 40 páginas. */

/* ── El hero, sin foto de fondo ────────────────────────────────────────────
   La maqueta abre en blanco: el peso de la primera pantalla lo lleva el panel
   del formulario, y una foto detrás le compite el contraste justo donde hay
   que leer cinco campos.

   ═══ VUELVE EL FONDO, 2026-08-13 ═══ pedido del operador, después de mirar
   la página. El hero de la maqueta es blanco y esta piel lo había apagado; se
   vuelve a encender con un fondo NUEVO, generado para este slot: el frente de
   una casa de los 80 del sur de Florida desde la entrada de autos, que es el
   sujeto que `diseno/imagenes.md` ya tenía escrito para `fondo-contact` desde
   el 2026-08-10 y que nunca se había generado.

   LO QUE HABÍA ERA OTRA COSA. Hasta hoy el slot lo ocupaba una foto REAL de
   una reunión del equipo de Gaven: pared de ladrillo saturada, ocho personas
   de negro, un monitor encendido. Es una buena foto y no es un fondo: al 10%
   de opacidad deja un damero rojo detrás del H1 y no pertenece al set de los
   otros siete. Queda guardada en `diseno/imagenes-sin-usar/`.

   VA EN EL CSS Y NO EN EL .md, y la diferencia importa. `hero_bg` no lo
   decide la página: lo pone `build.py` por convención —`fondo-{slot}` si el
   archivo existe, líneas 957-981— así que tocar la clave del front matter no
   cambia nada y deja creer que sí. Para volver al hero blanco de la maqueta
   se agrega acá `.v-contacto .hero::before { content: none; }` y listo. */
.v-contacto .hero { padding-block: 2.5rem; }

/* ── El panel del formulario ───────────────────────────────────────────────
   28/30 de relleno, campo a 15 y etiqueta a 13, que es la densidad de un
   formulario de trabajo. El filete de acento del H2 se apaga: el panel ya
   tiene el suyo arriba, de 3 px y del mismo color. */
/* `margin: 0` explícito: el `.form` es un <section> y arrastra los 40 px de
   margen vertical que le corresponden cuando es una sección de la página. Acá
   es el contenido de un panel y esos 80 px salían del lado de adentro del
   borde, que es donde no se ven como margen sino como panel mal proporcionado. */
.v-contacto .hero__form .form { padding: 1.75rem 1.875rem; margin: 0; }
/* El filete se apaga y CON ÉL SU RELLENO. `padding-top: 1.5rem` vive en la
   regla que reparte el filete entre los 24 H2 del sitio (línea 190) y no se va
   solo: apagando únicamente el `::before` quedaban 24 px de aire arriba del
   titular más otros 24 de `margin-bottom` del `h2` genérico, y el panel salía
   ~45 px más alto que el de la maqueta con el mismo contenido adentro. */
.v-contacto .hero__form .form__h2 { padding-top: 0; margin-bottom: 0.25rem; }
.v-contacto .hero__form .form__h2::before { content: none; display: none; }
.v-contacto .hero__form .form__nota { font-size: 0.875rem; margin-bottom: 1rem; }
.v-contacto .hero__form .form__campos { gap: 0.875rem; }
/* GRILLA, y las otras dos formas se probaron y fallan. La columna flex del
   sitio deja el "optional" en su propia línea, y la maqueta lo quiere AL LADO
   del nombre del campo. Con `display: block` sí quedan en la misma línea, pero
   el espacio en blanco que sigue al <input> abre una segunda caja de línea y
   cada etiqueta engorda 16 px —medido: 96 contra los 72 de allá, por cuatro
   campos—. Con `flex-wrap` el campo no baja de línea: se desborda al lado del
   texto. La grilla es la única de las tres donde el texto suelto y el <span>
   son dos celdas de la primera fila, el campo abarca la segunda, y el espacio
   en blanco no genera ítem. Sin tocar el HTML del parcial, que lo comparten
   las 40 páginas. */
.v-contacto .hero__form .form__campos label {
  display: grid; grid-template-columns: max-content 1fr;
  align-items: baseline;
  /* `gap: 0 …` y no `column-gap`: el 0.4rem de la regla base es un `gap` de
     los dos ejes, así que declarar sólo la columna deja vivo el renglón y el
     campo queda separado de su etiqueta por ese hueco MÁS el margen de abajo.
     El aire lo pone el margen, que es el que la maqueta usa (6 px). */
  gap: 0 0.5rem;
  font-size: 0.8125rem;
}
.v-contacto .hero__form .form__campos label > input,
.v-contacto .hero__form .form__campos label > textarea {
  /* `align-self: start` saca al campo del grupo de línea base. Con el
     `baseline` heredado de la etiqueta —que existe para que el "optional" se
     apoye en el texto del rótulo— la fila del campo crecía a 67 px para
     acomodar una línea base que ahí abajo no alinea nada. Medido: 95 px de
     etiqueta contra los 72 de la maqueta. */
  align-self: start;
  /* El margen se declara ENTERO. `base.css` le da 1rem abajo a todo campo de
     formulario y con sólo `margin-top` esos 16 px sobreviven dentro de la
     etiqueta, invisibles: 88 px contra los 72 de la maqueta, cuatro veces. */
  grid-column: 1 / -1; margin: 0.375rem 0 0;
  /* `line-height: normal`, que es lo que el navegador le da a un campo por
     defecto y lo que la maqueta deja pasar. El 1.65 del cuerpo lo hereda el
     input y le suma 7 px de alto a cada uno; en el textarea de 4 filas son 25. */
  font-size: 0.9375rem; line-height: normal;
  padding: 0.75rem 0.875rem;
}
.v-contacto .hero__form .form__campos button {
  font-size: 0.9375rem; line-height: normal;
  padding: 0.9375rem 1.875rem;
  /* Sin borde, como el botón de la maqueta: el del sitio lleva 2 px del mismo
     color que el relleno, invisibles y sumando 4 px de alto. */
  border: 0;
}
.v-contacto .hero__form .form__opcional {
  font-family: var(--mono); font-size: 0.625rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--mute); margin-left: 0.5rem;
}

/* ── La franja de confianza: clara, no oscura ──────────────────────────────
   En el resto del sitio la franja es oscura y cierra la primera pantalla con
   un bloque de valor. Acá la primera pantalla ya la cierra el formulario, y
   una barra negra entre el panel y la sección 01 parte la página en dos justo
   donde tiene que seguir de largo. La maqueta la resuelve al revés: papel,
   mono, centrada, y el filete de abajo haciendo el corte. */
.v-contacto .trust {
  background: var(--papel);
  border-bottom: 1px solid var(--pelo);
}
.v-contacto .trust__item {
  padding: 1rem 1.25rem;
  border-left: 1px solid var(--pelo);
  font-family: var(--mono); font-weight: 400;
  font-size: 0.75rem; line-height: 1.4;
  color: var(--tinta);
  text-align: center;
  /* Las versalitas las pone el CSS y no el dato: los cuatro textos viven en
     `datos.json` y los comparten las 40 páginas. Escribirlos en mayúsculas
     ahí los rompería en las otras 39. */
  text-transform: uppercase; letter-spacing: 0.02em;
}
.v-contacto .trust__item:first-child { border-left: 0; padding-left: 1.25rem; }
/* El filete de acento sobre cada señal es del bloque oscuro: sobre papel son
   cuatro guiones naranjas sin nada que separar. */
.v-contacto .trust__item::before { content: none; display: none; }
/* Los dos quiebres de la franja, espejados acá. La regla de arriba pisa el
   `border-left` de la base en TODOS los anchos, así que sin esto la columna de
   1.080 y la fila única de 560 conservan un filete vertical suelto a la
   izquierda de cada señal: un palito de 40 px que no separa nada. Medido a
   500 px, que es donde el README de esta piel dice que se prueba. */
@media (max-width: 1080px) {
  .v-contacto .trust__item { border-top: 1px solid var(--pelo); }
  .v-contacto .trust__item:nth-child(-n+2) { border-top: 0; }
  .v-contacto .trust__item:nth-child(3) { border-left: 0; }
}
@media (max-width: 560px) {
  .v-contacto .trust__item { border-left: 0; border-top: 1px solid var(--pelo); }
  .v-contacto .trust__item:first-child { border-top: 0; }
}

/* ── El cuerpo: blanco hasta el pie ────────────────────────────────────────
   Las secciones ya eran blancas, pero `main` no, así que la columna del índice
   —que es `main` y no una sección— salía en papel y dibujaba una banda gris de
   toda la altura de la página contra la que nada estaba alineado. */
.v-contacto main { background: var(--blanco); }

/* ── La canaleta del índice: 220 px de contenido, como la maqueta ──────────
   Con 14rem el contenido quedaba en 152 y pasaban las dos cosas que se ven en
   el render: los ítems de dos palabras partían en dos líneas y el teléfono se
   salía de su caja por la derecha. 17rem menos los 48 del gap dan los 220.

   Y el `top` del pegajoso baja a 1.5rem. Estaba en `--tope`, que son los 240
   px de la primera pantalla completa —topbar + cabecera + franja—, y esa
   cuenta solo sirve si la cabecera es pegajosa. No lo es: decisión del
   operador del 2026-08-10. Así, al scrollear, el índice quedaba clavado a un
   cuarto de pantalla del borde. */
@media (min-width: 62rem) {
  .v-contacto main { grid-template-columns: calc(var(--canaleta) + 17rem) minmax(0, 1fr); }
  .v-contacto main > .indice {
    padding: 2rem 3rem 2rem var(--canaleta);
    top: 1.5rem;
  }
}
.indice__tel a { font-size: 1.1875rem; }
.indice__tel span { font-size: 0.6875rem; }
.indice__tel small { font-size: 0.75rem; color: var(--mute); }

/* El ordinal pegado al título. 2.5rem era la medida contra un H2 de 43 px; con
   26 el número queda flotando y deja de leerse como parte del titular. La
   maqueta los separa 14 px. */
.v-contacto .contacto__h2, .v-contacto .areas__h2,
.v-contacto .refuerzo__h2, .v-contacto .normativa__h2 { padding-left: 2rem; }

/* ── Los tres datos: la escala exacta de la ficha ──────────────────────────
   El teléfono a 24 y el correo y la dirección a 16, que es la jerarquía que
   hace que la celda del medio no compita con la primera. */
.v-contacto .contacto__dato { padding: 1.5rem 1.625rem; }
.v-contacto .contacto__valor { font-size: 1.5rem; }
.v-contacto .contacto__valor--email { font-size: 1rem; }
.v-contacto .contacto__direccion { font-size: 1rem; line-height: 1.45; }
.v-contacto .contacto__pie { font-size: 0.875rem; }

/* ── Las píldoras y el enlace al hub ───────────────────────────────────────
   La píldora va en la tipografía de TEXTO, no en la display: son nueve
   nombres de ciudad seguidos y en Archivo 600 se leen como nueve botones.
   Y el enlace de abajo vuelve a ser un enlace: `enlace-fuerte` es el ancla
   gruesa de las páginas de dinero, y acá compite con las píldoras que tiene
   justo encima. */
.v-contacto .areas__lista li {
  font-family: var(--texto); font-weight: 400; font-size: 0.8125rem;
}
.v-contacto .areas .enlace-fuerte {
  font-weight: 400; border-bottom: 0;
  color: var(--acento-osc); text-decoration: underline;
  text-underline-offset: 2px;
}
.v-contacto .areas .enlace-fuerte:hover { color: var(--acento); }
.v-contacto .areas__lista + p { margin-top: 1rem; }

/* ── El refuerzo: la foto a 300 px fijos ───────────────────────────────────
   Con `0.34fr` la columna se movía con el ancho de la ventana y a 1440 daba
   260: la foto salía más angosta que en la maqueta y el texto más largo que
   sus 74ch. La maqueta la fija, y una foto de acompañamiento es exactamente
   el caso donde eso es correcto. */
@media (min-width: 56.01rem) {
  .v-contacto .refuerzo:has(.refuerzo__figura) {
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: 2rem;
  }
}

/* ── Las filas de normativa: filete gris abajo, no de acento arriba ────────
   `.v-contacto .normativa__dato` ya declaraba el filete de abajo, pero el
   `border-top: 2px solid var(--acento)` de la regla base seguía vivo: las
   cinco filas salían con una línea naranja gruesa encima. Se apaga acá y no
   allá, que es la regla de toda la piel. */
.v-contacto .normativa__dato {
  border-top: 0;
  padding: 1.125rem 0;
  grid-template-columns: 12.5rem minmax(0, 1fr);
  gap: 1.5rem;
}
.v-contacto .normativa__dato dt { font-size: 0.6875rem; margin-bottom: 0; }
.v-contacto .normativa__dato dd b { font-size: 1.0625rem; margin-bottom: 0.25rem; }
.v-contacto .normativa__dato dd { font-size: 0.9375rem; }
/* Los dos párrafos de arriba corrían los 992 px de la columna: a 15 px eso son
   ~150 caracteres por línea y el ojo pierde el renglón al volver. La maqueta
   los capa en 76ch, que es el único tope de medida que declara.

   Y EL WRAPPER SE SUELTA. `__texto` cae bajo la regla §16 —«sin foto, bloque
   centrado a 62rem»—, que acá desplazaba la sección 16 px a la derecha de las
   otras cuatro: el `04` arrancaba en x=360 contra los 344 del `01`, `02` y
   `03`. Con el tope en el párrafo, el H2 y la tabla vuelven al eje. */
.v-contacto .normativa__texto { max-width: none; margin-inline: 0; }
/* El selector va largo A PROPÓSITO. La §16 suelta la medida de los hijos del
   `__texto` con `main > section:not(.cta):not(:has(figure)) > [class$="__texto"] > *`,
   que pesa (0,2,3): un `.v-contacto .normativa__texto > p` pesa (0,2,1) y
   pierde, aunque esté 4.000 líneas más abajo. */
.v-contacto main > .normativa > .normativa__texto > p { max-width: 76ch; }
.v-contacto .normativa__dato dd span { max-width: 70ch; }

/* ── La FAQ: centrada, como el resto de la sección ─────────────────────────
   El sitio alinea el acordeón a la izquierda a propósito —una pregunta
   centrada con el signo a la derecha se lee torcida— y la maqueta hace lo
   contrario: las cinco preguntas centradas bajo un título centrado, que es lo
   único coherente cuando el H2 ya lo está.

   EL `+` SE QUEDA, y es la única pieza de esta sección que no es de la
   maqueta. Allá el `<details>` no tiene ninguna marca de que abre, y eso en
   una maqueta se perdona porque nadie la va a usar. Acá es el único
   afijo que dice que la pregunta se despliega. Se saca del flujo con
   `position: absolute` para que no le robe el centro al texto, que es lo que
   hacía el `margin-left: auto`. */
.v-contacto .faq__lista { max-width: 51.25rem; }
.v-contacto .faq__item { text-align: center; }
.v-contacto .faq__pregunta {
  position: relative;
  justify-content: center;
  padding: 1rem 2.5rem;
  font-size: 1.0625rem;
}
.v-contacto .faq__pregunta::after {
  position: absolute; right: 0; top: 1rem;
  margin-left: 0;
}
.v-contacto .faq p.faq__respuesta {
  margin: 0.75rem auto 1rem; max-width: 74ch;
  text-align: center;
}

/* ── La frase de vuelta: dentro del cuerpo, en blanco ──────────────────────
   En el resto del sitio va entre el CTA oscuro y el pie oscuro, y por eso
   lleva su propia franja de papel: es lo que la separa de las dos. Acá el CTA
   es claro, así que la franja no separa nada y sí agrega una tercera
   superficie gris. La maqueta la deja adentro de la columna de contenido, en
   blanco, con el mismo filete que corta las cinco secciones. */
.v-contacto .vuelta {
  background: var(--blanco);
  border-top: 1px solid var(--pelo);
  max-width: none;
  padding: 1.25rem 0 2.5rem;
}
.v-contacto .vuelta > p { max-width: 74ch; margin-inline: auto; }

/* ── EL CIERRE ─────────────────────────────────────────────────────────────
   El CTA del sitio es oscuro y va PEGADO al pie: dos superficies del mismo
   valor que leen como una sola pieza. La maqueta lo resuelve al revés, y en
   esta página tiene razón: la franja de confianza de arriba ya es papel, así
   que el cierre en papel cierra el paréntesis que abrió la primera pantalla,
   y el pie oscuro queda como el único bloque oscuro de la página.

   Los dos `!important` NO son un atajo: la regla base los usa, y sin ellos
   esto no la pisa. */
.v-contacto .cta {
  background: var(--papel) !important;
  border-top: 1px solid var(--pelo) !important;
  padding-block: 3.25rem;
}
.v-contacto .cta__h2 {
  color: var(--tinta);
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  max-width: 28ch;
}
.v-contacto .cta__texto {
  color: var(--cuerpo); max-width: 60ch;
  font-size: 0.9375rem; margin-bottom: 1.5rem;
}
.v-contacto .cta .btn--primario { background: var(--acento); color: var(--blanco); }
.v-contacto .cta .btn--primario:hover { background: var(--acento-osc); color: var(--blanco); }

/* ── LA GALERÍA, QUE NO ESTÁ EN LA MAQUETA ─────────────────────────────────
   Entró a `contact.html` desde afuera de este traslado. No se saca, pero
   entraba con el H2 a 43 px contra los 26 de los otros cinco, que es la misma
   diferencia que esta piel vino a corregir en todo lo demás.

   NO SE NUMERA, y es a propósito. El contador `cficha` corre sobre las cinco
   secciones del índice y el índice sólo lista esas cinco: darle ordinal
   correría la FAQ a 06 y dejaría el índice mintiendo. Se marca con el filete
   de acento que ya trae, que es lo que usan las secciones sin número en el
   resto del sitio. */
.v-contacto .galeria__h2 { font-size: 1.625rem; }

/* ══════════════════════════════════════════════════════════════════════════
   PIEL `contacto` · TODO CENTRADO — decisión del operador, 2026-08-13
   ══════════════════════════════════════════════════════════════════════════

   ESTO SE APARTA DE LA MAQUETA A PROPÓSITO, y queda escrito para que la
   próxima sesión no lo lea como un error de traslado. "Contacto Ficha" trae
   las cinco secciones alineadas a la izquierda y centra sólo la FAQ; el
   pedido fue centrar TODAS —título y contenido—, con la FAQ como referencia
   de cómo se ve.

   PARA REVERTIR: se borra este bloque entero y la página vuelve a la maqueta.
   No toca nada de lo de arriba.

   EL ÍNDICE NO ENTRA. Es la canaleta, no una sección: centrar una lista de
   cinco anclas en una caja de 220 px la deja sin eje contra el que leer los
   ordinales, que es lo único que la hace escaneable. */

/* ── Los encabezados: el ordinal arriba, como el de la FAQ ─────────────────
   El número dejaba de colgar a la izquierda y pasa a ser una línea propia
   sobre el título. Es exactamente lo que la FAQ ya hacía, y por eso era la
   sección que se veía distinta: ahora es la regla y no la excepción. */
.v-contacto .contacto__h2, .v-contacto .areas__h2, .v-contacto .refuerzo__h2,
.v-contacto .normativa__h2, .v-contacto .faq__h2, .v-contacto .galeria__h2 {
  text-align: center; padding-left: 0;
  margin-inline: auto; width: fit-content;
}
.v-contacto .contacto__h2::before, .v-contacto .areas__h2::before,
.v-contacto .refuerzo__h2::before, .v-contacto .normativa__h2::before {
  position: static; display: block;
  margin-bottom: 0.4rem;
}
/* La galería no tiene ordinal: lleva el filete de acento, que también se
   centra. Sin `left: 50%` seguía naciendo en el borde izquierdo del título. */
.v-contacto .galeria__h2::before { left: 50%; transform: translateX(-50%); }

/* ── 01 · Las tres celdas ──────────────────────────────────────────────────
   `justify-items` además de `text-align`: la celda es una grilla y el rótulo
   en mono es más angosto que el número, así que sin esto el texto se centra
   pero las cajas quedan pegadas a la izquierda. */
.v-contacto .contacto__dato { justify-items: center; text-align: center; }

/* ── 02 · Las píldoras y el enlace al hub ──────────────────────────────── */
.v-contacto .areas__lista { justify-content: center; }
/* `max-width: none` además del centrado: el <p> hereda el tope de medida de
   68ch, así que centrar el TEXTO lo centraba dentro de una caja que arrancaba
   pegada a la izquierda y el enlace quedaba a 240 px del centro real. */
.v-contacto .areas__lista + p { text-align: center; max-width: none; }

/* ── 03 · El refuerzo ──────────────────────────────────────────────────────
   La medida se conserva en 74ch y el bloque se centra: sin el tope, centrar
   un párrafo de 700 px de ancho deja las dos primeras líneas largas y la
   última corta en el medio, que es el efecto que hace ver desprolijo un
   texto centrado. */
.v-contacto .refuerzo__texto { text-align: center; }
/* El selector va largo por la misma razón que el de normativa, y desde que la
   sección se quedó sin foto: `:not(:has(figure))` empezó a matchear y la §16
   suelta la medida de los hijos del `__texto` con (0,2,3). Sin esto los tres
   párrafos corren los 992 px de la columna centrados, que es la peor de las
   dos opciones: centrado Y largo. */
.v-contacto main > .refuerzo > .refuerzo__texto > p { max-width: 74ch; margin-inline: auto; }
/* EL TÍTULO TIENE QUE SALIR DE LA COLUMNA. El H2 vive dentro de `__texto`, que
   es la primera columna, así que centrado quedaba sobre el texto y no sobre la
   sección: 200 px a la izquierda del `01`, del `02` y del `04`, que es
   justamente lo desprolijo que había que arreglar.

   `display: contents` disuelve el wrapper y sus hijos pasan a ser ítems de la
   grilla de la sección. Ahí el H2 abarca las dos columnas, los párrafos caen
   en la primera y la foto abarca las filas de la segunda. Es la estructura que
   la maqueta tiene escrita en el HTML —el encabezado FUERA del div de dos
   columnas— sin tocar el parcial, que lo comparte con `about.html`. */
@media (min-width: 56.01rem) {
  .v-contacto .refuerzo:has(.refuerzo__figura) { gap: 0 2rem; }
  .v-contacto .refuerzo:has(.refuerzo__figura) .refuerzo__texto { display: contents; }
  .v-contacto .refuerzo:has(.refuerzo__figura) .refuerzo__h2 { grid-column: 1 / -1; }
  .v-contacto .refuerzo:has(.refuerzo__figura) .refuerzo__figura {
    grid-column: 2; grid-row: 2 / span 50;
  }
}

/* ── 04 · La tabla de normativa pasa a fichas apiladas ─────────────────────
   Las filas de dos columnas —rótulo a la izquierda, dato a la derecha— no se
   pueden centrar: centrar cada celda por separado deja dos ejes y se lee
   torcido, que es la misma razón por la que el sitio alinea su acordeón a la
   izquierda. Centradas, las cinco se apilan: rótulo arriba, dato debajo. Es
   la forma que ya usa `.t-gbp_service.v-ficha` para lo mismo. */
.v-contacto .normativa__texto { text-align: center; }
.v-contacto main > .normativa > .normativa__texto > p { margin-inline: auto; }
.v-contacto .normativa__dato {
  grid-template-columns: minmax(0, 1fr);
  gap: 0.35rem; text-align: center;
}
/* El tope va en el `dd` y no en un `span`: la descripción no está envuelta
   —el parcial escribe `<b>dato</b> texto suelto`— así que lo único que se
   puede capar es la celda entera. Sin esto la última fila corre 1.000 px de
   ancho contra las 70ch de las otras. */
.v-contacto .normativa__dato dd { max-width: 70ch; margin-inline: auto; }

/* ── La galería: cabecera en columna y pies centrados ──────────────────────
   La cabecera es un `space-between` con el título a la izquierda y las
   flechas a la derecha. Centrar sólo el título lo dejaría descolgado de sus
   propios controles: van los dos al centro, uno debajo del otro. */
.v-contacto .galeria__cabecera { flex-direction: column; align-items: center; }
.v-contacto .galeria__pie { text-align: center; }

/* ═══ EL PIE DE TRES COLUMNAS, CON EL MAPA AL MEDIO ══════════════════════
   Decisión del operador, 2026-08-13: NAP · mapa · Quick Links, una sola fila
   pareja.

   `flex: 1 1 0` y NO el `0 1 340px` de antes. El corte de fila en flex se
   decide con la BASE, no con el ancho final: con base 340 y la separación de
   9vw, tres columnas piden 1.279 px y a 1.366 —un portátil cualquiera— no
   entraban, así que la tercera se caía sola a una segunda fila. Con base 0 la
   fila nunca se parte por aritmética, y el `min-width` es el que decide
   cuándo conviene partirla: por debajo de ~900 px de contenido las tres no
   llegan a 240 px cada una y ahí sí envuelven, que es lo que se quiere.

   De paso quedan IGUALES. Con base fija cada columna medía lo que su
   contenido dejaba y las tres arrancaban en un sitio distinto.

   `min-width` pisa a propósito el `.site-footer > * { min-width: 0 }` de
   arriba: aquél existe para que un bloque no desborde, y acá es justamente el
   número el que manda el corte.

   El filo claro no es adorno: el mapa es lo único brillante sobre `--pie`
   oscuro y sin él el recorte blanco flota. Es el mismo `--pelo-osc` que
   separa el copyright.

   Va al final del archivo a propósito: se agregó el 2026-08-13, con otra
   sesión editando las reglas del pie más arriba. */
.site-footer__datos,
.site-footer__links,
.site-footer__mapa { flex: 1 1 0; min-width: 240px; }

/* Privacy Policy YA NO es columna. Como cuarto bloque rompía la fila de tres
   y dejaba un huérfano en la segunda: a ancho completo cae en su propia
   franja, arriba del copyright, que es donde vive un enlace legal. */
.site-footer__legales { flex: 0 0 100%; }

.site-footer__mapa iframe {
  height: 220px;
  border: 1px solid var(--pelo-osc);
  border-radius: var(--radio);
}


/* ══════════════════════════════════════════════════════════════════════════
   LA PÁGINA LEGAL EN PIEL `ficha` — `.t-utility.v-ficha`
   ══════════════════════════════════════════════════════════════════════════

   DE DÓNDE SALE. `Privacidad Ficha.dc.html`, del proyecto de diseño del
   usuario. Es la variante `ficha` en la única página que no vende nada: se
   lee salteando, y el layout tiene que dejar salir con la respuesta sin
   leerla entera.

   ⚠ LO QUE ESTE BLOQUE **NO** HACE, Y ES LO IMPORTANTE. No declara ni una
   regla de layout: la caja de 1.320, la canaleta de 60, la columna del índice
   de 220 con su hueco de 48, el hero a sangre y el ritmo vertical de 40 ya
   estaban resueltos arriba para `location_page`, y desde el 2026-08-14 esas
   129 reglas dicen `:is(.t-location_page, .t-utility)`. Ampliar el alcance no
   le cambia una sola propiedad a la location page —`:is()` toma la
   especificidad de su argumento más específico, o sea la misma de antes— y le
   da a la legal el mismo contenedor.

   POR QUÉ SE ESCRIBE ASÍ Y NO CON UNA GRILLA PROPIA. La primera versión de
   esta piel declaraba su propio `grid-template-columns` en `main`. Pisaba la
   grilla con nombres del sitio, así que `full-start` y `cont-start` dejaban de
   existir, el hero caía en su caja centrada de 1.136 y las secciones volvían a
   su relleno de 72. Resultado medido: H1 en x=224, índice en x=72 y cuerpo en
   x=360 — tres bordes izquierdos distintos en una página que tiene dos. Lo
   cazó el usuario mirando, no un bloque de verificar.py.

   NINGÚN COLOR NUEVO. Los que usa la maqueta ya viven en `:root` y ya están
   medidos en `diseno/contraste.md`. La mono es la misma `--mono`. */

/* ── 1 · EL HERO: LA FICHA CONTRA EL BORDE DERECHO ─────────────────────────
   La maqueta pone H1 y bajada a la izquierda y los cuatro datos en una
   columna angosta a la derecha, alineados por abajo. El parcial dibuja los
   specs DENTRO de `.hero__texto`, así que la segunda columna se abre ahí.

   `.hero__texto` ocupa las dos columnas del hero porque esta página no tiene
   figura: si se quedara en la primera, la ficha caería a media caja en vez de
   contra el borde derecho del contenido.

   Las tres filas se declaran para que el `1 / -1` del `<dl>` signifique algo:
   sin `grid-template-rows` la grilla explícita tiene una sola línea, `-1`
   resuelve a la fila 1 y la ficha se apoya arriba en vez de abarcar. */
/* LA MEDIDA DE LECTURA, UNA SOLA VEZ Y EN REM.
   Antes era `74ch` repetido en cada regla, que es lo que la piel de servicio
   usa. No sirve para centrar: `ch` se mide contra la fuente DEL ELEMENTO, así
   que 74ch de prosa dan 755 px y 74ch del H2 —Archivo, 1.75rem, bold— dan más
   que la columna entera. El resultado era el texto centrado y el encabezado a
   todo lo ancho, o sea peor que antes. En rem los seis bloques miden igual.
   47rem = 752 px, que son los mismos 74ch de la prosa medidos. */
.t-utility.v-ficha { --legal-medida: 47rem; }

.t-utility.v-ficha .hero__texto {
  grid-column: 1 / -1;
  max-width: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 19rem);
  grid-template-rows: auto auto auto;
  column-gap: 48px;
  align-items: end;
}
.t-utility.v-ficha .hero__rotulo,
.t-utility.v-ficha .hero__h1,
.t-utility.v-ficha .hero__sub { grid-column: 1; }

/* El CTA del hero se va, y es lo único que le saco a la maqueta sin dudar:
   dos botones de "Call Now" arriba de una política la convierten en landing.
   El teléfono sigue en la barra, la cabecera, la tarjeta del índice, la
   sección 07 y el pie. */
.t-utility.v-ficha .hero__acciones { display: none; }

/* ── 2 · LOS CUATRO DATOS, EN VERTICAL ─────────────────────────────────────
   La piel de servicio los dibuja en FILA con filete vertical: ahí son specs
   de un material y se comparan de a pares. Acá son las cuatro preguntas que
   cualquiera le hace a una política —desde cuándo, quién los tiene, los
   venden, los borran— y se leen de arriba abajo. */
.t-utility.v-ficha .hero__specs {
  grid-column: 2; grid-row: 1 / -1;
  align-self: end;
  margin: 0;
  display: flex; flex-direction: column;
  border-top: 1px solid var(--pelo);
}
.t-utility.v-ficha .hero__spec {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem;
  padding: 0.7rem 0;
  border-right: 0; border-bottom: 1px solid var(--pelo);
}
.t-utility.v-ficha .hero__spec:last-child { border-bottom: 0; }
.t-utility.v-ficha .hero__spec dt { text-transform: uppercase; }
.t-utility.v-ficha .hero__spec dd { margin: 0; font-size: 0.95rem; }
/* "Never" en acento: es la única de las cuatro respuestas que es una NEGATIVA
   y es la que el visitante vino a buscar. Va por posición porque el `<dl>` no
   distingue una fila de otra; si se reordenan los specs, esta regla se muda
   con la fila que niega. */
.t-utility.v-ficha .hero__spec:nth-child(3) dd { color: var(--acento); }

/* ── 3 · LAS SIETE SECCIONES, NUMERADAS ────────────────────────────────────
   Mismo mecanismo que las otras dos pieles `ficha`: el ordinal es un contador
   y el `::before` del H2, así que sacar o agregar una sección en el .md
   renumera sola. La apertura y el pie de vigencia NO cuentan: son la bajada
   del H1 y el cierre del documento, no capítulos.

   ⚠ EL `:not()` VA EN LA REGLA DEL CONTADOR, no en una corrección más abajo.
   El primer intento fue un `counter-increment: none` al final del archivo y
   no hizo nada: esta regla lleva cinco clases contando las de los `:not()` y
   una de tres no le gana por venir después. */
.t-utility.v-ficha main { counter-reset: legal; }
.t-utility.v-ficha .legal:not(.legal__apertura):not(.legal__meta) {
  counter-increment: legal;
}
.t-utility.v-ficha .legal__h2 {
  position: relative;
  padding-top: 20px; padding-left: 3.2rem;
  max-width: var(--legal-medida);
  margin: 0 auto 14px;
  font-size: clamp(1.35rem, 2.2vw, 1.75rem); letter-spacing: -0.022em;
}
.t-utility.v-ficha .legal__h2::before {
  content: counter(legal, decimal-leading-zero);
  position: absolute; top: 1.45em; left: 0;
  width: auto; height: auto; background: none;
  font-family: var(--mono);
  font-size: 0.75rem; font-weight: 400; letter-spacing: 0.06em;
  color: var(--acento);
}
/* La FAQ va DESPUÉS del documento y fuera de su numeración. La regla de la
   piel de servicio le pone ordinal a todo `.faq__h2` de un `.v-ficha`, así
   que acá se apaga en vez de contarla. */
.t-utility.v-ficha .faq__h2 { padding-left: 0; }
.t-utility.v-ficha .faq__h2::before { content: none; }

/* Filete entre secciones, y superficie plana. La alternancia papel/blanco le
   da ritmo al resto del sitio; en un documento que se escanea compite con la
   única jerarquía que importa, que es la numeración. */
.t-utility.v-ficha main > section.legal { background: var(--blanco); }
.t-utility.v-ficha main > section.legal + section.legal {
  border-top: 1px solid var(--pelo);
}

/* ── 4 · LA APERTURA ES LA BAJADA ──────────────────────────────────────────
   Filete lateral de acento y sin número, igual que en la piel de servicio.
   Acá además es la frase que dice QUIÉN es "nosotros", que en un sitio de
   marca con otra empresa detrás es el dato más importante de la página. */
.t-utility.v-ficha .legal__apertura > p:first-of-type {
  font-size: 1.1rem; line-height: 1.55; color: var(--tinta);
  border-left: 3px solid var(--acento);
  padding-left: 1.25rem;
  max-width: var(--legal-medida);
  margin-inline: auto;
}

/* ── 5 · LAS LISTAS SON FILAS, NO VIÑETAS ──────────────────────────────────
   Lo que enumera una política es lo que el negocio tiene de vos y lo que hace
   con eso: la maqueta lo trata como un inventario, con filete por renglón y
   un punto de acento en la canaleta. Se lee contando, que es como se lee. */
.t-utility.v-ficha .legal ul {
  margin: 0 auto 1.1rem; padding: 0;
  list-style: none;
  border-top: 1px solid var(--pelo);
  max-width: var(--legal-medida);
}
.t-utility.v-ficha .legal ul li {
  position: relative;
  margin: 0;
  padding: 0.7rem 0 0.7rem 1.15rem;
  border-bottom: 1px solid var(--pelo);
}
.t-utility.v-ficha .legal ul li::before {
  content: "·";
  position: absolute; left: 0; top: 0.7rem;
  color: var(--acento);
}
.t-utility.v-ficha .legal p { max-width: var(--legal-medida); margin-inline: auto; }

/* ── 6 · LA PROMESA QUE SE LEE SIN LEER ────────────────────────────────────
   "No vendemos tus datos" es la única frase de la página que alguien busca a
   propósito, y en la maqueta es lo único que sale del ritmo del texto.

   SE TOMA POR FORMA Y NO POR POSICIÓN: es el párrafo que el .md escribió
   entero en negrita, o sea un `<p>` con un `<strong>` como único hijo. Un
   `p:last-of-type` habría atado la piel al orden de los párrafos y se rompía
   el día que alguien agrega una aclaración después. */
.t-utility.v-ficha .legal p:has(> strong:only-child) {
  max-width: var(--legal-medida);
  margin: 1.3rem auto 0;
  background: var(--papel);
  border-left: 3px solid var(--acento);
  padding: 1.1rem 1.35rem;
}
.t-utility.v-ficha .legal p:has(> strong:only-child) strong {
  font-family: var(--display); font-weight: 700;
  font-size: 1.05rem; line-height: 1.45; color: var(--tinta);
}

/* ── 7 · EL BLOQUE DE CONTACTO ─────────────────────────────────────────────
   Dos y dos, con el filete de arriba en acento: es el único borde de 3px de
   la página y marca dónde termina la lectura y empieza la acción. Con el
   `auto-fit` que tenía antes entraban tres en los 792 de la columna y la
   cuarta celda quedaba huérfana en su propia fila. */
.t-utility.v-ficha .legal__datos {
  margin-inline: auto;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 1px solid var(--pelo);
  border-top: 3px solid var(--acento);
  max-width: var(--legal-medida);
}
.t-utility.v-ficha .legal__dato {
  padding: 1.15rem 1.3rem;
  border-right: 1px solid var(--pelo);
  border-bottom: 1px solid var(--pelo);
  display: flex; flex-direction: column; gap: 0.2rem;
}
.t-utility.v-ficha .legal__dato:nth-child(2n) { border-right: 0; }
.t-utility.v-ficha .legal__dato:nth-last-child(-n+2) { border-bottom: 0; }
.t-utility.v-ficha .legal__dato dt {
  font-family: var(--mono); font-size: 0.68rem;
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--mute);
}
.t-utility.v-ficha .legal__dato dd {
  margin: 0;
  font-family: var(--display); font-weight: 700; font-size: 0.95rem;
  color: var(--tinta);
}
.t-utility.v-ficha .legal__dato dd a { color: var(--tinta); text-decoration: none; }
.t-utility.v-ficha .legal__dato dd a:hover { color: var(--acento); }
.t-utility.v-ficha .legal__dato address { font-style: normal; line-height: 1.45; }

/* ── 8 · EL PIE DEL DOCUMENTO ──────────────────────────────────────────────
   La vigencia en mono y en gris: cierra sin competir con nada. Es el
   tratamiento de la maqueta y el de cualquier texto legal impreso. */
.t-utility.v-ficha .legal__meta { border-top: 1px solid var(--pelo); }
.t-utility.v-ficha .legal__vigencia,
.t-utility.v-ficha .legal__fecha {
  margin-inline: auto; max-width: var(--legal-medida);
  font-family: var(--mono); font-size: 0.75rem; line-height: 1.7;
  color: var(--mute);
}

/* ── 9 · TELÉFONO ──────────────────────────────────────────────────────────
   El colapso a una columna lo hace la grilla del sitio. Acá sólo la ficha del
   hero, que con `space-between` no tiene de dónde sacar el ancho: "SOLD TO
   THIRD PARTIES" se come la línea y el valor se salía de la pantalla. Debajo
   de 40rem el par se apila, que es como se lee una ficha en papel angosto. */
@media (max-width: 62rem) {
  /* LA MEDIDA DE LECTURA, UNA SOLA VEZ Y EN REM.
   Antes era `74ch` repetido en cada regla, que es lo que la piel de servicio
   usa. No sirve para centrar: `ch` se mide contra la fuente DEL ELEMENTO, así
   que 74ch de prosa dan 755 px y 74ch del H2 —Archivo, 1.75rem, bold— dan más
   que la columna entera. El resultado era el texto centrado y el encabezado a
   todo lo ancho, o sea peor que antes. En rem los seis bloques miden igual.
   47rem = 752 px, que son los mismos 74ch de la prosa medidos. */
.t-utility.v-ficha { --legal-medida: 47rem; }

.t-utility.v-ficha .hero__texto { grid-template-columns: minmax(0, 1fr); }
  .t-utility.v-ficha .hero__specs {
    grid-column: 1; grid-row: auto;
    margin-top: 1.25rem;
  }
}
@media (max-width: 40rem) {
  .t-utility.v-ficha .hero__spec {
    flex-direction: column; align-items: flex-start;
    gap: 0.15rem;
  }
  .t-utility.v-ficha .hero__spec dd { font-size: 1rem; }
  .t-utility.v-ficha .legal__datos { grid-template-columns: minmax(0, 1fr); }
  .t-utility.v-ficha .legal__dato { border-right: 0; }
  .t-utility.v-ficha .legal__dato:nth-last-child(-n+2) { border-bottom: 1px solid var(--pelo); }
  .t-utility.v-ficha .legal__dato:last-child { border-bottom: 0; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   SUPPORTING CONTENT — EL ESQUELETO DEL TIPO Y SUS DOS PIELES
   2026-08-15 · trasladadas de `Soporte Bandas.dc.html` y `Soporte Mosaico.dc.html`

   POR QUÉ HAY UN BLOQUE BASE ANTES DE LAS DOS VARIANTES. Las clases `.sc__*`
   no existían en esta hoja: una pieza sin `variante` en su front matter salía
   con el H1 y la respuesta al tamaño del cuerpo y el `<article>` pegado al
   borde. El bloque base la deja publicable sola; las variantes la visten.

   ⚠ TODO VA SCOPEADO CON `.t-supporting_content`, SIN EXCEPCIÓN. `v-mosaico`
   YA EXISTE en esta hoja: son 108 selectores de `location_page`, y los 108
   llevan su tipo adelante. Un `.v-mosaico` pelado acá le caería encima a cinco
   páginas geográficas ya cerradas. Se midió antes de escribir una línea.

   LOS COLORES SALEN DE LOS TOKENS, NO DE LA MAQUETA. Mosaico ya venía con los
   hexadecimales del sitio. Bandas trae cuatro corridos por un pelo —#fbfaf8
   contra `--papel`, #17171a contra `--tinta`, #6b6b73 contra `--mute`, #e2e0db
   contra `--pelo`— y se toman los del sitio: la diferencia no se ve y un color
   sin par de contraste declarado deja ciego al bloque C de `verificar.py`.

   LO QUE LAS MAQUETAS DIBUJAN Y ACÁ NO ESTÁ, Y ES A PROPÓSITO:
   · La barra de confianza de 4 celdas bajo el hero. Es el parcial
     `trust_badges` y esta plantilla no lo incluye. Meterlo es cambiar la
     plantilla del modelo, no la piel.
   · El rótulo «Timelines · Davie, FL» sobre el H1. No hay dato que lo alimente
     en este tipo; inventarlo en CSS sería texto que ningún bot lee.
   · El CTA en terracota. Las dos maquetas lo pintan así y acá queda en
     `--profunda`, que es lo que cierran las otras ~40 páginas. El cierre es
     chrome compartido: exceptuar un tipo crea una página que termina distinto
     sin que el visitante sepa por qué. Es el mismo argumento con el que la
     galería se quedó. Se revierte con una línea si el operador lo decide.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── EL ESQUELETO DEL TIPO ─────────────────────────────────────────────────
   `.sc` es un <article>, NO un <section>: la regla `main > section` que
   reparte relleno y alterna papel/blanco no lo alcanza. El relleno se lo damos
   acá o el texto sale contra el borde de la ventana. */
.t-supporting_content .sc {
  padding-block: var(--seccion);
  padding-inline: max(var(--canaleta), (100% - var(--ancho)) / 2);
  background: var(--papel);
}
.t-supporting_content .sc__h1 { margin-bottom: 1.25rem; }

/* La respuesta es lo único que esta página tiene que hacer bien: se lee más
   grande que el cuerpo y en la tipografía de display, para que se distinga de
   un párrafo cualquiera sin necesidad de una caja. */
.t-supporting_content .sc__respuesta > p {
  margin: 0;
  max-width: 62ch;
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.05rem, 1.4vw, 1.2rem);
  line-height: 1.5;
  letter-spacing: -0.012em;
  color: var(--tinta);
  text-wrap: pretty;
}

/* Las dos cifras. Dos celdas con un filete al medio; la segunda es la que
   cambia el caso y va en acento. */
.t-supporting_content .sc__cifras {
  margin: 1.75rem 0 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 1px solid var(--pelo);
  background: var(--blanco);
  max-width: 34rem;
}
.t-supporting_content .sc__cifra { padding: 1rem 1.25rem; }
.t-supporting_content .sc__cifra + .sc__cifra { border-left: 1px solid var(--pelo); }
.t-supporting_content .sc__cifra-rotulo {
  font-family: var(--display);
  font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--mute);
}
.t-supporting_content .sc__cifra-dato {
  margin: 0.375rem 0 0;
  font-family: var(--display); font-weight: 800;
  font-size: 1.375rem; line-height: 1.05; letter-spacing: -0.03em;
  color: var(--tinta);
}
.t-supporting_content .sc__cifra:nth-child(2) .sc__cifra-dato { color: var(--acento); }
.t-supporting_content .sc__cifra-pie {
  margin: 0.125rem 0 0;
  font-size: 0.8125rem; color: var(--mute);
}

.t-supporting_content .sc__figura,
.t-supporting_content .sc__figura2 { margin: 2rem 0 0; }
.t-supporting_content .sc__figura img,
.t-supporting_content .sc__figura2 img {
  width: 100%; height: auto; display: block;
  border: 1px solid var(--pelo);
}

.t-supporting_content .sc__desarrollo { margin-top: 2.5rem; }
.t-supporting_content .sc__desarrollo > p { max-width: 74ch; }

/* El cierre hacia el Homepage: es prosa, centrada, y cierra el cuerpo.
   ⚠ EL `max-width` EXPLÍCITO NO ES DECORATIVO. La hoja base le pone
   `max-width: var(--ancho-texto)` —68ch, 693,6px medidos— a los párrafos. La
   primera versión de esta regla centraba con relleno, `max(canaleta, (100% -
   76ch)/2)`: con `box-sizing: border-box` los 332px de cada lado se comían la
   caja de 693 y al texto le quedaban 30px, o sea UNA PALABRA POR RENGLÓN. Se
   veía en la captura y la sonda lo confirmó. Se centra con `margin-inline` y
   la medida se declara acá, sin depender de lo que herede. */
.t-supporting_content .sc__home {
  max-width: 76ch;
  margin: 0 auto;
  padding: var(--seccion) var(--canaleta);
  background: var(--papel);
  text-align: center; text-wrap: pretty;
}

/* ═══ VARIANTE `bandas` ═════════════════════════════════════════════════════
   La página como una pila de franjas a sangre completa: cada H2 es una banda
   con su propio fondo, y el contraste lo llevan la 02 en blanco y el contexto
   local en oscuro.

   TRASLADADA 1 A 1 DE `Soporte Bandas.dc.html`, midiendo la maqueta renderizada
   al lado y no de memoria. La primera vuelta dejó afuera tres cosas por
   criterio propio —la barra de confianza, el rótulo y el CTA en terracota— y
   eso no era una decisión mía: si la maqueta lo dibuja, va.

   LOS COLORES SON LOS DE LA MAQUETA, y acá sí se apartan de los tokens. Cuatro
   corren por un pelo del sistema (#fbfaf8 contra `--papel`, #17171a contra
   `--tinta`, #6b6b73 contra `--mute`, #e2e0db contra `--pelo`) y se declaran
   como variables LOCALES de la variante: no entran a `:root`, así que no
   arrastran al resto del sitio y mueren con la piel. El bloque C los mide
   igual, porque son hex y no oklch.

   LA ÚNICA DIFERENCIA QUE QUEDA CONTRA LA MAQUETA, y es de modelo: el bloque
   `.vuelta` que va entre la galería y el CTA. La maqueta lo fusionó con el
   cierre hacia el Homepage; el modelo lo exige porque SIN BREADCRUMBS esa frase
   es la única arista de vuelta al padre que existe, y `cierre-de-pagina` la
   chequea. Se puede sacar, pero es una decisión de modelo y no de piel. */
.t-supporting_content.v-bandas {
  --b-ancho: 1240px;
  --b-canaleta: 32px;
  --b-sangre: max(var(--b-canaleta), (100% - var(--b-ancho)) / 2);
  --b-papel: #fbfaf8;
  --b-tinta: #17171a;
  --b-mute:  #6b6b73;
  --b-pelo:  #e2e0db;
  --b-num:   #dcd6cc;
  --b-trust: #f2f1ed;
  --b-slot:  #cfccc4;
  background: var(--b-papel);
}

.t-supporting_content.v-bandas main { counter-reset: banda; background: var(--b-papel); }

/* El ritmo del sitio no se aplica: cada banda trae el suyo, y la alternancia
   papel/blanco tampoco — acá el fondo lo decide la banda, no la posición. */
.t-supporting_content.v-bandas main > section {
  padding: 0;
  background: transparent;
  border-top-color: transparent;
}

/* ── LA APERTURA ───────────────────────────────────────────────────────────
   Medido: 1.240 de contenido, relleno 48/32/0, grilla `1.05fr 1fr` con hueco
   de 44 y centrada. La figura del slot 1 va a la derecha y ocupa las filas del
   texto; en el DOM sigue DESPUÉS de la respuesta, que es lo que pide la
   plantilla. Las filas van declaradas para que nada quede a la colocación
   automática. */
.t-supporting_content.v-bandas .sc {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  column-gap: 2.75rem;
  align-items: center;
  padding: 3rem var(--b-sangre) 0;
  background: var(--b-papel);
}
.t-supporting_content.v-bandas .sc__rotulo { grid-column: 1; grid-row: 1; }
.t-supporting_content.v-bandas .sc__h1 { grid-column: 1; grid-row: 2; }
.t-supporting_content.v-bandas .sc__respuesta { grid-column: 1; grid-row: 3; }
.t-supporting_content.v-bandas .sc__cifras { grid-column: 1; grid-row: 4; }
.t-supporting_content.v-bandas .sc__figura { grid-column: 2; grid-row: 1 / 5; }

.t-supporting_content.v-bandas .sc__rotulo {
  margin: 0 0 1.25rem;
  font-family: var(--display);
  font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--acento);
}
.t-supporting_content.v-bandas .sc__h1 {
  margin: 0 0 1.25rem;
  font-size: clamp(1.875rem, 3.8vw, 3.125rem);
  line-height: 1.0; letter-spacing: -0.035em;
  color: var(--b-tinta);
}
.t-supporting_content.v-bandas .sc__respuesta > p {
  max-width: none; color: var(--b-tinta);
}
.t-supporting_content.v-bandas .sc__cifras {
  margin-top: 1.25rem; max-width: none;
  border-color: var(--b-pelo);
}
.t-supporting_content.v-bandas .sc__cifra + .sc__cifra { border-left-color: var(--b-pelo); }
.t-supporting_content.v-bandas .sc__cifra-rotulo,
.t-supporting_content.v-bandas .sc__cifra-pie { color: var(--b-mute); }
.t-supporting_content.v-bandas .sc__cifra-dato { color: var(--b-tinta); }
.t-supporting_content.v-bandas .sc__cifra:nth-child(2) .sc__cifra-dato { color: var(--acento); }
/* La figura ocupa las cuatro filas del hero, así que ACOMPAÑA a la columna de
   texto en vez de quedar centrada con alto propio. Con `center` + `44vh` la
   foto cortaba antes que el texto y el bloque de cifras quedaba solo: 56px en
   la pieza de plazos y 96px en la de los tres tipos de mueble, medido el
   2026-08-27. La diferencia entre las dos es cuántas líneas ocupa su H1, que
   depende del ancla y no se puede recortar. `cover` sigue evitando que la
   foto se deforme al estirarse, y en móvil no cambia nada: ahí la figura ya
   baja a una sola columna con `max-height: none`. */
.t-supporting_content.v-bandas .sc__figura {
  margin: 0; align-self: stretch;
}
.t-supporting_content.v-bandas .sc__figura img {
  height: 100%; object-fit: cover; max-height: none;
  border-color: var(--b-slot);
}

/* ── LA BARRA DE CONFIANZA ─────────────────────────────────────────────────
   Cuatro celdas a sangre completa, con filete entre ellas y arriba y abajo. Es
   el parcial `trust` del sitio; acá se le cambia la caja, no el contenido. */
.t-supporting_content.v-bandas .trust {
  grid-column: 1 / -1;
  margin: 2.5rem calc(var(--b-canaleta) - 50vw) 0;
  margin-inline: calc(-1 * max(var(--b-canaleta), (100vw - var(--b-ancho)) / 2));
  padding: 0;
  background: var(--b-trust);
  border-block: 1px solid var(--b-pelo);
}
.t-supporting_content.v-bandas .trust__lista {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 0; margin: 0; padding: 0; list-style: none;
  max-width: none;
}
.t-supporting_content.v-bandas .trust__item {
  padding: 1rem 1.5rem;
  border-right: 1px solid var(--b-pelo);
  font-family: var(--display); font-weight: 600;
  font-size: 0.84375rem; color: var(--b-tinta);
  text-align: center;
}
.t-supporting_content.v-bandas .trust__item:last-child { border-right: 0; }
.t-supporting_content.v-bandas .trust__item::before { content: none; }

/* ── LAS TRES BANDAS DEL DESARROLLO ────────────────────────────────────────
   Cada bloque es una franja a sangre con su propio fondo. La 02 es la blanca y
   lleva la foto del slot 2 adentro y a la derecha, que es lo que obligó a
   partir el desarrollo en tres en la plantilla.

   EL NÚMERO ES ORNAMENTO y por eso se genera con un contador de CSS: 01, 02,
   03 en el desarrollo y 04 en el contexto local. El contador arranca en `main`
   porque el 04 cuelga de un hermano del <article>. */
.t-supporting_content.v-bandas .sc__desarrollo {
  grid-column: 1 / -1;
  margin: 0;
  margin-inline: calc(-1 * max(var(--b-canaleta), (100vw - var(--b-ancho)) / 2));
  padding: 3.75rem max(var(--b-canaleta), (100vw - var(--b-ancho)) / 2);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.5rem 2.75rem;
  align-items: start;
  background: var(--b-papel);
}
.t-supporting_content.v-bandas .sc__desarrollo > h2 {
  grid-column: 1 / -1;
  margin: 0;
  display: flex; align-items: baseline; gap: 1rem;
  font-size: clamp(1.5625rem, 2.8vw, 2.25rem);
  line-height: 1.08; letter-spacing: -0.03em;
  color: var(--b-tinta);
}
.t-supporting_content.v-bandas .sc__desarrollo > h2::before,
.t-supporting_content.v-bandas .local__h2::before {
  counter-increment: banda;
  content: "0" counter(banda);
  font-size: 1.875rem; font-weight: 800; line-height: 1;
  letter-spacing: -0.03em; color: var(--b-num);
}
/* El párrafo de entrada de cada banda: ancho completo y en display. */
.t-supporting_content.v-bandas .sc__desarrollo > h2:first-child + p {
  grid-column: 1 / -1;
  max-width: 88ch;
  font-family: var(--display); font-weight: 700;
  font-size: clamp(1.0625rem, 1.8vw, 1.375rem);
  line-height: 1.42; letter-spacing: -0.018em;
  color: var(--b-tinta); text-wrap: pretty;
}
.t-supporting_content.v-bandas .sc__desarrollo > p { margin: 0; max-width: none; }

/* BANDA 01 — el filete que separa la entrada de las dos columnas de prosa. */
.t-supporting_content.v-bandas .sc__desarrollo--1 > h2:first-child + p {
  margin-bottom: 0.125rem;
  padding-bottom: 1.625rem;
  border-bottom: 1px solid var(--b-pelo);
}

/* BANDA 02 — blanca, con filete arriba y abajo, y la foto del slot 2 a la
   derecha. La CAJA es la banda; adentro, el texto a la izquierda y la foto a
   la derecha. Los dos párrafos NO van en dos columnas acá: van apilados contra
   la foto, con medida de lectura, como en la maqueta. */
.t-supporting_content.v-bandas .sc__banda2 {
  grid-column: 1 / -1;
  margin-inline: calc(-1 * max(var(--b-canaleta), (100vw - var(--b-ancho)) / 2));
  padding: 3.75rem max(var(--b-canaleta), (100vw - var(--b-ancho)) / 2);
  background: var(--blanco);
  border-block: 1px solid var(--b-pelo);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 440px);
  column-gap: 3rem;
  align-items: center;
}
.t-supporting_content.v-bandas .sc__banda2:empty { display: none; }
/* Adentro de la caja, el bloque de texto deja de ser banda: no repite fondo ni
   relleno ni sangrado, sólo ocupa su columna. */
.t-supporting_content.v-bandas .sc__desarrollo--2 {
  grid-column: 1;
  margin: 0; padding: 0;
  background: transparent;
  display: block;
}
.t-supporting_content.v-bandas .sc__desarrollo--2 > h2 {
  max-width: 26ch; margin-bottom: 1.375rem;
}
/* En esta banda el primer párrafo NO es lead: la maqueta lo deja en cuerpo. */
.t-supporting_content.v-bandas .sc__desarrollo--2 > h2:first-child + p {
  max-width: 70ch;
  font-family: var(--texto); font-weight: 400;
  font-size: 1rem; line-height: 1.72; letter-spacing: normal;
  color: var(--cuerpo);
}
.t-supporting_content.v-bandas .sc__desarrollo--2 > p { max-width: 70ch; }
.t-supporting_content.v-bandas .sc__desarrollo--2 > p:not(:last-child) {
  margin-bottom: 1.125rem;
}
.t-supporting_content.v-bandas .sc__figura2 {
  grid-column: 2; margin: 0;
}
.t-supporting_content.v-bandas .sc__figura2 img {
  aspect-ratio: 4 / 5; object-fit: cover;
  border-color: var(--b-slot);
}

/* BANDA 03 — la pregunta, con el filete de acento a la izquierda del lead. */
.t-supporting_content.v-bandas .sc__desarrollo--3 > h2:first-child + p {
  border-left: 3px solid var(--acento);
  padding-left: 1.375rem;
  max-width: 76ch;
  margin-bottom: 0.5rem;
}

/* ── EL CONTEXTO LOCAL: la banda oscura, y el 04 del contador ──────────────*/
.t-supporting_content.v-bandas .local {
  background: var(--b-tinta);
  padding: 3.75rem var(--b-sangre);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 360px);
  gap: 3rem; align-items: center;
}
.t-supporting_content.v-bandas .local__h2 {
  color: var(--claro);
  padding-top: 0;
  display: flex; align-items: baseline; gap: 1rem;
}
.t-supporting_content.v-bandas .local__h2::before {
  position: static; width: auto; height: auto; background: none;
  color: #4a423a;
}
.t-supporting_content.v-bandas .local__texto p { color: var(--claro-mute); max-width: 72ch; }
.t-supporting_content.v-bandas .local__figura { margin: 0; }
.t-supporting_content.v-bandas .local__figura img {
  aspect-ratio: 3 / 4; object-fit: cover;
  border: 1px solid var(--pelo-osc);
}

/* ── EL CIERRE HACIA EL HOMEPAGE ───────────────────────────────────────────
   El rótulo es ORNAMENTO y se genera en CSS: no es contenido, no lo lee un bot
   y no entra en el conteo de palabras del bloque H. */
.t-supporting_content.v-bandas .sc__home {
  max-width: 76ch; margin: 0 auto;
  padding: 3.25rem var(--b-canaleta) 0;
  background: transparent;
  font-size: 1.0625rem;
}
.t-supporting_content.v-bandas .sc__home::before {
  content: "Back to the full scope";
  display: block; margin-bottom: 0.75rem;
  font-family: var(--display);
  font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--acento);
}

/* ── LA FAQ: tres fichas blancas con el filete de acento arriba ────────────*/
.t-supporting_content.v-bandas .faq {
  padding: 3.25rem var(--b-sangre) 0;
  background: transparent;
}
.t-supporting_content.v-bandas .faq__h2 {
  text-align: center; padding-top: 0;
  font-size: clamp(1.5625rem, 2.8vw, 2.25rem);
  line-height: 1.08; letter-spacing: -0.03em;
  color: var(--b-tinta);
  margin-bottom: 1.375rem;
}
.t-supporting_content.v-bandas .faq__h2::before { content: none; }
/* `max-width: none` porque la hoja base le pone 60rem a `.faq__lista`, y con
   960px y hueco de 16 sólo entran DOS fichas de 320: la maqueta tiene tres. */
.t-supporting_content.v-bandas .faq__lista {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 1rem; align-items: stretch;
  text-align: left;
  max-width: none;
}
.t-supporting_content.v-bandas .faq__item {
  background: var(--blanco);
  border: 1px solid var(--b-pelo);
  border-top: 3px solid var(--acento);
  padding: 1.5rem 1.625rem;
}
.t-supporting_content.v-bandas .faq__pregunta {
  font-family: var(--display); font-weight: 700;
  font-size: 1.0625rem; line-height: 1.4; color: var(--b-tinta);
}
.t-supporting_content.v-bandas .faq__respuesta { margin: 0.875rem 0 0; font-size: 0.9375rem; }

/* ── LA GALERÍA: de carrusel a mosaico de ocho ─────────────────────────────
   La maqueta muestra las 8 fotos a la vez en cuatro columnas. El componente del
   sitio es un carrusel de dos páginas de cuatro y se aplana SIN TOCAR EL HTML:
   las dos <ul> pasan a `display: contents` y sus ocho <li> caen en la grilla del
   padre. Los radios y las flechas se ocultan porque ya no queda qué paginar. */
.t-supporting_content.v-bandas .galeria {
  padding: 3.25rem var(--b-sangre) 0;
  background: transparent;
}
.t-supporting_content.v-bandas .galeria__cabecera {
  display: flex; flex-wrap: wrap;
  align-items: baseline; justify-content: space-between;
  gap: 1rem; margin-bottom: 1.125rem;
}
.t-supporting_content.v-bandas .galeria__h2 {
  padding-top: 0; margin: 0;
  font-size: clamp(1.3125rem, 2.2vw, 1.75rem);
  letter-spacing: -0.025em; color: var(--b-tinta);
}
.t-supporting_content.v-bandas .galeria__h2::before { content: none; }
/* El rótulo del conteo: es una etiqueta de la propia galería, no copy. */
.t-supporting_content.v-bandas .galeria__cabecera::after {
  content: "8 photos";
  font-family: var(--display);
  font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--b-mute);
}
.t-supporting_content.v-bandas .galeria__flechas,
.t-supporting_content.v-bandas .galeria__estado { display: none; }
.t-supporting_content.v-bandas .galeria__viewport { overflow: visible; }
/* `grid-auto-flow: row` EXPLÍCITO: el carrusel de base.css declara flujo por
   COLUMNA para correr la pista con un transform, y eso sobrevive al cambio a
   grilla. Medido: las 8 fotos caían en 8 columnas —4 explícitas a 0px y 4
   implícitas a 1.240— y la primera foto ocupaba la pantalla entera. */
.t-supporting_content.v-bandas .galeria__pista {
  display: grid;
  grid-auto-flow: row;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.75rem;
  transform: none; width: auto;
}
.t-supporting_content.v-bandas .galeria__pagina { display: contents; }
.t-supporting_content.v-bandas .galeria__item { width: auto; }
.t-supporting_content.v-bandas .galeria__figura img { aspect-ratio: 1; object-fit: cover; }

/* ── EL CTA EN TERRACOTA ───────────────────────────────────────────────────
   `!important` porque la hoja base fija `background: var(--profunda) !important`
   para todo el sitio. Acá el cierre es el acento, como en las dos maquetas:
   titular a la izquierda, texto y botón a la derecha, y el botón en el negro
   del pie para que el CTA y el pie sigan separándose por valor. */
.t-supporting_content.v-bandas .cta {
  background: var(--acento) !important;
  margin-top: 3.5rem;
  padding: 3.5rem var(--b-sangre);
  text-align: left;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 2rem; align-items: center;
}
.t-supporting_content.v-bandas .cta__h2 {
  grid-row: 1 / 3; margin: 0 auto 0 0;
  max-width: 24ch; color: #fff;
  font-size: clamp(1.625rem, 3vw, 2.375rem);
  line-height: 1.08; letter-spacing: -0.03em;
}
.t-supporting_content.v-bandas .cta__texto {
  grid-column: 2; margin: 0; max-width: none;
  color: #fbe8df;
}
.t-supporting_content.v-bandas .cta .btn--primario {
  grid-column: 2; justify-self: start;
  margin-top: 1.125rem;
  background: var(--pie); color: var(--claro);
}
.t-supporting_content.v-bandas .cta .btn--primario:hover { background: #000; color: var(--claro); }

/* La vuelta al padre queda sobre el papel de la variante, no sobre `--papel`. */
.t-supporting_content.v-bandas .vuelta { background: transparent; }

@media (max-width: 56rem) {
  .t-supporting_content.v-bandas .sc {
    grid-template-columns: minmax(0, 1fr);
    padding-top: 2.25rem;
  }
  .t-supporting_content.v-bandas .sc__rotulo,
  .t-supporting_content.v-bandas .sc__h1,
  .t-supporting_content.v-bandas .sc__respuesta,
  .t-supporting_content.v-bandas .sc__cifras,
  .t-supporting_content.v-bandas .sc__figura { grid-column: 1; grid-row: auto; }
  .t-supporting_content.v-bandas .sc__figura { margin-top: 1.75rem; }
  .t-supporting_content.v-bandas .sc__figura img { max-height: none; }
  .t-supporting_content.v-bandas .sc__desarrollo,
  .t-supporting_content.v-bandas .sc__desarrollo--2 { grid-template-columns: minmax(0, 1fr); }
  /* LA CAJA, no sólo sus hijos. Acá faltaba `.sc__banda2` y el efecto era mudo
     y feo: los dos hijos colapsaban a una columna cada uno, pero el CONTENEDOR
     seguía en `minmax(0,1fr) minmax(0,440px)`. En 390px la figura se llevaba
     los 278px disponibles y la columna del texto se resolvía en CERO, así que
     el desarrollo 2 salía a UNA PALABRA POR LÍNEA, título incluido. Medido el
     2026-08-24 con el estilo computado: `grid-template-columns: 0px 278px`.
     La `.sc__figura2` vuelve a la columna 1 por lo mismo que `.sc__figura`:
     está fijada en `grid-column: 2`, y sin resetearla el grid le inventa una
     segunda columna implícita y el colapso no sirve de nada. */
  .t-supporting_content.v-bandas .sc__banda2 { grid-template-columns: minmax(0, 1fr); }
  .t-supporting_content.v-bandas .sc__figura2 { grid-template-columns: minmax(0, 1fr); }
  .t-supporting_content.v-bandas .sc__figura2 { grid-column: 1; margin-top: 1.75rem; }
  .t-supporting_content.v-bandas .sc__figura2 img { grid-column: 1; }
  .t-supporting_content.v-bandas .local { grid-template-columns: minmax(0, 1fr); }
  .t-supporting_content.v-bandas .galeria__pista { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .t-supporting_content.v-bandas .cta__texto,
  .t-supporting_content.v-bandas .cta .btn--primario { grid-column: 1; }
  .t-supporting_content.v-bandas .cta__h2 { grid-row: auto; }
}
@media (max-width: 40rem) {
  .t-supporting_content.v-bandas .sc__cifras { grid-template-columns: minmax(0, 1fr); }
  .t-supporting_content.v-bandas .sc__cifra + .sc__cifra {
    border-left: 0; border-top: 1px solid var(--b-pelo);
  }
  .t-supporting_content.v-bandas .galeria__pista { grid-template-columns: minmax(0, 1fr); }
  .t-supporting_content.v-bandas .trust__item { border-right: 0; border-bottom: 1px solid var(--b-pelo); }
  .t-supporting_content.v-bandas .trust__item:last-child { border-bottom: 0; }
}


/* ═══ VARIANTE `mosaico` ════════════════════════════════════════════════════
   La misma página como piezas apoyadas sobre el papel: una apertura oscura a
   sangre y, debajo, tarjetas blancas con filete que se leen como fichas. El
   ritmo lo dan los bordes, no las superficies.

   Medido de la maqueta: contenido 1.280, canaleta 32, apertura sobre
   `--profunda`, H1 de 44px, tarjetas con relleno 34/38 y filete `--pelo`.

   ⚠ ES OTRA `v-mosaico` QUE LA DE LOCATION PAGE. Comparten nombre y no se
   tocan: aquélla lleva `.t-location_page` delante en sus 108 selectores y ésta
   `.t-supporting_content` en todos los suyos. El nombre se repite a propósito
   —es la misma idea de composición— y el scope es lo que lo hace seguro. */
.t-supporting_content.v-mosaico {
  --s-ancho: 1280px;
  --s-canaleta: 32px;
  --s-sangre: max(var(--s-canaleta), (100% - var(--s-ancho)) / 2);
}

/* ── La apertura oscura, a sangre ──────────────────────────────────────────
   El <article> entero es la franja: fondo `--profunda`, dos columnas y el
   slot 1 a la derecha. El desarrollo sale de ahí y vuelve al papel, así que
   la franja termina donde termina la apertura. */
/* ⚠ LA FRANJA OSCURA NO ES EL FONDO DEL <article>, Y ESA FUE LA PRIMERA
   VERSIÓN. Pintar `.sc` entero dejaba `--profunda` DETRÁS DE TODO el
   desarrollo: las tarjetas blancas flotaban sobre oscuro y los huecos entre
   ellas se leían negros, cuando la maqueta los tiene sobre papel. Se vio
   mirando la captura, no midiendo.
   La franja es un `::before` colocado en la grilla —columnas enteras, filas 1
   a 4, que son H1, respuesta y cifras— y sangrado con márgenes negativos hasta
   el borde de la ventana. Va detrás con `z-index: -1` y el `isolation` le
   acota el contexto para que no se meta debajo del chrome. */
.t-supporting_content.v-mosaico .sc {
  position: relative;
  isolation: isolate;
  background: var(--papel);
  /* ⚠ ACÁ NO VA `color: var(--claro)`, Y LO CAZÓ EL BLOQUE C: sobre `--papel`
     da 1,09:1. Funcionaba de casualidad —cada hijo que cae sobre la franja
     oscura declara su propio color— pero dejaba armada la trampa para el
     próximo hijo que no lo declare, que nacería claro sobre claro. Es el mismo
     texto fantasma que ya apareció una vez en esta variante. El color claro se
     declara pieza por pieza: H1, respuesta y las dos celdas de cifras. */
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 2.5rem;
  align-items: center;
  padding: 2.5rem var(--s-sangre) 0;
}
/* ⚠ CON LA FRANJA PUESTA, LAS TRES FILAS SE COLOCAN A MANO. Un ítem colocado
   explícitamente ocupa sus celdas ANTES de que corra la colocación automática:
   el `::before` reservó las filas 1 a 3 en las dos columnas y empujó al H1, a
   la respuesta y a las cifras a las filas 4, 5 y 6 — fuera de la franja, con
   `color: var(--claro)` sobre papel, o sea texto CLARO SOBRE CLARO. La captura
   lo mostró de una: el H1 fantasma. Con las filas declaradas no queda nada
   librado a la colocación automática y el orden es el del DOM. */
.t-supporting_content.v-mosaico .sc::before {
  content: "";
  grid-column: 1 / -1; grid-row: 1 / 6;
  /* `align-self` EXPLÍCITO: la grilla del hero lleva `align-items: center`, y
     un ítem vacío centrado mide CERO de alto. La franja salía como una tira
     detrás de las cifras y el H1 quedaba claro sobre papel. */
  align-self: stretch;
  /* ⚠ `100vw` Y NO `100%`, Y NO ES INTERCAMBIABLE. `--s-sangre` lleva un `%`
     adentro, y un porcentaje se resuelve contra el CONTENEDOR: en el relleno
     de `.sc` eso es el ancho de <main> —1.440, da 80— pero en el margen de un
     ítem de grilla es su ÁREA —1.280, da 0 y cae al mínimo de 32—. La franja
     salía angosta, metida 48px de cada lado, mientras las tarjetas de abajo
     respetaban los 80: se leía como un error de alineación. Medido, no
     deducido. Con `vw` el número es el mismo en los dos lugares.
     La barra de scroll no rompe nada: `main` ya lleva `overflow-x: clip`, así
     que los ~7px que `vw` se pasa cuando hay barra se recortan y no aparece
     scroll horizontal. Se verifica midiendo `scrollWidth`. */
  margin-block: -2.5rem;
  margin-inline: calc(-1 * max(var(--s-canaleta), (100vw - var(--s-ancho)) / 2));
  background: var(--profunda);
  z-index: -1;
}
.t-supporting_content.v-mosaico .sc__rotulo { grid-column: 1; grid-row: 1; }
.t-supporting_content.v-mosaico .sc__h1 { grid-row: 2; }
.t-supporting_content.v-mosaico .sc__respuesta { grid-row: 3; }
.t-supporting_content.v-mosaico .sc__cifras { grid-row: 4; }
.t-supporting_content.v-mosaico .sc__figura { grid-row: 1 / 5; }
.t-supporting_content.v-mosaico .sc__rotulo {
  margin: 0 0 1.5rem;
  font-family: var(--display);
  font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--acento-cl);
}

/* ── LA BARRA DE CONFIANZA, OSCURA Y DENTRO DE LA APERTURA ─────────────────
   En esta maqueta la tira cierra la franja: fondo más profundo que el hero,
   filetes en `--pelo-osc` y texto claro. Va a sangre, como la franja. */
.t-supporting_content.v-mosaico .trust {
  grid-column: 1 / -1; grid-row: 5;
  margin: 2.5rem 0 -2.5rem;
  margin-inline: calc(-1 * max(var(--s-canaleta), (100vw - var(--s-ancho)) / 2));
  padding: 0;
  background: var(--tinta);
}
.t-supporting_content.v-mosaico .trust__lista {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 0; margin: 0; padding: 0; list-style: none; max-width: none;
}
.t-supporting_content.v-mosaico .trust__item {
  padding: 1rem 1.5rem;
  border-right: 1px solid var(--pelo-osc);
  font-family: var(--display); font-weight: 600;
  font-size: 0.84375rem; color: var(--claro);
}
.t-supporting_content.v-mosaico .trust__item:last-child { border-right: 0; }
.t-supporting_content.v-mosaico .trust__item::before { content: none; }
.t-supporting_content.v-mosaico .sc__h1 {
  grid-column: 1; margin: 0 0 1.5rem; color: var(--claro);
  font-size: clamp(1.75rem, 3.4vw, 2.75rem);
  line-height: 1.01; letter-spacing: -0.035em;
}
.t-supporting_content.v-mosaico .sc__respuesta { grid-column: 1; }
/* El filete de acento a la izquierda de la respuesta: es lo que la separa del
   H1 sin necesidad de una caja, y es la marca de la maqueta. */
.t-supporting_content.v-mosaico .sc__respuesta > p {
  border-left: 3px solid var(--acento-cl);
  padding-left: 1.25rem;
  color: var(--claro);
}
.t-supporting_content.v-mosaico .sc__cifras {
  grid-column: 1; max-width: none;
  border-color: var(--pelo-osc);
  background: var(--pelo-osc);
  gap: 1px;
}
.t-supporting_content.v-mosaico .sc__cifra {
  background: var(--profunda); padding: 1rem 1.125rem;
}
.t-supporting_content.v-mosaico .sc__cifra + .sc__cifra { border-left: 0; }
.t-supporting_content.v-mosaico .sc__cifra-rotulo { color: var(--claro-mute); }
.t-supporting_content.v-mosaico .sc__cifra-dato { color: var(--claro); font-size: 1.4375rem; }
.t-supporting_content.v-mosaico .sc__cifra:nth-child(2) .sc__cifra-dato { color: var(--acento-cl); }
.t-supporting_content.v-mosaico .sc__cifra-pie { color: var(--claro-mute); }
.t-supporting_content.v-mosaico .sc__figura {
  grid-column: 2; grid-row: 1 / 4; margin: 0; align-self: center;
}
.t-supporting_content.v-mosaico .sc__figura img {
  aspect-ratio: 4 / 3; object-fit: cover; max-height: 42vh;
  border-color: var(--pelo-osc);
}

/* ── El desarrollo: dos tarjetas blancas sobre el papel ────────────────────
   Cada bloque `.sc__desarrollo` es una tarjeta. La segunda estrena el filete
   de acento arriba, que en la maqueta marca la sección de la pregunta. */
.t-supporting_content.v-mosaico .sc__desarrollo,
.t-supporting_content.v-mosaico .sc__banda2 {
  grid-column: 1 / -1;
  margin: 3.5rem 0 0;
}
/* La banda 2 de ESTA maqueta no pone la foto al lado: el texto va sin ficha,
   sobre el papel y con un filete arriba, y debajo la panorámica 21:9 a todo el
   ancho del contenido. Por eso la caja es de UNA columna acá. */
.t-supporting_content.v-mosaico .sc__banda2 {
  display: grid; grid-template-columns: minmax(0, 1fr);
  gap: 2.75rem;
}
.t-supporting_content.v-mosaico .sc__desarrollo--2 {
  margin: 0;
  background: transparent;
  border: 0;
  border-top: 1px solid var(--pelo);
  padding: 2.5rem 0 0;
}
.t-supporting_content.v-mosaico .sc__figura2 { margin: 0; }
/* La tarjeta reparte su prosa en dos columnas por la misma razón que `bandas`,
   y con la misma regla de lead: sin esto los párrafos heredan los 68ch de la
   hoja base y la tarjeta queda con la mitad derecha vacía. Se veía en la
   captura: 1.200px de ficha con el texto apretado contra el borde izquierdo. */
.t-supporting_content.v-mosaico .sc__desarrollo {
  background: var(--blanco);
  border: 1px solid var(--pelo);
  padding: 2.125rem 2.375rem;
  color: var(--cuerpo);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.375rem 2.5rem;
  align-items: start;
}
.t-supporting_content.v-mosaico .sc__desarrollo > p { margin: 0; max-width: none; }
.t-supporting_content.v-mosaico .sc__desarrollo > h2:first-child + p { grid-column: 1 / -1; }
.t-supporting_content.v-mosaico .sc__desarrollo--3 { border-top: 3px solid var(--acento); }

/* ⚠ CLASE DOBLE, Y NO ES ADORNO. `.v-mosaico .sc__desarrollo--2` y
   `.v-mosaico .sc__desarrollo` tienen LA MISMA especificidad, así que decide
   el orden del archivo y la ficha blanca genérica —que va más abajo— le ganaba
   a la excepción. La banda 02 de esta maqueta no es ficha: es prosa sobre el
   papel, con un filete arriba y en dos columnas, y su primer párrafo NO es
   lead. Se vio en la captura: salía blanca y con la entrada en negrita. */
.t-supporting_content.v-mosaico .sc__desarrollo.sc__desarrollo--2 {
  background: transparent;
  border: 0;
  border-top: 1px solid var(--pelo);
  padding: 2.5rem 0 0;
  margin: 0;
}
.t-supporting_content.v-mosaico .sc__desarrollo.sc__desarrollo--2 > h2:first-child + p {
  grid-column: auto;
  font-family: var(--texto); font-weight: 400;
  font-size: 1rem; line-height: 1.7; letter-spacing: normal;
  color: var(--cuerpo);
}

/* ── EL H2 DE LA BANDA 01 VA FUERA DE LA FICHA ─────────────────────────────
   En la maqueta el título se apoya sobre el papel y la ficha blanca empieza
   DEBAJO. El H2 vive dentro del bloque de markdown rendido y no hay dónde
   cortarlo, así que la ficha no es el fondo del bloque: es un `::before`
   colocado en la grilla desde la fila 2 hasta el final, detrás del contenido.
   Misma técnica que la franja oscura del hero, y por el mismo motivo.
   `align-self: stretch` otra vez: con `align-items: start` un pseudo vacío
   mide cero. */
.t-supporting_content.v-mosaico .sc__desarrollo.sc__desarrollo--1,
.t-supporting_content.v-mosaico .sc__desarrollo.sc__desarrollo--3 {
  position: relative;
  isolation: isolate;
}
/* La ficha sigue siendo el fondo del bloque; lo que se saca de adentro es el
   H2, con un margen negativo que se come el relleno Y EL BORDE —de ahí el
   `- 1px`— y con el papel de la página como fondo propio. El borde superior de
   la ficha se apaga y lo dibuja el filete de abajo del H2, que cae justo donde
   la maqueta lo tiene.

   POR QUÉ ASÍ Y NO CON UN PSEUDO EN LA GRILLA. Se probó con un `::before`
   colocado de la fila 2 en adelante y no hay número que sirva: las filas las
   crea el markdown rendido, o sea que son IMPLÍCITAS. Con `-1` el rango
   colapsa y la ficha sale como una tira arriba de todo; con `span 50` se
   estira cincuenta filas y queda una caja blanca vacía de media pantalla. Las
   dos se vieron en captura. Esto no depende de cuántos párrafos traiga la
   pieza. */
.t-supporting_content.v-mosaico .sc__desarrollo.sc__desarrollo--1 {
  border-top: 0;
}
.t-supporting_content.v-mosaico .sc__desarrollo--1 > h2:first-child {
  margin-top: calc(-2.125rem - 1px);
  margin-inline: calc(-2.375rem - 1px);
  margin-bottom: 1.625rem;
  padding: 0 2.375rem 1.625rem;
  background: var(--papel);
  border-bottom: 1px solid var(--pelo);
  /* El `max-width: 26ch` que llevan los H2 de esta piel acota la CAJA, y acá la
     caja es la que tapa el blanco de la ficha: con 26ch el papel llegaba hasta
     la mitad y el resto del ancho seguía blanco arriba del título. Medido en
     captura. El texto igual entra en una línea. */
  max-width: none;
}
.t-supporting_content.v-mosaico .sc__desarrollo--1 > h2:first-child + p {
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--pelo);
}

/* El H2 del contexto local va SIN el filete de acento del sitio: la maqueta lo
   deja limpio, apoyado sobre el blanco de la sección. */
.t-supporting_content.v-mosaico .local__h2 { padding-top: 0; }
.t-supporting_content.v-mosaico .local__h2::before { content: none; }

/* ── LA FAQ: fichas blancas, título a la izquierda y sin filete de acento ──*/
.t-supporting_content.v-mosaico .faq {
  padding: 3.5rem var(--s-sangre) 0;
  background: transparent;
  text-align: left;
}
.t-supporting_content.v-mosaico .faq__h2 {
  text-align: left; padding-top: 0; margin-bottom: 1.5rem;
  font-size: clamp(1.6875rem, 3.2vw, 2.375rem);
  line-height: 1.08; letter-spacing: -0.03em; color: var(--tinta);
}
.t-supporting_content.v-mosaico .faq__h2::before { content: none; }
.t-supporting_content.v-mosaico .faq__lista {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 1rem; align-items: start;
  max-width: none; text-align: left;
}
.t-supporting_content.v-mosaico .faq__pregunta {
  font-family: var(--display); font-weight: 700;
  font-size: 1.0625rem; line-height: 1.4; color: var(--tinta);
}
.t-supporting_content.v-mosaico .faq__respuesta { margin: 0.875rem 0 0; font-size: 0.9375rem; }

/* ── LA GALERÍA COMO CARRIL ────────────────────────────────────────────────
   Esta maqueta NO aplana el carrusel: lo deja como una pista horizontal de
   tarjetas de 300px que se arrastra. El componente del sitio ya es eso; se le
   sacan las flechas y la paginación por radios y se le deja el scroll. */
.t-supporting_content.v-mosaico .galeria {
  padding: 3rem 0 0;
  background: transparent;
  border-top: 1px solid var(--pelo);
  margin-top: 4rem;
}
.t-supporting_content.v-mosaico .galeria__cabecera {
  max-width: var(--s-ancho); margin: 0 auto;
  padding: 0 var(--s-canaleta);
  display: flex; flex-wrap: wrap;
  align-items: baseline; justify-content: space-between; gap: 1rem;
}
.t-supporting_content.v-mosaico .galeria__h2 {
  padding-top: 0; margin: 0;
  font-size: clamp(1.375rem, 2.4vw, 1.875rem);
  letter-spacing: -0.025em; color: var(--tinta);
}
.t-supporting_content.v-mosaico .galeria__h2::before { content: none; }
.t-supporting_content.v-mosaico .galeria__cabecera::after {
  content: "8 photos · scroll →";
  font-family: var(--display);
  font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--mute);
}
.t-supporting_content.v-mosaico .galeria__flechas,
.t-supporting_content.v-mosaico .galeria__estado { display: none; }
.t-supporting_content.v-mosaico .galeria__viewport { overflow-x: auto; overflow-y: hidden; }
.t-supporting_content.v-mosaico .galeria__pista {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 300px;
  gap: 0.75rem;
  margin-top: 1.375rem;
  padding: 0 var(--s-canaleta) 0.75rem;
  transform: none; width: auto;
}
.t-supporting_content.v-mosaico .galeria__pagina { display: contents; }
.t-supporting_content.v-mosaico .galeria__item { width: auto; }
.t-supporting_content.v-mosaico .galeria__figura img { aspect-ratio: 4 / 3; object-fit: cover; }

/* ── EL CTA EN TERRACOTA ───────────────────────────────────────────────────
   Igual que en `bandas`: las dos maquetas cierran con el acento, y la hoja
   base fija `--profunda !important` para todo el sitio. */
.t-supporting_content.v-mosaico .cta {
  background: var(--acento) !important;
  margin-top: 3.5rem;
  padding: 3.5rem var(--s-sangre);
  text-align: left;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 2rem; align-items: center;
}
.t-supporting_content.v-mosaico .cta__h2 {
  grid-row: 1 / 3; margin: 0 auto 0 0;
  max-width: 24ch; color: #fff;
  font-size: clamp(1.625rem, 3vw, 2.375rem);
  line-height: 1.08; letter-spacing: -0.03em;
}
.t-supporting_content.v-mosaico .cta__texto {
  grid-column: 2; margin: 0; max-width: none; color: #fbe8df;
}
.t-supporting_content.v-mosaico .cta .btn--primario {
  grid-column: 2; justify-self: start; margin-top: 1.125rem;
  background: var(--pie); color: var(--claro);
}
.t-supporting_content.v-mosaico .cta .btn--primario:hover { background: #000; color: var(--claro); }
/* El H2 cruza las dos columnas de la tarjeta. Sin esto queda en la columna 1 y
   su primer párrafo salta a la 2, que es lo que se veía en «What Permitting
   Adds»: título a la izquierda y su propio texto arrancando a la derecha. */
.t-supporting_content.v-mosaico .sc__desarrollo > h2 {
  grid-column: 1 / -1;
  max-width: 26ch; margin: 0 0 1.375rem;
  font-size: clamp(1.6875rem, 3.2vw, 2.375rem);
  line-height: 1.08; letter-spacing: -0.03em;
  color: var(--tinta);
}
.t-supporting_content.v-mosaico .sc__desarrollo > h2 ~ h2 { margin-top: 2rem; }
.t-supporting_content.v-mosaico .sc__desarrollo > h2:first-child + p {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(1.0625rem, 1.8vw, 1.3125rem);
  line-height: 1.45; letter-spacing: -0.016em;
  color: var(--tinta); text-wrap: pretty;
  max-width: none;
}
/* La franja panorámica del slot 2: en la maqueta es lo único que corta las
   tarjetas, y por eso va sin filete y bien ancha. */
.t-supporting_content.v-mosaico .sc__figura2 img {
  aspect-ratio: 21 / 9; object-fit: cover; border: 0;
}

/* ── El contexto local: sección blanca a sangre, foto a la derecha ─────────*/
.t-supporting_content.v-mosaico .local {
  background: var(--blanco);
  border-block: 1px solid var(--pelo);
  padding: 3.5rem var(--s-sangre);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 460px);
  gap: 2.75rem; align-items: center;
}
.t-supporting_content.v-mosaico .local__h2 { max-width: 24ch; }
.t-supporting_content.v-mosaico .local__texto p { max-width: 70ch; }
.t-supporting_content.v-mosaico .local__figura { margin: 0; }
.t-supporting_content.v-mosaico .local__figura img {
  aspect-ratio: 4 / 3; object-fit: cover; border: 1px solid var(--pelo);
}

/* ── La FAQ como fichas blancas ────────────────────────────────────────────*/
.t-supporting_content.v-mosaico .faq__item {
  background: var(--blanco);
  border: 1px solid var(--pelo);
  padding: 1.5rem 1.625rem;
}

/* ── El cierre, centrado y angosto, con el mismo rótulo que bandas ─────────*/
.t-supporting_content.v-mosaico .sc__home::before {
  content: "Back to the full scope";
  display: block; margin-bottom: 0.75rem;
  font-family: var(--display);
  font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--acento);
}

@media (max-width: 56rem) {
  .t-supporting_content.v-mosaico .sc {
    grid-template-columns: minmax(0, 1fr);
    padding-top: 2rem;
  }
  .t-supporting_content.v-mosaico .sc__h1,
  .t-supporting_content.v-mosaico .sc__respuesta,
  .t-supporting_content.v-mosaico .sc__cifras,
  .t-supporting_content.v-mosaico .sc__figura { grid-column: 1; }
  .t-supporting_content.v-mosaico .sc__figura { grid-row: auto; margin-top: 1.5rem; }
  .t-supporting_content.v-mosaico .sc__figura img { max-height: none; }
  .t-supporting_content.v-mosaico .local { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 40rem) {
  .t-supporting_content.v-mosaico .sc__cifras { grid-template-columns: minmax(0, 1fr); }
  .t-supporting_content.v-mosaico .sc__desarrollo { padding: 1.75rem 1.5rem; }
}

/* ── SIN SLOT DE IMAGEN, LA GRILLA CAE A UNA COLUMNA ───────────────────────
   Los tres slots son opcionales en el motor y esta pieza todavía no tiene sus
   fotos. Sin esto la grilla reserva igual la segunda columna y el texto se lee
   a media caja contra un hueco — el defecto que ya se cazó una vez trasladando
   una piel con los slots vacíos.
   Va al FINAL y repetido por variante a propósito: una regla genérica tiene
   menos especificidad que `.t-supporting_content.v-mosaico .sc` y no ganaría. */
.t-supporting_content.v-bandas .sc:not(:has(.sc__figura)),
.t-supporting_content.v-mosaico .sc:not(:has(.sc__figura)),
.t-supporting_content.v-bandas .local:not(:has(.local__figura)),
.t-supporting_content.v-mosaico .local:not(:has(.local__figura)),
.t-supporting_content.v-bandas .sc__banda2:not(:has(.sc__figura2)) {
  grid-template-columns: minmax(0, 1fr);
}


/* ══════════════════════════════════════════════════════════════════════════
   PIEL `contacto` · LOS DOS CENTRADOS      pedido del operador, 2026-08-17
   ══════════════════════════════════════════════════════════════════════════

   VA AL FINAL DEL ARCHIVO, y no al lado de las reglas que corrige, por lo
   mismo que ya está documentado dos veces más arriba: las declaraciones que
   se pisan tienen la MISMA especificidad que estas, así que lo único que
   decide es el orden. Escribirlas junto a su original no cambiaría nada.

   ── 1 · LA FILA DE SPECS TOCABA EL FILETE ─────────────────────────────────
   `.hero__spec` sale con relleno izquierdo 0 y filete a la derecha, y la regla
   que levanta ese relleno a 0.6rem está escrita SOLO bajo `.v-ficha`: en esta
   piel nunca se aplicó. "Reply window", "Cities" y "License" arrancaban
   pegados al filete de su izquierda. Se centra el par dentro de su columna y
   el relleno vuelve simétrico a los dos lados, incluido el último, que lo
   tenía apagado junto con su filete. El filete del último SÍ se queda
   apagado; lo que vuelve es el relleno. */
.v-contacto .hero__spec { padding: 0.7rem 0.75rem; text-align: center; }
.v-contacto .hero__spec:last-child { padding-right: 0.75rem; }

/* ── 2 · EL PANEL DEL FORMULARIO VUELVE AL CENTRO ──────────────────────────
   Revierte a propósito la decisión que dejó escrita la regla de arriba ("el
   formulario del sitio va centrado y acá es un panel de trabajo: vuelve a la
   izquierda"). Se centra SOLO el chrome del panel: el titular, la línea del
   teléfono, la de consentimiento y el botón.

   LAS ETIQUETAS Y LOS CAMPOS NO SE TOCAN, por lo que dice la regla base de
   `.form__campos`: un campo con el texto centrado se lee mal y se llena peor.
   Por eso el centrado se declara pieza por pieza y no con un `text-align` en
   `.form`, que bajaría heredado hasta adentro de cada <input>. */
.v-contacto .hero__form .form__h2,
.v-contacto .hero__form .form__nota,
.v-contacto .hero__form .form__legal { text-align: center; }
.v-contacto .hero__form .form__campos > button { justify-self: center; }

/* La línea de consentimiento es hija directa de la grilla de dos columnas y
   nunca declaró columna: se auto-colocaba en la mitad izquierda y se leía a
   media caja. Se le da el ancho entero, que además es la condición para que
   centrarla se note. Mismo defecto tiene el formulario de cierre del resto
   del sitio, que es otra piel y no se toca desde acá. */
.v-contacto .hero__form .form__campos > .form__legal { grid-column: 1 / -1; }

/* En móvil la fila cae a dos columnas y el filete del SEGUNDO spec queda
   colgando contra el borde derecho de la caja, sin nada a la derecha que
   separar. `.v-ficha` lo apaga por posición par desde el bloque de 860px;
   esta piel no estaba en ese selector. Se apaga solo el filete: el relleno
   simétrico se queda, que es lo que despega el dato de la línea del medio. */
@media (max-width: 860px) {
  .v-contacto .hero__spec:nth-child(even) { border-right: 0; }
}


/* ══════════════════════════════════════════════════════════════════════════
   LA FIGURA DE `apertura` VUELVE A LA COLUMNA 1 CUANDO LA CAJA APILA
   detectado por el bloque I · 2026-08-25 · ver MEMORY.md §4 #245 y #246
   ══════════════════════════════════════════════════════════════════════════

   MISMO defecto que el de `.sc__banda2`, en otras tres pieles, y esta vez lo
   encontró `scripts/layout.py` en lugar de una persona mirando el teléfono.

   `.apertura__figura` está fijada en `grid-column: 2` FUERA de todo @media.
   Cada piel apila su `.apertura` a una columna en el breakpoint que le toca,
   pero NINGUNA devuelve la figura a la columna 1. El grid entonces le fabrica
   una columna implícita, la implícita se lleva el ancho disponible y la pista
   explícita —la del TEXTO— se resuelve en casi cero.

   Medido sobre las páginas publicadas, antes de esto:
     · 9 gbp_service `v-revista` @890px → `0px 756.5px`, con tres párrafos de
       139, 482 y 281 caracteres en CERO de ancho
     · 5 location_page `v-zigzag` @390px → una pista de 50px, con un párrafo
       de 726 caracteres saliendo a una palabra por línea

   VA AL FINAL, por lo mismo que las otras dos correcciones de más arriba: la
   declaración que se pisa tiene la misma especificidad que ésta, así que lo
   único que decide es el orden.

   Y va SEPARADO POR BREAKPOINT a propósito. Las pieles no apilan todas en el
   mismo ancho —`v-revista` en 56rem, `v-zigzag` y `v-ficha` en 860px— y un
   reset que se adelante al colapso de su propia caja es PEOR que el bug: mete
   la foto encima del texto en una caja que todavía tiene dos columnas. El
   reset acompaña al colapso, uno por uno. */

@media (max-width: 56rem) {
  .t-gbp_service.v-revista .apertura__figura { grid-column: 1; grid-row: auto; }
}

@media (max-width: 860px) {
  .t-location_page.v-zigzag .apertura__figura,
  :is(.t-location_page, .t-utility).v-ficha .apertura__figura {
    grid-column: 1; grid-row: auto;
  }
}

/* Y la SEGUNDA causa del mismo síntoma, que no es grid sino relleno.
   `.apertura` de zigzag corre en una caja más angosta a propósito —canaleta de
   170 contra 1.100 de ancho, para que el ojo baje del hero al texto—, y ese
   piso de 170px está escrito con un `max()` que NO se afloja en móvil:

       padding-inline: max(170px, (100% - 1100px) / 2);

   En 390px eso es `max(170px, -355px)` = 170 por lado, o sea 340 de los 390.
   Quedan CINCUENTA para el texto, y ahí es donde salían los párrafos de 726
   caracteres a una palabra por línea. El resto de las secciones de la misma
   página usa 20px a ese ancho: la apertura era la única con el piso puesto.

   Se iguala al resto SOLO cuando apila. Arriba de 860px la canaleta ancha es
   la maqueta y se respeta. */
@media (max-width: 860px) {
  .t-location_page.v-zigzag .apertura {
    padding-inline: max(var(--canaleta), (100% - var(--ancho)) / 2);
  }
}


/* ══════════════════════════════════════════════════════════════════════════
   LA APERTURA DE `v-ficha` APILA MIENTRAS NO HAYA LUGAR, NO 36 px DESPUÉS
   detectado por el bloque I · 2026-08-25
   ══════════════════════════════════════════════════════════════════════════

   Las cinco `countertop-contractor-near-*` publicaban la bajada del H1 en una
   columna de 170 px con ~400 vacíos al lado: párrafos de 776 caracteres a tres
   palabras por línea.

   QUEDÓ ANOTADO EL 2026-08-25 COMO UNA VENTANA DE 36 px —`v-ficha` colapsa en
   860 y `v-revista` en 56rem (896)— Y ESA LECTURA ERA INCOMPLETA. Barrido el
   2026-08-25 sobre `/countertop-contractor-near-flamingo-gardens/`:

       855 px → limpia, sin un aviso        (ya apiló)
       865 px → texto en 145 px
       890 px → texto en 170 px
       900 px → texto en 180 px
       920 px → texto en 200 px

   O sea que el defecto no se termina en 896: sigue subiendo con la pantalla.
   La cuenta lo explica y no deja lugar a interpretación — a 890, el `main` de
   esta piel resuelve

       [full-start] 60 [ind-start] 220 [ind-end] 48 [cont-start] 502 [cont-end] 60

   así que el riel del índice se lleva 268 fijos, y de los 502 que quedan la
   apertura reserva 300 para la foto más 32 de canaleta:

       texto = viewport − 60 − 220 − 48 − 60 − 32 − 300 = viewport − 720

   Con esa recta, el texto recién llega a 400 px —unos 50 caracteres por
   línea— a los 1.120. Unificar los dos breakpoints habría movido el borde de
   860 a 896 y bajado la cuenta de avisos, que se lee como progreso y deja las
   pantallas de 900 a 1.050 igual de rotas. Es el #247 otra vez: el síntoma se
   cierra midiendo los casos, no leyendo la mejora.

   Por eso el corte va en 70rem (1.120 px) y no en 56, y va SOLO en esta piel:
   `v-revista` no tiene riel de índice y su cuenta es otra. Arriba de 1.120 la
   foto al costado es la maqueta y se respeta intacta.

   Y VA EN LAS CUATRO SECCIONES, no sólo en la apertura. Arreglada la apertura
   sola, los avisos de esa página cayeron de 16 a 4 —que otra vez se lee como
   terminado— y los 4 que quedaban eran el MISMO defecto en dos hermanas que
   nadie había nombrado, medidas en el DOM a 890:

       section.angulo        → `175.312px 300px`, párrafo de 583 caracteres
       section.servicio-ahi  → `195.312px 280px`, párrafo de 545 caracteres

   `.direcciones` entra por coherencia y no por su aviso: es `1fr 1fr`, a 890
   da 238 px por lado y su párrafo de 698 caracteres queda bajo el umbral por
   poco. Dejarla al costado sería publicar la misma piel con tres secciones
   apiladas y una no. Las cuatro comparten forma —texto en la 1, `__figura` en
   la 2— así que comparten el corte. */
@media (max-width: 70rem) {
  :is(.t-location_page, .t-utility).v-ficha :is(.apertura, .angulo, .servicio-ahi, .direcciones) {
    grid-template-columns: minmax(0, 1fr);
  }
  :is(.t-location_page, .t-utility).v-ficha
    :is(.apertura__figura, .angulo__figura, .servicio-ahi__figura, .direcciones__figura) {
    grid-column: 1; grid-row: auto;
  }
}


/* ══════════════════════════════════════════════════════════════════════════
   LA TIRA DE SPECS PASA A DOS Y DOS DONDE DEJA DE ENTRAR, NO 30 px ANTES
   detectado por el bloque I · 2026-08-25
   ══════════════════════════════════════════════════════════════════════════

   Este arreglo no inventa un criterio: LO COPIA. La maqueta ya decide pasar a
   dos y dos, y su propio comentario dice por qué —«cuatro columnas en 350 px
   dan 87 px cada una y el valor se parte»—. Lo único mal puesto era el umbral:
   la regla vive en `max-width: 860px`, y a 890 la tira mide 341 px, o sea

       341 / 4 = 85 px por columna

   que es el ancho que ese mismo comentario declara roto. El defecto estaba
   descrito con precisión y medido en el lugar equivocado.

   Medido en el DOM sobre `/marble-countertop-installation-davie/` @890, con
   los cuatro `dd` en `white-space: nowrap`:

       «2 cm / 3 cm»        79 px de texto en 85  → entra
       «Polished or honed» 130 px de texto en 65  → SE VA 65 px afuera
       «1–2 days»           65 px de texto en 65  → entra justo

   El `nowrap` NO se toca y no es el culpable: es lo que impide que «2 cm /
   3 cm» o «1–2 days» se partan al medio, que es peor que desbordar. Lo que
   sobra son columnas. Con dos, esos 341 px dan 170 por columna y el valor
   largo entra con lugar de sobra.

   Va hasta 70rem, el mismo corte que la corrección de arriba, y por la misma
   cuenta: a 1.100 la tira todavía no junta los ~140 px por columna que pide
   el valor más largo. Arriba de eso la maqueta queda intacta, en cuatro.

   Los filetes y los rellenos viajan CON el cambio de columnas. Son los mismos
   que ya trae el bloque de 860: sin ellos, dos y dos publica el filete de la
   segunda columna contra el borde, que es el defecto que ese bloque arregló
   en su momento. */
@media (max-width: 70rem) {
  .v-ficha .hero__specs,
  .v-contacto .hero__specs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .v-ficha .hero__spec:nth-child(even) { border-right: 0; padding-right: 0; }
  .v-ficha .hero__spec:nth-child(odd) { padding-left: 0; }
}


/* El mail de la legal se parte. No es layout: es UNA PALABRA que no entra.
   `info@kitchenremodelerdavie.com` mide 246 px en una caja de 208 y el
   navegador no corta solo por la arroba ni por el punto, así que se iba de la
   caja con `white-space: normal` y todo. Sin regla, achicar la caja no
   arregla nada: la palabra es la palabra.

   Va `anywhere` y no `break-word` a propósito: en un contenedor flex —éste lo
   es— sólo `anywhere` afecta también el tamaño mínimo del ítem, que es lo que
   hace que la caja acepte el corte en lugar de estirarse. Y va acotado a los
   datos de la legal: partir palabras en cualquier lado es correcto para un
   mail o una URL y no lo es para la prosa. */
.legal__datos dd { overflow-wrap: anywhere; }
