/* ---------------------------------------------------------------------------
   Brand accent: #f3350c -> #F65600

   The template exposes the accent as a custom property, so redefining it here
   recolours everything that reads the variable. Four selectors hardcode the
   old hex instead of reading it, so they are overridden explicitly -- the
   template stylesheet itself is left untouched.
--------------------------------------------------------------------------- */
:root { --_colors---primary--accent: #F65600; }

.navbar_works-number-wrap,
.work-list_number,
.work-list_dot,
.home-services_number { background-color: #F65600; }

/* kv — custom sections for the Kensho content migration.
   Pattern source: diroz/reports/section-spec.md, rebuilt in Alture vocabulary.
   Rules honoured (design-system/DESIGN-SYSTEM.md):
   - spacing joins the template scale (8/16/20/24/32 gaps, section padding via classes)
   - colours come from the template tokens; accent = --_colors---primary--accent
   - radii 12/18, transitions 0.2s ease only
   - fluid type via template utility classes in the markup, not here */

/* ---------- services accordion rows (diroz .services) ---------- */
.kv-services_list { display: flex; flex-direction: column; }

.kv-services_row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px;
  align-items: start;
  padding-top: 48px;
  padding-bottom: 48px;
  border-top: 1px solid var(--_colors---grey--200, rgba(0, 0, 0, .1));
}
.kv-services_row:last-child { border-bottom: 1px solid var(--_colors---grey--200, rgba(0, 0, 0, .1)); }

.kv-services_head { display: flex; flex-direction: column; gap: 24px; align-items: flex-start; }

.kv-services_number {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .05em;
  color: var(--_colors---primary--accent, #F65600);
}

.kv-services_items { display: flex; flex-direction: column; gap: 8px; }
.kv-services_item { display: flex; align-items: center; gap: 8px; }
.kv-services_dot {
  width: 6px; height: 6px; border-radius: 50%;
  background-color: var(--_colors---primary--accent, #F65600);
  flex-shrink: 0;
}

.kv-services_img-wrap {
  border-radius: 18px;
  overflow: hidden;
  aspect-ratio: 588 / 500;
}
.kv-services_img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* buttons: template pill, accent filled (diroz's View Full Details, Kensho red) */
.kv-button {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 12px 24px;
  border-radius: 144px;
  background-color: var(--_colors---primary--accent, #F65600);
  color: #fff;
  font-size: 14px; font-weight: 600;
  transition: opacity 0.2s ease;
  text-decoration: none;
}
.kv-button:hover { opacity: .85; }
.kv-button.is-ghost {
  background-color: transparent;
  color: #000;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .2);
}

/* ---------- service detail split (diroz .service-details, 300px gutter) ---------- */
.kv-detail_grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px 300px; /* the 300px gutter is the section's signature — spec'd from diroz */
  align-items: start;
}
.kv-detail_right { display: flex; flex-direction: column; gap: 32px; }
.kv-detail_items { display: flex; flex-direction: column; gap: 16px; }
.kv-detail_hero-wrap { border-radius: 18px; overflow: hidden; }
.kv-detail_hero { width: 100%; height: auto; display: block; }

/* caption pattern (diroz .section-caption: 20px icon + label, gap 8) */
.kv-caption { display: flex; align-items: center; gap: 8px; }

/* ---------- sticky stacking process cards (diroz .process) ---------- */
.section_kv-process { background-color: var(--_colors---grey--100, #efeeea); }

/* El wrap define el recorrido; el sticky se pega dentro de él y el runway es
   sólo la altura que da ese recorrido. Antes el runway iba DEBAJO del sticky y
   sumaba su altura como hueco gris vacío: ahora el sticky se superpone al
   runway (margin-bottom negativo), así que la sección mide el recorrido y
   nada más. */
.kv-process_wrap { position: relative; }
.kv-process_sticky {
  position: sticky;
  top: 160px;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  z-index: 1;
  margin-bottom: -420px;      /* alto de una card: el runway pasa por debajo */
}
.kv-process_runway { height: 1500px; }
.kv-process_card {
  border-radius: 18px;
  background-color: var(--_colors---primary--accent, #F65600);
  color: #000;
  padding: 32px;
  min-height: 420px;
  display: flex; flex-direction: column; justify-content: space-between;
  will-change: transform;
}
.kv-process_card-top { display: flex; justify-content: space-between; align-items: flex-start; }
.kv-process_card-number { font-size: 14px; font-weight: 600; letter-spacing: .05em; }
.kv-process_card-icon { width: 64px; height: 64px; object-fit: cover; border-radius: 12px; }
.kv-process_card-body { display: flex; flex-direction: column; gap: 8px; }

/* ---------- pricing ---------- */
.kv-plans_grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  align-items: stretch;
}
.kv-plans_grid.is-4 { grid-template-columns: repeat(4, 1fr); }
.kv-plan {
  border-radius: 18px;
  background-color: #fff;
  padding: 32px;
  display: flex; flex-direction: column; gap: 24px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
  position: relative;
}
.kv-plan.is-featured { box-shadow: inset 0 0 0 2px var(--_colors---primary--accent, #F65600); }
.kv-plan_ribbon {
  position: absolute; top: 24px; right: 24px;
  font-size: 12px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  color: #fff;
  background-color: var(--_colors---primary--accent, #F65600);
  border-radius: 144px;
  padding: 4px 12px;
}
.kv-plan_price-row { display: flex; align-items: baseline; gap: 8px; }
.kv-plan_features { display: flex; flex-direction: column; gap: 8px; }
.kv-plan_feature { display: flex; gap: 8px; align-items: flex-start; }
.kv-plan_feature .kv-services_dot { margin-top: 7px; }
.kv-plan_feature.is-off { opacity: .45; }
.kv-plan_feature.is-off .kv-services_dot { background-color: var(--_colors---grey--400, #999); }
.kv-plan_foot { margin-top: auto; display: flex; flex-direction: column; gap: 16px; }

/* specialized services grid */
.kv-espec_grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.kv-espec_card {
  border-radius: 18px;
  overflow: hidden;
  background-color: #fff;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
  display: flex; flex-direction: column;
}
.kv-espec_img-wrap { aspect-ratio: 4 / 3; overflow: hidden; }
.kv-espec_img { width: 100%; height: 100%; object-fit: cover; display: block; }
.kv-espec_body { padding: 24px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.kv-espec_price { margin-top: auto; padding-top: 16px; font-weight: 600; color: var(--_colors---primary--accent, #F65600); }

/* ---------- reveals: initial state only; GSAP animates (no CSS transition) ---------- */
.kv-reveal { opacity: 0; }
html.kv-no-js .kv-reveal { opacity: 1; }

/* ---------- responsive: grids collapse at 991 like the template ---------- */
@media screen and (max-width: 991px) {
  .kv-services_row, .kv-detail_grid { grid-template-columns: 1fr; }
  .kv-detail_grid { gap: 48px; }
  .kv-plans_grid, .kv-plans_grid.is-4, .kv-espec_grid { grid-template-columns: 1fr 1fr; }
  .kv-process_sticky { grid-template-columns: 1fr 1fr; position: static; }
  .kv-process_runway { display: none; }
  .kv-process_card { min-height: 320px; }
}
@media screen and (max-width: 767px) {
  .kv-plans_grid, .kv-plans_grid.is-4, .kv-espec_grid { grid-template-columns: 1fr; }
  .kv-process_sticky { grid-template-columns: 1fr; }
}

/* detail hero keeps diroz's wide 1360x592 crop */
.kv-detail_hero-wrap { aspect-ratio: 1360 / 592; }
.kv-detail_hero { height: 100%; object-fit: cover; }

/* ---------- fixes de revisión (2026-08-23) ---------- */

/* FAQ: la primera pregunta es más ancha que las demás y `flex-flow: wrap`
   empujaba el botón + a una segunda fila. Medido: botón a +48px del texto en
   el item 1 vs -8px en el resto. nowrap lo devuelve a la derecha siempre. */
.faq_question-wrap { flex-wrap: nowrap; align-items: center; }
.faq_question-wrap .faq_button { flex: none; }

/* Footer: copyright a la izquierda.
   `.footer_legal-links` es un grid de 3 columnas con place-items:center y el
   wrap vive en la columna central por un id de Webflow (w-node). Se colapsa a
   una sola columna alineada al inicio, que es lo que fuerza la izquierda. */
.footer_legal-links {
  /* El template lo centra con place-items:center en un grid de 3 columnas.
     Sólo cambiamos la alineación; NO tocamos su participación en el grid
     padre (hacerlo lo sacaba del recuadro blanco del footer). */
  place-items: center start;
}
.footer_legal-wrap { justify-content: flex-start; }
.footer_copyright { text-align: left; }

/* Footer: el wordmark en UNA sola fila y recortado por abajo, de modo que la
   parte inferior del trazo sangre contra el fondo de la página.
   El tamaño del template (20vw / 25vw) desbordaba a lo ancho y quedaba
   "Kensho Visu…": 12.2vw es el que hace caber "Kensho Visual" completo en el
   ancho del contenedor a cualquier viewport. */
.footer_brand {
  white-space: nowrap;
  display: block;
  overflow: hidden;
  font-size: 12.2vw;
  line-height: 1;
  /* El texto ocupaba 1.185em de alto con el ® original; al reducir el  pasa a
     1.0em, así que 1.12em ya no recortaba nada. 0.95em vuelve a sangrar sólo la
     puntita inferior del trazo, que es el efecto buscado. */
  max-height: 0.95em;
  margin-bottom: -0.03em;
}
@media screen and (max-width: 767px) {
  .footer_brand { font-size: 13.2vw; max-height: 0.96em; }
}

/* Loader: el wordmark queda pequeño a 7rem (90×16 medidos). Sube a 11rem. */
.brand_logo { width: var(--fixed--11rem, 11rem); height: auto; }
@media screen and (max-width: 767px) { .brand_logo { width: var(--fixed--8rem, 8rem); } }

/* ---------- process cards: legibilidad + variante home ---------- */
/* Sergio: títulos y texto en blanco sobre el rojo, se lee mejor */
.kv-process_card, .kv-process_card h3, .kv-process_card p, .kv-process_card .kv-process_card-number { color: #fff; }
.kv-services_dot.is-light { background-color: #fff; }
.kv-process_card-arrow { font-size: 20px; line-height: 1; }

.kv-process_card.is-home {
  text-decoration: none;
  min-height: 380px;
  transition: opacity 0.2s ease;
}
.kv-process_card.is-home:hover { opacity: .9; }
.kv-process_wrap.is-home .kv-process_sticky { top: 160px; margin-bottom: -380px; }
/* runway más corto: Sergio reportó demasiado scroll vacío antes de que entren */
.kv-process_wrap.is-home .kv-process_runway { height: 1400px; }
.kv-home-services_cta { display: flex; justify-content: center; }

/* ================= /services — filas apiladas (patrón diroz) =================
   Medido en diroz: .services-collection es position:sticky top:32px; la tarjeta
   es blanca, radius 16, padding 68/40; título 80px/600. El apilado es CSS puro:
   cada fila se pega y la siguiente la cubre. */
.kv-svc_list { display: flex; flex-direction: column; gap: 32px; }

.kv-svc_sticky {
  position: sticky;
  /* cada tarjeta se pega 12px más abajo que la anterior: deja ver el borde
     de las de atrás, como en diroz */
  top: calc(96px + var(--kv-svc-i) * 12px);
}

.kv-svc_card {
  display: grid;
  grid-template-columns: 1fr 588px;
  gap: 40px;
  align-items: stretch;
  background-color: #fff;
  border-radius: 18px;
  padding: 56px 40px;
  /* Mismo borde sombreado que las stacking cards de la home (.is-home): borde
     interior de 1px + labio superior + sombra de apoyo. Antes esta versión
     llevaba sólo una línea plana y las tarjetas apiladas no se separaban
     unas de otras. */
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08),
              0 -1px 0 rgba(0, 0, 0, .10),
              0 8px 24px rgba(0, 0, 0, .28);
}

.kv-svc_left { display: flex; flex-direction: column; }
.kv-svc_head { display: flex; align-items: baseline; gap: 20px; }
.kv-svc_number {
  font-size: 20px; font-weight: 500;
  color: var(--_colors---primary--accent, #F65600);
  flex: none;
}
.kv-svc_title {
  font-size: 64px; font-weight: 600; line-height: 1.05; letter-spacing: -.03em;
  margin: 0;
}
.kv-svc_items {
  display: flex; flex-direction: column; gap: 8px;
  margin-top: 32px;
  font-size: 20px;
}
.kv-svc_item { display: flex; align-items: center; gap: 12px; }

/* botón: alineado al fondo del bloque, es decir a lo largo del alto de la
   imagen — como en diroz, donde queda al pie de la fila */
.kv-svc_btn-wrap { margin-top: auto; padding-top: 40px; }
.kv-svc_button {
  display: inline-flex; align-items: center; gap: 16px;
  background-color: var(--_colors---primary--accent, #F65600);
  border-radius: 4px;
  padding: 10px 20px 10px 12px;
  text-decoration: none;
  transition: opacity 0.2s ease;
}
.kv-svc_button:hover { opacity: .88; }
.kv-svc_button-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border-radius: 4px;
  /* Solid white square, black arrow -- was a translucent white that read as a
     washed-out patch on the accent. */
  background-color: #fff;
  color: #000; font-size: 18px; line-height: 1;
}
/* Sergio: el texto del botón en BLANCO (diroz lo tiene oscuro y se lee mal) */
.kv-svc_button-text { color: #fff; font-size: 18px; font-weight: 500; }

.kv-svc_img-wrap { border-radius: 12px; overflow: hidden; min-height: 460px; }
.kv-svc_img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media screen and (max-width: 991px) {
  .kv-svc_card { grid-template-columns: 1fr; padding: 40px 28px; gap: 32px; }
  .kv-svc_title { font-size: 44px; }
  .kv-svc_items { font-size: 18px; margin-top: 24px; }
  .kv-svc_img-wrap { min-height: 0; aspect-ratio: 588 / 420; order: -1; }
  .kv-svc_btn-wrap { padding-top: 28px; }
  /* en móvil se sigue apilando, con menos desplazamiento */
  .kv-svc_sticky { top: calc(80px + var(--kv-svc-i) * 8px); }
}
@media screen and (max-width: 767px) {
  .kv-svc_title { font-size: 34px; }
  .kv-svc_head { flex-direction: column; align-items: flex-start; gap: 8px; }
  .kv-svc_card { padding: 28px 20px; }
  .kv-svc_items { font-size: 16px; }
  .kv-svc_button-text { font-size: 16px; }
}

/* ================= filtro de proyectos (pestañas) ================= */
.kv-filter { display: flex; }
.kv-filter_tabs {
  display: flex; flex-wrap: wrap; gap: 8px;
}
.kv-filter_tab {
  display: inline-flex; align-items: center; gap: 8px;
  border: 0;
  border-radius: 144px;
  padding: 10px 20px;
  background-color: rgba(0, 0, 0, .06);
  color: #000;
  font-family: inherit; font-size: 14px; font-weight: 500;
  cursor: pointer;
  transition: opacity 0.2s ease;
}
.kv-filter_tab:hover { opacity: .7; }
.kv-filter_tab.is-active { background-color: #000; color: #fff; }
.kv-filter_count { font-size: 12px; opacity: .5; }
.kv-filter_tab.is-active .kv-filter_count { opacity: .6; }
.work-list_item.is-hidden,
.work-list_list-v3 > .work-list_item.is-hidden { display: none; }
/* los vídeos de tarjeta se comportan como las imágenes */
video.work-list_image-v2 { width: 100%; height: 100%; object-fit: cover; display: block; }

@media screen and (max-width: 767px) {
  .kv-filter_tab { padding: 8px 14px; font-size: 13px; }
}

/* ================= espaciado entre secciones =================
   Bug medido: mis secciones nuevas metían `padding-section-*` en un div
   interno, así que la propia <section> cerraba a 0px y la siguiente (la CTA
   negra, o el bloque gris de proceso) quedaba pegada sin white space.
   El template usa 128px como ritmo por defecto (padding-section-medium). */
.section_kv-header,
.section_kv-services,
.section_kv-detail,
.section_kv-includes,
.section_kv-plans,
.section_kv-espec { padding-bottom: 128px; }

.section_kv-header { padding-bottom: 64px; }   /* el header ya respira arriba */

/* la sección de proceso es la que trae fondo propio: necesita aire a ambos lados */
.section_kv-process { padding-top: 96px; padding-bottom: 128px; }

@media screen and (max-width: 991px) {
  .section_kv-header, .section_kv-services, .section_kv-detail,
  .section_kv-includes, .section_kv-plans, .section_kv-espec { padding-bottom: 80px; }
  .section_kv-header { padding-bottom: 48px; }
  .section_kv-process { padding-top: 64px; padding-bottom: 80px; }
}
@media screen and (max-width: 767px) {
  .section_kv-header, .section_kv-services, .section_kv-detail,
  .section_kv-includes, .section_kv-plans, .section_kv-espec { padding-bottom: 64px; }
  .section_kv-process { padding-top: 48px; padding-bottom: 64px; }
}

/* ================= /pricing: selector pill + aire lateral =================
   Patrón tomado de kenshovisual.com (.svc-tabs / .svc-tab.active): contenedor
   con fondo y píldora activa rellena. Traducido a la paleta Alture. */
.kv-plans_switch { display: flex; justify-content: center; }
.kv-pill {
  display: inline-flex; gap: 4px; padding: 4px;
  background-color: rgba(0, 0, 0, .05);
  border-radius: 144px;
}
.kv-pill_tab {
  border: 0; cursor: pointer;
  font-family: inherit; font-size: 14px; font-weight: 500;
  color: var(--_colors---grey--500, #4d4d4d);
  background: transparent;
  border-radius: 144px;
  padding: 10px 22px;
  transition: opacity 0.2s ease;
}
.kv-pill_tab:hover { opacity: .7; }
.kv-pill_tab.is-active { color: #fff; }
.kv-plans_panel { display: none; }
.kv-plans_panel.is-active { display: block; }

/* Sergio: más room lateral para las cards */
.section_kv-plans .container-medium,
.section_kv-espec .container-medium { padding-left: 24px; padding-right: 24px; }
.kv-plans_grid { gap: 20px; }

/* títulos de plan SIEMPRE en una línea (rompían el diseño a dos) */
.kv-plan h3.heading-style-h4 {
  white-space: nowrap;
  font-size: clamp(15px, 1.35vw, 20px);
  letter-spacing: -.02em;
}
.kv-plan .kv-plan_price-row h3 { white-space: nowrap; font-size: clamp(26px, 2.4vw, 40px); }

@media screen and (max-width: 991px) {
  .kv-plan h3.heading-style-h4 { font-size: 18px; }
  .section_kv-plans .container-medium,
  .section_kv-espec .container-medium { padding-left: 12px; padding-right: 12px; }
}

/* ================= /contact: form izquierda, FAQ derecha =================
   Sergio: el formulario baja bajo el título y las preguntas frecuentes van a
   su derecha (donde antes estaba el hueco del form).
   `contact_component` es la fila título|contenido del template; el grid se
   inserta como hermano de `contact_content` y ocupa todo el ancho. */
.contact_component { display: block; }
.contact_content { max-width: 720px; }
.kv-contact_grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px;
  align-items: start;
  margin-top: 64px;
}
.kv-contact_col > div { margin: 0; }
.kv-contact_grid .spacer-xhuge { display: none; }

@media screen and (max-width: 991px) {
  .kv-contact_grid { grid-template-columns: 1fr; gap: 48px; margin-top: 40px; }
}

/* El spacer-huge del final de cada panel ya aporta 96px; sumarle los 128 de
   la sección daba 224px de vacío. El último panel no necesita el suyo. */
.kv-plans_panel > .spacer-huge:last-child { display: none; }

/* ---------- variante home del stack de servicios ----------
   Mismas filas que /services (patrón diroz), sobre el panel oscuro de la home. */
.kv-svc_list.is-home .kv-svc_sticky { top: calc(104px + var(--kv-svc-i) * 12px); }
/* Cada tarjeta necesita leerse como una pieza propia al apilarse. Sobre el
   panel negro una sombra oscura no se ve, así que el separador real es el
   filo: hairline que oscurece el borde de la tarjeta blanca (el mismo token
   de .kv-plan / .kv-v2_block) + una sombra exterior suave que despega la que
   cubre de la de debajo. Muy sutil, sin marco visible. */
.kv-svc_list.is-home .kv-svc_card {
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08),
              0 -1px 0 rgba(0, 0, 0, .10),
              0 8px 24px rgba(0, 0, 0, .28);
}
.kv-home-services_cta { display: flex; justify-content: center; }
@media screen and (max-width: 991px) {
  .kv-svc_list.is-home .kv-svc_sticky { top: calc(80px + var(--kv-svc-i) * 8px); }
}

/* /works/3: la lista llega hasta el borde de la sección y el footer quedaba
   pegado. El template usa 128px de ritmo. */
.section_work-list { padding-bottom: 128px; }
@media screen and (max-width: 991px) { .section_work-list { padding-bottom: 80px; } }
@media screen and (max-width: 767px) { .section_work-list { padding-bottom: 64px; } }

/* Servicios especializados: el h4 del template renderiza a 44px y desbordaba
   las tarjetas (medido: "Gestión de anuncios/campañas" a 389px en 368px). */
.kv-espec_card h3 {
  font-size: clamp(19px, 1.5vw, 22px);
  line-height: 1.2;
  letter-spacing: -.02em;
  overflow-wrap: break-word;
}

/* Hero wordmark: TM in a lighter grey than the near-black heading.
   Position/size deliberately untouched -- only the colour changes. */
.home-header_mark {
  color: #6b6b6b;
  /* The template sets extra-bold (800) here, heavier than the 600 heading it
     sits on -- fine for the ® it shipped with, too heavy for a . */
  font-weight: 400;
}

/* ---------------------------------------------------------------------------
   Logo cloud (replaces the brands carousel)

   Rebuilt from the 21st.dev logo-cloud block, which is React + Tailwind +
   @remixicon/react -- none of which exist on this static Webflow site. What is
   reproduced is the design: monochrome icon + wordmark, one row, continuous
   translateX(0 -> -50%) over a duplicated track, edge fade, pause on hover.

   Colours measured off this page, not invented: body background #f8f7f3,
   heading #000. The resting grey is the template's own muted tone.
--------------------------------------------------------------------------- */
.kv-cloud {
  position: relative;
  overflow: hidden;
  /* The fade IS the "blur" of the reference: content dissolves into the page
     background at both edges instead of being cut by a hard line. */
  /* Long, soft ramps: fully opaque only across the middle third, so the row
     reads as a narrow band instead of a full-width strip. The reference used
     12%/88%; these much wider ramps are what shortens it visually without
     touching the track width. */
  -webkit-mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,.15) 12%, #000 34%, #000 66%, rgba(0,0,0,.15) 88%, transparent 100%);
          mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,.15) 12%, #000 34%, #000 66%, rgba(0,0,0,.15) 88%, transparent 100%);
}

.kv-cloud_track {
  display: flex;
  width: max-content;
  align-items: center;
  /* 90s: the track travels half its 9366px width per cycle, so this is ~52px/s
     (was ~78px/s at 60s). Slow enough to read each name as it passes. */
  animation: kv-cloud-marquee 90s linear infinite;
}

/* Deliberately NOT paused on hover: the reference block pauses, Sergio asked
   for continuous motion. */

@keyframes kv-cloud-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.kv-cloud_item {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 10px;
  /* Vertical padding gives the row presence: a bare 24px strip reads as thin
     in a section whose spacing scale is 56/128. Horizontal 32px is the
     reference block's own px-8. */
  padding: 20px 38px;
  color: rgba(0, 0, 0, .45);
  transition: color .2s ease;
}

.kv-cloud .kv-cloud_item:hover { color: #000; }

.kv-cloud_icon {
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
}

.kv-cloud_name {
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -.01em;
  line-height: 1;
  white-space: nowrap;
}

@media (max-width: 767px) {
  /* Keep the vertical padding from the base rule -- an earlier `0 22px` here
     reset it and collapsed the row to 20px on phones. */
  .kv-cloud_item { padding: 15px 24px; gap: 9px; }
  .kv-cloud_name { font-size: 17px; }
  .kv-cloud_icon { width: 22px; height: 22px; }
}

/* Keep the composition, drop the motion. */
@media (prefers-reduced-motion: reduce) {
  .kv-cloud_track { animation: none; }
}

/* The template puts a full-width divider at the top of section_work-list (it is
   in the untouched Alture pristine too). Under the logo cloud it reads as a
   stray dotted rule, so it is hidden on the home page only. */
.section_work-list > .padding-global.is-tiny > .line { display: none; }

/* ---------------------------------------------------------------------------
   /works/3 cards — image and info as ONE object

   The template ships these as two detached pieces: a square image, a 20px gap,
   then a separately-rounded colour block whose height follows its own text. So
   the row read as six loose shapes with ragged bottoms.

   Now: one rounded card, image flush on top, info panel welded beneath it, and
   the panels bottom-aligned so a row ends on a straight line. Colour, type and
   radius all stay the template's own.
--------------------------------------------------------------------------- */
.work-list_block-v2 {
  border-radius: var(--border-radius--large, 18px);
  overflow: hidden;               /* the image corners follow the card */
  background: #fff;
  height: 100%;
}

/* kill the gap that split the card in two -- it is flex `gap: 20px` on the
   block itself, not a margin on either child */
.work-list_block-v2 { gap: 0; }

.work-list_image-wrap-v2 {
  border-radius: 0;
  overflow: hidden;
}

.work-list_infos-v2 {
  border-radius: 0;
  margin-top: 0;
  /* the panel takes the leftover height, so every card in a row ends level */
  flex: 1 1 auto;
  align-items: center;
}

/* Equal-height cards across the row. */
.work-list_list-v3 > .work-list_item { display: flex; }
.work-list_list-v3 > .work-list_item > .work-list_block-v2 { width: 100%; }

/* Lift on hover: the whole card responds as one object. */
.work-list_block-v2 {
  transition: transform .2s ease;
}
.work-list_block-v2:hover { transform: translateY(-4px); }

/* ---------------------------------------------------------------------------
   Pricing — the audit is not a plan

   Auditoría SEO is a prerequisite you buy BEFORE choosing a plan, but styled
   like its neighbours it reads as a third competing option. Setting it on the
   template's own grey--50 (#f1efed) separates it as a different KIND of thing
   Uses the template's own grey--50 (#f1efed). A darker #e4e0da was tried for
   stronger separation, but Sergio preferred this lighter, subtler tone -- it
   reads as a different kind of card without shouting.
   Readability measured on that ground: 18.3:1 for the black body copy and
   7.4:1 for the muted grey-500 text, both well past the 4.5:1 WCAG AA
   threshold. The border is darkened a step so the edge stays defined.
--------------------------------------------------------------------------- */
.kv-plan.is-prerequisite {
  background-color: var(--_colors---grey--50, #f1efed);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
}

/* "Pago único" badge — the audit is billed once, not monthly.

   Corrected: the first version imported kensho-web's beige (#E8DDD4/#8B7355),
   a palette from the OLD site that has nothing to do with this template. Every
   colour here must come from this design system. Now it is the template's own
   white surface with grey--700 text -- the same surface language as the plan
   cards -- reading as a quiet chip on the card's grey ground. Contrast 17.9:1. */
.kv-plan_once {
  display: inline-flex;
  align-items: center;
  background: var(--_colors---primary--white, #fff);
  color: var(--_colors---grey--700, #171717);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .1);
  border-radius: 144px;
  padding: 4px 12px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
}

/* "No incluye" label above the greyed items. Deliberately tiny -- it is a
   signpost, not a heading, and the card has no vertical room to spare. */
.kv-plan_offs-label {
  margin-top: 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--_colors---grey--400, #9c9287);
}

/* The trademark mark in running text. Small and raised, so "Kensho Visual"
   reads as a wordmark rather than the  competing with the words. Inherits
   colour so it works on both the light and dark panels it appears on. */
.kv-tm {
  font-weight: 400;
  /* A flat .55em collapsed to 6.6px inside the 12px labels -- unreadable.
     clamp gives a 9px floor for small text while staying proportional in the
     96px headings. */
  font-size: clamp(9px, .55em, 48px);
  vertical-align: super;
  line-height: 0;
  letter-spacing: 0;
}

/* Footer wordmark mark: the template sizes it 10vw (144px at 1440), which was
   fine for the ® it shipped with but makes the  overrun the wordmark's clipped
   box -- its top sat 16px above the box and got sliced. Sized to match .kv-tm's
   proportion and pulled inside the box. */
.footer_mark {
  /* Sits at the TOP of the wordmark, like the original ®. Measured at 1440:
     the letters run from -19 to 193 relative to the clipped box, so the mark's
     top must land near -19, not at 71 (which put it halfway down the "l").
     top:-1.05em on a .26em glyph does that; `super` alone only reached 47. */
  font-size: .26em;
  font-weight: 400;
  vertical-align: baseline;
  position: relative;
  /* NB: `em` here resolves against the MARK's own 45.7px, not the wordmark's
     175.7px -- so the offset is expressed in the parent's scale via a
     multiple of the mark's em: 90px needed / 45.7px = 1.97em. */
  top: -1.97em;
  line-height: 0;
}

/* The wordmark is sized to fill the line, so the  had nowhere to go and
   touched the right edge. A hair of right padding keeps it inside. */
.footer_brand { padding-right: .04em; }

/* CTA button ("Solicita tu auditoría gratuita")

   The template's own 24px line-space plus 16px right padding puts 40px between
   the label and the dot. On the short labels it ships with ("Ver todo") that
   reads as balance; on this long one it reads as a hole. Tightened to 12px --
   the same value the template's own small button variant uses -- and the whole
   button stepped down to that variant's scale, so it stops looking oversized
   next to everything else. */
.cta_component .button-secondary { padding: 10px 14px; }
.cta_component .button-secondary .button-line_space { width: 12px; }
.cta_component .button-secondary .button_text { font-size: 13px; }

/* "Ver precios"/"View pricing" button at the bottom of each individual
   service page (/servicios/<slug>, /en/services/<slug>): same
   `.button-secondary` variant as the home CTA above, same 24px template
   line-space + 12px/16px padding bug -- Sergio reported it as too long /
   badly spaced, most visible on mobile where the pill is nearly as wide as
   the whole content column. Same fix, scoped to `.kv-detail_price` (the
   wrapper this button ships in) instead of `.cta_component`. */
.kv-detail_price .button-secondary { padding: 10px 14px; }
.kv-detail_price .button-secondary .button-line_space { width: 12px; }
.kv-detail_price .button-secondary .button_text { font-size: 13px; }

/* The padding/font-size fix above wasn't the whole story: `.button-secondary`
   is `display: flex` in the template, and a flex box with no `width` set
   still behaves like any other block box outside a flex container -- it
   fills the available width instead of shrinking to its content. That's why
   the pill stretched edge-to-edge (visible on every breakpoint, worst on
   mobile where "the whole content column" IS the available width).
   `inline-flex` + `width: fit-content` makes it size to the label instead of
   the container.

   Its wrapper, `.kv-detail_price`, sits OUTSIDE `.container-medium` in the
   markup (a sibling, not a child, of the padded content block above it) --
   harmless while the button stretched edge to edge, but once it hugs its own
   content it needs the same left offset as the cards above it, or it reads
   as flush against the browser edge. The template's `.padding-global` value
   is responsive (3rem desktop, stepping down at each breakpoint) and isn't a
   single CSS variable that can be read and reused directly, so instead of
   recalculating it here, the HTML now also carries the `padding-global`
   class on this wrapper (see the service-page templates) to pick up that
   same responsive padding automatically. `padding-right` would normally add
   unwanted space after a fit-content box, so it's zeroed back out. */
.kv-detail_price .button-secondary { display: inline-flex; width: fit-content; }
.kv-detail_price.padding-global {
  width: fit-content;
  padding-right: 0;
  margin-top: var(--fixed--1rem);
}

/* ===========================================================================
   /pricing-v2 — pricing page in the home section's visual language

   The home's own .pricing_* classes do the heavy lifting (glass blur, radius,
   the gradient-clipped price); these rules only adapt that two-card section to
   a full page of three switchable groups.
   =========================================================================== */

/* The section is on the black component, so page-level text flips to light. */
.kv-v2 .pricing_wrap { width: 100%; }

.kv-v2_title {
  text-align: center;
  margin-bottom: 8px;
}

.kv-v2_intro {
  max-width: 40rem;
  margin: 0 auto;
  text-align: center;
  color: rgba(255, 255, 255, .6);
}

/* Pill switcher on the dark ground (the light-page rule is black-on-white). */
.kv-v2_switch-label {
  margin-top: 48px;
  text-align: center;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .45);
}

.kv-v2 .kv-plans_switch { margin: 14px 0 0; }
.kv-v2 .kv-pill {
  background-color: rgba(255, 255, 255, .07);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .12);
}
.kv-v2 .kv-pill_tab { color: rgba(255, 255, 255, .65); }
.kv-v2 .kv-pill_tab.is-active { color: #000; }

/* The group heading sits BEHIND the cards: the cards ride up over it so only
   its upper part shows, which is the effect from the home section.
   Sized down hard from .pricing_heading's 240px -- at full size it wrapped to
   three lines and swamped the cards instead of backing them. */
.kv-v2_heading {
  position: relative;
  z-index: 0;
  text-align: center;
  font-size: clamp(48px, 7.4vw, 112px);
  line-height: .95;
  white-space: nowrap;
  margin-bottom: 0;
  pointer-events: none;
}

/* The overlap is owned by .kv-v2_blocks, not the heading: the template's own
   .pricing_blocks carries margin-top:-5rem (-80px), which overrode anything
   set on the heading and buried 94 of the glyphs' 129px -- unreadable.
   -0.14em then went too far the other way: a 16px overlap barely touched the
   descenders, so there was nothing for the glass to blur. -0.32em covers ~35px
   of the 129px glyph -- a real blur band with 73% of the word still legible. */
/* NB: `em` on .kv-v2_blocks resolves against ITS OWN 16px font, not the
   heading's 106px -- -0.32em was only 5px. The heading is clamp(48,7.4vw,112),
   so the overlap is expressed in the same vw unit to track it. */
.kv-v2_blocks { margin-top: clamp(24px, 2.2vw, 40px); }

.kv-v2_blocks {
  position: relative;
  z-index: 1;
  grid-template-columns: repeat(3, 1fr);
}
.kv-v2_blocks.is-4 { grid-template-columns: repeat(4, 1fr); }

/* Four cards in the container-large gutters leave only 312px each, which reads
   as cramped next to the 3-up rows. This row alone breaks out of the 48px
   padding-global so the extra width goes into the cards, not the gutters. */
.kv-v2_blocks.is-4 {
  width: calc(100% + 68px);
  margin-left: -34px;
  margin-right: -34px;
}
/* Below 768 the padding-global is smaller than the 34px breakout, so the row
   would push past the black component's edge. It is a single column there. */
@media screen and (max-width: 767px) {
  .kv-v2_blocks.is-4 { width: 100%; margin-left: 0; margin-right: 0; }
}


/* Cards: same glass as the home, just less padding since there are 3-4 across. */
.kv-v2_block {
  padding: 96px 32px 32px;
  display: flex;
  flex-direction: column;
}
.kv-v2_block .pricing_main { flex: 1 1 auto; }
/* The featured card carries the SAME glass edge as the others -- the template's
   own white top highlight plus grey inner glow. It used to override that with
   an accent outline; not overriding it at all is what makes it identical. */

.kv-v2_desc {
  color: rgba(255, 255, 255, .55);
  font-size: 14px;
  margin-top: 12px;
}

.kv-v2 .pricing_features { margin-top: 24px; }

.kv-v2_offs-label {
  margin-top: 16px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .4);
}
.kv-v2 .pricing_feature.is-off .pricing_feature-text { color: rgba(255, 255, 255, .35); }

.kv-v2_once {
  display: inline-flex;
  align-items: center;
  margin-left: 10px;
  position: relative;
  top: -0.42em;
  align-self: center;
  padding: 4px 12px;
  border-radius: 144px;
  background-color: rgba(255, 255, 255, .1);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .2);
  color: #fff;
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
}

.kv-v2_conditions {
  text-align: center;
  font-size: 12px;
  color: rgba(255, 255, 255, .45);
  max-width: 52rem;
  margin: 0 auto;
}

@media screen and (max-width: 991px) {
  .kv-v2_blocks, .kv-v2_blocks.is-4 { grid-template-columns: 1fr 1fr; }
  .kv-v2_heading { white-space: normal; }
  .kv-v2_block { padding: 80px 24px 24px; }
}
@media screen and (max-width: 767px) {
  .kv-v2_blocks, .kv-v2_blocks.is-4 { grid-template-columns: 1fr; }
  .kv-v2_heading { font-size: clamp(32px, 9vw, 48px); white-space: normal; }
  .kv-v2_block { padding: 72px 22px 22px; }
}

/* ===========================================================================
   Plan recommender — logic ported from kenshovisual.com, design rebuilt here.

   The source modal is beige on cream (#E8DDD4 / #8B7355 / serif headings),
   which belongs to the old branding. This version uses the same glass surface
   as the pricing cards: blur, 40px radius, the white top highlight, and the
   template's accent for the primary action only.
   =========================================================================== */

/* Floating launcher: a question-mark circle with a notification dot, and a
   tooltip that appears after 5s -- the same pattern kensho-web uses, rebuilt
   on this site's accent and glass rather than its teal/cream. */
.kv-rec_bubble-wrap {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 900;
  width: 56px;
  height: 56px;
}

.kv-rec_bubble {
  width: 56px;
  height: 56px;
  border: 0;
  border-radius: 50%;
  background-color: var(--_colors---primary--accent, #F65600);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 4px 20px rgba(246, 86, 0, .4), 0 2px 8px rgba(0, 0, 0, .25);
  transition: transform 0.2s ease;
}
.kv-rec_bubble:hover { transform: scale(1.08); }
.kv-rec_bubble:active { transform: scale(.95); }

.kv-rec_dot {
  position: absolute;
  top: 1px;
  right: 1px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #ef4444;
  border: 2px solid #0d0d0d;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.kv-rec_dot.is-hidden { opacity: 0; transform: scale(0); }

.kv-rec_tooltip {
  position: fixed;
  right: 22px;
  bottom: 92px;
  z-index: 900;
  max-width: 248px;
  padding: 14px 30px 14px 16px;
  border-radius: 14px;
  /* Light ground: the template's own paper tone, so the tooltip reads as a
     note laid over the dark page rather than part of it. Contrast measured
     16.7:1 for the body text and 5.4:1 for the close button -- both past AA. */
  background: var(--_colors---primary--paper, #f8f7f3);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9),
              inset 0 0 0 1px rgba(0, 0, 0, .08),
              0 12px 40px rgba(0, 0, 0, .45);
  font-size: 13px;
  line-height: 1.55;
  color: var(--_colors---grey--700, #171717);
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.kv-rec_tooltip.is-visible { opacity: 1; transform: translateY(0); pointer-events: auto; }

/* the little pointer aiming at the bubble */
.kv-rec_tooltip::after {
  content: "";
  position: absolute;
  bottom: -6px;
  right: 22px;
  width: 13px;
  height: 6px;
  background: var(--_colors---primary--paper, #f8f7f3);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}

.kv-rec_tooltip-close {
  position: absolute;
  top: 6px;
  right: 7px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--_colors---grey--400, #666);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.2s ease;
}
.kv-rec_tooltip-close:hover { background: rgba(0, 0, 0, .07); color: #000; }

.kv-rec[hidden] { display: none; }
.kv-rec {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.kv-rec_backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, .72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.kv-rec_panel {
  position: relative;
  width: 100%;
  max-width: 520px;
  max-height: 86vh;
  overflow-y: auto;
  border-radius: 28px;
  background-color: #0d0d0d;
  box-shadow: inset 0 5px 3px -3px rgba(255, 255, 255, .41),
              inset 0 4px 20px -5px rgb(78, 78, 78),
              0 30px 80px rgba(0, 0, 0, .6);
}

.kv-rec_close {
  position: absolute;
  top: 18px; right: 18px;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 32px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .08);
  color: rgba(255, 255, 255, .7);
  cursor: pointer;
  transition: background 0.2s ease;
}
.kv-rec_close:hover { background: rgba(255, 255, 255, .16); }

.kv-rec_body { padding: 40px 32px 32px; }

.kv-rec_step { display: none; }
.kv-rec_step.is-active { display: block; }

.kv-rec_step-label {
  margin-bottom: 18px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .4);
}

.kv-rec_q {
  margin: 0 0 8px;
  font-size: clamp(20px, 2.2vw, 26px);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -.02em;
  color: #fff;
}

.kv-rec_help {
  margin: 0 0 20px;
  font-size: 14px;
  line-height: 1.6;
  color: rgba(255, 255, 255, .55);
}
.kv-rec_help.is-lead { color: rgba(255, 255, 255, .8); margin-bottom: 8px; }

.kv-rec_advisory {
  margin-bottom: 20px;
  padding: 14px 16px;
  border-radius: 12px;
  background: rgba(255, 255, 255, .05);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .09);
  font-size: 13px;
  line-height: 1.6;
  color: rgba(255, 255, 255, .68);
}
.kv-rec_advisory strong { color: #fff; font-weight: 600; }

.kv-rec_options { display: flex; flex-direction: column; gap: 10px; }

.kv-rec_option {
  padding: 15px 18px;
  border: 0;
  border-radius: 12px;
  background: rgba(255, 255, 255, .05);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .1);
  color: #fff;
  font-size: 16px;
  text-align: left;
  cursor: pointer;
  transition: background 0.2s ease;
}
.kv-rec_option:hover {
  background: rgba(255, 255, 255, .1);
  box-shadow: inset 0 0 0 1px var(--_colors---primary--accent, #F65600);
}

/* ---- result ---- */
.kv-rec_kicker {
  margin-bottom: 12px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--_colors---primary--accent, #F65600);
}
.kv-rec_kicker.is-small { margin-top: 26px; color: rgba(255, 255, 255, .4); }

.kv-rec_card {
  padding: 24px;
  border-radius: 18px;
  background: rgba(255, 255, 255, .04);
  box-shadow: inset 0 3px 2px -2px rgba(255, 255, 255, .3),
              inset 0 0 0 1px rgba(255, 255, 255, .08);
}

.kv-rec_plan-name {
  margin: 0;
  font-size: 26px;
  font-weight: 500;
  letter-spacing: -.02em;
  color: #fff;
}

.kv-rec_plan-price-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 6px;
}

.kv-rec_plan-price {
  font-size: 18px;
  font-weight: 500;
  color: rgba(255, 255, 255, .75);
}

.kv-rec_saving[hidden] { display: none; }
.kv-rec_saving {
  display: inline-flex;
  padding: 4px 12px;
  border-radius: 144px;
  background: rgba(255, 255, 255, .1);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18);
  font-size: 12px;
  font-weight: 500;
  color: #fff;
}

.kv-rec_bullets {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.kv-rec_bullets li {
  position: relative;
  padding-left: 18px;
  font-size: 14px;
  line-height: 1.5;
  color: rgba(255, 255, 255, .7);
}
.kv-rec_bullets li::before {
  content: "";
  position: absolute;
  left: 0; top: 8px;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--_colors---primary--accent, #F65600);
}

.kv-rec_cta {
  display: block;
  width: 100%;
  margin-top: 18px;
  padding: 15px 24px;
  border: 0;
  border-radius: 144px;
  background-color: var(--_colors---primary--accent, #F65600);
  color: #fff;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.2s ease;
}
.kv-rec_cta:hover { opacity: .88; }

.kv-rec_extras[hidden] { display: none; }
.kv-rec_extra[hidden] { display: none; }

.kv-rec_extra {
  padding: 16px 18px;
  border-radius: 12px;
  background: rgba(255, 255, 255, .04);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08);
}
.kv-rec_extra + .kv-rec_extra { margin-top: 10px; }

.kv-rec_extra-title {
  margin-bottom: 6px;
  font-size: 16px;
  font-weight: 500;
  color: #fff;
}
.kv-rec_extra-title span { color: rgba(255, 255, 255, .5); font-size: 14px; }

.kv-rec_extra-text {
  margin: 0;
  font-size: 13px;
  line-height: 1.6;
  color: rgba(255, 255, 255, .55);
}

.kv-rec_restart {
  display: block;
  width: 100%;
  margin-top: 18px;
  padding: 0;
  border: 0;
  background: none;
  color: rgba(255, 255, 255, .45);
  font-size: 13px;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.kv-rec_restart:hover { color: #fff; }

/* the recommended card flashes when the CTA scrolls you to it */
.kv-rec-flash {
  animation: kv-rec-flash 1.7s ease;
}
@keyframes kv-rec-flash {
  0%, 100% { box-shadow: inset 0 5px 3px -3px rgba(255,255,255,.41), inset 0 4px 20px -5px rgb(78,78,78); }
  25%, 75% { box-shadow: inset 0 0 0 2px var(--_colors---primary--accent, #F65600); }
}

@media screen and (max-width: 767px) {
  .kv-rec { padding: 12px; }
  .kv-rec_body { padding: 34px 20px 24px; }
  .kv-rec_panel { max-height: 90vh; }
  .kv-rec_bubble-wrap { right: 16px; bottom: 16px; }
  .kv-rec_tooltip { right: 14px; bottom: 84px; max-width: calc(100vw - 40px); }
}

@media (prefers-reduced-motion: reduce) {
  .kv-rec-flash { animation: none; }
  .kv-rec_tooltip { transition: none; }
}


/* ============ ajustes pedidos por Sergio ============ */

/* --- features: quitar el círculo del check, dejar sólo la marca --- */
/* El template pinta un PNG (círculo oscuro + check blanco) como background de
   .pricing_feature. Sobre las cards oscuras el círculo pesa demasiado, así que
   se sustituye por un SVG inline: sólo el trazo del check. */
.kv-v2 .pricing_feature,
.kv-plans_panel .pricing_feature {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23F65600' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  background-size: 0.95rem;
  background-position: 0 0.42em;
}

/* --- lo que NO incluye: una X, no un check --- */
.kv-v2 .pricing_feature.is-off,
.kv-plans_panel .pricing_feature.is-off {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23808080' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E");
  background-size: 0.82rem;
  background-position: 0.06rem 0.5em;
}

/* --- burbuja del recomendador: sin punto rojo, con profundidad --- */
.kv-rec_dot { display: none; }

.kv-rec_bubble {
  /* degradado sutil del acento + luz interior arriba y sombra interior abajo:
     el mismo lenguaje de "glass edge" que usan las cards del template. */
  background-image: linear-gradient(160deg,
                    rgba(255, 255, 255, .22) 0%,
                    rgba(255, 255, 255, 0) 42%,
                    rgba(0, 0, 0, .16) 100%);
  box-shadow: inset 0 1.5px 0 rgba(255, 255, 255, .45),
              inset 0 -2px 6px rgba(0, 0, 0, .22),
              inset 0 0 0 1px rgba(255, 255, 255, .14),
              0 6px 18px rgba(246, 86, 0, .34),
              0 12px 34px rgba(0, 0, 0, .30);
}
.kv-rec_bubble:hover {
  transform: scale(1.08);
  box-shadow: inset 0 1.5px 0 rgba(255, 255, 255, .5),
              inset 0 -2px 6px rgba(0, 0, 0, .2),
              inset 0 0 0 1px rgba(255, 255, 255, .18),
              0 8px 24px rgba(246, 86, 0, .44),
              0 16px 40px rgba(0, 0, 0, .34);
}

/* --- tarjeta de contacto en el footer --- */
/* El marcado es una COPIA LITERAL de la del hero (data-w-id incluido), así que
   hereda tamaño, padding, radios y la animación IX2 de despliegue. Aquí sólo
   se corrige lo único que no puede heredarse: el hero va sobre vídeo oscuro
   (cristal blanco translúcido) y el footer es claro, donde ese tratamiento la
   dejaría invisible. Se invierte a la escala de grises del template y NADA
   más: ni tamaños, ni radios, ni transiciones propias. */
.footer_social { align-items: center; }

.kv-fcontact {
  position: relative;   /* ancla el punto naranja; sin esto se iba al viewport */
  margin-top: var(--fixed--1-5rem, 1.5rem);
}

.kv-fcontact .home-header_contact-infos {
  background-color: transparent;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .10);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.kv-fcontact .home-header_contact-cta { color: var(--_colors---grey--700, #171717); }
.kv-fcontact .home-header_contact-text { color: var(--_colors---grey--400, #666); }
.kv-fcontact .home-header_contact-link { color: var(--_colors---grey--700, #171717); }

@media screen and (max-width: 767px) {
  .footer_social { justify-content: flex-start; }
}

/* ---------- desarrollo web (/pricing-v2): mismo lenguaje que .kv-espec_card,
   en 4 columnas porque son 4 productos cerrados ---------- */
.kv-web_grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
}
.kv-web_card {
  border-radius: 18px;
  overflow: hidden;
  background-color: #fff;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
  display: flex;
  flex-direction: column;
  transition: transform 0.2s ease;
}
.kv-web_card:hover { transform: translateY(-4px); }
.kv-web_img-wrap { aspect-ratio: 16 / 10; overflow: hidden; }
.kv-web_img { width: 100%; height: 100%; object-fit: cover; display: block; }
.kv-web_body { padding: 24px; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.kv-web_note {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--_colors---grey--400, #666);
}
.kv-web_name {
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -.02em;
  margin: 2px 0 0;
}
.kv-web_price {
  font-weight: 600;
  color: var(--_colors---primary--accent, #F65600);
}
.kv-web_desc {
  margin-top: 6px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--_colors---grey--500, #4d4d4d);
}
.section_kv-web { padding-bottom: 0; }

@media screen and (max-width: 991px) {
  .kv-web_grid { grid-template-columns: 1fr 1fr; }
}
@media screen and (max-width: 767px) {
  .kv-web_grid { grid-template-columns: 1fr; }
}

/* ============ switcher con deslizamiento + destello ============ */

.kv-pill { position: relative; }

/* las pestañas van por encima del indicador */
.kv-pill_tab { position: relative; z-index: 1; }

/* el indicador que se desliza */
.kv-pill_glider {
  position: absolute;
  top: 4px;
  left: 0;
  height: calc(100% - 8px);
  width: 0;
  border-radius: 144px;
  background-color: #000;
  /* el desplazamiento es lo que da el "flow": un ease con un punto de
     asentamiento, no un lineal seco */
  transition: transform 0.2s cubic-bezier(.34, 1.32, .48, 1),
              width 0.2s cubic-bezier(.34, 1.32, .48, 1);
  z-index: 0;
  pointer-events: none;
}
.kv-v2 .kv-pill_glider { background-color: #fff; }

/* destello que recorre el borde del switcher */
.kv-pill::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 144px;
  padding: 1px;
  background: conic-gradient(from var(--kv-ang, 0deg),
              transparent 0turn,
              transparent .62turn,
              rgba(246, 86, 0, .10) .76turn,
              rgba(246, 86, 0, .85) .88turn,
              rgba(255, 255, 255, .95) .94turn,
              rgba(246, 86, 0, .85) 1turn);
  /* sólo el borde: se recorta el interior */
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  animation: kv-pill-sheen 4.5s linear infinite;
  pointer-events: none;
}

@property --kv-ang {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}
@keyframes kv-pill-sheen {
  to { --kv-ang: 360deg; }
}

@media (prefers-reduced-motion: reduce) {
  .kv-pill_glider { transition: none; }
  .kv-pill::after { animation: none; }
}

/* ============ H1 de precios: mismo degradado que los importes ============ */
/* .pricing_money usa linear-gradient(131deg,#fff,#353535) recortado al texto. */
.kv-v2_title {
  -webkit-text-fill-color: transparent;
  background-image: linear-gradient(131deg, #fff, #353535);
  -webkit-background-clip: text;
  background-clip: text;
}

/* ============ más aire encima de "Selecciona lo que necesitas" ============ */
.kv-v2_switch-label { margin-top: 96px; }
@media screen and (max-width: 767px) {
  .kv-v2_switch-label { margin-top: 64px; }
}

/* ============ footer sin panel blanco ============ */
/* Sergio: que navegación, la tarjeta de contacto y los sociales compartan el
   mismo fondo que la zona de debajo del wordmark, que es el fondo de página
   (--_colors---primary--paper, #f8f7f3). El panel blanco redondeado
   desaparece. */
.footer_wrap {
  background-color: var(--_colors---primary--paper, #f8f7f3);
  border-radius: 0;
}

/* ---------------------------------------------------------------------------
   Brand accent: #f3350c -> #F65600

   The template exposes the accent as a custom property, so redefining it here
   recolours everything that reads the variable. Four selectors hardcode the
   old hex instead of reading it, so they are overridden explicitly -- the
   template stylesheet itself is left untouched.
--------------------------------------------------------------------------- */
:root { --_colors---primary--accent: #F65600; }

.navbar_works-number-wrap,
.work-list_number,
.work-list_dot,
.home-services_number { background-color: #F65600; }

/* kv — custom sections for the Kensho content migration.
   Pattern source: diroz/reports/section-spec.md, rebuilt in Alture vocabulary.
   Rules honoured (design-system/DESIGN-SYSTEM.md):
   - spacing joins the template scale (8/16/20/24/32 gaps, section padding via classes)
   - colours come from the template tokens; accent = --_colors---primary--accent
   - radii 12/18, transitions 0.2s ease only
   - fluid type via template utility classes in the markup, not here */

/* ---------- services accordion rows (diroz .services) ---------- */
.kv-services_list { display: flex; flex-direction: column; }

.kv-services_row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px;
  align-items: start;
  padding-top: 48px;
  padding-bottom: 48px;
  border-top: 1px solid var(--_colors---grey--200, rgba(0, 0, 0, .1));
}
.kv-services_row:last-child { border-bottom: 1px solid var(--_colors---grey--200, rgba(0, 0, 0, .1)); }

.kv-services_head { display: flex; flex-direction: column; gap: 24px; align-items: flex-start; }

.kv-services_number {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .05em;
  color: var(--_colors---primary--accent, #F65600);
}

.kv-services_items { display: flex; flex-direction: column; gap: 8px; }
.kv-services_item { display: flex; align-items: center; gap: 8px; }
.kv-services_dot {
  width: 6px; height: 6px; border-radius: 50%;
  background-color: var(--_colors---primary--accent, #F65600);
  flex-shrink: 0;
}

.kv-services_img-wrap {
  border-radius: 18px;
  overflow: hidden;
  aspect-ratio: 588 / 500;
}
.kv-services_img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* buttons: template pill, accent filled (diroz's View Full Details, Kensho red) */
.kv-button {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 12px 24px;
  border-radius: 144px;
  background-color: var(--_colors---primary--accent, #F65600);
  color: #fff;
  font-size: 14px; font-weight: 600;
  transition: opacity 0.2s ease;
  text-decoration: none;
}
.kv-button:hover { opacity: .85; }
.kv-button.is-ghost {
  background-color: transparent;
  color: #000;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .2);
}

/* ---------- service detail split (diroz .service-details, 300px gutter) ---------- */
.kv-detail_grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px 300px; /* the 300px gutter is the section's signature — spec'd from diroz */
  align-items: start;
}
.kv-detail_right { display: flex; flex-direction: column; gap: 32px; }
.kv-detail_items { display: flex; flex-direction: column; gap: 16px; }
.kv-detail_hero-wrap { border-radius: 18px; overflow: hidden; }
.kv-detail_hero { width: 100%; height: auto; display: block; }

/* caption pattern (diroz .section-caption: 20px icon + label, gap 8) */
.kv-caption { display: flex; align-items: center; gap: 8px; }

/* ---------- sticky stacking process cards (diroz .process) ---------- */
.section_kv-process { background-color: var(--_colors---grey--100, #efeeea); }

/* El wrap define el recorrido; el sticky se pega dentro de él y el runway es
   sólo la altura que da ese recorrido. Antes el runway iba DEBAJO del sticky y
   sumaba su altura como hueco gris vacío: ahora el sticky se superpone al
   runway (margin-bottom negativo), así que la sección mide el recorrido y
   nada más. */
.kv-process_wrap { position: relative; }
.kv-process_sticky {
  position: sticky;
  top: 160px;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  z-index: 1;
  margin-bottom: -420px;      /* alto de una card: el runway pasa por debajo */
}
.kv-process_runway { height: 1500px; }
.kv-process_card {
  border-radius: 18px;
  background-color: var(--_colors---primary--accent, #F65600);
  color: #000;
  padding: 32px;
  min-height: 420px;
  display: flex; flex-direction: column; justify-content: space-between;
  will-change: transform;
}
.kv-process_card-top { display: flex; justify-content: space-between; align-items: flex-start; }
.kv-process_card-number { font-size: 14px; font-weight: 600; letter-spacing: .05em; }
.kv-process_card-icon { width: 64px; height: 64px; object-fit: cover; border-radius: 12px; }
.kv-process_card-body { display: flex; flex-direction: column; gap: 8px; }

/* ---------- pricing ---------- */
.kv-plans_grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  align-items: stretch;
}
.kv-plans_grid.is-4 { grid-template-columns: repeat(4, 1fr); }
.kv-plan {
  border-radius: 18px;
  background-color: #fff;
  padding: 32px;
  display: flex; flex-direction: column; gap: 24px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
  position: relative;
}
.kv-plan.is-featured { box-shadow: inset 0 0 0 2px var(--_colors---primary--accent, #F65600); }
.kv-plan_ribbon {
  position: absolute; top: 24px; right: 24px;
  font-size: 12px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  color: #fff;
  background-color: var(--_colors---primary--accent, #F65600);
  border-radius: 144px;
  padding: 4px 12px;
}
.kv-plan_price-row { display: flex; align-items: baseline; gap: 8px; }
.kv-plan_features { display: flex; flex-direction: column; gap: 8px; }
.kv-plan_feature { display: flex; gap: 8px; align-items: flex-start; }
.kv-plan_feature .kv-services_dot { margin-top: 7px; }
.kv-plan_feature.is-off { opacity: .45; }
.kv-plan_feature.is-off .kv-services_dot { background-color: var(--_colors---grey--400, #999); }
.kv-plan_foot { margin-top: auto; display: flex; flex-direction: column; gap: 16px; }

/* specialized services grid */
.kv-espec_grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.kv-espec_card {
  border-radius: 18px;
  overflow: hidden;
  background-color: #fff;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
  display: flex; flex-direction: column;
}
.kv-espec_img-wrap { aspect-ratio: 4 / 3; overflow: hidden; }
.kv-espec_img { width: 100%; height: 100%; object-fit: cover; display: block; }
.kv-espec_body { padding: 24px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.kv-espec_price { margin-top: auto; padding-top: 16px; font-weight: 600; color: var(--_colors---primary--accent, #F65600); }

/* ---------- reveals: initial state only; GSAP animates (no CSS transition) ---------- */
.kv-reveal { opacity: 0; }
html.kv-no-js .kv-reveal { opacity: 1; }

/* ---------- responsive: grids collapse at 991 like the template ---------- */
@media screen and (max-width: 991px) {
  .kv-services_row, .kv-detail_grid { grid-template-columns: 1fr; }
  .kv-detail_grid { gap: 48px; }
  .kv-plans_grid, .kv-plans_grid.is-4, .kv-espec_grid { grid-template-columns: 1fr 1fr; }
  .kv-process_sticky { grid-template-columns: 1fr 1fr; position: static; }
  .kv-process_runway { display: none; }
  .kv-process_card { min-height: 320px; }
}
@media screen and (max-width: 767px) {
  .kv-plans_grid, .kv-plans_grid.is-4, .kv-espec_grid { grid-template-columns: 1fr; }
  .kv-process_sticky { grid-template-columns: 1fr; }
}

/* detail hero keeps diroz's wide 1360x592 crop */
.kv-detail_hero-wrap { aspect-ratio: 1360 / 592; }
.kv-detail_hero { height: 100%; object-fit: cover; }

/* ---------- fixes de revisión (2026-08-23) ---------- */

/* FAQ: la primera pregunta es más ancha que las demás y `flex-flow: wrap`
   empujaba el botón + a una segunda fila. Medido: botón a +48px del texto en
   el item 1 vs -8px en el resto. nowrap lo devuelve a la derecha siempre. */
.faq_question-wrap { flex-wrap: nowrap; align-items: center; }
.faq_question-wrap .faq_button { flex: none; }

/* Footer: copyright a la izquierda.
   `.footer_legal-links` es un grid de 3 columnas con place-items:center y el
   wrap vive en la columna central por un id de Webflow (w-node). Se colapsa a
   una sola columna alineada al inicio, que es lo que fuerza la izquierda. */
.footer_legal-links {
  /* El template lo centra con place-items:center en un grid de 3 columnas.
     Sólo cambiamos la alineación; NO tocamos su participación en el grid
     padre (hacerlo lo sacaba del recuadro blanco del footer). */
  place-items: center start;
}
.footer_legal-wrap { justify-content: flex-start; }
.footer_copyright { text-align: left; }

/* Footer: el wordmark en UNA sola fila y recortado por abajo, de modo que la
   parte inferior del trazo sangre contra el fondo de la página.
   El tamaño del template (20vw / 25vw) desbordaba a lo ancho y quedaba
   "Kensho Visu…": 12.2vw es el que hace caber "Kensho Visual" completo en el
   ancho del contenedor a cualquier viewport. */
.footer_brand {
  white-space: nowrap;
  display: block;
  overflow: hidden;
  font-size: 12.2vw;
  line-height: 1;
  /* El texto ocupaba 1.185em de alto con el ® original; al reducir el  pasa a
     1.0em, así que 1.12em ya no recortaba nada. 0.95em vuelve a sangrar sólo la
     puntita inferior del trazo, que es el efecto buscado. */
  max-height: 0.95em;
  margin-bottom: -0.03em;
}
@media screen and (max-width: 767px) {
  .footer_brand { font-size: 13.2vw; max-height: 0.96em; }
}

/* Loader: el wordmark queda pequeño a 7rem (90×16 medidos). Sube a 11rem. */
.brand_logo { width: var(--fixed--11rem, 11rem); height: auto; }
@media screen and (max-width: 767px) { .brand_logo { width: var(--fixed--8rem, 8rem); } }

/* ---------- process cards: legibilidad + variante home ---------- */
/* Sergio: títulos y texto en blanco sobre el rojo, se lee mejor */
.kv-process_card, .kv-process_card h3, .kv-process_card p, .kv-process_card .kv-process_card-number { color: #fff; }
.kv-services_dot.is-light { background-color: #fff; }
.kv-process_card-arrow { font-size: 20px; line-height: 1; }

.kv-process_card.is-home {
  text-decoration: none;
  min-height: 380px;
  transition: opacity 0.2s ease;
}
.kv-process_card.is-home:hover { opacity: .9; }
.kv-process_wrap.is-home .kv-process_sticky { top: 160px; margin-bottom: -380px; }
/* runway más corto: Sergio reportó demasiado scroll vacío antes de que entren */
.kv-process_wrap.is-home .kv-process_runway { height: 1400px; }
.kv-home-services_cta { display: flex; justify-content: center; }

/* ================= /services — filas apiladas (patrón diroz) =================
   Medido en diroz: .services-collection es position:sticky top:32px; la tarjeta
   es blanca, radius 16, padding 68/40; título 80px/600. El apilado es CSS puro:
   cada fila se pega y la siguiente la cubre. */
.kv-svc_list { display: flex; flex-direction: column; gap: 32px; }

.kv-svc_sticky {
  position: sticky;
  /* cada tarjeta se pega 12px más abajo que la anterior: deja ver el borde
     de las de atrás, como en diroz */
  top: calc(96px + var(--kv-svc-i) * 12px);
}

.kv-svc_card {
  display: grid;
  grid-template-columns: 1fr 588px;
  gap: 40px;
  align-items: stretch;
  background-color: #fff;
  border-radius: 18px;
  padding: 56px 40px;
  /* Mismo borde sombreado que las stacking cards de la home (.is-home): borde
     interior de 1px + labio superior + sombra de apoyo. Antes esta versión
     llevaba sólo una línea plana y las tarjetas apiladas no se separaban
     unas de otras. */
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08),
              0 -1px 0 rgba(0, 0, 0, .10),
              0 8px 24px rgba(0, 0, 0, .28);
}

.kv-svc_left { display: flex; flex-direction: column; }
.kv-svc_head { display: flex; align-items: baseline; gap: 20px; }
.kv-svc_number {
  font-size: 20px; font-weight: 500;
  color: var(--_colors---primary--accent, #F65600);
  flex: none;
}
.kv-svc_title {
  font-size: 64px; font-weight: 600; line-height: 1.05; letter-spacing: -.03em;
  margin: 0;
}
.kv-svc_items {
  display: flex; flex-direction: column; gap: 8px;
  margin-top: 32px;
  font-size: 20px;
}
.kv-svc_item { display: flex; align-items: center; gap: 12px; }

/* botón: alineado al fondo del bloque, es decir a lo largo del alto de la
   imagen — como en diroz, donde queda al pie de la fila */
.kv-svc_btn-wrap { margin-top: auto; padding-top: 40px; }
.kv-svc_button {
  display: inline-flex; align-items: center; gap: 16px;
  background-color: var(--_colors---primary--accent, #F65600);
  border-radius: 4px;
  padding: 10px 20px 10px 12px;
  text-decoration: none;
  transition: opacity 0.2s ease;
}
.kv-svc_button:hover { opacity: .88; }
.kv-svc_button-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border-radius: 4px;
  /* Solid white square, black arrow -- was a translucent white that read as a
     washed-out patch on the accent. */
  background-color: #fff;
  color: #000; font-size: 18px; line-height: 1;
}
/* Sergio: el texto del botón en BLANCO (diroz lo tiene oscuro y se lee mal) */
.kv-svc_button-text { color: #fff; font-size: 18px; font-weight: 500; }

.kv-svc_img-wrap { border-radius: 12px; overflow: hidden; min-height: 460px; }
.kv-svc_img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media screen and (max-width: 991px) {
  .kv-svc_card { grid-template-columns: 1fr; padding: 40px 28px; gap: 32px; }
  .kv-svc_title { font-size: 44px; }
  .kv-svc_items { font-size: 18px; margin-top: 24px; }
  .kv-svc_img-wrap { min-height: 0; aspect-ratio: 588 / 420; order: -1; }
  .kv-svc_btn-wrap { padding-top: 28px; }
  /* en móvil se sigue apilando, con menos desplazamiento */
  .kv-svc_sticky { top: calc(80px + var(--kv-svc-i) * 8px); }
}
@media screen and (max-width: 767px) {
  .kv-svc_title { font-size: 34px; }
  .kv-svc_head { flex-direction: column; align-items: flex-start; gap: 8px; }
  .kv-svc_card { padding: 28px 20px; }
  .kv-svc_items { font-size: 16px; }
  .kv-svc_button-text { font-size: 16px; }
}

/* ================= filtro de proyectos (pestañas) ================= */
.kv-filter { display: flex; }
.kv-filter_tabs {
  display: flex; flex-wrap: wrap; gap: 8px;
}
.kv-filter_tab {
  display: inline-flex; align-items: center; gap: 8px;
  border: 0;
  border-radius: 144px;
  padding: 10px 20px;
  background-color: rgba(0, 0, 0, .06);
  color: #000;
  font-family: inherit; font-size: 14px; font-weight: 500;
  cursor: pointer;
  transition: opacity 0.2s ease;
}
.kv-filter_tab:hover { opacity: .7; }
.kv-filter_tab.is-active { background-color: #000; color: #fff; }
.kv-filter_count { font-size: 12px; opacity: .5; }
.kv-filter_tab.is-active .kv-filter_count { opacity: .6; }
.work-list_item.is-hidden,
.work-list_list-v3 > .work-list_item.is-hidden { display: none; }
/* los vídeos de tarjeta se comportan como las imágenes */
video.work-list_image-v2 { width: 100%; height: 100%; object-fit: cover; display: block; }

@media screen and (max-width: 767px) {
  .kv-filter_tab { padding: 8px 14px; font-size: 13px; }
}

/* ================= espaciado entre secciones =================
   Bug medido: mis secciones nuevas metían `padding-section-*` en un div
   interno, así que la propia <section> cerraba a 0px y la siguiente (la CTA
   negra, o el bloque gris de proceso) quedaba pegada sin white space.
   El template usa 128px como ritmo por defecto (padding-section-medium). */
.section_kv-header,
.section_kv-services,
.section_kv-detail,
.section_kv-includes,
.section_kv-plans,
.section_kv-espec { padding-bottom: 128px; }

.section_kv-header { padding-bottom: 64px; }   /* el header ya respira arriba */

/* la sección de proceso es la que trae fondo propio: necesita aire a ambos lados */
.section_kv-process { padding-top: 96px; padding-bottom: 128px; }

@media screen and (max-width: 991px) {
  .section_kv-header, .section_kv-services, .section_kv-detail,
  .section_kv-includes, .section_kv-plans, .section_kv-espec { padding-bottom: 80px; }
  .section_kv-header { padding-bottom: 48px; }
  .section_kv-process { padding-top: 64px; padding-bottom: 80px; }
}
@media screen and (max-width: 767px) {
  .section_kv-header, .section_kv-services, .section_kv-detail,
  .section_kv-includes, .section_kv-plans, .section_kv-espec { padding-bottom: 64px; }
  .section_kv-process { padding-top: 48px; padding-bottom: 64px; }
}

/* ================= /pricing: selector pill + aire lateral =================
   Patrón tomado de kenshovisual.com (.svc-tabs / .svc-tab.active): contenedor
   con fondo y píldora activa rellena. Traducido a la paleta Alture. */
.kv-plans_switch { display: flex; justify-content: center; }
.kv-pill {
  display: inline-flex; gap: 4px; padding: 4px;
  background-color: rgba(0, 0, 0, .05);
  border-radius: 144px;
}
.kv-pill_tab {
  border: 0; cursor: pointer;
  font-family: inherit; font-size: 14px; font-weight: 500;
  color: var(--_colors---grey--500, #4d4d4d);
  background: transparent;
  border-radius: 144px;
  padding: 10px 22px;
  transition: opacity 0.2s ease;
}
.kv-pill_tab:hover { opacity: .7; }
.kv-pill_tab.is-active { color: #fff; }
.kv-plans_panel { display: none; }
.kv-plans_panel.is-active { display: block; }

/* Sergio: más room lateral para las cards */
.section_kv-plans .container-medium,
.section_kv-espec .container-medium { padding-left: 24px; padding-right: 24px; }
.kv-plans_grid { gap: 20px; }

/* títulos de plan SIEMPRE en una línea (rompían el diseño a dos) */
.kv-plan h3.heading-style-h4 {
  white-space: nowrap;
  font-size: clamp(15px, 1.35vw, 20px);
  letter-spacing: -.02em;
}
.kv-plan .kv-plan_price-row h3 { white-space: nowrap; font-size: clamp(26px, 2.4vw, 40px); }

@media screen and (max-width: 991px) {
  .kv-plan h3.heading-style-h4 { font-size: 18px; }
  .section_kv-plans .container-medium,
  .section_kv-espec .container-medium { padding-left: 12px; padding-right: 12px; }
}

/* ================= /contact: form izquierda, FAQ derecha =================
   Sergio: el formulario baja bajo el título y las preguntas frecuentes van a
   su derecha (donde antes estaba el hueco del form).
   `contact_component` es la fila título|contenido del template; el grid se
   inserta como hermano de `contact_content` y ocupa todo el ancho. */
.contact_component { display: block; }
.contact_content { max-width: 720px; }
.kv-contact_grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px;
  align-items: start;
  margin-top: 64px;
}
.kv-contact_col > div { margin: 0; }
.kv-contact_grid .spacer-xhuge { display: none; }

@media screen and (max-width: 991px) {
  .kv-contact_grid { grid-template-columns: 1fr; gap: 48px; margin-top: 40px; }
}

/* El spacer-huge del final de cada panel ya aporta 96px; sumarle los 128 de
   la sección daba 224px de vacío. El último panel no necesita el suyo. */
.kv-plans_panel > .spacer-huge:last-child { display: none; }

/* ---------- variante home del stack de servicios ----------
   Mismas filas que /services (patrón diroz), sobre el panel oscuro de la home. */
.kv-svc_list.is-home .kv-svc_sticky { top: calc(104px + var(--kv-svc-i) * 12px); }
/* Cada tarjeta necesita leerse como una pieza propia al apilarse. Sobre el
   panel negro una sombra oscura no se ve, así que el separador real es el
   filo: hairline que oscurece el borde de la tarjeta blanca (el mismo token
   de .kv-plan / .kv-v2_block) + una sombra exterior suave que despega la que
   cubre de la de debajo. Muy sutil, sin marco visible. */
.kv-svc_list.is-home .kv-svc_card {
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08),
              0 -1px 0 rgba(0, 0, 0, .10),
              0 8px 24px rgba(0, 0, 0, .28);
}
.kv-home-services_cta { display: flex; justify-content: center; }
@media screen and (max-width: 991px) {
  .kv-svc_list.is-home .kv-svc_sticky { top: calc(80px + var(--kv-svc-i) * 8px); }
}

/* /works/3: la lista llega hasta el borde de la sección y el footer quedaba
   pegado. El template usa 128px de ritmo. */
.section_work-list { padding-bottom: 128px; }
@media screen and (max-width: 991px) { .section_work-list { padding-bottom: 80px; } }
@media screen and (max-width: 767px) { .section_work-list { padding-bottom: 64px; } }

/* Servicios especializados: el h4 del template renderiza a 44px y desbordaba
   las tarjetas (medido: "Gestión de anuncios/campañas" a 389px en 368px). */
.kv-espec_card h3 {
  font-size: clamp(19px, 1.5vw, 22px);
  line-height: 1.2;
  letter-spacing: -.02em;
  overflow-wrap: break-word;
}

/* Hero wordmark: TM in a lighter grey than the near-black heading.
   Position/size deliberately untouched -- only the colour changes. */
.home-header_mark {
  color: #6b6b6b;
  /* The template sets extra-bold (800) here, heavier than the 600 heading it
     sits on -- fine for the ® it shipped with, too heavy for a . */
  font-weight: 400;
}

/* ---------------------------------------------------------------------------
   Logo cloud (replaces the brands carousel)

   Rebuilt from the 21st.dev logo-cloud block, which is React + Tailwind +
   @remixicon/react -- none of which exist on this static Webflow site. What is
   reproduced is the design: monochrome icon + wordmark, one row, continuous
   translateX(0 -> -50%) over a duplicated track, edge fade, pause on hover.

   Colours measured off this page, not invented: body background #f8f7f3,
   heading #000. The resting grey is the template's own muted tone.
--------------------------------------------------------------------------- */
.kv-cloud {
  position: relative;
  overflow: hidden;
  /* The fade IS the "blur" of the reference: content dissolves into the page
     background at both edges instead of being cut by a hard line. */
  /* Long, soft ramps: fully opaque only across the middle third, so the row
     reads as a narrow band instead of a full-width strip. The reference used
     12%/88%; these much wider ramps are what shortens it visually without
     touching the track width. */
  -webkit-mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,.15) 12%, #000 34%, #000 66%, rgba(0,0,0,.15) 88%, transparent 100%);
          mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,.15) 12%, #000 34%, #000 66%, rgba(0,0,0,.15) 88%, transparent 100%);
}

.kv-cloud_track {
  display: flex;
  width: max-content;
  align-items: center;
  /* 90s: the track travels half its 9366px width per cycle, so this is ~52px/s
     (was ~78px/s at 60s). Slow enough to read each name as it passes. */
  animation: kv-cloud-marquee 90s linear infinite;
}

/* Deliberately NOT paused on hover: the reference block pauses, Sergio asked
   for continuous motion. */

@keyframes kv-cloud-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.kv-cloud_item {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 10px;
  /* Vertical padding gives the row presence: a bare 24px strip reads as thin
     in a section whose spacing scale is 56/128. Horizontal 32px is the
     reference block's own px-8. */
  padding: 20px 38px;
  color: rgba(0, 0, 0, .45);
  transition: color .2s ease;
}

.kv-cloud .kv-cloud_item:hover { color: #000; }

.kv-cloud_icon {
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
}

.kv-cloud_name {
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -.01em;
  line-height: 1;
  white-space: nowrap;
}

@media (max-width: 767px) {
  /* Keep the vertical padding from the base rule -- an earlier `0 22px` here
     reset it and collapsed the row to 20px on phones. */
  .kv-cloud_item { padding: 15px 24px; gap: 9px; }
  .kv-cloud_name { font-size: 17px; }
  .kv-cloud_icon { width: 22px; height: 22px; }
}

/* Keep the composition, drop the motion. */
@media (prefers-reduced-motion: reduce) {
  .kv-cloud_track { animation: none; }
}

/* The template puts a full-width divider at the top of section_work-list (it is
   in the untouched Alture pristine too). Under the logo cloud it reads as a
   stray dotted rule, so it is hidden on the home page only. */
.section_work-list > .padding-global.is-tiny > .line { display: none; }

/* ---------------------------------------------------------------------------
   /works/3 cards — image and info as ONE object

   The template ships these as two detached pieces: a square image, a 20px gap,
   then a separately-rounded colour block whose height follows its own text. So
   the row read as six loose shapes with ragged bottoms.

   Now: one rounded card, image flush on top, info panel welded beneath it, and
   the panels bottom-aligned so a row ends on a straight line. Colour, type and
   radius all stay the template's own.
--------------------------------------------------------------------------- */
.work-list_block-v2 {
  border-radius: var(--border-radius--large, 18px);
  overflow: hidden;               /* the image corners follow the card */
  background: #fff;
  height: 100%;
}

/* kill the gap that split the card in two -- it is flex `gap: 20px` on the
   block itself, not a margin on either child */
.work-list_block-v2 { gap: 0; }

.work-list_image-wrap-v2 {
  border-radius: 0;
  overflow: hidden;
}

.work-list_infos-v2 {
  border-radius: 0;
  margin-top: 0;
  /* the panel takes the leftover height, so every card in a row ends level */
  flex: 1 1 auto;
  align-items: center;
}

/* Equal-height cards across the row. */
.work-list_list-v3 > .work-list_item { display: flex; }
.work-list_list-v3 > .work-list_item > .work-list_block-v2 { width: 100%; }

/* Lift on hover: the whole card responds as one object. */
.work-list_block-v2 {
  transition: transform .2s ease;
}
.work-list_block-v2:hover { transform: translateY(-4px); }

/* ---------------------------------------------------------------------------
   Pricing — the audit is not a plan

   Auditoría SEO is a prerequisite you buy BEFORE choosing a plan, but styled
   like its neighbours it reads as a third competing option. Setting it on the
   template's own grey--50 (#f1efed) separates it as a different KIND of thing
   Uses the template's own grey--50 (#f1efed). A darker #e4e0da was tried for
   stronger separation, but Sergio preferred this lighter, subtler tone -- it
   reads as a different kind of card without shouting.
   Readability measured on that ground: 18.3:1 for the black body copy and
   7.4:1 for the muted grey-500 text, both well past the 4.5:1 WCAG AA
   threshold. The border is darkened a step so the edge stays defined.
--------------------------------------------------------------------------- */
.kv-plan.is-prerequisite {
  background-color: var(--_colors---grey--50, #f1efed);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
}

/* "Pago único" badge — the audit is billed once, not monthly.

   Corrected: the first version imported kensho-web's beige (#E8DDD4/#8B7355),
   a palette from the OLD site that has nothing to do with this template. Every
   colour here must come from this design system. Now it is the template's own
   white surface with grey--700 text -- the same surface language as the plan
   cards -- reading as a quiet chip on the card's grey ground. Contrast 17.9:1. */
.kv-plan_once {
  display: inline-flex;
  align-items: center;
  background: var(--_colors---primary--white, #fff);
  color: var(--_colors---grey--700, #171717);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .1);
  border-radius: 144px;
  padding: 4px 12px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
}

/* "No incluye" label above the greyed items. Deliberately tiny -- it is a
   signpost, not a heading, and the card has no vertical room to spare. */
.kv-plan_offs-label {
  margin-top: 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--_colors---grey--400, #9c9287);
}

/* The trademark mark in running text. Small and raised, so "Kensho Visual"
   reads as a wordmark rather than the  competing with the words. Inherits
   colour so it works on both the light and dark panels it appears on. */
.kv-tm {
  font-weight: 400;
  /* A flat .55em collapsed to 6.6px inside the 12px labels -- unreadable.
     clamp gives a 9px floor for small text while staying proportional in the
     96px headings. */
  font-size: clamp(9px, .55em, 48px);
  vertical-align: super;
  line-height: 0;
  letter-spacing: 0;
}

/* Footer wordmark mark: the template sizes it 10vw (144px at 1440), which was
   fine for the ® it shipped with but makes the  overrun the wordmark's clipped
   box -- its top sat 16px above the box and got sliced. Sized to match .kv-tm's
   proportion and pulled inside the box. */
.footer_mark {
  /* Sits at the TOP of the wordmark, like the original ®. Measured at 1440:
     the letters run from -19 to 193 relative to the clipped box, so the mark's
     top must land near -19, not at 71 (which put it halfway down the "l").
     top:-1.05em on a .26em glyph does that; `super` alone only reached 47. */
  font-size: .26em;
  font-weight: 400;
  vertical-align: baseline;
  position: relative;
  /* NB: `em` here resolves against the MARK's own 45.7px, not the wordmark's
     175.7px -- so the offset is expressed in the parent's scale via a
     multiple of the mark's em: 90px needed / 45.7px = 1.97em. */
  top: -1.97em;
  line-height: 0;
}

/* The wordmark is sized to fill the line, so the  had nowhere to go and
   touched the right edge. A hair of right padding keeps it inside. */
.footer_brand { padding-right: .04em; }

/* CTA button ("Solicita tu auditoría gratuita")

   The template's own 24px line-space plus 16px right padding puts 40px between
   the label and the dot. On the short labels it ships with ("Ver todo") that
   reads as balance; on this long one it reads as a hole. Tightened to 12px --
   the same value the template's own small button variant uses -- and the whole
   button stepped down to that variant's scale, so it stops looking oversized
   next to everything else. */
.cta_component .button-secondary { padding: 10px 14px; }
.cta_component .button-secondary .button-line_space { width: 12px; }
.cta_component .button-secondary .button_text { font-size: 13px; }

/* ===========================================================================
   /pricing-v2 — pricing page in the home section's visual language

   The home's own .pricing_* classes do the heavy lifting (glass blur, radius,
   the gradient-clipped price); these rules only adapt that two-card section to
   a full page of three switchable groups.
   =========================================================================== */

/* The section is on the black component, so page-level text flips to light. */
.kv-v2 .pricing_wrap { width: 100%; }

.kv-v2_title {
  text-align: center;
  margin-bottom: 8px;
}

.kv-v2_intro {
  max-width: 40rem;
  margin: 0 auto;
  text-align: center;
  color: rgba(255, 255, 255, .6);
}

/* Pill switcher on the dark ground (the light-page rule is black-on-white). */
.kv-v2_switch-label {
  margin-top: 48px;
  text-align: center;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .45);
}

.kv-v2 .kv-plans_switch { margin: 14px 0 0; }
.kv-v2 .kv-pill {
  background-color: rgba(255, 255, 255, .07);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .12);
}
.kv-v2 .kv-pill_tab { color: rgba(255, 255, 255, .65); }
.kv-v2 .kv-pill_tab.is-active { color: #000; }

/* The group heading sits BEHIND the cards: the cards ride up over it so only
   its upper part shows, which is the effect from the home section.
   Sized down hard from .pricing_heading's 240px -- at full size it wrapped to
   three lines and swamped the cards instead of backing them. */
.kv-v2_heading {
  position: relative;
  z-index: 0;
  text-align: center;
  font-size: clamp(48px, 7.4vw, 112px);
  line-height: .95;
  white-space: nowrap;
  margin-bottom: 0;
  pointer-events: none;
}

/* The overlap is owned by .kv-v2_blocks, not the heading: the template's own
   .pricing_blocks carries margin-top:-5rem (-80px), which overrode anything
   set on the heading and buried 94 of the glyphs' 129px -- unreadable.
   -0.14em then went too far the other way: a 16px overlap barely touched the
   descenders, so there was nothing for the glass to blur. -0.32em covers ~35px
   of the 129px glyph -- a real blur band with 73% of the word still legible. */
/* NB: `em` on .kv-v2_blocks resolves against ITS OWN 16px font, not the
   heading's 106px -- -0.32em was only 5px. The heading is clamp(48,7.4vw,112),
   so the overlap is expressed in the same vw unit to track it. */
.kv-v2_blocks { margin-top: clamp(24px, 2.2vw, 40px); }

.kv-v2_blocks {
  position: relative;
  z-index: 1;
  grid-template-columns: repeat(3, 1fr);
}
.kv-v2_blocks.is-4 { grid-template-columns: repeat(4, 1fr); }

/* Four cards in the container-large gutters leave only 312px each, which reads
   as cramped next to the 3-up rows. This row alone breaks out of the 48px
   padding-global so the extra width goes into the cards, not the gutters. */
.kv-v2_blocks.is-4 {
  width: calc(100% + 68px);
  margin-left: -34px;
  margin-right: -34px;
}
/* Below 768 the padding-global is smaller than the 34px breakout, so the row
   would push past the black component's edge. It is a single column there. */
@media screen and (max-width: 767px) {
  .kv-v2_blocks.is-4 { width: 100%; margin-left: 0; margin-right: 0; }
}


/* Cards: same glass as the home, just less padding since there are 3-4 across. */
.kv-v2_block {
  padding: 96px 32px 32px;
  display: flex;
  flex-direction: column;
}
.kv-v2_block .pricing_main { flex: 1 1 auto; }
/* The featured card carries the SAME glass edge as the others -- the template's
   own white top highlight plus grey inner glow. It used to override that with
   an accent outline; not overriding it at all is what makes it identical. */

.kv-v2_desc {
  color: rgba(255, 255, 255, .55);
  font-size: 14px;
  margin-top: 12px;
}

.kv-v2 .pricing_features { margin-top: 24px; }

.kv-v2_offs-label {
  margin-top: 16px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .4);
}
.kv-v2 .pricing_feature.is-off .pricing_feature-text { color: rgba(255, 255, 255, .35); }

.kv-v2_once {
  display: inline-flex;
  align-items: center;
  margin-left: 10px;
  position: relative;
  top: -0.42em;
  align-self: center;
  padding: 4px 12px;
  border-radius: 144px;
  background-color: rgba(255, 255, 255, .1);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .2);
  color: #fff;
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
}

.kv-v2_conditions {
  text-align: center;
  font-size: 12px;
  color: rgba(255, 255, 255, .45);
  max-width: 52rem;
  margin: 0 auto;
}

@media screen and (max-width: 991px) {
  .kv-v2_blocks, .kv-v2_blocks.is-4 { grid-template-columns: 1fr 1fr; }
  .kv-v2_heading { white-space: normal; }
  .kv-v2_block { padding: 80px 24px 24px; }
}
@media screen and (max-width: 767px) {
  .kv-v2_blocks, .kv-v2_blocks.is-4 { grid-template-columns: 1fr; }
  .kv-v2_heading { font-size: clamp(32px, 9vw, 48px); white-space: normal; }
  .kv-v2_block { padding: 72px 22px 22px; }
}

/* ===========================================================================
   Plan recommender — logic ported from kenshovisual.com, design rebuilt here.

   The source modal is beige on cream (#E8DDD4 / #8B7355 / serif headings),
   which belongs to the old branding. This version uses the same glass surface
   as the pricing cards: blur, 40px radius, the white top highlight, and the
   template's accent for the primary action only.
   =========================================================================== */

/* Floating launcher: a question-mark circle with a notification dot, and a
   tooltip that appears after 5s -- the same pattern kensho-web uses, rebuilt
   on this site's accent and glass rather than its teal/cream. */
.kv-rec_bubble-wrap {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 900;
  width: 56px;
  height: 56px;
}

.kv-rec_bubble {
  width: 56px;
  height: 56px;
  border: 0;
  border-radius: 50%;
  background-color: var(--_colors---primary--accent, #F65600);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 4px 20px rgba(246, 86, 0, .4), 0 2px 8px rgba(0, 0, 0, .25);
  transition: transform 0.2s ease;
}
.kv-rec_bubble:hover { transform: scale(1.08); }
.kv-rec_bubble:active { transform: scale(.95); }

.kv-rec_dot {
  position: absolute;
  top: 1px;
  right: 1px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #ef4444;
  border: 2px solid #0d0d0d;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.kv-rec_dot.is-hidden { opacity: 0; transform: scale(0); }

.kv-rec_tooltip {
  position: fixed;
  right: 22px;
  bottom: 92px;
  z-index: 900;
  max-width: 248px;
  padding: 14px 30px 14px 16px;
  border-radius: 14px;
  /* Light ground: the template's own paper tone, so the tooltip reads as a
     note laid over the dark page rather than part of it. Contrast measured
     16.7:1 for the body text and 5.4:1 for the close button -- both past AA. */
  background: var(--_colors---primary--paper, #f8f7f3);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9),
              inset 0 0 0 1px rgba(0, 0, 0, .08),
              0 12px 40px rgba(0, 0, 0, .45);
  font-size: 13px;
  line-height: 1.55;
  color: var(--_colors---grey--700, #171717);
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.kv-rec_tooltip.is-visible { opacity: 1; transform: translateY(0); pointer-events: auto; }

/* the little pointer aiming at the bubble */
.kv-rec_tooltip::after {
  content: "";
  position: absolute;
  bottom: -6px;
  right: 22px;
  width: 13px;
  height: 6px;
  background: var(--_colors---primary--paper, #f8f7f3);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}

.kv-rec_tooltip-close {
  position: absolute;
  top: 6px;
  right: 7px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--_colors---grey--400, #666);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.2s ease;
}
.kv-rec_tooltip-close:hover { background: rgba(0, 0, 0, .07); color: #000; }

.kv-rec[hidden] { display: none; }
.kv-rec {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.kv-rec_backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, .72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.kv-rec_panel {
  position: relative;
  width: 100%;
  max-width: 520px;
  max-height: 86vh;
  overflow-y: auto;
  border-radius: 28px;
  background-color: #0d0d0d;
  box-shadow: inset 0 5px 3px -3px rgba(255, 255, 255, .41),
              inset 0 4px 20px -5px rgb(78, 78, 78),
              0 30px 80px rgba(0, 0, 0, .6);
}

.kv-rec_close {
  position: absolute;
  top: 18px; right: 18px;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 32px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .08);
  color: rgba(255, 255, 255, .7);
  cursor: pointer;
  transition: background 0.2s ease;
}
.kv-rec_close:hover { background: rgba(255, 255, 255, .16); }

.kv-rec_body { padding: 40px 32px 32px; }

.kv-rec_step { display: none; }
.kv-rec_step.is-active { display: block; }

.kv-rec_step-label {
  margin-bottom: 18px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .4);
}

.kv-rec_q {
  margin: 0 0 8px;
  font-size: clamp(20px, 2.2vw, 26px);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -.02em;
  color: #fff;
}

.kv-rec_help {
  margin: 0 0 20px;
  font-size: 14px;
  line-height: 1.6;
  color: rgba(255, 255, 255, .55);
}
.kv-rec_help.is-lead { color: rgba(255, 255, 255, .8); margin-bottom: 8px; }

.kv-rec_advisory {
  margin-bottom: 20px;
  padding: 14px 16px;
  border-radius: 12px;
  background: rgba(255, 255, 255, .05);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .09);
  font-size: 13px;
  line-height: 1.6;
  color: rgba(255, 255, 255, .68);
}
.kv-rec_advisory strong { color: #fff; font-weight: 600; }

.kv-rec_options { display: flex; flex-direction: column; gap: 10px; }

.kv-rec_option {
  padding: 15px 18px;
  border: 0;
  border-radius: 12px;
  background: rgba(255, 255, 255, .05);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .1);
  color: #fff;
  font-size: 16px;
  text-align: left;
  cursor: pointer;
  transition: background 0.2s ease;
}
.kv-rec_option:hover {
  background: rgba(255, 255, 255, .1);
  box-shadow: inset 0 0 0 1px var(--_colors---primary--accent, #F65600);
}

/* ---- result ---- */
.kv-rec_kicker {
  margin-bottom: 12px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--_colors---primary--accent, #F65600);
}
.kv-rec_kicker.is-small { margin-top: 26px; color: rgba(255, 255, 255, .4); }

.kv-rec_card {
  padding: 24px;
  border-radius: 18px;
  background: rgba(255, 255, 255, .04);
  box-shadow: inset 0 3px 2px -2px rgba(255, 255, 255, .3),
              inset 0 0 0 1px rgba(255, 255, 255, .08);
}

.kv-rec_plan-name {
  margin: 0;
  font-size: 26px;
  font-weight: 500;
  letter-spacing: -.02em;
  color: #fff;
}

.kv-rec_plan-price-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 6px;
}

.kv-rec_plan-price {
  font-size: 18px;
  font-weight: 500;
  color: rgba(255, 255, 255, .75);
}

.kv-rec_saving[hidden] { display: none; }
.kv-rec_saving {
  display: inline-flex;
  padding: 4px 12px;
  border-radius: 144px;
  background: rgba(255, 255, 255, .1);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18);
  font-size: 12px;
  font-weight: 500;
  color: #fff;
}

.kv-rec_bullets {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.kv-rec_bullets li {
  position: relative;
  padding-left: 18px;
  font-size: 14px;
  line-height: 1.5;
  color: rgba(255, 255, 255, .7);
}
.kv-rec_bullets li::before {
  content: "";
  position: absolute;
  left: 0; top: 8px;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--_colors---primary--accent, #F65600);
}

.kv-rec_cta {
  display: block;
  width: 100%;
  margin-top: 18px;
  padding: 15px 24px;
  border: 0;
  border-radius: 144px;
  background-color: var(--_colors---primary--accent, #F65600);
  color: #fff;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.2s ease;
}
.kv-rec_cta:hover { opacity: .88; }

.kv-rec_extras[hidden] { display: none; }
.kv-rec_extra[hidden] { display: none; }

.kv-rec_extra {
  padding: 16px 18px;
  border-radius: 12px;
  background: rgba(255, 255, 255, .04);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08);
}
.kv-rec_extra + .kv-rec_extra { margin-top: 10px; }

.kv-rec_extra-title {
  margin-bottom: 6px;
  font-size: 16px;
  font-weight: 500;
  color: #fff;
}
.kv-rec_extra-title span { color: rgba(255, 255, 255, .5); font-size: 14px; }

.kv-rec_extra-text {
  margin: 0;
  font-size: 13px;
  line-height: 1.6;
  color: rgba(255, 255, 255, .55);
}

.kv-rec_restart {
  display: block;
  width: 100%;
  margin-top: 18px;
  padding: 0;
  border: 0;
  background: none;
  color: rgba(255, 255, 255, .45);
  font-size: 13px;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.kv-rec_restart:hover { color: #fff; }

/* the recommended card flashes when the CTA scrolls you to it */
.kv-rec-flash {
  animation: kv-rec-flash 1.7s ease;
}
@keyframes kv-rec-flash {
  0%, 100% { box-shadow: inset 0 5px 3px -3px rgba(255,255,255,.41), inset 0 4px 20px -5px rgb(78,78,78); }
  25%, 75% { box-shadow: inset 0 0 0 2px var(--_colors---primary--accent, #F65600); }
}

@media screen and (max-width: 767px) {
  .kv-rec { padding: 12px; }
  .kv-rec_body { padding: 34px 20px 24px; }
  .kv-rec_panel { max-height: 90vh; }
  .kv-rec_bubble-wrap { right: 16px; bottom: 16px; }
  .kv-rec_tooltip { right: 14px; bottom: 84px; max-width: calc(100vw - 40px); }
}

@media (prefers-reduced-motion: reduce) {
  .kv-rec-flash { animation: none; }
  .kv-rec_tooltip { transition: none; }
}


/* ============ ajustes pedidos por Sergio ============ */

/* --- features: quitar el círculo del check, dejar sólo la marca --- */
/* El template pinta un PNG (círculo oscuro + check blanco) como background de
   .pricing_feature. Sobre las cards oscuras el círculo pesa demasiado, así que
   se sustituye por un SVG inline: sólo el trazo del check. */
.kv-v2 .pricing_feature,
.kv-plans_panel .pricing_feature {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23F65600' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  background-size: 0.95rem;
  background-position: 0 0.42em;
}

/* --- lo que NO incluye: una X, no un check --- */
.kv-v2 .pricing_feature.is-off,
.kv-plans_panel .pricing_feature.is-off {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23808080' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E");
  background-size: 0.82rem;
  background-position: 0.06rem 0.5em;
}

/* --- burbuja del recomendador: sin punto rojo, con profundidad --- */
.kv-rec_dot { display: none; }

.kv-rec_bubble {
  /* degradado sutil del acento + luz interior arriba y sombra interior abajo:
     el mismo lenguaje de "glass edge" que usan las cards del template. */
  background-image: linear-gradient(160deg,
                    rgba(255, 255, 255, .22) 0%,
                    rgba(255, 255, 255, 0) 42%,
                    rgba(0, 0, 0, .16) 100%);
  box-shadow: inset 0 1.5px 0 rgba(255, 255, 255, .45),
              inset 0 -2px 6px rgba(0, 0, 0, .22),
              inset 0 0 0 1px rgba(255, 255, 255, .14),
              0 6px 18px rgba(246, 86, 0, .34),
              0 12px 34px rgba(0, 0, 0, .30);
}
.kv-rec_bubble:hover {
  transform: scale(1.08);
  box-shadow: inset 0 1.5px 0 rgba(255, 255, 255, .5),
              inset 0 -2px 6px rgba(0, 0, 0, .2),
              inset 0 0 0 1px rgba(255, 255, 255, .18),
              0 8px 24px rgba(246, 86, 0, .44),
              0 16px 40px rgba(0, 0, 0, .34);
}

/* --- tarjeta de contacto en el footer --- */
/* El marcado es una COPIA LITERAL de la del hero (data-w-id incluido), así que
   hereda tamaño, padding, radios y la animación IX2 de despliegue. Aquí sólo
   se corrige lo único que no puede heredarse: el hero va sobre vídeo oscuro
   (cristal blanco translúcido) y el footer es claro, donde ese tratamiento la
   dejaría invisible. Se invierte a la escala de grises del template y NADA
   más: ni tamaños, ni radios, ni transiciones propias. */
.footer_social { align-items: center; }

.kv-fcontact {
  position: relative;   /* ancla el punto naranja; sin esto se iba al viewport */
  margin-top: var(--fixed--1-5rem, 1.5rem);
}

.kv-fcontact .home-header_contact-infos {
  background-color: transparent;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .10);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.kv-fcontact .home-header_contact-cta { color: var(--_colors---grey--700, #171717); }
.kv-fcontact .home-header_contact-text { color: var(--_colors---grey--400, #666); }
.kv-fcontact .home-header_contact-link { color: var(--_colors---grey--700, #171717); }

@media screen and (max-width: 767px) {
  .footer_social { justify-content: flex-start; }
}

/* ---------- desarrollo web (/pricing-v2): mismo lenguaje que .kv-espec_card,
   en 4 columnas porque son 4 productos cerrados ---------- */
.kv-web_grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
}
.kv-web_card {
  border-radius: 18px;
  overflow: hidden;
  background-color: #fff;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
  display: flex;
  flex-direction: column;
  transition: transform 0.2s ease;
}
.kv-web_card:hover { transform: translateY(-4px); }
.kv-web_img-wrap { aspect-ratio: 16 / 10; overflow: hidden; }
.kv-web_img { width: 100%; height: 100%; object-fit: cover; display: block; }
.kv-web_body { padding: 24px; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.kv-web_note {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--_colors---grey--400, #666);
}
.kv-web_name {
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -.02em;
  margin: 2px 0 0;
}
.kv-web_price {
  font-weight: 600;
  color: var(--_colors---primary--accent, #F65600);
}
.kv-web_desc {
  margin-top: 6px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--_colors---grey--500, #4d4d4d);
}
.section_kv-web { padding-bottom: 0; }

@media screen and (max-width: 991px) {
  .kv-web_grid { grid-template-columns: 1fr 1fr; }
}
@media screen and (max-width: 767px) {
  .kv-web_grid { grid-template-columns: 1fr; }
}

/* ============ switcher con deslizamiento + destello ============ */

.kv-pill { position: relative; }

/* las pestañas van por encima del indicador */
.kv-pill_tab { position: relative; z-index: 1; }

/* el indicador que se desliza */
.kv-pill_glider {
  position: absolute;
  top: 4px;
  left: 0;
  height: calc(100% - 8px);
  width: 0;
  border-radius: 144px;
  background-color: #000;
  /* el desplazamiento es lo que da el "flow": un ease con un punto de
     asentamiento, no un lineal seco */
  transition: transform 0.2s cubic-bezier(.34, 1.32, .48, 1),
              width 0.2s cubic-bezier(.34, 1.32, .48, 1);
  z-index: 0;
  pointer-events: none;
}
.kv-v2 .kv-pill_glider { background-color: #fff; }

/* destello que recorre el borde del switcher */
.kv-pill::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 144px;
  padding: 1px;
  background: conic-gradient(from var(--kv-ang, 0deg),
              transparent 0turn,
              transparent .62turn,
              rgba(246, 86, 0, .10) .76turn,
              rgba(246, 86, 0, .85) .88turn,
              rgba(255, 255, 255, .95) .94turn,
              rgba(246, 86, 0, .85) 1turn);
  /* sólo el borde: se recorta el interior */
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  animation: kv-pill-sheen 4.5s linear infinite;
  pointer-events: none;
}

@property --kv-ang {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}
@keyframes kv-pill-sheen {
  to { --kv-ang: 360deg; }
}

@media (prefers-reduced-motion: reduce) {
  .kv-pill_glider { transition: none; }
  .kv-pill::after { animation: none; }
}

/* ============ H1 de precios: mismo degradado que los importes ============ */
/* .pricing_money usa linear-gradient(131deg,#fff,#353535) recortado al texto. */
.kv-v2_title {
  -webkit-text-fill-color: transparent;
  background-image: linear-gradient(131deg, #fff, #353535);
  -webkit-background-clip: text;
  background-clip: text;
}

/* ============ más aire encima de "Selecciona lo que necesitas" ============ */
.kv-v2_switch-label { margin-top: 96px; }
@media screen and (max-width: 767px) {
  .kv-v2_switch-label { margin-top: 64px; }
}

/* ============ footer sin panel blanco ============ */
/* Sergio: que navegación, la tarjeta de contacto y los sociales compartan el
   mismo fondo que la zona de debajo del wordmark, que es el fondo de página
   (--_colors---primary--paper, #f8f7f3). El panel blanco redondeado
   desaparece. */
.footer_wrap {
  background-color: var(--_colors---primary--paper, #f8f7f3);
  border-radius: 0;
}



/* ============ ajustes finales pedidos por Sergio ============ */

/* --- lo que incluye cada pack: más claro (estaba en grey--300, 3.9:1 sobre
       la card oscura, por debajo de AA). Se sube a los tokens claros. --- */
.kv-v2 .pricing_feature-text { color: var(--_colors---grey--100, #ddd); }
.kv-v2 .pricing_feature-detail { color: var(--_colors---grey--50, #f1efed); }

/* --- "Pago único": el borde inferior de la píldora alineado con la base del €
       (medido: hacía falta bajarla 1.893em respecto a -0.06em) --- */
.kv-v2_once { top: 1.833em; }

/* --- cards de desarrollo web: más profundidad, en el lenguaje del template --- */
.kv-web_card {
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08),
              0 1px 2px rgba(0, 0, 0, .04),
              0 8px 24px rgba(0, 0, 0, .07);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.kv-web_card:hover {
  transform: translateY(-6px);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12),
              0 2px 4px rgba(0, 0, 0, .05),
              0 18px 40px rgba(0, 0, 0, .13);
}
/* la imagen acompaña con un zoom muy leve */
.kv-web_img-wrap { position: relative; }
.kv-web_img { transition: transform 0.2s ease; }


/* --- servicios especializados: mismo tamaño y 4 columnas que desarrollo web --- */
.kv-espec_grid { grid-template-columns: repeat(4, 1fr); }
.kv-espec_img-wrap { aspect-ratio: 16 / 10; }
.kv-espec_card {
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08),
              0 1px 2px rgba(0, 0, 0, .04),
              0 8px 24px rgba(0, 0, 0, .07);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.kv-espec_card:hover {
  transform: translateY(-6px);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12),
              0 2px 4px rgba(0, 0, 0, .05),
              0 18px 40px rgba(0, 0, 0, .13);
}
.kv-espec_img { transition: transform 0.2s ease; }


@media screen and (max-width: 991px) {
  .kv-espec_grid { grid-template-columns: 1fr 1fr; }
}
@media screen and (max-width: 767px) {
  .kv-espec_grid { grid-template-columns: 1fr; }
}

/* Las cards de especializados salían a 306px frente a 318px de las de web: la
   sección llevaba 24px de padding lateral que la de desarrollo web no tiene.
   Se iguala para que ambas rejillas den cards del mismo tamaño. */
.section_kv-espec .container-medium { padding-left: 0; padding-right: 0; }
@media screen and (max-width: 991px) {
  .section_kv-espec .container-medium { padding-left: 0; padding-right: 0; }
}

/* ============ PRUEBA: desarrollo web en lenguaje glass ============
   Sólo se aplica bajo .section_kv-web.is-glass (ruta /pricing-webtest), así
   que /pricing no se ve afectada. Valores medidos sobre .pricing_component /
   .kv-v2_block / .kv-v2_heading. */

.kv-webglass_component {
  background-color: var(--_colors---primary--black, #000);
  border-radius: 20px;
  overflow: hidden;
}

.kv-webglass_head { text-align: center; }
.kv-webglass_head .label_wrap { justify-content: center; }

.kv-webglass_heading {
  font-size: clamp(48px, 7.4vw, 112px);
  line-height: .95;
  padding-bottom: .16em;
  white-space: nowrap;
  text-align: center;
  margin-bottom: 0;
  /* mismo degradado recortado que los importes */
  -webkit-text-fill-color: transparent;
  background-image: linear-gradient(131deg, #fff, #353535);
  -webkit-background-clip: text;
  background-clip: text;
}

.kv-webglass_intro {
  max-width: 40rem;
  margin: 10px auto 18px;
  text-align: center;
  color: var(--_colors---grey--200, #b6b6b6);
}

/* las cards suben para solapar el título: es lo que deja ver el blur */
.kv-web_grid.is-glass {
  /* Sin solape: Sergio pidió aire en todo. La separación acompaña al tamaño
     del título, que es fluido. */
  margin-top: clamp(24px, 2.2vw, 40px);
  position: relative;
  z-index: 1;
}




/* la imagen, redondeada dentro de la card de cristal */


/* textos sobre fondo oscuro */





@media screen and (max-width: 991px) {
  .kv-webglass_heading { white-space: normal; }
}

/* ---------- PRUEBA: variante CLARA de la sección glass ----------
   Misma estructura y mismas medidas que la oscura; sólo cambia el terreno.
   El panel usa grey--50 (token del template) y las cards van en blanco: sobre
   paper (1.07:1) serían invisibles, así que el panel baja un punto y el filo
   remata la separación. El degradado del título se invierte (oscuro -> gris
   claro), que es el equivalente del blanco -> #353535 del fondo negro. */

.section_kv-web.is-glass.is-light .kv-webglass_component {
  background-color: var(--_colors---grey--50, #f1efed);
}

.section_kv-web.is-glass.is-light .kv-webglass_heading {
  /* Sergio: "Desarrollo web" y "Servicios de marketing" en negro plano.
     Se anula el background-clip:text ENTERO, no sólo el degradado: dejar el
     fill transparente sin degradado detrás dejaría el texto invisible. */
  background-image: none;
  -webkit-text-fill-color: var(--_colors---primary--black, #171717);
  color: var(--_colors---primary--black, #171717);
}

.section_kv-web.is-glass.is-light .text-color-white,
.section_kv-web.is-glass.is-light .text-style-label {
  color: var(--_colors---grey--700, #171717);
}

.section_kv-web.is-glass.is-light .kv-webglass_intro {
  color: var(--_colors---grey--500, #4d4d4d);
}

/* cristal en claro: el inset oscuro se traduce a luz blanca arriba + sombra
   interior suave, el mismo patrón que ya usa .kv-rec_tooltip */
.section_kv-web.is-glass.is-light .kv-web_card {
  border-radius: 40px;
  overflow: hidden;
  background-color: rgba(255, 255, 255, .72);
  -webkit-backdrop-filter: blur(15px);
  backdrop-filter: blur(15px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9),
              inset 0 0 0 1px rgba(0, 0, 0, .07),
              0 8px 24px rgba(0, 0, 0, .07);
}
.section_kv-web.is-glass.is-light .kv-web_card:hover {
  transform: translateY(-6px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .95),
              inset 0 0 0 1px rgba(0, 0, 0, .11),
              0 18px 40px rgba(0, 0, 0, .12);
}

.section_kv-web.is-glass.is-light .kv-web_note { color: var(--_colors---grey--400, #666); }
.section_kv-web.is-glass.is-light .kv-web_name { color: var(--_colors---grey--700, #171717); }
.section_kv-web.is-glass.is-light .kv-web_desc { color: var(--_colors---grey--500, #4d4d4d); }

/* ============ sin solapes: espaciado limpio ============
   Las cards de precios llevaban padding-top 96px para dejar hueco al título
   que las atravesaba. Al quitar el solape ese espacio queda muerto, así que se
   ajusta al ritmo normal de la card. */
.kv-v2_block { padding-top: 64px; }

/* aire bajo el switcher antes de los títulos */
.kv-v2 .kv-plans_switch { margin-bottom: clamp(28px, 2.6vw, 48px); }

.section_kv-web.is-glass.is-light .kv-web_img-wrap {
  border-radius: 28px;
  overflow: hidden;
  margin: 8px 8px 0;
}
.section_kv-web.is-glass.is-light .kv-web_body { padding: 20px 24px 28px; }

/* ============ servicios especializados: mismo tratamiento que web ============ */
.section_kv-espec .kv-webglass_head { text-align: center; }
.kv-espec_heading {
  /* mismo tamaño que "Desarrollo web", pero puede necesitar dos líneas */
  white-space: normal;
  /* Sergio lo quiere en negro plano, sin degradado: se anula el
     background-clip:text que hereda de .kv-webglass_heading. */
  background-image: none;
  -webkit-text-fill-color: var(--_colors---primary--black, #171717);
  color: var(--_colors---primary--black, #171717);
  /* line-height .95 recorta el descendente y background-clip:text no pinta
     fuera de la caja: se amplía para que la "g" se vea entera */
  padding-bottom: .16em;
}
.section_kv-espec .kv-webglass_intro { color: var(--_colors---grey--500, #4d4d4d); }
.section_kv-espec .text-color-white,
.section_kv-espec .text-style-label { color: var(--_colors---grey--700, #171717); }

/* ============ precio dentro de la imagen, en cristal ============ */
.kv-web_img-wrap { position: relative; }

.kv-web_pricetag {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 2;
  padding: 7px 14px;
  border-radius: 144px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--_colors---grey--700, #171717);
  /* cristal: el mismo patrón que .kv-rec_tooltip / las cards claras */
  background-color: rgba(255, 255, 255, .72);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  backdrop-filter: blur(12px) saturate(140%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9),
              inset 0 0 0 1px rgba(0, 0, 0, .07),
              0 2px 8px rgba(0, 0, 0, .12);
  white-space: nowrap;
}

/* ============ entrada de las cards web: parallax + barrido ============
   El reveal genérico (.kv-reveal) lo mueve GSAP; aquí se usa una clase propia
   para no colisionar con él.

   - la card entra desde la izquierda, escalonada
   - la imagen arranca desplazada y con zoom, y se asienta: al ir en sentido
     contrario a la card, se lee como parallax
   - el parallax de scroll continúa en JS (kv.js) */
.kv-webin {
  opacity: 0;
  transform: translate3d(-38px, 0, 0);
  transition: opacity .5s cubic-bezier(.22, .61, .36, 1),
              transform .5s cubic-bezier(.22, .61, .36, 1);
  transition-delay: calc(var(--kv-i, 0) * 90ms);
}
.kv-webin .kv-web_img {
  transform: scale(1.16) translate3d(26px, 0, 0);
  transition: transform .8s cubic-bezier(.22, .61, .36, 1);
  transition-delay: calc(var(--kv-i, 0) * 90ms);
  will-change: transform;
}
.kv-webin .kv-web_pricetag {
  opacity: 0;
  transform: translate3d(0, -8px, 0);
  transition: opacity .35s ease, transform .35s cubic-bezier(.22, .61, .36, 1);
  transition-delay: calc(var(--kv-i, 0) * 90ms + 260ms);
}

.kv-webin.is-in { opacity: 1; transform: translate3d(0, 0, 0); }
.kv-webin.is-in .kv-web_img { transform: scale(1.04) translate3d(0, 0, 0); }
.kv-webin.is-in .kv-web_pricetag { opacity: 1; transform: translate3d(0, 0, 0); }

/* el parallax de scroll lo aplica JS con --kv-par; el hover suma su propio zoom */
.kv-webin.is-in .kv-web_img {
  transform: scale(1.04) translate3d(0, var(--kv-par, 0px), 0);
}
/* Sin zoom en hover: al escalar una imagen grande en cada frame el scroll se
   ralentizaba y el recorte dejaba ver los bordes. Se queda sólo la entrada. */

html.kv-no-js .kv-webin { opacity: 1; transform: none; }
html.kv-no-js .kv-webin .kv-web_img { transform: scale(1.04); }
html.kv-no-js .kv-webin .kv-web_pricetag { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .kv-webin, .kv-webin .kv-web_img, .kv-webin .kv-web_pricetag {
    transition: none;
    opacity: 1;
    transform: none;
  }
  .kv-webin.is-in .kv-web_img { transform: scale(1.04); }
}

/* ---- precio en píldora sobre la imagen también en servicios de marketing ---- */
.kv-espec_img-wrap { position: relative; }

.kv-espec_pricetag {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 2;
  padding: 7px 14px;
  border-radius: 144px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--_colors---grey--700, #171717);
  background-color: rgba(255, 255, 255, .72);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  backdrop-filter: blur(12px) saturate(140%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9),
              inset 0 0 0 1px rgba(0, 0, 0, .07),
              0 2px 8px rgba(0, 0, 0, .12);
  white-space: nowrap;
}

/* el precio ya no va al pie de la card */
.kv-espec_price { display: none; }

/* ================= páginas de proyecto (caso de estudio) =================
   Vocabulario de esta plantilla: tokens --_colors---*, radios del set medido,
   transiciones 0.2s. Nada importado de kensho-web. */

.kv-case_intro {
  margin-top: 20px;
  max-width: 46rem;
  color: var(--_colors---grey--500, #4d4d4d);
  font-size: 18px;
  line-height: 1.55;
}

.kv-case_pills { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 24px; }
.kv-case_pill {
  padding: 6px 14px;
  border-radius: 144px;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .02em;
  color: var(--_colors---grey--700, #171717);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
}

.kv-case_hero { border-radius: 18px; overflow: hidden; }
.kv-case_hero img, .kv-case_hero video {
  width: 100%; height: 100%; object-fit: cover; display: block;
}

/* --- filas: índice a la izquierda, contenido a la derecha --- */
.kv-case_section { padding-top: 96px; }
.kv-case_row {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 48px;
  align-items: start;
}
.kv-case_aside { position: sticky; top: 120px; }
.kv-case_num {
  font-size: 14px;
  font-weight: 600;
  color: var(--_colors---primary--accent, #F65600);
  margin-bottom: 6px;
}
.kv-case_heading {
  font-size: clamp(28px, 3.2vw, 44px);
  line-height: 1.12;
  letter-spacing: -.02em;
  margin: 0 0 20px;
  max-width: 34ch;
}
.kv-case_para {
  color: var(--_colors---grey--500, #4d4d4d);
  font-size: 17px;
  line-height: 1.6;
  max-width: 60ch;
}
.kv-case_close {
  margin-top: 20px;
  color: var(--_colors---grey--500, #4d4d4d);
  font-size: 16px;
  line-height: 1.6;
  max-width: 60ch;
}

.kv-case_list { list-style: none; margin: 24px 0 0; padding: 0; }
.kv-case_li {
  position: relative;
  padding-left: 24px;
  margin-bottom: 12px;
  color: var(--_colors---grey--700, #171717);
  font-size: 16px;
  line-height: 1.5;
}
.kv-case_li::before {
  content: "";
  position: absolute;
  left: 2px; top: .55em;
  width: 6px; height: 6px;
  border-radius: 50%;
  background-color: var(--_colors---primary--accent, #F65600);
}

/* --- métricas del resultado --- */
.kv-metrics {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-top: 32px;
}
.kv-metric {
  padding: 24px 20px;
  border-radius: 18px;
  background-color: var(--_colors---grey--50, #f1efed);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .07);
}
.kv-metric_value {
  font-size: clamp(28px, 2.6vw, 38px);
  font-weight: 600;
  letter-spacing: -.02em;
  line-height: 1;
  color: var(--_colors---primary--accent, #F65600);
}
.kv-metric_label {
  margin-top: 8px;
  font-size: 13px;
  line-height: 1.4;
  color: var(--_colors---grey--500, #4d4d4d);
}

.kv-case_quote {
  margin: 32px 0 0;
  padding: 24px 28px;
  border-radius: 18px;
  background-color: var(--_colors---grey--50, #f1efed);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .07);
  font-size: 17px;
  line-height: 1.55;
  color: var(--_colors---grey--700, #171717);
}

/* --- ficha: servicios + stack --- */
.kv-case_facts { display: grid; grid-template-columns: minmax(0, .62fr) minmax(0, 1.38fr); gap: 28px; }
.kv-fact_title {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--_colors---grey--400, #666);
  margin: 0 0 4px;
}
.kv-stack { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; }
.kv-stack_chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: 144px;
  font-size: 14px;
  font-weight: 500;
  color: var(--_colors---grey--700, #171717);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .1);
  transition: box-shadow 0.2s ease;
}
.kv-stack_chip:hover { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .22); }
.kv-stack_icon { width: 18px; height: 18px; object-fit: contain; display: block; }

.kv-case_media { border-radius: 18px; overflow: hidden; }
.kv-case_media-el { width: 100%; display: block; }

@media screen and (max-width: 991px) {
  .kv-case_row { grid-template-columns: 1fr; gap: 20px; }
  .kv-case_aside { position: static; display: flex; align-items: baseline; gap: 10px; }
  .kv-case_num { margin-bottom: 0; }
  .kv-case_section { padding-top: 64px; }
  .kv-metrics { grid-template-columns: 1fr 1fr; }
  .kv-case_facts { grid-template-columns: 1fr; gap: 28px; }
}
@media screen and (max-width: 767px) {
  .kv-metrics { grid-template-columns: 1fr 1fr; }
  .kv-case_section { padding-top: 48px; }
}

/* --- galería de proyecto --- */
.kv-gal {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}
.kv-gal.is-single { grid-template-columns: 1fr; }
.kv-gal_item {
  border-radius: 18px;
  overflow: hidden;
  background-color: var(--_colors---grey--50, #f1efed);
}
.kv-gal_media {
  width: 100%;
  display: block;
  aspect-ratio: 16 / 10;
  object-fit: cover;
}
.kv-gal.is-single .kv-gal_media { aspect-ratio: 16 / 9; }

@media screen and (max-width: 767px) {
  .kv-gal { grid-template-columns: 1fr; }
}

/* ================= PRUEBAS: sección de debajo del hero =================
   Tres variantes en rutas /home-v1, /home-v2, /home-v3. La home no se toca.
   Tokens, radios y duraciones de esta plantilla. */

.section_kv-below .kv-caption { display: flex; align-items: center; gap: 10px; }

/* ---------- v1: manifiesto que se ilumina al hacer scroll ---------- */
.kv-mf {
  font-size: clamp(26px, 3.4vw, 52px);
  line-height: 1.24;
  letter-spacing: -.02em;
  font-weight: 500;
  max-width: 22ch;
  margin: 0;
}
.kv-mf em { font-style: normal; color: var(--_colors---primary--accent, #F65600); }
.kv-mf_w {
  color: var(--_colors---grey--100, #ddd);
  transition: color 0.5s ease;
}
.kv-mf_w.is-lit { color: var(--_colors---grey--700, #171717); }

.kv-mf_pillars {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
  border-top: 1px solid rgba(0, 0, 0, .1);
  padding-top: 32px;
}
.kv-mf_pillar-t {
  font-size: 15px; font-weight: 600; margin-bottom: 6px;
  color: var(--_colors---grey--700, #171717);
}
.kv-mf_pillar-d {
  font-size: 14px; line-height: 1.5;
  color: var(--_colors---grey--500, #4d4d4d);
}

/* ---------- v2: comparador Sin / Con ---------- */
.kv-cmp { border-top: 1px solid rgba(0, 0, 0, .1); }
.kv-cmp_head, .kv-cmp_row {
  display: grid;
  grid-template-columns: 160px 1fr 1fr;
  gap: 20px;
  align-items: center;
}
.kv-cmp_head {
  padding: 14px 0;
  font-size: 12px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
}
.kv-cmp_hneg { color: var(--_colors---grey--400, #666); }
.kv-cmp_hpos { color: var(--_colors---primary--accent, #F65600); }

.kv-cmp_row {
  padding: 20px 0;
  border-top: 1px solid rgba(0, 0, 0, .08);
  opacity: 0;
  transform: translate3d(0, 14px, 0);
  transition: opacity .5s cubic-bezier(.22,.61,.36,1),
              transform .5s cubic-bezier(.22,.61,.36,1);
  transition-delay: calc(var(--kv-i, 0) * 70ms);
}
.kv-cmp_row.is-in { opacity: 1; transform: none; }

.kv-cmp_cat {
  font-size: 12px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--_colors---grey--400, #666);
}
.kv-cmp_neg, .kv-cmp_pos {
  display: flex; align-items: center; gap: 12px;
  font-size: 17px; line-height: 1.35;
}
.kv-cmp_neg { color: var(--_colors---grey--400, #666); }
.kv-cmp_pos { color: var(--_colors---grey--700, #171717); font-weight: 500; }
.kv-cmp_ico {
  flex: none;
  width: 22px; height: 22px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px;
}
.kv-cmp_ico.is-neg { color: var(--_colors---grey--400, #666);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .14); }
.kv-cmp_ico.is-pos { color: #fff;
  background-color: var(--_colors---primary--accent, #F65600); }

/* ---------- v3: resultados reales ---------- */
.kv-res {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}
.kv-res_card {
  padding: 32px 28px;
  border-radius: 18px;
  background-color: var(--_colors---grey--50, #f1efed);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .07);
  opacity: 0;
  transform: translate3d(0, 16px, 0);
  transition: opacity .5s cubic-bezier(.22,.61,.36,1),
              transform .5s cubic-bezier(.22,.61,.36,1),
              box-shadow 0.2s ease;
  transition-delay: calc(var(--kv-i, 0) * 70ms);
}
.kv-res_card.is-in { opacity: 1; transform: none; }
.kv-res_card:hover { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .16); }
.kv-res_value {
  font-size: clamp(34px, 3.6vw, 52px);
  font-weight: 600; line-height: 1; letter-spacing: -.02em;
  color: var(--_colors---primary--accent, #F65600);
}
.kv-res_label {
  margin-top: 10px; font-size: 15px; line-height: 1.45;
  color: var(--_colors---grey--500, #4d4d4d);
}
.kv-res_link {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 15px; font-weight: 500;
  color: var(--_colors---grey--700, #171717);
  text-decoration: none;
  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);
  transition: box-shadow 0.2s ease;
}
.kv-res_link:hover { box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .6); }

@media screen and (max-width: 991px) {
  .kv-mf_pillars { grid-template-columns: 1fr 1fr; gap: 24px; }
  .kv-res { grid-template-columns: 1fr 1fr; }
  .kv-cmp_head, .kv-cmp_row { grid-template-columns: 1fr 1fr; }
  .kv-cmp_cat { grid-column: 1 / -1; margin-bottom: 4px; }
  .kv-cmp_head .kv-cmp_cat { display: none; }
}
@media screen and (max-width: 767px) {
  .kv-mf_pillars { grid-template-columns: 1fr; }
  .kv-res { grid-template-columns: 1fr; }
  .kv-cmp_head, .kv-cmp_row { grid-template-columns: 1fr; gap: 10px; }
  .kv-cmp_head { display: none; }
}

/* atribución de cada métrica: de qué proyecto sale */
.kv-res_attr {
  display: inline-block;
  margin-top: 14px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--_colors---grey--400, #666);
  text-decoration: none;
  transition: color 0.2s ease;
}
.kv-res_attr:hover { color: var(--_colors---grey--700, #171717); }

/* v2: la asimetría es la que persuade — el lado "sin" va apagado y el
   lado "con" con más peso, no como una tabla neutra */
.kv-cmp_row .kv-cmp_neg { opacity: .62; }
.kv-cmp_pos { font-size: 18px; }

/* Los iconos se recortaron a su contenido real (Stripe venía 16:9 con 55% de
   relleno y salía diminuto), así que ya pueden ir todos al mismo tamaño. */
.kv-stack_icon { width: 20px; height: 20px; }
.kv-stack { gap: 8px; }
.kv-stack_chip { padding: 7px 12px; gap: 7px; font-size: 13.5px; }

/* ================= v4: manifiesto centrado con blur que se disipa =========
   Cada palabra entra desenfocada y desplazada; el blur se disipa al llegar.
   No es un fade de opacidad: el filtro es lo que da la sensación de que el
   texto "se enfoca". */

.section_kv-below.is-v4 { position: relative; overflow: hidden; }

/* resplandor muy suave detrás del texto, en el acento de la marca */
.kv-v4_glow {
  position: absolute;
  top: 42%; left: 50%;
  width: min(1100px, 92vw);
  height: min(520px, 60vh);
  transform: translate(-50%, -50%);
  pointer-events: none;
  background: radial-gradient(ellipse at center,
              rgba(246, 86, 0, .13) 0%,
              rgba(246, 86, 0, .05) 38%,
              transparent 70%);
  opacity: 0;
  transition: opacity .8s ease;
}
.section_kv-below.is-v4.is-in .kv-v4_glow { opacity: 1; }

.kv-v4_cap {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  opacity: 0;
  transform: translate3d(0, 10px, 0);
  transition: opacity .5s ease, transform .5s cubic-bezier(.22,.61,.36,1);
}
.section_kv-below.is-v4.is-in .kv-v4_cap { opacity: 1; transform: none; }

.kv-v4_text {
  position: relative;
  margin: 28px auto 0;
  max-width: 20ch;
  text-align: center;
  font-size: clamp(30px, 4.6vw, 68px);
  line-height: 1.16;
  letter-spacing: -.03em;
  font-weight: 500;
}
.kv-v4_line { display: block; }
.kv-v4_text em {
  font-style: normal;
  color: var(--_colors---primary--accent, #F65600);
}

.kv-v4_w {
  display: inline-block;
  opacity: 0;
  filter: blur(14px);
  transform: translate3d(0, 18px, 0) scale(1.04);
  transition: opacity .8s cubic-bezier(.22,.61,.36,1),
              filter .8s cubic-bezier(.22,.61,.36,1),
              transform .8s cubic-bezier(.22,.61,.36,1);
  transition-delay: calc(var(--kv-w, 0) * 55ms);
  will-change: filter, transform;
}
.section_kv-below.is-v4.is-in .kv-v4_w {
  opacity: 1;
  filter: blur(0);
  transform: none;
}

/* línea que se abre desde el centro */
.kv-v4_rule {
  width: 100%; height: 1px;
  margin: 56px auto 0;
  background: linear-gradient(to right, transparent,
              rgba(0, 0, 0, .16) 22%, rgba(0, 0, 0, .16) 78%, transparent);
  transform: scaleX(0);
  transition: transform .8s cubic-bezier(.22,.61,.36,1) .5s;
}
.section_kv-below.is-v4.is-in .kv-v4_rule { transform: scaleX(1); }

.kv-v4_proof {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  margin-top: 36px;
  text-align: center;
}
.kv-v4_item {
  opacity: 0;
  transform: translate3d(0, 14px, 0);
  filter: blur(6px);
  transition: opacity .5s ease, transform .5s cubic-bezier(.22,.61,.36,1),
              filter .5s ease;
  transition-delay: calc(.7s + var(--kv-p, 0) * 90ms);
}
.section_kv-below.is-v4.is-in .kv-v4_item {
  opacity: 1; transform: none; filter: blur(0);
}
.kv-v4_item-k {
  font-size: 12px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--_colors---primary--accent, #F65600);
  margin-bottom: 6px;
}
.kv-v4_item-v {
  font-size: 15px; line-height: 1.5;
  color: var(--_colors---grey--500, #4d4d4d);
}

@media screen and (max-width: 991px) {
  .kv-v4_proof { grid-template-columns: 1fr 1fr; gap: 28px; }
  .kv-v4_text { max-width: 16ch; }
}
@media screen and (max-width: 767px) {
  .kv-v4_proof { grid-template-columns: 1fr; gap: 22px; }
  .kv-v4_rule { margin-top: 40px; }
}
@media (prefers-reduced-motion: reduce) {
  .kv-v4_w, .kv-v4_item, .kv-v4_cap {
    opacity: 1; filter: none; transform: none; transition: none;
  }
  .kv-v4_rule { transform: scaleX(1); transition: none; }
  .kv-v4_glow { opacity: 1; transition: none; }
}
html.kv-no-js .kv-v4_w,
html.kv-no-js .kv-v4_item,
html.kv-no-js .kv-v4_cap { opacity: 1; filter: none; transform: none; }

/* ================= v5: bloques ligados al scroll =========================
   Sin glow. Cada bloque tiene su propio progreso (--kv-p, 0..1) que calcula
   el JS a partir de su posición en pantalla: el texto se aclara, sube y se
   enfoca de forma continua mientras haces scroll — no es un disparo único al
   entrar en viewport. */

.section_kv-below.is-v5 .kv-v5_head { max-width: 30ch; }

.kv-v5_lede {
  margin: 22px 0 0;
  font-size: clamp(26px, 3.6vw, 52px);
  line-height: 1.18;
  letter-spacing: -.025em;
  font-weight: 500;
}
.kv-v5_w {
  display: inline-block;
  color: var(--_colors---grey--700, #171717);
  opacity: calc(.18 + var(--kv-lp, 0) * .82);
  filter: blur(calc((1 - var(--kv-lp, 0)) * 5px));
  transform: translate3d(0, calc((1 - var(--kv-lp, 0)) * 10px), 0);
  will-change: opacity, filter, transform;
}
.kv-v5_w--dim { color: var(--_colors---primary--accent, #F65600); }

.kv-v5_list { margin-top: clamp(48px, 6vw, 88px); }

.kv-v5_block {
  position: relative;
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr);
  gap: 28px;
  padding: clamp(28px, 3.4vw, 44px) 0;
  border-top: 1px solid rgba(0, 0, 0, .1);
  /* el bloque entero acompaña: se aclara y sube según su progreso */
  opacity: calc(.28 + var(--kv-p, 0) * .72);
  transform: translate3d(0, calc((1 - var(--kv-p, 0)) * 22px), 0);
  will-change: opacity, transform;
}

.kv-v5_num {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .1em;
  color: var(--_colors---primary--accent, #F65600);
  padding-top: .5em;
}

.kv-v5_what {
  margin: 0;
  font-size: clamp(21px, 2.1vw, 30px);
  font-weight: 600;
  letter-spacing: -.02em;
  line-height: 1.15;
}
.kv-v5_how {
  margin: 12px 0 0;
  max-width: 54ch;
  font-size: 16.5px;
  line-height: 1.6;
  color: var(--_colors---grey--500, #4d4d4d);
}
.kv-v5_gain {
  margin: 16px 0 0;
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--_colors---grey--700, #171717);
}
.kv-v5_arrow {
  color: var(--_colors---primary--accent, #F65600);
  transform: translate3d(calc((1 - var(--kv-p, 0)) * -6px), 0, 0);
}

/* barra fina que se llena con el progreso del bloque */
.kv-v5_bar {
  position: absolute;
  left: 0; top: -1px;
  width: 100%; height: 1px;
  overflow: hidden;
}
.kv-v5_bar i {
  display: block;
  height: 100%;
  width: 100%;
  background-color: var(--_colors---primary--accent, #F65600);
  transform: scaleX(var(--kv-p, 0));
  transform-origin: left center;
}

@media screen and (max-width: 767px) {
  .kv-v5_block { grid-template-columns: 1fr; gap: 10px; }
  .kv-v5_num { padding-top: 0; }
}

/* sin JS o con motion reducido: todo legible y quieto */
html.kv-no-js .kv-v5_w,
html.kv-no-js .kv-v5_block { opacity: 1; filter: none; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .kv-v5_w, .kv-v5_block, .kv-v5_arrow {
    opacity: 1; filter: none; transform: none;
  }
  .kv-v5_bar i { transform: scaleX(1); }
}

/* ============================================================================
   v6 — rejilla inclinada ligada al scroll  (/home-v6)
   ============================================================================
   Reimplementación en CSS/JS plano del scroll-tilted-grid que pasó Sergio.
   JS sólo escribe cinco variables por tarjeta; todo el aspecto vive aquí.

   Valores dentro del sistema medido:
     radio 40px          -> el de .kv-web_card en la sección glass clara
     cristal 2 partes    -> inset blanco arriba + filo negro, igual que pricing
     acento #F65600      -> --_colors---primary--accent
     mono                -> --_typography---font-family--detail (Roboto Mono VF),
                            la tercera familia del template, hasta ahora sin usar
     duraciones          -> 0.2s (hover) y 0.5s (entrada), ya en el checker    */

.section_kv-below.is-v6 {
  background-color: var(--_colors---grey--50, #f1efed);
  overflow: hidden;
}

/* ---- cabecera ---- */
.kv-t6_head { text-align: center; }
.kv-t6_head .kv-caption { justify-content: center; }

.kv-t6_heading {
  font-size: clamp(48px, 7.4vw, 112px);
  line-height: .95;
  padding-bottom: .16em;   /* background-clip:text no pinta fuera de la caja */
  margin: 10px 0 0;
  text-align: center;
  /* Sergio lo quiere en negro plano, sin degradado. Se quita el
     background-clip:text entero: dejar el fill transparente sin degradado
     detrás haría el texto invisible. */
  color: var(--_colors---primary--black, #171717);
}

.kv-t6_intro {
  max-width: 34rem;
  margin: 6px auto 0;
  text-align: center;
  color: var(--_colors---grey--500, #4d4d4d);
}

/* ---- rótulos de columna, en mono ---- */
.kv-t6_cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px;
  margin-top: clamp(48px, 5vw, 88px);
}
.kv-t6_col {
  font-family: var(--_typography---font-family--detail, "Roboto Mono VF", monospace);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  /* Cada rótulo va centrado en SU columna (el grid ya le da una a cada uno);
     antes heredaba el alineado a la izquierda. La línea inferior sigue
     ocupando el ancho completo de la columna. */
  text-align: center;
  padding-bottom: 12px;
  border-bottom: 1px solid rgba(0, 0, 0, .12);
}
.kv-t6_col.is-neg { color: var(--_colors---grey--400, #666); }
.kv-t6_col.is-pos {
  color: var(--_colors---primary--accent, #F65600);
  border-bottom-color: rgba(246, 86, 0, .35);
}

/* ---- la rejilla ---- */
.kv-t6_grid { margin-top: 28px; }

.kv-t6_pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px;
  align-items: start;
}

/* La perspectiva vive en el <figure>, no en el contenedor: así cada tarjeta
   tiene su propio punto de fuga y no se abanican todas hacia el mismo sitio. */
.kv-t6_tile {
  margin: 0;
  perspective: 1200px;
  padding-bottom: clamp(40px, 5vw, 96px);
}
/* el desfase que intercala la lectura problema -> solución */
.kv-t6_tile.is-pos { padding-top: clamp(48px, 7vw, 132px); }

.kv-t6_card {
  position: relative;
  overflow: hidden;
  border-radius: 40px;
  padding: 30px 32px 28px;
  min-height: 268px;
  display: flex;
  flex-direction: column;
  transform-style: preserve-3d;
  will-change: transform, filter;
  /* variables que escribe el JS; estos son los valores en reposo */
  filter: blur(var(--t6-blur, 0px))
          brightness(var(--t6-bright, 1))
          saturate(var(--t6-sat, 1));
  transform: var(--t6-tf, translate3d(0, 0, 0));
}

/* ---- columna "sin Kensho": el terreno se apaga ---- */
.kv-t6_tile.is-neg .kv-t6_card {
  background-color: rgba(255, 255, 255, .55);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .8),
              inset 0 0 0 1px rgba(0, 0, 0, .09),
              0 10px 30px rgba(0, 0, 0, .07);
}

/* grano/ruido muy leve: da la sensación de imagen degradada sin usar imagen */
.kv-t6_grain {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .5;
  background-image: repeating-linear-gradient(
    -45deg, rgba(0, 0, 0, .022) 0 2px, transparent 2px 5px);
}

/* ---- columna "con Kensho": negro con distintivos accent ---- */
.kv-t6_tile.is-pos .kv-t6_card {
  background-color: var(--_colors---primary--black, #171717);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .16),
              inset 0 0 0 1px rgba(255, 255, 255, .12),
              0 14px 38px rgba(0, 0, 0, .2);
}

.kv-t6_tile.is-pos .kv-t6_title { color: #fff; }
.kv-t6_tile.is-pos .kv-t6_desc {
  color: #fff;
  font-weight: 600;
}
.kv-t6_tile.is-pos .kv-t6_cat { color: #fff; }   /* nada de opacidad: baja a 2.6:1 */
.kv-t6_tile.is-pos .kv-t6_state.is-pos { color: #fff; }

/* Sobre negro, la foto de fondo competiría con la lectura del contenido. */
.kv-t6_tile.is-pos .kv-t6_bg { display: none; }

.kv-t6_bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  border-radius: 40px;
}
.kv-t6_bgimg {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* La foto es textura, no protagonista, pero a .22 con el velo encima no
     llegaba a leerse: sólo ensuciaba. Medido sobre captura, .42 es donde se
     reconoce el proyecto sin competir con el texto. */
  opacity: .42;
  filter: saturate(.62) contrast(1.02);
  transform: scale(var(--t6-imgscale, 1.06));
}
/* velo que garantiza el contraste del texto sobre cualquier foto */
.kv-t6_bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(180deg,
    rgba(248, 247, 243, .34) 0%,
    rgba(248, 247, 243, .72) 46%,
    rgba(248, 247, 243, .93) 100%);
}

/* el contenido va por encima del fondo */
.kv-t6_top, .kv-t6_title, .kv-t6_desc, .kv-t6_foot { position: relative; z-index: 1; }

/* ---- tipografía de la tarjeta ---- */
.kv-t6_top {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 20px;
}
.kv-t6_num,
.kv-t6_cat,
.kv-t6_state {
  font-family: var(--_typography---font-family--detail, "Roboto Mono VF", monospace);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.kv-t6_num {
  color: var(--_colors---grey--700, #171717);
  padding: 4px 8px;
  border-radius: 6px;
  background-color: rgba(0, 0, 0, .05);
}
.kv-t6_cat { color: var(--_colors---grey--400, #666); }
.kv-t6_tile.is-pos .kv-t6_num {
  color: #fff;
  background-color: var(--_colors---primary--accent, #F65600);
}


.kv-t6_title {
  font-size: clamp(24px, 2.3vw, 32px);
  line-height: 1.14;
  font-weight: 500;
  margin: 0 0 12px;
  color: var(--_colors---grey--700, #171717);
}
.kv-t6_tile.is-neg .kv-t6_title { color: var(--_colors---grey--400, #666); }

.kv-t6_desc {
  font-size: 16px;
  line-height: 1.5;
  margin: 0;
  color: var(--_colors---grey--500, #4d4d4d);
}
.kv-t6_tile.is-neg .kv-t6_desc { color: var(--_colors---grey--400, #666); }

.kv-t6_foot {
  margin-top: auto;
  padding-top: 22px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.kv-t6_state { color: var(--_colors---grey--400, #666); }
.kv-t6_tile.is-pos .kv-t6_state.is-pos {
  color: #fff;
  background-color: var(--_colors---primary--accent, #F65600);
  padding: 4px 8px;
  border-radius: 6px;
}

.kv-t6_arrow { display: none; }

/* ---- responsive ---- */
@media screen and (max-width: 991px) {
  .kv-t6_pair, .kv-t6_cols { gap: 20px; }
  .kv-t6_card { padding: 24px 22px 22px; min-height: 236px; border-radius: 32px; }
  .kv-t6_bg { border-radius: 32px; }
  .kv-t6_tile.is-pos { padding-top: 56px; }
}

@media screen and (max-width: 767px) {
  /* En una sola columna el eje izquierda/derecha desaparece, así que el par
     pasa a leerse en vertical y el rótulo va dentro de cada tarjeta (que ya
     lo lleva: .kv-t6_state). Los encabezados de columna sobran. */
  .kv-t6_cols { display: none; }
  .kv-t6_pair { grid-template-columns: 1fr; gap: 0; }
  .kv-t6_tile { padding-bottom: 20px; perspective: 900px; }
  .kv-t6_tile.is-pos { padding-top: 0; padding-bottom: 44px; }
  .kv-t6_card { min-height: 0; }
  .kv-t6_heading { font-size: clamp(40px, 12vw, 64px); }
}

/* ---- accesibilidad: sin movimiento, todo resuelto ---- */
@media (prefers-reduced-motion: reduce) {
  .kv-t6_card {
    filter: none !important;
    transform: none !important;
  }
  .kv-t6_bgimg { transform: none !important; }
  .kv-t6_arrow { transition: none; }
}

/* ============================================================================
   v6 — "Quiénes somos": reveal editorial palabra a palabra  (/home-v6)
   ============================================================================
   Port del manifiesto de kenshoconstruction (Manifesto.tsx + man-kf-* de
   globals.css). Allí el mecanismo es scroll-driven nativo:

     .man-section { height: 480vh; view-timeline: --man-scroll block; }
     .man-panel   { position: sticky; top: 0; height: 100svh; }
     @keyframes man-kf-word { blur(6px) translateY(8px) opacity 0 -> resuelto }
     salidas de etapa: blur(10px) translateY(-12px)

   Se conservan esos valores. Lo que cambia es el terreno: allí es serif sobre
   claro; aquí la tipografía y los colores salen del sistema de esta plantilla.

   IMPORTANTE — el estado BASE (fuera del @supports) deja todo visible y sin
   blur. Safari y Firefox todavía no soportan animation-timeline, y sin ese
   estado base la sección entera sería texto invisible. */

.section_kv-about {
  background-color: var(--_colors---primary--paper, #f8f7f3);
  position: relative;
}

.kv-ab_panel {
  /* Casi toda la pantalla, con márgenes correctos: el ancho lo pone
     container-large (1344px), que ya es del sistema. */
  min-height: 88svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: clamp(80px, 10vh, 160px);
}

.kv-ab_cap {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: clamp(28px, 4vh, 56px);
}

/* ---- etapa 1: el titular, en grande y editorial ---- */
/* Degradado del titular: se aclara hacia el final de la frase, de modo que
   "escalable." queda desvanecido. Va con una capa en `mix-blend-mode: lighten`
   y no con `background-clip: text`, porque cada palabra es un span propio con
   su blur y el clip recortaría contra su caja (texto invisible — comprobado).
   La capa se ancla al bloque de texto, no a las palabras. */
.kv-ab_lead { position: relative; }
.kv-ab_lead::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  mix-blend-mode: lighten;
  background-image: linear-gradient(103deg,
    rgba(248, 247, 243, 0) 52%,
    rgba(248, 247, 243, .30) 74%,
    rgba(248, 247, 243, .80) 100%);
}

.kv-ab_lead {
  font-size: clamp(40px, 6.2vw, 104px);
  line-height: 1.04;
  font-weight: 500;
  letter-spacing: -.02em;
  margin: 0;
  max-width: 17ch;
  text-wrap: balance;
  color: var(--_colors---grey--700, #171717);
}

/* ---- etapa 2: el cuerpo ---- */
.kv-ab_body {
  /* Sergio lo pidió un poco más pequeño, sólo en escritorio: el bloque
     de móvil (767px) lo redefine aparte y no se toca. */
  font-size: clamp(20px, min(2.7vw, 3.7vh), 45px);
  line-height: 1.18;
  font-weight: 500;
  letter-spacing: -.02em;
  margin: 0;
  /* Las líneas tienen que cruzar el centro de la pantalla, no quedarse en su
     mitad: 15ch dejaba el bloque corto. */
  max-width: 26ch;
  color: var(--_colors---grey--700, #171717);
}

/* ---- etapa 3: cierre + coda ---- */
/* Las dos frases comparten pantalla en diagonal: la primera arriba a la
   izquierda, el remate abajo a la derecha. Ocupa casi todo el alto útil, que
   es lo que crea la tensión de página de revista. */
.kv-ab_duo {
  display: grid;
  gap: clamp(36px, 20vh, 260px);
  justify-items: start;
}
.kv-ab_duo .kv-ab_close-t { justify-self: end; text-align: right; }

.kv-ab_close-t {
  font-size: clamp(30px, min(5.9vw, 7.8vh), 98px);
  line-height: 1.1;
  font-weight: 600;
  letter-spacing: -.024em;
  margin: 0;
  max-width: 26ch;
  text-wrap: balance;
  color: var(--_colors---grey--700, #171717);
}


/* ---- indicador de scroll (calcado de .man-hint de kenshoconstruction) ---- */
.kv-ab_hint {
  display: flex;
  flex-direction: column;
  align-items: center;   /* icono centrado sobre "SIGUE BAJANDO" */
  gap: 8px;
  margin: 0;
  font-family: var(--_typography---font-family--detail, "Roboto Mono VF", monospace);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--_colors---grey--400, #666);
}

/* flotación lenta de la flecha: por tiempo, no ligada al scroll */
.kv-ab_hint-icon { animation: kv-ab-hint-float 2.8s ease-in-out infinite; }

@keyframes kv-ab-hint-float {
  0%, 100% { transform: translateY(-2px); }
  50%      { transform: translateY(3px); }
}

@media (prefers-reduced-motion: reduce) {
  .kv-ab_hint-icon { animation: none; }
}

/* En el estado base (sin scroll-driven) el hint no aporta: no hay nada que
   "seguir bajando" dentro de la sección porque no se ancla. Se oculta. */
.kv-ab_hint { display: none; }

/* palabra: inline-block para que transform y blur la afecten individualmente */
.kv-ab_w { display: inline-block; }

/* palabra destacada en el acento de marca */
.kv-ab_hl {
  font-style: normal;
  color: var(--_colors---primary--accent, #F65600);
}

/* ---- ESTADO BASE (sin soporte / reduced motion): todo legible ----
   Las tres etapas se apilan y se leen como una columna editorial normal. */
.kv-ab_stage + .kv-ab_stage { margin-top: clamp(32px, 5vh, 72px); }


/* ---- scroll-driven: sólo donde el navegador lo soporta ---- */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    .section_kv-about {
      /* Recorrido fijado. OJO: el rango `contain` depende de la altura de la
         sección respecto al viewport, así que acortarla sin reajustar los
         porcentajes de las palabras NO sirve — sólo mueve el problema.
         Con 360vh medí 1690px (casi 2 pantallas) de scroll muerto DESPUÉS de
         que el texto terminara: eso era lo que obligaba a seguir bajando sin
         que pasara nada. Se baja a 260vh Y se estiran los tramos de palabras
         hasta el 100% (ver build_belowhero.py), que es lo que de verdad
         elimina la espera final. */
      height: 200vh;
      view-timeline: --kv-ab block;
    }

    .kv-ab_panel {
      position: sticky;
      top: 0;
      height: 100svh;
      display: grid;
      align-content: center;
      /* Una sola columna explícita a ancho completo. Sin declararla, el grid
         crea una columna auto que se encoge al contenido (medido: 1290px de
         1440) y el bloque entero aparecía indentado. */
      grid-template-columns: minmax(0, 1fr);
      overflow: hidden;
    }

    /* las etapas se superponen en la misma celda y se turnan */
    /* El caption vive FUERA de la pila de etapas: si comparte celda con
       ellas se solapa con el titular (medido: encajaba sobre la primera
       línea). Se posiciona contra el CONTAINER, no contra el panel, para que
       conserve el gutter de padding-global en lugar de pegarse al borde. */
    .kv-ab_panel > .padding-global { grid-area: 1 / 1; }
    /* El caption va absoluto encima de la pila y no aporta altura, así que
       el hueco se reserva aquí: sin esto el bloque llena los 900px del panel
       y el caption se sale por arriba (medido: top=-22). */
    .kv-ab_panel > .padding-global {
      padding-top: 56px;
      /* banda inferior reservada al indicador de scroll: sin ella el remate
         llega hasta abajo y el texto del hint se lee sobre su desenfoque */
      padding-bottom: 76px;
    }
    .kv-ab_panel .container-large { position: relative; }
    .kv-ab_cap {
      position: absolute;
      bottom: calc(100% + 18px);   /* justo encima de la pila de etapas */
      left: 0;
      margin-bottom: 0;
    }
    /* el contenedor abarca la altura útil, así el caption queda arriba y las
       etapas centradas dentro de la misma caja */
    /* .padding-global es hijo de un grid (el panel) y se quedaba en 1290px en
       vez de 1440: shrink-to-fit. Sin esto el container hereda un ancho corto
       y todo el bloque aparece indentado. */
    .kv-ab_panel > .padding-global {
      display: grid;
      align-content: center;
      width: 100%;
      justify-self: stretch;
    }
    .kv-ab_panel .container-large {
      /* sin min-height: la caja se ajusta a la etapa más alta y es el panel
         (align-content: center) quien centra el conjunto en la pantalla */
      display: grid;
      align-content: center;
      /* Sin esto los hijos son shrink-to-fit y el párrafo renderizaba a 672px
         (justo la mitad del container) por mucho max-width que tuviera:
         medido en el árbol de layout. */
      justify-items: stretch;
      /* .container-large de la plantilla YA declara dos columnas (medido:
         grid-template-columns: 672px 672px). Al ponerle display:grid se
         activaban, y cada etapa caía en media caja. Una sola columna. */
      grid-template-columns: minmax(0, 1fr);
      /* container-large tiene max-width 1344 pero el grid de dos columnas lo
         dejaba en 1194 y centrado (medido: left=123 en vez del gutter de 48).
         Con una sola columna recupera el ancho completo del contenedor. */
      width: 100%;
      max-width: 1344px;
      margin-inline: auto;
    }

    .kv-ab_stage {
      grid-area: 1 / 1;
      align-self: center;
    }
    /* las etapas ocupan la banda central, ya centradas por align-content */
    .kv-ab_panel { align-content: center; }
    .kv-ab_stage + .kv-ab_stage { margin-top: 0; }

    /* cada palabra entra con su propio rango, puesto en línea */
    .kv-ab_w {
      animation: kv-ab-word linear both;
      animation-timeline: --kv-ab;
    }
    /* La entrada del titular se prolonga un poco DENTRO del tramo anclado para
       que no haya costura entre las dos fases (medido: 120px sin movimiento
       justo tras "crecer"). */
    .kv-ab_lead .kv-ab_w { animation-fill-mode: both; }

    /* salidas de etapa: mismo blur(10px) / -12px que el manifiesto */
    .kv-ab_lead  { animation: kv-ab-out-lead  linear both; }
    .kv-ab_duo   { animation: kv-ab-out-body  linear both; }
    .kv-ab_lead, .kv-ab_duo {
      animation-timeline: --kv-ab;
      animation-range: contain 0% contain 100%;
    }
    /* Indicador de scroll: se pega al borde inferior del panel mientras el
       texto se lee y se desvanece con blur cuando la sección se despega.
       Mismos valores que .man-hint en kenshoconstruction. */
    /* La diagonal ocupa el centro-derecha abajo, así que el hint deja de ir
       centrado (se cruzaba con el remate) y baja a la izquierda, que es el
       hueco que la composición deja libre. */
    .kv-ab_hint {
      display: flex;
      align-items: center;   /* el icono va centrado sobre el texto */
      position: absolute;
      bottom: max(2.75rem, 6svh);
      /* En escritorio va centrado; en móvil se queda a la izquierda, que es
         donde la diagonal deja hueco (ver el breakpoint de 767px). */
      left: 50%;
      transform: translateX(-50%);
      animation: kv-ab-hint-out linear both;
      animation-timeline: --kv-ab;
      animation-range: exit 15% exit 38%;
    }
  }
}

@keyframes kv-ab-hint-out {
  from { opacity: 1; filter: blur(0px); }
  to   { opacity: 0; filter: blur(6px); }
}

/* móvil: centrado como en escritorio, más pequeño y pegado al borde de abajo
   para que no toque el final del remate ("...trabajo conjunto."). */
@media screen and (max-width: 767px) {
  .kv-ab_hint { font-size: 9px; gap: 5px; letter-spacing: .08em; }
  .kv-ab_hint-icon { width: 13px; height: 15px; }
  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
      .kv-ab_hint {
        left: 50%;
        transform: translateX(-50%);
        bottom: max(1.1rem, 2.2svh);
      }
    }
  }
}

@keyframes kv-ab-word {
  from { opacity: 0; filter: blur(6px); }
  to   { opacity: 1; filter: blur(0px); }
}

/* el titular sostiene y sale antes de que entre el cuerpo */
@keyframes kv-ab-out-lead {
  /* El titular salía al 30%, justo cuando sus palabras acababan de aparecer:
     se leía "escalable." y ya se estaba yendo. Ahora sostiene hasta el 46% y
     se va más despacio (46->56 en vez de 30->37). */
  0%, 46%   { opacity: 1; filter: blur(0px);  transform: translateY(0); }
  56%, 100% { opacity: 0; filter: blur(10px); transform: translateY(-12px); }
}

/* La pareja es la última etapa: entra y se queda. No tiene salida, porque
   detrás no viene nada — la sección se despega y sigue la página. */
@keyframes kv-ab-out-body {
  0%, 100% { opacity: 1; filter: blur(0px); }
}



@media screen and (max-width: 767px) {
  .kv-ab_lead { font-size: clamp(32px, 9vw, 48px); max-width: none; }
  .kv-ab_close-t { font-size: clamp(24px, 6.5vw, 34px); max-width: none; }
  .kv-ab_body { max-width: 17ch; font-size: clamp(17px, min(5.5vw, 3.3vh), 30px); }
  .kv-ab_close-t { max-width: 17ch; font-size: clamp(24px, min(9.6vw, 5.8vh), 54px); }
  .kv-ab_duo { gap: clamp(24px, 16vh, 170px); }
  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
      .section_kv-about { height: 300vh; }
      .kv-ab_cap { bottom: calc(100% + 12px); top: auto; }
    }
  }
}

/* Móviles bajos (360x640 y similares): el caption llegaba a solaparse con la
   cabecera. Ahí manda la altura, así que el cuerpo baja un punto más. */
@media screen and (max-width: 767px) and (max-height: 700px) {
  .kv-ab_body   { font-size: clamp(15px, min(5.5vw, 2.7vh), 30px); }
  .kv-ab_close-t { font-size: clamp(20px, min(9.6vw, 4.6vh), 54px); }
}

/* ============================================================================
   Botón "Ver todos los proyectos": fuera el fade de entrada
   ============================================================================
   El botón va envuelto en un `.fade-in` que IX2 mantiene a opacity 0 hasta que
   está casi en pantalla y entonces lo mete de golpe (medido: op=0 hasta 100px
   antes, luego 0.41 -> 0.65). Se lee como un parpadeo. Queda fijo y visible.

   Sólo afecta a ESE wrapper (el que contiene .button-secondary dentro de la
   sección de proyectos), no a los demás `.fade-in` de la plantilla. */
.section_work-list .fade-in:has(> .button-secondary) {
  opacity: 1 !important;
  transform: none !important;
}

/* ============================================================================
   Hero: galería 3D dentro del recuadro  (/home-v6)
   ============================================================================
   Referencia: componente de 21st.dev, reimplementado en CSS puro.

   TRES filas que cruzan el recuadro de arriba abajo. La del medio va en
   sentido contrario a las de fuera: eso es lo que da profundidad de verdad, en
   vez de una sola cinta desplazándose.

   El desvanecido a negro va en tres capas apiladas — general, laterales y las
   dos zonas de texto ("Somos Kensho Visual" a la izquierda, "Contacta con
   Sergio" abajo a la derecha). Cada capa resuelve una zona, así ninguna tiene
   que ser agresiva y la caída queda progresiva. */

.kv-g3d {
  background-color: #000;
  overflow: hidden;
}

/* El escenario. La perspectiva corta (900px) exagera la fuga: es lo que hace
   que se lea como 3D y no como tres tiras planas. */
.kv-g3d_stage {
  position: absolute;
  /* se desborda por los cuatro lados para que las filas entren y salgan por
     fuera del recuadro, nunca "empezando" a la vista */
  inset: -14% -6%;
  perspective: 900px;
  perspective-origin: 50% 50%;
  transform-style: preserve-3d;
  /* la inclinación del conjunto: las filas huyen hacia el fondo por la dcha. */
  /* Sin rotateX: inclina en el eje horizontal y comprime las filas de abajo
     más que las de arriba, así que el espaciado deja de ser uniforme (medido:
     -20 vs -46 px). rotateY + rotateZ dan la fuga sin tocar el reparto. */
  transform: rotateY(-26deg) rotateZ(-3deg) scale(1.18);
}

/* Colocación explícita en tercios. Con flex + transformaciones 3D cada fila se
   proyecta a una caja distinta y `space-between` dejaba un hueco de 185px
   (medido); en absoluto el reparto es determinista y no queda negro. */
.kv-g3d_row {
  position: absolute;
  left: 0;
  /* Paso vertical IGUAL que la altura (si no, el espaciado se descuadra) y un
     hueco explícito e idéntico entre las tres filas, que lo pone la tarjeta.
     Antes se tocaban borde con borde y el redondeo dejaba 1px de diferencia. */
  --kv-gap: 18px;
  height: 33.333%;
  top: calc(var(--r) * 33.333%);
  display: flex;
  gap: 22px;
  transform-style: preserve-3d;
  will-change: transform;
  animation: kv-g3d-drift 78s linear infinite;
}

/* la fila del medio, en sentido contrario */
.kv-g3d_row.is-rev {
  animation-name: kv-g3d-drift-rev;
  animation-duration: 92s;
}

/* Recorre media fila exactamente (10 tarjetas de 340 + 22 de hueco = 3620px),
   así el bucle no tiene salto. */
@keyframes kv-g3d-drift {
  from { transform: translateX(0); }
  to   { transform: translateX(-3620px); }
}
@keyframes kv-g3d-drift-rev {
  from { transform: translateX(-3620px); }
  to   { transform: translateX(0); }
}

.kv-g3d_card {
  flex: 0 0 340px;
  /* el hueco entre filas sale de aquí: mismo valor para las tres */
  height: calc(100% - var(--kv-gap, 18px));
  margin-block: calc(var(--kv-gap, 18px) / 2);
  border-radius: 12px;
  overflow: hidden;
  background-color: #0d0d0d;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .7);
}

.kv-g3d_img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* apagadas: el hero es el texto, la galería es ambiente */
  opacity: .66;
  filter: grayscale(.18) contrast(1.04) brightness(.96);
}

/* ---- capa 1: velo general, funde arriba y abajo ---- */
.kv-g3d_veil {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: linear-gradient(180deg,
    #000 0%,
    rgba(0, 0, 0, .88) 5%,
    rgba(0, 0, 0, .58) 12%,
    rgba(0, 0, 0, .28) 20%,
    rgba(0, 0, 0, .14) 30%,
    rgba(0, 0, 0, .14) 68%,
    rgba(0, 0, 0, .30) 79%,
    rgba(0, 0, 0, .60) 88%,
    rgba(0, 0, 0, .88) 95%,
    #000 100%);
}

/* ---- capa 2: los lados a negro, progresivo ---- */
.kv-g3d_sides {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* Izquierda mucho más suave que antes: la galería tiene que verse en el
     corner superior izquierdo. El negro de esa zona lo pone .kv-g3d_zones,
     sólo abajo. */
  background-image: linear-gradient(90deg,
    rgba(0, 0, 0, .92) 0%, rgba(0, 0, 0, .34) 8%, rgba(0, 0, 0, 0) 22%,
    rgba(0, 0, 0, 0) 66%, rgba(0, 0, 0, .88) 90%, #000 100%);
}

/* ---- capa 3: las dos zonas de texto ----
   Elipses, no rectángulos: un rectángulo se vería como un parche. */
.kv-g3d_zones {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    /* abajo-derecha: "Contacta con Sergio" */
    radial-gradient(34% 44% at 90% 96%, #000 40%, rgba(0, 0, 0, .84) 62%, rgba(0, 0, 0, 0) 100%),
    /* abajo-izquierda: SÓLO la esquina del texto. Anclada al 100% de alto para
       que el corner superior izquierdo siga enseñando la galería. */
    radial-gradient(40% 56% at 0% 100%, #000 42%, rgba(0, 0, 0, .90) 62%,
                    rgba(0, 0, 0, .40) 82%, rgba(0, 0, 0, 0) 100%);
}

@media screen and (max-width: 991px) {
  .kv-g3d_card { flex-basis: 240px; }
  .kv-g3d_row { gap: 16px; }
  .kv-g3d_stage { transform: rotateY(-24deg) rotateZ(-3deg) scale(1.14); }
  @keyframes kv-g3d-drift {
    from { transform: translateX(0); }
    to   { transform: translateX(-2560px); }
  }
  @keyframes kv-g3d-drift-rev {
    from { transform: translateX(-2560px); }
    to   { transform: translateX(0); }
  }
}

@media (prefers-reduced-motion: reduce) {
  .kv-g3d_row { animation: none; }
}

/* ============================================================================
   Páginas de detalle de servicio: bloque bajo el titular + "Qué incluye"
   ============================================================================
   Sólo escritorio. En móvil ya estaba bien (una columna), así que estas reglas
   viven dentro de un media query y no tocan nada por debajo de 992px. */

@media screen and (min-width: 992px) {
  /* El párrafo, los bullets y el botón iban en una segunda COLUMNA a la
     derecha del titular. Sergio los quiere DEBAJO. Pasa a una sola columna y
     el bloque derecho se limita en ancho para no quedar como una línea larga
     de lado a lado. */
  .kv-detail_grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
  }
  .kv-detail_right {
    max-width: 46rem;
    gap: 28px;
  }
  /* Los bullets, en línea. En dos columnas el tercero quedaba suelto con un
     hueco al lado; en fila se alinean y ocupan lo que necesitan. */
  .kv-detail_items {
    display: flex;
    flex-wrap: wrap;
    gap: 10px 12px;
    max-width: none;
  }
  .kv-detail_items .kv-services_item {
    padding: 7px 14px;
    border-radius: 144px;
    background-color: rgba(0, 0, 0, .045);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .07);
    font-size: 15px;
  }
  /* el botón no debe estirarse al ancho del bloque */
  .kv-detail_right .kv-button { align-self: flex-start; }

  /* ---- "Qué incluye": tarjetas en vez de lista con puntito ---- */
  /* Mismo lenguaje que las cards de proyectos (radio 18px, filo y sombra
     suaves), pero sin imagen: aquí lo que manda es el texto. */
  .section_kv-includes .kv-plans_grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 20px;
  }
  .section_kv-includes .kv-services_head {
    padding: 26px 26px 28px;
    border-radius: 18px;
    background-color: var(--_colors---primary--white, #fff);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9),
                inset 0 0 0 1px rgba(0, 0, 0, .07),
                0 6px 20px rgba(0, 0, 0, .05);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
  }
  .section_kv-includes .kv-services_head:hover {
    transform: translateY(-4px);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .95),
                inset 0 0 0 1px rgba(0, 0, 0, .1),
                0 14px 32px rgba(0, 0, 0, .09);
  }
  .section_kv-includes .kv-services_head .kv-services_item {
    margin-bottom: 10px;
  }
  /* h4 dentro de una tarjeta se come el espacio y parte los títulos largos en
     dos líneas, descuadrando la rejilla. Se baja a la escala de la card. */
  .section_kv-includes .kv-services_head h3 {
    font-size: 22px;
    line-height: 1.2;
    font-weight: 500;
    margin: 0;
  }
}

/* ---- el puntito naranja fuera, también en móvil ----
   Sergio lo pidió en las dos: en escritorio porque ahora son tarjetas, y en
   móvil por sí solo. Sólo en estas dos secciones; el resto del sitio sigue
   usando .kv-services_dot con normalidad. */
.section_kv-includes .kv-services_dot,
.kv-detail_items .kv-services_dot {
  display: none;
}

/* ============================================================================
   "Contacta con Sergio": cristal esmerilado en vez del lavado gris
   ============================================================================
   El box venía con `background-color: #fff3` de la plantilla, que sobre el
   fondo oscuro se lee como un gris plano. Se sustituye por el mismo patrón de
   cristal de las cards de precios (.kv-web_card): desenfoque de fondo + inset
   en dos partes — luz blanca arriba y filo oscuro alrededor — que es lo que da
   la textura del borde.

   Sólo el del HERO. El del footer (.kv-fcontact) va sobre fondo claro y
   conserva sus overrides. */

.home-header_contact:not(.kv-fcontact) .home-header_contact-infos {
  background-color: rgba(255, 255, 255, .07);
  /* El brillo lo pone el propio cristal: el box está sobre la zona más oscura
     del panel, así que desenfocar el fondo no aporta luz. */
  background-image: linear-gradient(157deg,
    rgba(255, 255, 255, .26) 0%,
    rgba(255, 255, 255, .10) 34%,
    rgba(255, 255, 255, .03) 62%,
    rgba(255, 255, 255, .07) 100%);
  -webkit-backdrop-filter: blur(22px) saturate(160%) brightness(1.35);
  backdrop-filter: blur(22px) saturate(160%) brightness(1.35);
  /* textura del borde: filo claro arriba, sombra interior abajo y un filo
     alrededor — el inset de dos partes de las cards de precios */
  box-shadow: inset 0 1.5px 0 rgba(255, 255, 255, .55),
              inset 0 0 0 1px rgba(255, 255, 255, .20),
              inset 0 -16px 28px rgba(0, 0, 0, .26),
              0 12px 34px rgba(0, 0, 0, .38);

  /* Ancho fijo: al abrirse pasaba de 194 a 221px (medido) y el salto lateral
     se veía brusco. Con el ancho reservado sólo cambia la altura. */
  width: 232px;
  box-sizing: border-box;
}

@media screen and (max-width: 767px) {
  .home-header_contact:not(.kv-fcontact) .home-header_contact-infos {
    width: 214px;
  }
}

/* ── Fondo ASCII del CTA del footer ─────────────────────────────────────────
   Sergio: quitar los puntitos y poner el dibujo ASCII de 21st.dev (las manos
   de "La creación de Adán"), ocupando todo el recuadro, con fade negro por los
   bordes para que el texto se lea bien.

   La imagen es el export de 21st.dev tal cual, no un efecto reconstruido.

   La imagen de puntos venía de .cta_component (background-image "Pixel...").
   Se anula ahí, no borrando el nodo, para que el template siga intacto. */
.cta_component {
  background-image: none;
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
/* El contenido (titular, botón, nota) tiene que quedar por encima del fondo.
   .cta_component era el contexto de apilamiento y sus hijos son estáticos. */
.cta_component > *:not(.kv-ascii) { position: relative; z-index: 1; }

.kv-ascii {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  overflow: hidden;
  pointer-events: none;
}

/* La foto del export. El original es claro (crema) y el recuadro es negro con
   texto blanco encima: se baja el brillo y se sube el contraste para que las
   manos sigan leyéndose sobre fondo oscuro en vez de deslumbrar. */
.kv-ascii_img {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: 50% 46%;
  background-repeat: no-repeat;
  filter: brightness(.60) contrast(1.14) saturate(.90);
  /* Latido muy leve, como en el ejemplo. */
  animation: kv-ascii-breathe 9s ease-in-out infinite;
}

/* Barrido de líneas: la parte animada. Va en multiply para que oscurezca la
   trama existente en vez de añadir un velo gris encima. */
.kv-ascii_scan {
  position: absolute;
  inset: -10% 0;
  mix-blend-mode: multiply;
  opacity: .5;
  background-image: repeating-linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0px,
    rgba(0, 0, 0, 0) 2px,
    rgba(0, 0, 0, .55) 3px,
    rgba(0, 0, 0, 0) 4px);
  animation: kv-ascii-scan 7s linear infinite;
}

@keyframes kv-ascii-breathe {
  0%, 100% { filter: brightness(.60) contrast(1.14) saturate(.90); }
  50%      { filter: brightness(.52) contrast(1.16) saturate(.92); }
}
@keyframes kv-ascii-scan {
  from { transform: translateY(0); }
  to   { transform: translateY(4px); }
}

/* Sin movimiento si el sistema lo pide. */
@media (prefers-reduced-motion: reduce) {
  .kv-ascii_img, .kv-ascii_scan { animation: none; }
}

/* El velo: viñeta (pfx.vignette 55) + el fade que pidió Sergio. Suave en el
   centro — la foto tiene que verse — y cerrando en los bordes, que es donde
   caen el titular y el botón. */
.kv-ascii_veil {
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(125% 145% at 50% 46%,
      rgba(0, 0, 0, 0) 0%,
      rgba(0, 0, 0, .08) 50%,
      rgba(0, 0, 0, .44) 77%,
      rgba(0, 0, 0, .86) 100%),
    linear-gradient(180deg,
      #000 0%, rgba(0, 0, 0, .76) 8%, rgba(0, 0, 0, .20) 25%,
      rgba(0, 0, 0, 0) 48%, rgba(0, 0, 0, .20) 74%,
      rgba(0, 0, 0, .76) 92%, #000 100%),
    linear-gradient(90deg,
      #000 0%, rgba(0, 0, 0, .62) 5%, rgba(0, 0, 0, .12) 17%,
      rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, .12) 83%,
      rgba(0, 0, 0, .62) 95%, #000 100%);
}


@media screen and (max-width: 767px) {
  /* En móvil el titular ocupa casi todo el ancho: se cierra un poco más. */
  .kv-ascii_veil { background-color: rgba(0, 0, 0, .18); }
}

/* ── Barra superior ─────────────────────────────────────────────────────────
   Sergio: fuera la línea de puntitos bajo el menú, fuera la pastilla "VISUAL"
   del logo (con un  pequeño en su lugar) y "CREATIVE STUDIO" pasa a
   "MARKETING & AI AGENCY" en dos líneas, al mismo tamaño. */

/* La línea de puntitos era un border-top punteado de 1px a todo el ancho. */
.navbar_line { display: none; }

/* El  va como texto, no dentro del PNG: así escala con el logo y se puede
   ajustar. El logo nuevo ya viene recortado sin la pastilla naranja. */
.navbar_logo-wrap { display: inline-flex; align-items: flex-start; gap: 3px; }
/* El  se dimensiona CONTRA LA ALTURA DEL LOGO, no con un valor suelto.
   OJO: un `em` aquí NO sirve — resuelve contra el font-size heredado del
   contenedor (16px), no contra el alto del logo, y sale más pequeño todavía.
   El logo del nav mide 24px (medido), así que se fija en 13px, que es poco
   más de la mitad de esa altura: la marca se lee y sigue siendo un superíndice.
   La variable permite subirlo en un sitio sin tocar el resto. */
.navbar_logo-wrap { --kv-tm-size: 13px; }
.kv-logo_tm {
  font-family: var(--_typography---font-family--primary, "BDO Grotesk VF", Arial, sans-serif);
  font-size: var(--kv-tm-size, 13px);
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0;
  margin-top: 1px;
  color: currentColor;
}

/* Dos líneas al mismo tamaño (12px, medido): sólo se aprieta el interlineado
   para que la barra no crezca. */
.navbar_creative-text {
  line-height: 1.12;
  white-space: normal;
}

/* ── Barra superior: se esconde al bajar, vuelve al subir ───────────────────
   Sergio: que desaparezca al hacer BASTANTE scroll hacia abajo (no un toque) y
   que vuelva al subir BASTANTE. Fondo y posición como estaban, sin tocar.

   El movimiento va en `transform`, no en `top`: así lo resuelve el compositor
   y no dispara relayout en cada fotograma. La transición es la del propio
   template (0.35s), no un valor inventado. */
.navbar {
  transition: transform 0.35s ease;
  will-change: transform;
}
.navbar.kv-nav-hidden {
  transform: translateY(-100%);
}
/* Si el sistema pide menos movimiento, la barra no se mueve. */
@media (prefers-reduced-motion: reduce) {
  .navbar { transition: none; }
  .navbar.kv-nav-hidden { transform: none; }
}

/* ── Titular de /agencia: "Nuestra" <-> "Tu" ────────────────────────────────
   Sergio: que alterne solo cada 2-3s, cinematográfico y sin saltos.

   Las dos palabras se apilan en la MISMA celda de grid, así el ancho lo fija
   siempre la más larga y "Agencia" no se mueve al cambiar el texto — que es lo
   que haría que se viera choppy. */
.kv-swap {
  display: inline-grid;
  grid-template-areas: "w";
  vertical-align: baseline;
}
.kv-swap_w {
  grid-area: w;
  opacity: 0;
  transform: translateY(.28em);
  filter: blur(6px);
  /* Entra y sale con el mismo easing suave; 0.8s es lo bastante largo para que
     lea como fundido y no como corte. */
  transition: opacity .8s cubic-bezier(.22, .61, .36, 1),
              transform .8s cubic-bezier(.22, .61, .36, 1),
              filter .8s cubic-bezier(.22, .61, .36, 1);
}
.kv-swap_w.is-on {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
}
/* La que sale se va hacia arriba, no hacia abajo: da sensación de relevo. */
.kv-swap_w.is-out {
  opacity: 0;
  transform: translateY(-.28em);
  filter: blur(6px);
}
@media (prefers-reduced-motion: reduce) {
  .kv-swap_w { transition: none; }
}

/* ── Precios de la home: 3 tarjetas ─────────────────────────────────────────
   Sergio: añadir "Auditoría" a la izquierda, con el mismo diseño, y usar los
   mismos checkmarks rojos que en /pricing. La de Auditoría sólo en escritorio. */

/* Mismo tick que en la página de precios (.kv-v2 / .kv-plans_panel): flecha
   SVG en el color de acento, como fondo del <li>. Se reutiliza el mismo data
   URI para que sean idénticos, no parecidos. */
.section_pricing .pricing_feature {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23F65600' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-size: 0.95rem;
  background-position: 0 0.42em;
  padding-left: 1.6rem;
}

/* Tres en fila en escritorio. El bloque venía en un `container-xsmall` (960px),
   pensado para DOS tarjetas: con tres salían a 304px, demasiado estrechas.
   Se sube al paso siguiente de la escala del template (container-large,
   1344px), que es un valor del sistema, no uno inventado. */
@media screen and (min-width: 992px) {
  /* OJO: sólo la home. /precios usa las MISMAS clases (.section_pricing
     .pricing_blocks) pero con .kv-v2, y allí hay paneles de 4 planes: forzar
     3 columnas hacía saltar "Sistema Completo" a una segunda fila. */
  .section_pricing:not(.kv-v2) .container-xsmall { max-width: 1344px; }
  .section_pricing:not(.kv-v2) .pricing_blocks {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 28px;
  }
}

/* La de Auditoría no aparece en móvil ni en tablet: Sergio la quiere sólo en
   escritorio. Se oculta la tarjeta, no se duplica el marcado. */
@media screen and (max-width: 991px) {
  .section_pricing .pricing_block.kv-only-desktop { display: none; }
}

/* ── Selector de idioma en la barra ─────────────────────────────────────────
   Sergio: fuera el botón de menú en escritorio (con los enlaces visibles no
   aporta nada) y en su sitio un ES/EN con el globo animado de /agencia,
   sin banderas. */

.kv-lang {
  display: flex;
  align-items: center;
  gap: 7px;
  /* en la esquina superior derecha, tras 'Contacto' */
  margin-left: 26px;
  order: 99;
  font-family: var(--_typography---font-family--detail, "Roboto Mono VF", monospace);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: .06em;
}
.kv-lang_globe { width: 22px; height: 22px; flex: none; margin-right: 5px; display: block; }
.kv-lang_globe svg { width: 100%; height: 100%; display: block; }
/* el meridiano gira: mismo gesto que el globo lottie de /agencia */
.kv-lang_mer { animation: kv-globe-spin 6s linear infinite; transform-origin: 12px 12px; }
@keyframes kv-globe-spin {
  0%   { transform: scaleX(1); }
  25%  { transform: scaleX(.15); }
  50%  { transform: scaleX(1); }
  75%  { transform: scaleX(.15); }
  100% { transform: scaleX(1); }
}
@media (prefers-reduced-motion: reduce) { .kv-lang_mer { animation: none; } }
.kv-lang_opt {
  color: var(--_colors---grey--400, #666);
  text-decoration: none;
  transition: color 0.2s ease;
}
.kv-lang_opt:hover { color: var(--_colors---primary--black, #171717); }
.kv-lang_opt.is-on { color: var(--_colors---primary--black, #171717); font-weight: 700; }
.kv-lang_globe { color: var(--_colors---primary--accent, #F65600); }
.kv-lang_sep { color: rgba(0, 0, 0, .25); }

/* Header/navbar: Sergio dice que la barra queda "too narrow" en altura.
   Medido: sólo 31.8px de alto en móvil / 48px en escritorio -- toda esa
   altura sale del contenido (logo + enlaces), `.navbar_content` no lleva
   padding vertical propio. Se añade un respiro moderado (12px arriba y
   abajo, --fixed--0-75rem del propio sistema) en vez de tocar el tamaño del
   logo o los enlaces -- un ajuste, no un rediseño. */
.navbar_content { padding-top: var(--fixed--0-75rem, 12px); padding-bottom: var(--fixed--0-75rem, 12px); }

/* En escritorio el menú hamburguesa sobra: los enlaces ya están a la vista.
   Se oculta sólo el botón, no su contenedor: era él quien daba altura a la
   barra (sin esto bajaba de 40px a 27px y el conjunto quedaba apretado). */
@media screen and (min-width: 992px) {
  .navbar_links-menu .hamburger { display: none; }
  .navbar_links-menu .menu_component { min-height: 40px; display: flex; align-items: center; }
}
/* En móvil manda la hamburguesa; el selector se queda, más compacto.

   Sergio pidió varias veces que la hamburguesa quede PEGADA al borde
   derecho del todo, con el selector ES/EN justo a su izquierda -- y varios
   intentos anteriores no lo consiguieron. La causa real, medida con
   getBoundingClientRect: `.navbar_content` sólo tiene DOS hijos directos,
   `.navbar_brand` y `.kv-lang` (no tres). La hamburguesa NO es hija directa
   de `.navbar_content` -- vive dentro de `.navbar_brand` > .navbar_links-menu
   > .menu_component > .hamburger, varios niveles anidada junto al logo. Por
   mucho `order`/`margin-left:auto` que se le ponga a `.navbar_links-menu`
   dentro de `.navbar_brand`, como flex item nunca puede salir de la caja de
   `.navbar_brand`, que en móvil sólo mide su propio contenido (~177px) y
   queda muy lejos del borde derecho real (390px) -- por eso quedaba
   "flotando" a media barra con un hueco antes de ES/EN.

   La solución que sí llega al borde: sacar `.navbar_links-menu` del flujo
   con position:absolute anclado al borde derecho de `.navbar_content`
   (que pasa a ser el `position:relative` de referencia), igual que ya se
   hace en escritorio con `.navbar_content { justify-content: flex-start }`
   + `margin-left:auto` en `.navbar_brand` -- incluso ese truco de escritorio
   sólo funciona porque ahí SÍ hay overflow de flujo normal disponible; en
   móvil no lo hay porque `.navbar_brand` no se estira. Con la hamburguesa
   fuera del flujo, `.kv-lang` (que sigue siendo flex item normal de
   `.navbar_content` con `order:99`, así que ya cae al final) sólo necesita
   suficiente margen a la derecha para no meterse debajo. */
@media screen and (max-width: 991px) {
  .kv-lang { margin-left: 0; margin-right: 12px; font-size: 14px; }
  .kv-lang_globe { width: 18px; height: 18px; }

  .navbar_content { position: relative; }

  .navbar_links-menu {
    /* NB: `transform` (even just for vertical centering) on this element makes
       it the CSS containing block for its fixed-position descendant, `.menu`
       (the hamburger dropdown -- see .menu_component > .hamburger + .menu
       further down the tree). `.menu` used `inset:0% 0% auto auto` expecting
       the VIEWPORT as its containing block; with `.navbar_links-menu` (56px
       wide, sized to just the hamburger button) as the real containing block
       instead, `right:0` resolved against that 56px box, not the 390px
       viewport -- shifting the whole opened panel ~334px left and leaving a
       gap on the right. Fix: centre vertically with top/bottom + auto margin,
       which does NOT create a containing block, instead of `transform`. */
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    margin: auto 0;
  }

  .navbar_links-menu .menu_component {
    width: var(--fixed--3-5rem);
    display: grid;
    place-items: center;
    margin-right: 0;
  }
  .navbar_links-menu .hamburger {
    margin: 0;
    justify-self: center;
  }

  /* Hueco real de la hamburguesa fuera del flujo (~56px de .menu_component,
     con margin-right:-.625rem en .hamburger de la plantilla -> ancho visual
     efectivo ~46px) + el gap estándar del sitio antes de que ES/EN se meta
     debajo de ella. */
  .kv-lang { margin-right: calc(var(--fixed--3-5rem) + 12px); }

  /* El panel desplegado del menú (.menu, no .menu_component -- el que
     contiene los links, no el botón) hereda `width: 50vw` de la plantilla,
     pensado para un panel lateral de escritorio. En móvil eso deja la mitad
     derecha de la pantalla vacía en vez de que el menú ocupe toda la
     ventana. */
  .menu { width: 100vw; }
}

/* Los enlaces se quedan a la derecha (como estaban) y el selector va detrás,
   ya en la esquina. El `margin-left:auto` iba antes en el bloque de enlaces y
   empujaba todo a la izquierda. */
@media screen and (min-width: 992px) {
  /* .navbar_content usa space-between con 3 hijos, lo que dejaba el selector
     descolgado a 344px de los enlaces. Se agrupan los dos de la derecha. */
  .navbar_content { justify-content: flex-start; }
  /* .navbar_brand contiene el logo Y los enlaces. Los enlaces se empujan al
     final de ese bloque para que queden pegados al selector, en la esquina
     derecha, en vez de flotando en el medio. */
  .navbar_brand { margin-right: 0; flex: 1 1 auto; width: auto; }
  /* Los enlaces se van al final de .navbar_brand (que ocupa todo el ancho
     libre), así quedan pegados al selector en la esquina en vez de flotando
     en mitad de la barra. */
  .navbar_links-menu { margin-left: auto; }
  .navbar_links { gap: 26px; }
  .kv-lang { margin-left: 22px; }
}

/* ── Saludo multiidioma en la cortina de carga ──────────────────────────────
   Sergio: en vez de "Kensho", el saludo va cambiando de idioma rápido, estilo
   Apple. Las palabras se apilan en la misma celda para que no haya salto de
   maquetación al cambiar de longitud. */
.kv-hello {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  place-items: center;
  grid-template-areas: "w";
  pointer-events: none;
}
.kv-hello_w {
  grid-area: w;
  /* mismo metal líquido que "Visual", aquí sobre negro */
  background-color: #F65600;
  background-image:
    radial-gradient(60% 120% at 20% 30%, #FFD9A8 0%, rgba(255,217,168,0) 55%),
    radial-gradient(50% 100% at 75% 70%, #C24A00 0%, rgba(194,74,0,0) 60%),
    radial-gradient(70% 140% at 50% 100%, #FF8A3D 0%, rgba(255,138,61,0) 65%),
    linear-gradient(105deg, #FFB067 0%, #F65600 40%, #FFD9A8 70%, #F65600 100%);
  background-size: 180% 180%, 200% 200%, 220% 220%, 300% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: kv-liquid-flow 6s ease-in-out infinite;
  font-family: var(--_typography---font-family--primary, "BDO Grotesk VF", Arial, sans-serif);
  font-size: clamp(38px, 6vw, 86px);
  font-weight: 500;
  letter-spacing: -.02em;
  color: transparent;
  opacity: 0;
  transform: translateY(.14em) scale(.985);
  filter: blur(5px);
  /* rápido y progresivo: entra y sale con la misma curva suave */
  transition: opacity .16s cubic-bezier(.22,.61,.36,1),
              transform .16s cubic-bezier(.22,.61,.36,1),
              filter .16s cubic-bezier(.22,.61,.36,1);
}
.kv-hello_w.is-on { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
.kv-hello_w.is-out { opacity: 0; transform: translateY(-.14em) scale(1.015); filter: blur(5px); }

/* El logo de la cortina se oculta: lo sustituye el saludo. IX2 le escribe
   `opacity` en línea, así que hace falta !important para ganarle. */
.brand_wrap .brand_logo { opacity: 0 !important; }
/* La primera palabra debe verse ya en el primer fotograma, sin esperar a la
   transición (si no, la cortina arranca vacía). */
.kv-hello_w:first-child { transition-delay: 0s; }

@media (prefers-reduced-motion: reduce) {
  .kv-hello_w { transition: none; }
}

/* ── "Visual": metal líquido cálido ─────────────────────────────────────────
   Sergio: que la palabra lleve dentro una animación abstracta tipo liquid
   metal, en tonos cálidos que peguen con el naranja de acento.

   Se hace con `background-clip: text`: el degradado vive DETRÁS de las letras
   y sólo se ve a través de ellas. Tres capas de radiales que se mueven a
   ritmos distintos dan la sensación de metal fundido, sin necesidad de canvas
   ni de una imagen. */
.kv-liquid {
  /* cobre → ámbar → bronce, todos derivados del acento #F65600 */
  /* Bastante más oscuro: metal quemado. Los claros bajan de #FFD9A8/#FFB067
     a cobres apagados, y la base pasa a marrones casi negros, para que
     "Visual" pese lo mismo que "Kensho" en negro y no cante al lado. */
  background-color: #6B2600;
  background-image:
    radial-gradient(60% 120% at 20% 30%, #C4681F 0%, rgba(196,104,31,0) 55%),
    radial-gradient(50% 100% at 75% 70%, #2E0F00 0%, rgba(46,15,0,0) 60%),
    radial-gradient(70% 140% at 50% 100%, #A8410A 0%, rgba(168,65,10,0) 65%),
    linear-gradient(105deg, #1A0800 0%, #7A2C00 34%, #C4681F 58%, #3D1400 100%);
  background-size: 180% 180%, 200% 200%, 220% 220%, 300% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  animation: kv-liquid-flow 14s ease-in-out infinite;
}

@keyframes kv-liquid-flow {
  0%   { background-position:   0% 40%,  100% 60%,  50% 100%,   0% 50%; }
  25%  { background-position:  60% 10%,   40% 90%,  20%  40%,  40% 50%; }
  50%  { background-position: 100% 70%,    0% 20%,  90%  70%, 100% 50%; }
  75%  { background-position:  30% 100%,  70% 40%,  40%   0%,  60% 50%; }
  100% { background-position:   0% 40%,  100% 60%,  50% 100%,   0% 50%; }
}

/* Sin soporte de background-clip:text el texto sería invisible: se vuelve al
   color sólido del template. */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .kv-hello_w { -webkit-text-fill-color: #f8f7f3; background-image: none; }
  .kv-liquid { color: var(--_colors---primary--black, #171717);
               -webkit-text-fill-color: currentColor; background-image: none; }
}
@media (prefers-reduced-motion: reduce) { .kv-liquid { animation: none; } }

/* ── Hero de la home en móvil: una pantalla exacta ──────────────────────────
   Sergio: que en móvil el hero quepa en el viewport — arriba "Kensho Visual"
   y abajo el recuadro, sin hueco muerto debajo ni scroll para verlo entero.

   Antes la sección medía 521px de 844 y el recuadro acababa a media pantalla,
   dejando 323px vacíos.

   Se usa `svh` (small viewport height) y NO `vh`: en móvil `vh` ignora la
   barra del navegador, así que el recuadro se saldría por abajo justo al
   cargar, que es cuando la barra está visible. */
@media screen and (max-width: 767px) {
  .section_home-header {
    min-height: 100svh;
    display: flex;
    flex-direction: column;
  }
  /* el bloque del recuadro se come el espacio libre que quede */
  .section_home-header .home-header_component {
    flex: 1 1 auto;
    display: flex;
    min-height: 0;              /* sin esto un hijo flex no puede encoger */
  }
  .section_home-header .home-header_content,
  .section_home-header .home-header_video {
    flex: 1 1 auto;
    min-height: 0;
  }
  /* El padding inferior del template (12px) hace de margen respecto al borde;
     se le suma el área segura de los móviles con notch. */
  .section_home-header .home-header_component {
    padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  }
  /* Al estirar el recuadro, el bloque interior (rótulo, titular y la tarjeta
     de contacto) se quedaba flotando a media altura. Se reparte: texto arriba
     y "Contacta con Sergio" pegado abajo, como estaba antes de estirar. */
  .section_home-header .home-header_content {
    display: flex;
    flex-direction: column;
    /* El texto arranca arriba (no centrado: con space-between quedaba
       demasiado bajo) y el contacto se ancla al fondo con margin-top:auto. */
    justify-content: flex-start;
  }
  /* .home-header_bottom lleva DENTRO el texto y la tarjeta de contacto, así
     que empujarlo entero con margin-top:auto bajaba también el titular. El
     reparto se hace dentro: texto arriba, contacto pegado al fondo. */
  .section_home-header .home-header_bottom {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
  }
  .section_home-header .home-header_contact {
    margin-top: auto;
  }
}

/* ===========================================================================
   Revisión móvil (2026-08-27)
   =========================================================================== */

/* ---------- footer en móvil ----------

   Tres problemas medidos a 390px, todos con la misma raíz: el footer se
   compone para escritorio y en móvil queda estrecho y descentrado.

   1) El wordmark "Kensho Visual" salía a 51px (13.2vw) y ocupaba ~600 de 780
      px reales, así que sobraba aire a la derecha. Y como el blur inferior
      (.progressive-blur_panel, 96px fijos al fondo del viewport) cae justo
      encima, lo poco que había quedaba ilegible. La solución que pidió Sergio
      es la correcta: si el trazo ocupa TODO el ancho, el blur se come sólo la
      puntita inferior en vez de la palabra entera.

      16.4vw es el valor que hace caber "Kensho Visual" exacto en el ancho
      del viewport (medido: a 17vw ya recorta la "l" final). El wordmark
      cuelga fuera de .padding-global a propósito -- el template ya lo hace en
      escritorio; en móvil hay que anular el gutter de 12px para que llegue de
      borde a borde de verdad.

   2) Copyright y la tarjeta de contacto arrancaban en x=44, porque
      .footer_wrap añade 32px de padding propio SOBRE los 12px de
      .padding-global. Ese padding es de escritorio; en móvil el resto de la
      web respeta 24px de gutter, así que se iguala a eso.

   3) La columna "Navegación" se quita en móvil: los mismos enlaces ya están
      en el menú hamburguesa, y aquí ocupaban 123px de altura repetida.
*/
@media screen and (max-width: 767px) {
  /* 1) wordmark a ancho completo, fuera del gutter */
  .footer_brand {
    font-size: 16.4vw;
    max-height: 0.98em;
    /* .padding-global mete 12px a cada lado; se compensan para que el trazo
       toque los dos bordes del viewport. */
    width: 100vw;
    margin-left: -12px;
    margin-right: -12px;
  }

  /* 2) mismo gutter que el resto de la web (24px), no los 32+12 de escritorio */
  .footer_wrap { padding-left: 12px; padding-right: 12px; }

  /* 3) el bloque de enlaces ya vive en el menú; aquí sobra */
  .footer_links-groups { display: none; }
}

/* La tarjeta de contacto y los iconos sociales seguían a la derecha (x=101 de
   390) pese a la regla `justify-content: flex-start` que ya había sobre
   .footer_social: quien manda es el padre, .footer_secondary, que es un flex
   en columna con align-items:flex-end. En una columna es `align-items` el eje
   horizontal, así que ahí es donde hay que actuar. */
@media screen and (max-width: 767px) {
  .footer_secondary { align-items: flex-start; }
}

/* ---------- stack de servicios en móvil ----------

   El fallo medido a 390x844: la tarjeta mide 642px y se pega en top:88px, así
   que su borde inferior cae en 730. Pero la siguiente se pega en 96px y cubre
   de 96 a 738, y el botón de la tarjeta de debajo vive a 562px de su propio
   borde superior -> y absoluta 650. Es decir: el botón queda TAPADO por la
   tarjeta siguiente en todas menos la última. Por eso no se podía pulsar de la
   2 en adelante.

   Hay que atacar las dos causas, no una:

   a) La tarjeta es demasiado alta para el viewport. Se recorta ~110px sin
      quitar contenido: la imagen pasa de 16:9 recortado a un panorámico más
      bajo, y se aprieta el ritmo interno (que en móvil no necesita el
      respiro de escritorio).

   b) El anclaje estaba demasiado bajo (88-112px) y desperdiciaba viewport.
      Sergio pide que enganche "casi arriba del todo". 20px + 6 por índice
      deja ver el filo de las de atrás sin comerse espacio útil.

   Con ambas: tarjeta ~533px pegada en 20px -> pie en 553, y la siguiente
   tapa desde 26px. El botón queda en 20+~455=475, muy por encima de los
   553 donde acaba la tarjeta, así que queda destapado y pulsable.
*/
@media screen and (max-width: 767px) {
  .kv-svc_list.is-home .kv-svc_sticky,
  .kv-svc_list .kv-svc_sticky {
    top: calc(20px + var(--kv-svc-i) * 6px);
  }
  .kv-svc_card {
    padding: 22px 18px;
    gap: 20px;
  }
  /* 16:9 en vez del 588/420 (1.4:1) de tablet: más panorámico y ~50px más
     bajo, que es de donde sale la mayor parte del recorte. */
  .kv-svc_img-wrap { aspect-ratio: 16 / 9; }
  .kv-svc_items { margin-top: 16px; gap: 6px; }
  .kv-svc_btn-wrap { padding-top: 18px; }
  .kv-svc_button { padding: 8px 16px 8px 10px; }
  .kv-svc_button-icon { width: 26px; height: 26px; font-size: 16px; }
}

/* ---------- /proyectos: tarjetas v2 ----------

   Sergio pidió acercarlas a las de kensho-web: portada panorámica, tags
   visibles y fuera el recuadro de color saturado por categoría (#1f4d45,
   #8f2f0e...) que dominaba la tarjeta.

   Se porta el DISEÑO de kensho-web (media a sangre arriba, cuerpo blanco,
   borde fino, jerarquía categoría > título > descripción > pills), pero NO su
   paleta: los colores salen de los tokens medidos de esta plantilla. El beige
   de kensho-web (#E5DCD0 / #F5F0EA / #8B7355) aquí desentonaría.

   La rejilla es la que ya tenía la lista (.work-list_list-v3); sólo cambia la
   pieza que va dentro. */
.kv-pc {
  display: flex;
  flex-direction: column;
  height: 100%;
  background-color: var(--_colors---primary--white, #fff);
  /* radius del token `large`, el mismo de .kv-plan y .kv-v2_block */
  border-radius: var(--border-radius--large, 1.125rem);
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  /* El borde va como inset shadow y no como `border`: así no suma al box model
     y la media puede llegar al filo sin una línea a media altura. */
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}
.kv-pc:hover {
  transform: translateY(-3px);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12),
              0 8px 28px rgba(0, 0, 0, .10);
}

/* "más panorámica": antes era un bloque vertical que ocupaba media pantalla.
   16/10 mantiene el carácter apaisado a cualquier ancho de columna, en vez de
   la altura fija de 200px de kensho-web (que a 3 columnas se queda corta). */
.kv-pc_media-wrap {
  aspect-ratio: 16 / 10;
  overflow: hidden;
  flex: none;
  background-color: var(--_colors---grey--50, #f1efed);
}
.kv-pc_media {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.5s ease;
}
.kv-pc:hover .kv-pc_media { transform: scale(1.04); }

.kv-pc_body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  padding: 24px;
  gap: 10px;
}

/* Categoría: el rótulo pequeño en mono del sistema (.text-style-label), no una
   píldora de color. Es la pieza que más "integrada" la deja. */
.kv-pc_cat {
  font-family: var(--_typography---font-family--detail, "Roboto Mono VF", monospace);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--_colors---primary--accent, #F65600);
}
.kv-pc_title {
  font-size: 22px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -.02em;
  margin: 0;
  color: var(--_colors---grey--700, #171717);
}
.kv-pc_desc {
  font-size: 15px;
  line-height: 1.5;
  margin: 0;
  color: var(--_colors---grey--400, #666);
  /* 3 líneas: con descripciones de largo desigual, sin recorte las tarjetas de
     una misma fila quedaban descuadradas. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Las pills se van al fondo para que todas las tarjetas de una fila las
   alineen a la misma altura, independientemente del largo del título. */
.kv-pc_pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: auto;
  padding-top: 6px;
}
.kv-pc_pill {
  font-family: var(--_typography---font-family--detail, "Roboto Mono VF", monospace);
  font-size: 11px;
  line-height: 1;
  padding: 6px 10px;
  border-radius: 999px;
  background-color: var(--_colors---grey--50, #f1efed);
  color: var(--_colors---grey--500, #4d4d4d);
}

@media screen and (max-width: 767px) {
  .kv-pc_body { padding: 20px; }
  .kv-pc_title { font-size: 20px; }
  .kv-pc_desc { font-size: 14px; }
}

/* ---------- galería para pantallazos de interfaz ----------

   .kv-gal recorta a 16/10 con object-fit:cover, que es lo correcto para
   fotografía: encuadra y todas las piezas casan. Pero con capturas de una
   aplicación recorta información -- en los mockups de Casa Castagno se comía
   la barra lateral por la izquierda y parte del contenido por la derecha, y
   los dos mockups de móvil (proporción 0.6, verticales) quedaban destrozados.

   La variante .is-ui muestra la imagen ENTERA: proporción real vía `contain`
   sobre una caja 16/9, que es la de las capturas de escritorio. Los verticales
   se llevan a una fila propia con .kv-gal_item.is-tall para que no se estiren.
*/
.kv-gal.is-ui .kv-gal_media {
  aspect-ratio: 16 / 9;
  object-fit: contain;
  /* El fondo de los mockups es hueso claro; el token grey--50 del sistema es
     el que menos corta contra ellos. */
  background-color: var(--_colors---grey--50, #f1efed);
}
/* Los mockups de móvil son verticales: se les da una caja alta y se centran,
   en una rejilla de 2 para que no ocupen media pantalla cada uno. */
.kv-gal.is-ui .kv-gal_item.is-tall .kv-gal_media {
  aspect-ratio: 3 / 4;
  object-fit: contain;
}
@media screen and (max-width: 767px) {
  .kv-gal.is-ui .kv-gal_item.is-tall .kv-gal_media { aspect-ratio: 3 / 4; }
}

/* ── "Visual" con shader Silk (21st.dev) ───────────────────────────────────
   Sustituye al degradado líquido de .kv-liquid. El canvas se coloca ENCIMA
   del <h2>, recortado a las letras por el propio script; el texto del h2 se
   vuelve transparente para que no asome por debajo.

   .kv-silk-on la pone el JS sólo cuando el shader ya está pintando, así que
   si no hay WebGL, o el navegador ignora el script, el degradado de
   .kv-liquid sigue en su sitio y no se ve un hueco. */
.kv-liquid { position: relative; }

.kv-silk_canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.kv-liquid.kv-silk-on {
  /* fuera el degradado: manda el canvas */
  background-image: none;
  background-color: transparent;
  -webkit-text-fill-color: transparent;
  color: transparent;
  animation: none;
}

/* Ajustes específicos de la home. */
.kv-home-services_head {
  grid-template-columns: 1fr;
  place-items: center;
  text-align: center;
}

/* El botón "Ver blog"/"View blog" (.blog-list_button, con el nodo
   #w-node-da7739c7-892d-bf18-ed05-3a2a205f319d-e2a330fc) se eliminó del
   HTML por pedido de Sergio -- ya no hace falta la grid de 2 filas
   "label title" / ". button" que se le había montado encima en la sesión
   anterior.

   OJO: la causa real de "Últimos artículos" desplazado a la derecha no era
   sólo esa grid de la sesión pasada -- es la grid NATIVA de la plantilla
   (.blog-list_head { grid-template-columns: .25fr 1fr .75fr }), pensada
   para poner la etiqueta "Blog" y el título EN LA MISMA FILA, uno al lado
   del otro. El resto de headings de sección (FAQ "Preguntas, respondidas.",
   testimonios "Lo que dicen nuestros clientes") usan un patrón distinto:
   label ENCIMA del título, en columna, los dos con el mismo margen
   izquierdo = el borde del container. Medido con getBoundingClientRect en
   1440px: esos headings arrancan en left:48px (el padding-global del
   sitio); "Últimos artículos" arrancaba en left:228px por la columna
   ".25fr" de la etiqueta. Se fuerza aquí el mismo patrón apilado que el
   resto del sitio, en vez de dejar la grid nativa de 3 columnas. */
@media screen and (min-width: 768px) {
  .section_blog-list .blog-list_head {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    /* No hay spacer en el HTML entre .sdadasasd (label) y .brands_heading
       (título) -- la grid nativa los separaba con su propio gap. Se repone
       aquí para que no queden pegados. */
    gap: var(--fixed--0-5rem);
  }
}

/* Nudge vertical del cuerpo de la sección "kv-ab" (about) en móvil -- no
   tiene relación con el blog, sólo compartía antes el mismo media query de
   767px que el botón del blog ya eliminado. Se mantiene aparte para que
   quede claro que es un ajuste independiente. */
@media screen and (max-width: 767px) {
  .kv-ab_body { position: relative; top: 8px; }
}

/* FAQ desktop: el retrato conserva su proporción nativa, sin crop ni upscale,
   y acompaña el recorrido de las preguntas dentro de su propia sección. */
@media screen and (min-width: 992px) {
  .section_faq .faq_component { align-items: start; }

  .section_faq .faq_img-wrap {
    align-self: start;
    justify-self: end;
    position: sticky;
    top: 2rem;
    width: min(100%, 30rem);
    height: auto;
    aspect-ratio: 1122 / 1402;
    overflow: hidden;
  }

  .section_faq .faq_img {
    display: block;
    position: static;
    width: 100%;
    height: auto;
    object-fit: contain;
  }
}

/* FAQ mobile: la plantilla trae `.faq_img-wrap { display: none }` bajo
   991px (alture-template...css línea ~8161) -- ahí es donde se oculta el
   retrato, no en las clases hide-mobile-landscape/portrait del heading (esas
   solo tapan el subtítulo). `.faq_img-wrap` es hermano de `.faq_content`
   (que agrupa heading + subtítulo + lista de preguntas), no hijo suyo, así
   que no se puede colar entre el heading y la lista sin tocar el HTML. Se
   pone antes de todo el bloque (retrato primero, preguntas debajo), en una
   columna, centrado, con la misma proporción nativa sin crop ni upscale que
   ya lleva en desktop. Sin sticky: en una columna no tiene sentido fijar la
   imagen mientras se hace scroll por las preguntas. */
@media screen and (max-width: 767px) {
  .section_faq .faq_component {
    display: flex;
    flex-direction: column;
  }

  .section_faq .faq_img-wrap {
    display: block;
    position: static;
    width: min(100%, 22rem);
    height: auto;
    aspect-ratio: 1122 / 1402;
    margin: 0 auto;
    overflow: hidden;
    order: -1;
  }

  .section_faq .faq_img {
    display: block;
    position: static;
    width: 100%;
    height: auto;
    object-fit: contain;
  }
}

@media screen and (max-width: 767px) {
  .kv-testimonials-break-mobile { display: block; }
}

/* Sin motion: se deja el degradado CSS, que no se mueve, y el script ni
   siquiera arranca. */
@media (prefers-reduced-motion: reduce) {
  .kv-silk_canvas { display: none; }
}

/* ── Saludo de la cortina: blanco ──────────────────────────────────────────
   Se probó a meterle el mismo shader que "Visual" y se descartó: crear el
   contexto WebGL en el primer pintado competía con el montaje de la home y
   la cortina se cerraba en ~0,75 s mostrando un único saludo, en vez de los
   ~1,5 s y cuatro saludos que dura sin él. Sergio pidió blanco en ese caso.

   Va después del bloque de .kv-hello_w, así que gana sin !important. */
.kv-hello_w {
  /* OJO: hay que devolver background-clip a border-box. Quitando sólo la
     imagen, el clip:text seguía activo sobre un fondo transparente y el texto
     se pintaba con nada: se veía casi negro sobre la cortina negra. */
  background-image: none;
  background-color: transparent;
  -webkit-background-clip: border-box;
  background-clip: border-box;
  -webkit-text-fill-color: #f8f7f3;
  color: #f8f7f3;
  animation: none;
}

/* ── Ancla de servicios en la home ───────────────────────────────────────
   El link "Servicios"/"Services" del navbar (repetido en las ~80 páginas del
   sitio) apuntaba a /servicios y /en/services, que sólo repetían esta misma
   sección. Ahora enlaza a /#services y /en#services -- pero `nav.navbar` es
   `position:fixed`, así que sin esto el ancla llegaría tapada bajo la barra.
   El margen iguala la altura real de la barra en cada breakpoint (medida
   tras el ajuste de altura del navbar: 72px escritorio / 56px móvil),
   más algo de aire. */
#services { scroll-margin-top: 88px; }
@media screen and (max-width: 991px) { #services { scroll-margin-top: 72px; } }

/* ── Footer + menú móvil: ocultar LinkedIn e Instagram (sin publicaciones aún) ──
   Sergio: aún no hay contenido publicado en esas redes, así que los iconos
   quedan ocultos hasta que lo haya. `display:none` en vez de borrarlos del
   HTML -- reversible con solo quitar esta regla. `.footer_social-link` es
   el del footer (80 páginas); `.menu_social-link` es el mismo icono dentro
   del menú hamburguesa móvil -- se ocultó primero solo el footer porque así
   se pidió entonces, luego Sergio pidió también el del menú móvil. */
.footer_social-link,
.menu_social-link { display: none; }

/* ── /proyectos/casa-castagno: capturas de la app SIN recortar ────────────
   `.work_img-wrap`/`.case-content_image-wrap` son del template: aspect-ratio
   fijo (2 y 3/2) + object-fit:cover, pensado para fotografía donde un
   recorte no pierde información. Las capturas de Estate Manager son
   screenshots reales de interfaz -- 6 de escritorio a ~16/9 (1.77-1.81) y 2
   verticales de móvil a ~0.6-0.64 -- y con cover se comían barras laterales,
   cabeceras y bordes por los cuatro lados. Mismo diagnóstico que el patrón
   .kv-gal.is-ui ya documentado en este archivo, aplicado aquí a las clases
   que usa esta sección. Scoped a `.is-app` (marcador añadido sólo en el HTML
   de esta sección) porque work_img/case-content_image se reusan en San
   Marco, Optimal y casa-castagno-app con fotografía normal, donde el cover
   sigue siendo correcto y no se toca. */
.work_img-wrap.is-app,
.case-content_image-wrap.is-app,
.is-app .case-content_image-wrap {
  aspect-ratio: 16 / 9;
  background-color: var(--_colors---grey--50, #f1efed);
}
.work_img-wrap.is-app .work_img,
.case-content_image-wrap.is-app .case-content_image,
.is-app .case-content_image-wrap .case-content_image {
  object-fit: contain;
}
/* Los dos verticales (app-casa-castagno7/8) se quedarían diminutos dentro de
   una caja 16/9 horizontal: caja alta propia, mismo tratamiento contain. */
.work_img-wrap.is-app.is-tall,
.case-content_image-wrap.is-tall {
  aspect-ratio: 3 / 4;
}
@media screen and (max-width: 767px) {
  .work_img-wrap.is-app.is-tall,
  .case-content_image-wrap.is-tall {
    aspect-ratio: 3 / 4;
  }
}
