/* Hallmark · macrostructure: Split Studio + carousel · genre: modern-minimal · tone: corporativo/internacional
 * theme: GarantíaYa (proyecto, ref: garantiaya.es) · light paper + hero navy oscuro · Raleway display · accent rojo
 * pre-emit critique: P5 H5 E5 S4 R4 V5
 * dirección «GarantíaYa»: navy + rojo, hero oscuro, radios moderados, Raleway; + carrusel de audiencias */
/* ============================================================================
   COMPONENTES

   Patrones de interacción tomados como referencia de 21st.dev y portados a CSS
   vanilla — su registro es React/shadcn y aquí no hay React. Lo que se porta es el
   comportamiento (estados, elevación, foco), no el código.

   Movimiento según principios Emil: 150ms en hover, 200ms en cambios de estado,
   300ms en paneles. Toda transición da feedback; ninguna decora.
   ============================================================================ */

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

.btn {
  --btn-bg: var(--color-primary);
  --btn-fg: var(--text-inverse);
  --btn-border: transparent;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  min-height: 2.75rem;               /* 44px: objetivo táctil mínimo */
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  line-height: 1;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  color: var(--btn-fg);
  background-color: var(--btn-bg);
  border: var(--border-width) solid var(--btn-border);
  /* Radio moderado, corporativo (no píldora). */
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
  transition:
    background-color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard),
    transform var(--duration-fast) var(--ease-standard),
    box-shadow var(--duration-base) var(--ease-standard);
}

.btn:hover {
  --btn-bg: var(--color-primary-hover);
  color: var(--btn-fg);
  box-shadow: var(--shadow-sm);
}

/* 1px al pulsar: presión sin que la página salte. */
.btn:active {
  --btn-bg: var(--color-primary-active);
  transform: translateY(1px);
  box-shadow: var(--shadow-xs);
}

.btn[disabled],
.btn[aria-disabled="true"] {
  opacity: 0.5;
  pointer-events: none;
}

.btn--secondary {
  --btn-bg: transparent;
  --btn-fg: var(--color-primary);
  --btn-border: var(--color-border-strong);
}

.btn--secondary:hover {
  --btn-bg: var(--color-primary-soft);
  --btn-fg: var(--color-primary-hover);
  --btn-border: var(--color-primary);
}

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--text-secondary);
  box-shadow: none;
}

.btn--ghost:hover {
  --btn-bg: var(--color-surface-sunken);
  --btn-fg: var(--text-primary);
}

/* Marca externa de OMNIA. Aislado a propósito: es el único sitio donde entra su
   naranja, y no participa de la paleta del sitio. */
.btn--omnia {
  --btn-bg: var(--omnia-500);
  --btn-fg: var(--text-inverse);
}

.btn--omnia:hover { --btn-bg: var(--omnia-600); }
.btn--omnia:active { --btn-bg: var(--omnia-600); }

/* Chispa: el CTA principal de la marca. Rojo vivo con texto blanco (AA) y un halo rojo
   que crece en hover. Es el «Cotizar ahora» de la referencia. */
.btn--spark {
  --btn-bg: var(--accent-500);
  --btn-fg: var(--neutral-000);
  --btn-border: transparent;
  box-shadow: 0 4px 14px color-mix(in oklab, var(--accent-500) 38%, transparent);
}
.btn--spark:hover { --btn-bg: var(--accent-700); box-shadow: 0 8px 24px color-mix(in oklab, var(--accent-500) 48%, transparent); }
.btn--spark:active { --btn-bg: var(--accent-700); }

/* Sobre fondo oscuro (hero navy): contorno claro que se rellena en hover. */
.btn--ondark {
  --btn-bg: transparent;
  --btn-fg: var(--neutral-000);
  --btn-border: color-mix(in oklab, white 45%, transparent);
  box-shadow: none;
}
.btn--ondark:hover {
  --btn-bg: color-mix(in oklab, white 12%, transparent);
  --btn-fg: var(--neutral-000);
  --btn-border: var(--neutral-000);
}

.btn--lg {
  padding: var(--space-4) var(--space-6);
  min-height: 3.25rem;
  font-size: var(--text-lg);
}

.btn--sm {
  padding: var(--space-2) var(--space-4);
  min-height: 2.25rem;
  font-size: var(--text-sm);
}

.btn--block { width: 100%; }

.btn--danger {
  --btn-bg: var(--danger-600);
  --btn-fg: var(--text-inverse);
}

/* =================================================================== TARJETA */

.card {
  display: flex;
  flex-direction: column;
  background-color: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition:
    border-color var(--duration-base) var(--ease-standard),
    box-shadow var(--duration-base) var(--ease-standard),
    transform var(--duration-base) var(--ease-standard);
}

/* Solo las tarjetas que son enlace se elevan. Elevar una tarjeta que no lleva a
   ningún sitio promete una interacción que no existe. */
.card--link:hover {
  border-color: var(--color-border-strong);
  box-shadow: var(--shadow-lg);
  transform: translateY(-2px);
}

.card__media {
  aspect-ratio: 16 / 9;
  background-color: var(--color-surface-sunken);
}

.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  flex: 1;
}

.card__title {
  font-size: var(--text-xl);
}

/* El enlace cubre toda la tarjeta pero el texto del enlace sigue siendo el título:
   un lector de pantalla anuncia el titular, no "leer más". */
.card__title a::after {
  content: "";
  position: absolute;
  inset: 0;
}

.card--link { position: relative; }

.card__meta {
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.card__text {
  color: var(--text-secondary);
}

/* ==================================================================== REJILLA */

.grid {
  display: grid;
  gap: var(--space-5);
}

/* auto-fit + minmax en vez de media queries: la rejilla se reacomoda sola y no hay
   breakpoints que mantener. El min evita que la tarjeta baje de legible. */
.grid--cards {
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
}

.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr)); }

/* ================================================================== CABECERA */

/* Cabecera blanca (pedido del cliente): fija, con filete de acento abajo que es la
   firma de la marca. Logo real (PNG a todo color, ver logo.php): no necesita tematizado
   por CSS custom properties, se ve igual en cualquier fondo. */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background-color: var(--neutral-000);
  border-bottom: 1px solid color-mix(in oklab, var(--accent-500) 30%, transparent);
  transition: background-color var(--duration-base) var(--ease-standard), box-shadow var(--duration-base) var(--ease-standard);
}

/* Al desplazar, solo aparece la sombra: la cabecera se asienta sin cambiar de color. */
.site-header[data-scrolled="true"] {
  box-shadow: 0 8px 30px rgb(10 19 48 / 0.12);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  min-height: var(--header-height, 4.5rem);
}

.brand-logo { display: block; height: 2.6rem; width: auto; }
.site-header__logo { display: inline-flex; align-items: center; }
.site-footer__logo { display: inline-flex; }
.site-footer__logo .brand-logo { height: 2.4rem; }

/* Enlaces del menú sobre blanco: heredan el estilo oscuro base; el activo lleva filete
   de acento abajo. */
.site-header .nav__link[aria-current="page"] { box-shadow: inset 0 -2px 0 var(--accent-500); border-radius: 0; }

/* Escritorio: nav y CTAs en una sola línea. Sin esto, .nav y .nav__actions se apilan
   (block) y los botones caen a una segunda fila. */
@media (min-width: 64em) {
  .site-nav { display: flex; align-items: center; gap: var(--space-5); }
  /* Hay hueco de sobra en escritorio; sin esto "Seguro de alquiler" parte a dos líneas
     y desnivela la barra. En móvil se anula: ahí las etiquetas sí necesitan envolver. */
  .nav__link { white-space: nowrap; }
}

.nav {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.nav__item { position: relative; }

/* Submenú: oculto por defecto, se revela con hover o foco (teclado incluido gracias a
   :focus-within). En escritorio flota como tarjeta; en móvil no hace falta ocultarlo, el
   panel ya es una lista vertical y verlo desplegado de entrada no estorba. */
.nav__submenu {
  list-style: none;
  margin: 0;
  padding: var(--space-2);
}

@media (min-width: 64em) {
  .nav__submenu {
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 15rem;
    background-color: var(--color-surface);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-0.25rem);
    transition:
      opacity var(--duration-fast) var(--ease-standard),
      transform var(--duration-fast) var(--ease-standard),
      visibility var(--duration-fast);
  }

  .nav__item:hover > .nav__submenu,
  .nav__item:focus-within > .nav__submenu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
  }
}

.nav__submenu a {
  display: block;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  color: var(--text-secondary);
  text-decoration: none;
}

/* nowrap solo tiene sentido en el dropdown flotante de escritorio; en el panel móvil
   (estático, ancho de pantalla) forzaría scroll horizontal con las etiquetas largas. */
@media (min-width: 64em) {
  .nav__submenu a { white-space: nowrap; }
}

.nav__submenu a:hover { color: var(--text-primary); background-color: var(--color-surface-alt); }

.nav__link {
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--text-secondary);
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition:
    color var(--duration-fast) var(--ease-standard),
    background-color var(--duration-fast) var(--ease-standard);
}

.nav__link:hover {
  color: var(--text-primary);
  background-color: var(--color-surface-alt);
}

.nav__link[aria-current="page"] {
  color: var(--color-primary);
  font-weight: var(--weight-semibold);
}

.nav__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.nav-toggle { display: none; }

/* Menú de escritorio a partir de 1024px. Por debajo, panel desplegable.
   El sitio anterior tenía una guerra de especificidad aquí; se rehace limpio. */
@media (max-width: 63.999em) {
  .nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: var(--radius-md);
    color: var(--text-primary);
  }

  .nav-toggle:hover { background-color: var(--color-surface-alt); }

  .site-nav {
    position: fixed;
    inset: var(--header-height, 4.5rem) 0 auto 0;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-1);
    padding: var(--space-4) var(--gutter) var(--space-6);
    background-color: var(--color-surface);
    border-bottom: var(--border-width) solid var(--color-border);
    box-shadow: var(--shadow-lg);
    /* Cerrado se saca del flujo de foco: sin esto, tabular desde el logo entra en
       un menú invisible y el foco desaparece de pantalla. */
    visibility: hidden;
    opacity: 0;
    transform: translateY(-0.5rem);
    transition:
      opacity var(--duration-slow) var(--ease-out),
      transform var(--duration-slow) var(--ease-out),
      visibility var(--duration-slow);
  }

  .site-nav[data-open="true"] {
    visibility: visible;
    opacity: 1;
    transform: translateY(0);
  }

  .nav { flex-direction: column; align-items: stretch; }
  .nav__link { padding: var(--space-3); font-size: var(--text-base); }
  .nav__actions { flex-direction: column; align-items: stretch; margin-top: var(--space-3); }
}

/* ======================================================================= HERO */

.hero {
  padding-block: var(--section-y-lg);
  background-color: var(--color-surface-alt);
}

.hero__inner {
  display: grid;
  gap: var(--space-7);
  align-items: center;
}

@media (min-width: 60em) {
  .hero__inner {
    grid-template-columns: 1.1fr 1fr;
    gap: var(--space-8);
  }
}

.hero__eyebrow {
  display: inline-block;
  margin-bottom: var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-accent-strong);
}

.hero__title {
  font-size: var(--text-5xl);
}

.hero__subtitle {
  margin-top: var(--space-5);
  max-width: var(--measure-narrow);
  font-size: var(--text-lg);
  color: var(--text-secondary);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-6);
}

.hero__media img {
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
}

/* ================================================================ COBERTURAS */

.feature {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-6);
  background-color: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.feature__icon {
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: var(--radius-md);
  background-color: var(--color-primary-soft);
  color: var(--color-primary);
}

.feature__icon svg { width: 1.5rem; height: 1.5rem; }

.feature__title { font-size: var(--text-lg); font-family: var(--font-sans); }
.feature__text { color: var(--text-secondary); font-size: var(--text-base); }

/* ===================================================================== PASOS
   Columnas a ancho completo con filete y cifra grande, el mismo reparto que el panel
   de cifras del hero. Antes eran una lista estrecha con una pastilla numerada por
   fila: ocupaba media página y no se parecía a nada más del sitio.
   ============================================================================ */

.steps__heading { margin-bottom: var(--space-7); max-width: var(--measure-narrow); }

.steps {
  counter-reset: step;
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  border-top: 1px solid var(--color-border-strong);
}

.step {
  counter-increment: step;
  padding: var(--space-6) var(--space-6) var(--space-6) 0;
  transition: background-color var(--duration-fast) var(--ease-standard);
}
.step + .step { border-left: 1px solid var(--color-border); padding-left: var(--space-6); }
@media (hover: hover) {
  .step:hover { background-color: color-mix(in oklab, var(--brand-500) 8%, transparent); }
}

/* decimal-leading-zero: "01" pesa lo que tiene que pesar, "1" se lee como viuda. */
.step::before {
  content: counter(step, decimal-leading-zero);
  display: block;
  margin-bottom: var(--space-5);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.75rem, 1.3rem + 1.9vw, 2.5rem);
  line-height: 1;
  color: var(--color-primary);
  font-variant-numeric: tabular-nums;
}

.step__title { font-family: var(--font-sans); font-size: var(--text-lg); }
.step__text { margin-top: var(--space-2); color: var(--text-secondary); }

@media (max-width: 48em) {
  .steps { grid-auto-flow: row; grid-auto-columns: auto; }
  .step { padding: var(--space-5) 0; }
  .step + .step { border-left: 0; border-top: 1px solid var(--color-border); padding-left: 0; }
  .step::before { margin-bottom: var(--space-3); }
}

/* ================================================================ TEXTO LIBRE
   Nueve de las quince páginas internas son solo esto. Sin la banda gris el bloque
   arrancaba a pelo contra el page-hero; el filete le da un principio, el mismo que
   abre los pasos, la FAQ y el ledger.
   ============================================================================ */

.rich-text > .container {
  border-top: 1px solid var(--color-border-strong);
  padding-top: var(--space-6);
}

.rich-text__heading { margin-bottom: var(--space-5); }

/* ======================================================================= FAQ */

.faq-block__inner { display: grid; gap: var(--space-6); }
@media (min-width: 60em) {
  .faq-block__inner { grid-template-columns: 20rem 1fr; gap: var(--space-8); }
  .faq-block__head {
    position: sticky;
    top: calc(var(--header-height, 4.5rem) + var(--space-5));
    align-self: start;
  }
}
.faq-block__title { font-size: var(--text-3xl); }

/* Filas con filete, no tarjetas apiladas: una caja con borde y radio por pregunta
   troceaba la lista en diez rectángulos que competían entre sí. Mismo recurso que
   .ledger y que los pasos. */
.faq { display: grid; max-width: var(--measure); border-top: 1px solid var(--color-border-strong); }

.faq__item { border-bottom: 1px solid var(--color-border); }

.faq__question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-4) var(--space-5) 0;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  list-style: none;
  transition: color var(--duration-fast) var(--ease-standard);
}

.faq__question::-webkit-details-marker { display: none; }
.faq__question:hover { color: var(--color-primary); }
.faq__item[open] .faq__question { color: var(--color-primary); }

.faq__question::after {
  content: "";
  flex: none;
  width: 0.6rem;
  height: 0.6rem;
  border-right: 2px solid var(--text-muted);
  border-bottom: 2px solid var(--text-muted);
  transform: rotate(45deg) translate(-25%, -25%);
  transition: transform var(--duration-base) var(--ease-standard);
}

.faq__item[open] .faq__question::after {
  transform: rotate(-135deg) translate(-25%, -25%);
}

.faq__answer {
  padding: 0 var(--space-6) var(--space-5) 0;
  color: var(--text-secondary);
}

/* ======================================================================== CTA */

/* Alineado a la izquierda, no centrado: centrar todo era el ajuste por defecto y hacía
   que cada CTA del sitio se leyera igual que el anterior. Mismo radio y mismo filo cian
   que el panel de cifras del hero, para que se lean como piezas de la misma familia. */
.cta {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: grid;
  gap: var(--space-5);
  justify-items: start;
  padding: var(--section-y) var(--space-7);
  background-color: var(--color-surface-inverse);
  color: var(--text-inverse);
  border-radius: var(--radius-lg);
}
.cta::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--brand-700), var(--accent-500), var(--brand-700));
}

/* Blobs pastel translúcidos flotando en la banda uva: la firma «Bubble» también aquí. */
.cta::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  background:
    radial-gradient(18rem 18rem at 8% 120%, color-mix(in oklab, var(--color-accent) 45%, transparent) 0%, transparent 60%),
    radial-gradient(16rem 16rem at 96% -20%, color-mix(in oklab, var(--brand-500) 55%, transparent) 0%, transparent 60%);
}

.cta h2 { color: var(--text-inverse); max-width: 18ch; }
.cta p { color: var(--neutral-300); max-width: var(--measure-narrow); }
.cta__links { display: flex; flex-wrap: wrap; gap: var(--space-3); }

@media (max-width: 34em) {
  .cta { padding-inline: var(--space-5); }
}

/* ================================================================ FORMULARIOS */

/* Formularios con personalidad (feedback del cliente: "aburrido, soso"): campo
   "relleno" con filete inferior de color en vez de la caja gris plana de antes — el
   filete se anima al foco, es la única señal de marca que faltaba en todo el sitio
   que tiene formularios. */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.field__label {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-primary);
}

.field__label[data-required]::after {
  content: " *";
  color: var(--danger-600);
}

.input,
.select,
.textarea {
  width: 100%;
  padding: var(--space-3) var(--space-4);
  min-height: 2.75rem;
  /* Tinte de marca en vez de un token de superficie: el relleno se distingue esté el
     formulario donde esté (página, panel o modal blanco) sin depender de qué sección lo
     envuelva. Con --color-surface-alt coincidía con el fondo de la banda alterna que
     había entonces y el campo quedaba invisible, solo se veía el filete. */
  background-color: color-mix(in oklab, var(--color-primary) 5%, var(--color-surface));
  border: var(--border-width) solid transparent;
  border-bottom: 2px solid var(--color-border-strong);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  transition:
    background-color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard),
    transform var(--duration-fast) var(--ease-standard),
    box-shadow var(--duration-fast) var(--ease-standard);
}

.input:hover,
.select:hover,
.textarea:hover { background-color: color-mix(in oklab, var(--color-primary) 9%, var(--color-surface)); }

.input:focus,
.select:focus,
.textarea:focus {
  outline: none;
  background-color: var(--color-surface);
  border-bottom-color: var(--color-primary);
  box-shadow: var(--shadow-focus);
  transform: translateY(-1px);
}

/* aria-invalid, no una clase: el atributo que lo pinta es el mismo que lo anuncia
   al lector de pantalla, así que no pueden desincronizarse. */
.input[aria-invalid="true"],
.select[aria-invalid="true"],
.textarea[aria-invalid="true"] {
  border-bottom-color: var(--danger-600);
}

.textarea { min-height: 8rem; resize: vertical; }

.field__error {
  font-size: var(--text-sm);
  color: var(--danger-600);
}

.field__hint {
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.checkbox {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-3);
  align-items: start;
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.checkbox-group { display: grid; gap: var(--space-3); }
/* Las tres cláusulas en una línea, arrancando todas a la misma altura: con etiquetas de
   distinto largo, `align-items: start` evita que la casilla baile respecto a su vecina. */
.checkbox-group--row { grid-template-columns: repeat(3, 1fr); gap: var(--space-5); align-items: start; }

/* Fila de formulario con columnas fijas. `.grid--2` es auto-fit y en un modal ancho
   metía tres campos por línea, descolocando los pares. */
.form-row--2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-5); }

/* Envío del generador: centrado y ancho. Un botón del tamaño de su texto en una fila de
   900px se lee como un enlace más, no como el final del formulario. Tope en 34rem para
   que en escritorio no se estire hasta parecer una barra. */
.form-submit { display: grid; justify-items: center; }
.form-submit .btn { width: min(100%, 34rem); }

@media (max-width: 40em) {
  .form-row--2, .checkbox-group--row { grid-template-columns: 1fr; }
  .checkbox-group--row { gap: var(--space-3); }
}

/* Casilla propia en vez de la nativa (appearance:none + check dibujado con
   clip-path): mismo cero-dependencias, más marca que un cuadrado gris de sistema. */
.checkbox input {
  appearance: none;
  width: 1.35rem;
  height: 1.35rem;
  margin-top: 0.1rem;
  border: 2px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  display: grid;
  place-content: center;
  background-color: var(--color-surface);
  transition: background-color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}

.checkbox input::before {
  content: "";
  width: 0.7rem;
  height: 0.7rem;
  transform: scale(0);
  transition: transform var(--duration-fast) var(--ease-spring);
  box-shadow: inset 1em 1em var(--text-inverse);
  clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
}

.checkbox input:checked { background-color: var(--color-primary); border-color: var(--color-primary); }
.checkbox input:checked::before { transform: scale(1); }
.checkbox input:focus-visible { box-shadow: var(--shadow-focus); }

/* Grid del <form>, antes en línea en cada plantilla — en clase para poder apretar el
   ritmo solo dentro de modal (Regla del proyecto: nunca !important contra un estilo en
   línea, así que el valor se saca de línea en vez de pelear con especificidad). */
.form-grid { display: grid; gap: var(--space-4); margin-top: var(--space-5); }
/* Dentro de un modal el alto cuenta: menos aire entre campos, el mismo formulario cabe
   sin scroll interno visible (feedback del cliente). */
.modal .form-grid { gap: var(--space-3); margin-top: var(--space-4); }
.modal .grid { gap: var(--space-3); }

/* Modal ancho para formularios con rejilla de 2 columnas (contrato/rescisión): el
   mismo contenido en menos alto que en el modal estándar de 38rem. 60rem, no menos:
   con el padding del modal__box restado, .grid--2 necesita min 44rem libres
   (minmax(22rem,1fr) × 2) para no colapsar a una columna. */
/* .modal.modal--wide (compuesto), no .modal--wide a secas: la regla base .modal (más
   abajo en el archivo) fija su propio `width` y con la misma especificidad gana la
   que va después en la cascada — .modal--wide sola perdía por orden de aparición,
   no por especificidad. El selector compuesto (0,2,0) gana pase lo que pase. */
.modal.modal--wide { width: min(60rem, calc(100vw - 2 * var(--gutter))); }
.modal--wide .grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr)); }

/* ==================================================================== AVISOS */

.alert {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  border: var(--border-width) solid transparent;
  font-size: var(--text-sm);
}

.alert--success { background-color: var(--success-050); border-color: var(--success-600); color: var(--success-600); }
.alert--warning { background-color: var(--warning-050); border-color: var(--warning-600); color: var(--warning-600); }
.alert--danger  { background-color: var(--danger-050);  border-color: var(--danger-600);  color: var(--danger-600); }
.alert--spaced { margin-top: var(--space-5); }

/* ======================================================================= PIE */

.site-footer {
  padding-block: var(--section-y) var(--space-6);
  background-color: var(--color-surface-inverse);
  color: var(--neutral-300);
}

.site-footer a { color: var(--neutral-300); text-decoration: none; }
.site-footer a:hover { color: var(--text-inverse); text-decoration: underline; }

.site-footer__grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
}

.site-footer__heading {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-inverse);
  margin-bottom: var(--space-3);
}

.site-footer__list { list-style: none; padding: 0; display: grid; gap: var(--space-2); font-size: var(--text-sm); }

.site-footer__bottom {
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: var(--border-width) solid var(--neutral-700);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  justify-content: space-between;
  font-size: var(--text-sm);
}

/* ============================================================== PAGINACIÓN */

.pagination {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  justify-content: center;
  margin-top: var(--space-7);
  list-style: none;
  padding: 0;
}

.pagination a,
.pagination span {
  display: grid;
  place-items: center;
  min-width: 2.5rem;
  height: 2.5rem;
  padding-inline: var(--space-3);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  text-decoration: none;
  font-size: var(--text-sm);
  transition: all var(--duration-fast) var(--ease-standard);
}

.pagination a:hover { border-color: var(--color-primary); background-color: var(--color-primary-soft); }

.pagination [aria-current="page"] {
  background-color: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--text-inverse);
}

/* ============================================= HERO-CARRUSEL «GarantíaYa» ======
   Diapositivas a sangre con foto (Ken Burns), texto sobre velo navy, transición por
   fundido, barra de progreso con etiquetas y flechas. Forma portada de «Elegant
   Carousel» (21st.dev) a CSS/JS vanilla. Sin JS, las diapositivas quedan apiladas en
   flujo y visibles; con JS ([data-ready]) pasan a pila absoluta con fundido.
   ============================================================================ */

.hero-c {
  position: relative;
  isolation: isolate;
  background: var(--ink-950);
  color: var(--neutral-000);
}

.hero-c__viewport { position: relative; }
.hero-c[data-ready] .hero-c__viewport {
  min-height: clamp(30rem, 82dvh, 50rem);
  overflow: hidden;
}

.hero-c__slide {
  position: relative;
  display: flex;
  align-items: center;
  padding-block: clamp(3rem, 2rem + 6vw, 6rem);
  min-height: inherit;
}
.hero-c[data-ready] .hero-c__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
  /* visibility con retardo: se oculta al terminar el fundido, no de golpe. */
  transition: opacity var(--duration-slow) var(--ease-standard), visibility 0s linear var(--duration-slow);
}
.hero-c[data-ready] .hero-c__slide[data-active="true"] {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--duration-slow) var(--ease-standard);
  z-index: 1;
}

.hero-c__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -2;
}
/* Ken Burns solo en la activa (y solo con JS). */
.hero-c[data-ready] .hero-c__slide[data-active="true"] .hero-c__img {
  animation: hero-kenburns 8s var(--ease-standard) forwards;
}
@keyframes hero-kenburns { from { transform: scale(1.03); } to { transform: scale(1.12); } }

/* Velo navy: sólido a la izquierda (texto), se abre a la derecha (foto). */
.hero-c__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(90deg, var(--ink-950) 20%, color-mix(in oklab, var(--ink-950) 60%, transparent) 55%, color-mix(in oklab, var(--ink-950) 28%, transparent) 100%),
    linear-gradient(0deg, var(--ink-950) 2%, transparent 32%);
}

.hero-c__inner { position: relative; max-width: 40rem; }

/* Píldora roja del eyebrow: rojo relleno + texto blanco (AA), no rojo sobre navy. */
.hero-c__eyebrow {
  display: inline-flex;
  align-items: center;
  margin-bottom: var(--space-5);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-full);
  background: var(--accent-500);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--neutral-000);
}

.hero-c__title {
  color: var(--neutral-000);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.4rem, 1.5rem + 4.3vw, 4.75rem);
  line-height: 1.04;
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
  max-width: 16ch;
}

.hero-c__lead {
  margin-top: var(--space-5);
  max-width: 42ch;
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
  color: color-mix(in oklab, var(--neutral-000) 82%, transparent);
}

.hero-c__actions { margin-top: var(--space-6); }

/* --- controles: pestañas con barra de progreso + flechas --- */
.hero-c__ui {
  position: relative;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-5) var(--space-6);
}
.hero-c[data-ready] .hero-c__ui { margin-top: calc(var(--space-7) * -1); }
/* El panel de cifras solapa el hero 3rem: sin este aire se comía las flechas. Solo
   cuando la franja existe — si no hay stats, el hero no debe crecer por nada. */
.hero-c:has(+ .hero-c__stats-band) .hero-c__ui { padding-bottom: var(--space-9); }

.hero-c__tabs { display: flex; flex-wrap: wrap; gap: var(--space-5); }

.hero-c__tab {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 7rem;
  text-align: left;
  color: color-mix(in oklab, var(--neutral-000) 62%, transparent);
  transition: color var(--duration-fast) var(--ease-standard);
}
.hero-c__tab[aria-selected="true"], .hero-c__tab:hover { color: var(--neutral-000); }

.hero-c__tab-text {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.hero-c__tab-track {
  display: block;
  height: 3px;
  border-radius: var(--radius-full);
  background: color-mix(in oklab, white 20%, transparent);
  overflow: hidden;
}
.hero-c__tab-fill { display: block; height: 100%; width: 0; background: var(--accent-500); border-radius: inherit; }
/* La activa llena su barra en la duración del autoplay. */
.hero-c[data-ready] .hero-c__tab[aria-selected="true"] .hero-c__tab-fill {
  animation: hero-progress var(--hero-interval, 6000ms) linear forwards;
}
@keyframes hero-progress { from { width: 0; } to { width: 100%; } }

.hero-c__arrows { display: flex; gap: var(--space-3); }
.hero-c__arrow {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--radius-full);
  border: 1px solid color-mix(in oklab, white 35%, transparent);
  color: var(--neutral-000);
  transition: background-color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}
.hero-c__arrow:hover { background-color: color-mix(in oklab, white 12%, transparent); border-color: var(--neutral-000); }

/* --- franja de datos bajo el hero: panel elevado ---
   El planteamiento anterior (banda oscura dentro de la propia <section class="hero-c">)
   no tenía corte visible: heredaba --ink-950 del hero y su fondo era ese mismo negro un
   10% más oscuro, ~2 puntos de luminancia. Ahora la banda es hermana del hero y el
   panel es una superficie clara que lo solapa: la sombra hace de corte y no hay forma
   de confundirlos. Cuatro celdas iguales a 1fr, que era la otra queja — con
   `auto 1fr` el contenido se apelotonaba a la izquierda. */
.hero-c__stats-band { position: relative; z-index: 2; }
.hero-c__stats {
  position: relative;
  overflow: hidden;
  margin-top: calc(var(--space-7) * -1);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
/* Filo de marca, mismo recurso que .modal::after. */
.hero-c__stats::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--brand-700), var(--accent-500), var(--brand-700));
}
.hero-c__stat {
  padding: var(--space-7) var(--space-6) var(--space-6);
  text-align: left;
  transition: background-color var(--duration-fast) var(--ease-standard);
}
.hero-c__stat + .hero-c__stat { border-left: 1px solid var(--color-border); }
/* Mismo realce que .ledger__row:hover. Sin (hover:hover) el táctil lo deja pegado. */
@media (hover: hover) {
  .hero-c__stat:hover { background-color: color-mix(in oklab, var(--brand-500) 8%, transparent); }
}

.hero-c__stat-icon { flex: none; display: block; width: 1.5rem; height: 1.5rem; margin-bottom: var(--space-5); color: var(--color-primary); }
.hero-c__stat-icon svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }

.hero-c__stat-value {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1;
  font-size: clamp(1.75rem, 1.3rem + 1.9vw, 2.5rem);
  /* Sobre claro --accent-400 (#4cc1d3) no llega a AA; --brand-700 sí (5.2:1). */
  color: var(--color-primary);
  font-variant-numeric: tabular-nums;
}
.hero-c__stat-label { margin: var(--space-2) 0 0; font-size: var(--text-sm); color: var(--text-secondary); }

/* Sin sitio para solapar: el panel se aplana y pasa a ser franja a sangre. */
@media (max-width: 48em) {
  .hero-c__stats {
    grid-template-columns: 1fr 1fr;
    margin-top: 0;
    /* Anula el acolchado del .container que la envuelve: por debajo del ancho máximo
       ese padding es exactamente --gutter, así que la franja llega al borde sin
       desbordar. */
    margin-inline: calc(var(--gutter) * -1);
    border-radius: 0;
    box-shadow: none;
    border-bottom: 1px solid var(--color-border);
  }
  .hero-c__stat { padding: var(--space-6) var(--space-5); }
  .hero-c__stat:nth-child(n+3) { border-top: 1px solid var(--color-border); }
  /* Aquí ya no hay solape, así que tampoco hace falta el aire que lo compensaba. */
  .hero-c:has(+ .hero-c__stats-band) .hero-c__ui { padding-bottom: var(--space-6); }
}
@media (max-width: 34em) {
  .hero-c__stats { grid-template-columns: 1fr; }
  .hero-c__stat + .hero-c__stat { border-left: 0; border-top: 1px solid var(--color-border); }
}

@media (prefers-reduced-motion: reduce) {
  .hero-c[data-ready] .hero-c__slide[data-active="true"] .hero-c__img { animation: none; }
  .hero-c[data-ready] .hero-c__tab[aria-selected="true"] .hero-c__tab-fill { animation: none; width: 100%; }
}

/* Móvil: velo más sólido de abajo para legibilidad del texto sobre foto. */
@media (max-width: 48em) {
  .hero-c__scrim { background: linear-gradient(0deg, var(--ink-950) 10%, color-mix(in oklab, var(--ink-950) 76%, transparent) 58%, color-mix(in oklab, var(--ink-950) 52%, transparent) 100%); }
}

/* ============================================ CABECERA DE PÁGINA (internas) ==
   Banda navy compacta al inicio de cada página de contenido: le da un H1 y una
   entradilla, para que no arranque a pelo con el texto migrado.
   ============================================================================ */

.page-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background:
    radial-gradient(120% 120% at 90% -20%, color-mix(in oklab, var(--brand-700) 60%, transparent) 0%, transparent 60%),
    var(--ink-950);
  color: var(--neutral-000);
  padding-block: clamp(2.5rem, 2rem + 4vw, 4.5rem);
}

/* Filo cian de cierre: la misma firma que remata el panel de cifras de la home, aquí
   marcando dónde acaba la tinta. Es lo que hermana las 15 internas con la portada. */
.page-hero::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--brand-700), var(--accent-500), var(--brand-700));
}

.page-hero__grid {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.5;
  background-image: radial-gradient(color-mix(in oklab, var(--accent-500) 20%, transparent) 1.1px, transparent 1.2px);
  background-size: 26px 26px;
  mask-image: radial-gradient(120% 100% at 85% 0%, black 15%, transparent 70%);
}

/* Variante con foto representativa (og_image): más alto para que la imagen respire,
   mismo lenguaje visual que el hero-carrusel de la home (foto + velo navy). */
.page-hero--photo { padding-block: clamp(3.5rem, 2.5rem + 6vw, 6.5rem); }

.page-hero__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -2;
}

/* Velo navy: sólido a la izquierda, donde va el texto; se abre hacia la derecha. */
.page-hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(90deg, var(--ink-950) 25%, color-mix(in oklab, var(--ink-950) 65%, transparent) 55%, color-mix(in oklab, var(--ink-950) 35%, transparent) 100%),
    linear-gradient(0deg, var(--ink-950) 4%, transparent 40%);
}

/* Móvil: la foto pierde ancho para el texto, así que el velo se vuelve sólido de
   abajo entero (misma solución que el hero-carrusel). */
@media (max-width: 47.999em) {
  .page-hero__scrim {
    background:
      linear-gradient(0deg, var(--ink-950) 55%, color-mix(in oklab, var(--ink-950) 55%, transparent) 100%);
  }
}

.page-hero__eyebrow {
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  /* Rojo claro: pasa AA sobre navy incluso a tamaño de texto normal. */
  color: var(--accent-400);
  margin-bottom: var(--space-3);
}

.page-hero__title {
  color: var(--neutral-000);
  font-size: var(--text-4xl);
  max-width: 22ch;
}

.page-hero__lead {
  margin-top: var(--space-4);
  max-width: var(--measure);
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
  color: color-mix(in oklab, var(--neutral-000) 82%, transparent);
}

/* ============================================================== MARQUEE ======
   Banda cinética de coberturas. Dinamismo puro: se desliza en bucle, se para al
   pasar el cursor y se congela con prefers-reduced-motion.
   ============================================================================ */

.marquee {
  background-color: var(--color-primary);
  color: var(--neutral-000);
  overflow: hidden;
  padding-block: var(--space-4);
}

.marquee__track {
  display: flex;
  width: max-content;
  gap: var(--space-6);
  animation: marquee-scroll 32s linear infinite;
}

.marquee:hover .marquee__track { animation-play-state: paused; }

.marquee__item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 500;
  letter-spacing: -0.01em;
  white-space: nowrap;
  color: color-mix(in oklab, var(--neutral-000) 92%, transparent);
}

.marquee__item::before {
  content: "";
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  background: white;
}

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

@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; flex-wrap: wrap; }
}

/* ============================================ LEDGER (coberturas) ============
   Filas con numeral grande y filete, no rejilla de tarjetas. Cabecera pegajosa a la
   izquierda en escritorio; lista a la derecha.
   ============================================================================ */

.ledger__inner { display: grid; gap: var(--space-6); }

@media (min-width: 60em) {
  .ledger__inner { grid-template-columns: 20rem 1fr; gap: var(--space-8); }
  .ledger__head { position: sticky; top: calc(var(--header-height, 4.5rem) + var(--space-5)); align-self: start; }
}

.ledger__title { font-size: var(--text-3xl); }
.ledger__intro { margin-top: var(--space-4); color: var(--text-secondary); font-size: var(--text-lg); max-width: 34ch; }

/* min-width: 0 — un elemento de grid tiene min-width:auto, así que un dato sin espacios
   (el email de contacto, 38 caracteres) ensanchaba la pista y desbordaba la página en
   375. Con `anywhere` el dato parte por donde haga falta antes que romper el ancho. */
.ledger__list { list-style: none; margin: 0; padding: 0; min-width: 0; border-top: 1px solid var(--color-border-strong); }
.ledger__body { min-width: 0; }
.ledger__row-title, .ledger__row-text { overflow-wrap: anywhere; }

.ledger__row {
  display: grid;
  grid-template-columns: auto auto 1fr;
  gap: var(--space-4);
  align-items: baseline;
  padding: var(--space-5) 0;
  border-bottom: 1px solid var(--color-border);
  transition: background-color var(--duration-base) var(--ease-standard);
}

.ledger__row:hover { background-color: color-mix(in oklab, var(--brand-500) 8%, transparent); }

.ledger__num {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-xl);
  color: var(--color-primary);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.ledger__icon { color: var(--color-primary); display: grid; }
.ledger__icon svg { width: 1.5rem; height: 1.5rem; }

.ledger__row-title { font-family: var(--font-display); font-size: var(--text-xl); }
.ledger__row-text { margin-top: var(--space-2); color: var(--text-secondary); max-width: 60ch; }

@media (max-width: 34em) {
  .ledger__row { grid-template-columns: auto 1fr; }
  .ledger__icon { display: none; } /* en móvil, numeral + texto bastan */
}

/* ============================================ SPLIT STUDIO ===================
   Diptico que alterna lado. El zigzag es el ritmo.
   ============================================================================ */

.split__heading { font-size: var(--text-3xl); margin-bottom: var(--space-7); max-width: 20ch; }
.split__rows { display: grid; gap: var(--space-8); }

.split__row {
  display: grid;
  gap: var(--space-6);
  align-items: center;
}

@media (min-width: 56em) {
  .split__row { grid-template-columns: 1fr 1fr; gap: var(--space-8); }
  /* Zigzag: en las filas pares, la foto va a la izquierda. */
  .split__row:nth-child(even) .split__media { order: -1; }
}

.split__kicker {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  /* Coral que pasa AA como texto (accent-strong). El filete de al lado es coral vivo:
     decoración, no texto, así que no necesita contraste. */
  color: var(--color-accent-strong);
  margin-bottom: var(--space-4);
}

.split__tick { width: 1.6rem; height: 3px; border-radius: var(--radius-full); background: var(--color-spark); }

.split__title { font-family: var(--font-display); font-size: var(--text-2xl); max-width: 18ch; }
.split__body { margin-top: var(--space-4); color: var(--text-secondary); font-size: var(--text-lg); max-width: 46ch; }

/* Énfasis puntual dentro de un párrafo (p.ej. el nombre de marca o un término
   destacado): dos tonos ya existentes en la paleta, ninguno inventado. */
.split__mark { color: var(--color-primary); font-weight: var(--weight-semibold); }
.split__mark--alt { color: var(--color-accent-strong); font-weight: var(--weight-semibold); }

.split__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-5);
  font-weight: var(--weight-semibold);
  text-decoration: none;
  color: var(--color-primary);
}
.split__link span { transition: transform var(--duration-fast) var(--ease-standard); }
.split__link:hover span { transform: translateX(4px); }

.split__media { margin: 0; overflow: hidden; border-radius: var(--radius-xl); }
.split__media img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform var(--duration-slow) var(--ease-out);
}
.split__row:hover .split__media img { transform: scale(1.04); }

/* ================================================ GALERÍA DE SOLUCIONES =======
   Tarjetas a toda altura con foto y texto superpuesto (perfiles + coberturas). Forma
   portada de «Gallery With Image Cards» (21st.dev) a CSS vanilla: encabezado + intro +
   flechas arriba, scroll horizontal de tarjetas con peek. El scroll lo hace scroll-snap;
   motion.js añade flechas y autoplay. Cada tarjeta enlaza a su página.
   ============================================================================ */

.gallery__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-5);
  margin-bottom: var(--space-6);
}
.gallery__intro-wrap { max-width: 44rem; }
.gallery__heading { font-size: var(--text-3xl); max-width: 22ch; }
.gallery__intro { margin-top: var(--space-3); color: var(--text-secondary); font-size: var(--text-lg); max-width: 52ch; }

.gallery__nav { display: flex; gap: var(--space-3); flex: none; }

.gallery__arrow {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--radius-full);
  border: var(--border-width) solid var(--color-border-strong);
  background-color: var(--color-surface);
  color: var(--color-primary);
  transition:
    background-color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard);
}
.gallery__arrow:hover { background-color: var(--color-primary); border-color: var(--color-primary); color: var(--text-inverse); }

.gallery__viewport {
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  /* Sangrado para que la sombra de las tarjetas no se recorte. */
  margin-inline: calc(var(--space-1) * -1);
  padding: var(--space-1);
}
.gallery__viewport::-webkit-scrollbar { display: none; }
@media (prefers-reduced-motion: reduce) { .gallery__viewport { scroll-behavior: auto; } }

.gallery__track { display: flex; gap: var(--space-4); margin: 0; padding: 0; list-style: none; }

.gallery__card {
  flex: 0 0 clamp(15rem, 78vw, 21rem);
  min-width: 0;
  scroll-snap-align: start;
}

.gallery__link {
  position: relative;
  display: block;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
  text-decoration: none;
  isolation: isolate;
}

.gallery__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -1;
  transition: transform var(--duration-slow) var(--ease-out);
}
.gallery__link:hover .gallery__img { transform: scale(1.05); }
/* base.css da height:auto a toda img con width/height (anti-CLS de contenido). Su
   `img[width][height]` (0,2,1) ganaba a `.gallery__img` (0,1,0) y dejaba la foto a un
   tercio de la tarjeta. La foto va absoluta rellenando el enlace: se recupera la altura
   con un selector que supera esa especificidad, sin !important. */
.gallery__card .gallery__link .gallery__img { height: 100%; }

/* Velo navy de abajo arriba: garantiza el texto blanco legible sobre cualquier foto. */
.gallery__overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: var(--space-5);
  background: linear-gradient(0deg, var(--ink-950) 4%, color-mix(in oklab, var(--ink-950) 82%, transparent) 32%, transparent 64%);
}

.gallery__eyebrow {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--accent-400);
}
.gallery__title { color: var(--neutral-000); font-size: var(--text-xl); line-height: var(--leading-snug); }
.gallery__text { color: color-mix(in oklab, var(--neutral-000) 85%, transparent); font-size: var(--text-sm); }

/* Botón-flecha que aparece en hover: señal de que la tarjeta es un enlace. */
a.gallery__link::after {
  content: "→";
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  width: 2.2rem;
  height: 2.2rem;
  display: grid;
  place-items: center;
  border-radius: var(--radius-full);
  background: var(--color-accent);
  color: var(--neutral-000);
  font-size: var(--text-lg);
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity var(--duration-base) var(--ease-standard), transform var(--duration-base) var(--ease-standard);
}
a.gallery__link:hover::after { opacity: 1; transform: translateY(0); }

/* Escritorio con puntero: galería hover-expand (forma del componente Skiper52 portada a
   CSS vanilla). Las 6 tarjetas comparten la fila; la que recibe el cursor crece y las
   demás encogen, con el texto apareciendo solo en la expandida. Móvil/táctil conserva el
   scroll-snap de arriba (hover no existe en pantalla táctil). */
@media (min-width: 64em) and (hover: hover) {
  .gallery__viewport { overflow: visible; margin-inline: 0; padding-block: var(--space-1); padding-inline: 0; }
  .gallery__nav { display: none; }
  .gallery__track { gap: var(--space-3); }
  .gallery__card {
    flex: 1 1 0;
    height: 26rem;
    scroll-snap-align: none;
    transition: flex-grow var(--duration-slow) var(--ease-out);
  }
  .gallery__card:hover { flex-grow: 4; }
  .gallery__link { aspect-ratio: auto; height: 100%; }
  /* Texto solo en la tarjeta expandida; colapsada = foto limpia. */
  .gallery__overlay {
    opacity: 0;
    transition: opacity var(--duration-base) var(--ease-standard);
  }
  .gallery__card:hover .gallery__overlay { opacity: 1; }
}

/* ======================================================================= BLOG */

.blog-hero { background-color: var(--color-surface-alt); }
.blog-hero__lead {
  margin-top: var(--space-4);
  max-width: var(--measure);
  font-size: var(--text-lg);
  color: var(--text-secondary);
}

/* Contenido + barra lateral. La lateral desaparece bajo 60em y el contenido ocupa todo. */
.blog-layout {
  display: grid;
  gap: var(--space-7);
  align-items: start;
}

@media (min-width: 60em) {
  .blog-layout { grid-template-columns: minmax(0, 1fr) 18rem; }
  .blog-sidebar { position: sticky; top: calc(var(--header-height, 4.5rem) + var(--space-4)); }
}

.blog-widget + .blog-widget { margin-top: var(--space-6); }

.blog-widget__title {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-secondary);
  margin-bottom: var(--space-4);
}

.blog-cat-list { list-style: none; padding: 0; display: grid; gap: var(--space-1); }

.blog-cat-list li {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
}

.blog-cat-list li[aria-current="true"] { background-color: var(--color-primary-soft); }
.blog-cat-list a { text-decoration: none; color: var(--text-primary); }
.blog-cat-list a:hover { color: var(--color-primary); }
.blog-cat-list span { color: var(--text-muted); font-variant-numeric: tabular-nums; font-size: var(--text-sm); }

.blog-recent { list-style: none; padding: 0; display: grid; gap: var(--space-4); }
.blog-recent__item { display: grid; grid-template-columns: 4.5rem 1fr; gap: var(--space-3); align-items: center; }
.blog-recent__thumb { display: block; }
.blog-recent__thumb img { width: 4.5rem; height: 4.5rem; object-fit: cover; border-radius: var(--radius-sm); }
.blog-recent__title { display: block; text-decoration: none; color: var(--text-primary); font-weight: var(--weight-medium); font-size: var(--text-sm); line-height: var(--leading-snug); }
.blog-recent__title:hover { color: var(--color-primary); }

.breadcrumb { font-size: var(--text-sm); color: var(--text-muted); display: flex; flex-wrap: wrap; gap: var(--space-2); }
.breadcrumb a { color: var(--text-secondary); text-decoration: none; }
.breadcrumb a:hover { color: var(--color-primary); text-decoration: underline; }

.article-featured {
  width: 100%;
  max-height: 30rem;
  object-fit: cover;
  border-radius: var(--radius-xl);
  margin-top: var(--space-6);
}

/* ================================================== ENTRADA POR SCROLL ======
   El estado inicial solo se aplica si hay JS: sin él, `[data-reveal]` nunca
   recibiría la clase y el contenido quedaría invisible para siempre. La clase
   `js` la pone motion.js en <html> antes de pintar.
   ============================================================================ */

.js [data-reveal] {
  opacity: 0;
  transform: translateY(1rem);
}

@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] {
    opacity: 1;
    transform: none;
  }
}

/* Red de seguridad: la pone el inline del layout si motion.js no arranca en 2.5s.
   Sin esto, un fallo de JS dejaría el contenido invisible de forma permanente. */
.reveal-safety [data-reveal],
.reveal-safety [data-reveal-item] {
  opacity: 1 !important;
  transform: none !important;
}

/* ====================================================================== MODAL */

/* Bloque de captación en modo botón: el lead_form de la home muestra titular + texto y
   un botón que abre el formulario en un <dialog>. Centrado, sobre banda alterna. */
/* Panel elevado, mismo lenguaje que el de cifras del hero: antes era un titular y un
   botón centrados en medio de la página, sin nada que los sostuviera. */
.lead-cta {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
  padding: var(--space-7);
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.lead-cta::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--brand-700), var(--accent-500), var(--brand-700));
}
.lead-cta__text { max-width: var(--measure-narrow); }
.lead-cta__text p { margin-top: var(--space-3); color: var(--text-secondary); }
.lead-cta__actions { flex: none; }

@media (max-width: 48em) {
  .lead-cta { padding: var(--space-6) var(--space-5); }
}

/* <dialog> nativo: foco atrapado y cierre con Esc los da el navegador. El navegador
   centra un <dialog> modal con `margin: auto` en su hoja UA, pero el reset global
   (`* { margin: 0 }` en base.css) es de origen autor y gana a esa regla UA aunque tenga
   menos especificidad — el margen ganador lo decide el origen antes que la especificidad.
   Sin este `margin: auto` explícito el diálogo se queda pegado arriba-izquierda. */
.modal {
  position: fixed;
  inset: 0;
  margin: auto;
  width: min(38rem, calc(100vw - 2 * var(--gutter)));
  max-height: calc(100dvh - 2 * var(--space-6));
  padding: 0;
  border: none;
  border-radius: var(--radius-xl);
  background-color: var(--color-surface);
  box-shadow: var(--shadow-lg);
  color: var(--text-primary);
  overflow: hidden;
}
/* Franja de acento: identidad propia del modal (feedback del cliente: "no tienen
   personalidad" / "apenas se ve"). Engrosada a 6px y con un punto de sombra propio
   para que se lea como un filo de marca, no una línea decorativa perdida en el borde.
   El propio overflow:hidden + radius-xl del padre la recorta a las esquinas
   redondeadas sin cálculo extra. */
.modal::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 6px;
  background: linear-gradient(90deg, var(--brand-700), var(--accent-500), var(--brand-700));
  box-shadow: 0 1px 8px color-mix(in oklab, var(--accent-500) 55%, transparent);
  pointer-events: none;
}

/* Variante con iframe (portal de certificados embebido): tamaño fijo en vez de
   ajustado al contenido, cabecera con título separada del cuerpo, iframe a sangre. */
.modal--frame { width: min(60rem, calc(100vw - 2 * var(--gutter))); height: min(44rem, calc(100dvh - 2 * var(--space-6))); }
.modal--frame .modal__box { display: flex; flex-direction: column; height: 100%; padding: 0; }
.modal__frame-head { flex: none; padding: var(--space-5) var(--space-6) var(--space-4); padding-right: var(--space-9); border-bottom: 1px solid var(--color-border); }
.modal__frame-head h2 { margin: 0; }
.modal__frame-head p { margin-top: var(--space-2); color: var(--text-secondary); font-size: var(--text-sm); }
.modal__iframe { flex: 1 1 auto; width: 100%; border: 0; background: var(--color-surface-alt); }
.modal__frame-fallback { flex: none; padding: var(--space-3) var(--space-6); border-top: 1px solid var(--color-border); font-size: var(--text-sm); color: var(--text-secondary); }
/* Velo con desenfoque: se lee mejor qué hay detrás sin que compita con el modal.
   Tinta de marca (--ink-950) en vez de un literal rgb suelto: la regla del proyecto
   es cero color fuera de tokens.css. */
.modal::backdrop { background-color: color-mix(in oklab, var(--ink-950) 55%, transparent); backdrop-filter: blur(4px); }
@media (prefers-reduced-motion: no-preference) {
  .modal[open]::backdrop { animation: modal-backdrop-in var(--duration-slow) var(--ease-out); }
  .modal[data-closing]::backdrop { animation: modal-backdrop-out var(--duration-fast) var(--ease-out) forwards; }
}
@keyframes modal-backdrop-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-backdrop-out { from { opacity: 1; } to { opacity: 0; } }

.modal__box {
  position: relative;
  max-height: calc(100dvh - 2 * var(--space-6));
  overflow-y: auto;
  padding: var(--space-7) var(--space-6) var(--space-6);
}

/* Deja sitio al botón de cerrar, que se posiciona sobre la esquina superior derecha. */
.modal__title { max-width: 28ch; }

.modal__close {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  width: 2.25rem;
  height: 2.25rem;
  display: grid;
  place-items: center;
  border-radius: var(--radius-full);
  color: var(--text-secondary);
  background-color: transparent;
  transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
}
.modal__close:hover { background-color: var(--color-surface-alt); color: var(--text-primary); }

/* Entrada Y salida del diálogo (timing Emil): la entrada usa --duration-slow (300ms,
   el token que tokens.css ya reserva para "modales, paneles"; antes usaba
   --duration-base de 200ms por descuido). La salida es más rápida que la entrada
   (asimetría deliberada: se decide despacio, se libera rápido) y en ease-out, nunca
   ease-in — un cierre en ease-in arranca lento justo cuando el usuario más lo mira,
   se siente torpe. `[data-closing]` lo marca `initModals()` justo antes de cerrar de
   verdad, a la espera del `animationend`, sea cual sea el disparador (botón, clic
   fuera, Esc). Un roce de blur enmascara el corte entre estados (técnica Emil).
   Ambas se saltan por reduced-motion. */
@media (prefers-reduced-motion: no-preference) {
  .modal[open] { animation: modal-in var(--duration-slow) var(--ease-out); }
  .modal[data-closing] { animation: modal-out var(--duration-fast) var(--ease-out) forwards; }
}
@keyframes modal-in {
  from { opacity: 0; transform: translateY(1rem) scale(0.96); filter: blur(4px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}
@keyframes modal-out {
  from { opacity: 1; transform: none; filter: blur(0); }
  to   { opacity: 0; transform: translateY(0.5rem) scale(0.97); filter: blur(3px); }
}
