/* ==========================================================================
   ziflo.es - secciones de contenido
   Cada familia de layout aparece como maximo una vez por pagina.
   ========================================================================== */

/* --- Hero partido asimetrico (inicio) ------------------------------------ */

.hero {
  display: grid;
  grid-template-columns: 1.28fr 0.72fr;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
  min-height: calc(100dvh - 68px);
  padding-block: clamp(2.5rem, 6vh, 6rem);
}

/* Escala pensada para que el titular quepa en dos lineas en escritorio.
   Si se cambia el texto, hay que volver a comprobar el numero de lineas. */
.hero__title {
  font-size: clamp(2.5rem, 4.6vw, 3.65rem);
  letter-spacing: -0.038em;
  max-width: 22ch;
}

.hero__title em {
  font-style: normal;
  color: var(--accent);
}

/*
   Entrada del titular, palabra a palabra.

   Las palabras las envuelve site.js en <span class="palabra"><i>...</i></span>.
   El span exterior recorta y el interior es el que sube, asi que cada palabra
   asoma desde debajo de su propia linea en vez de aparecer flotando.

   Solo ocurre una vez, al cargar. Un titular que se reanima cada vez que pasas
   por delante cansa a la tercera visita.
*/

.palabra {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  /* Sitio para los rabos de la g, la j y la q, que si no se recortan. */
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}

.palabra > i {
  display: inline-block;
  font-style: inherit;
}

/*
   Coreografia de entrada del hero.

   El orden importa y no es decorativo: titular, luego la frase que lo explica,
   luego los botones y por ultimo el resumen de la derecha. Es el orden en que
   se lee, asi que el movimiento acompana a la lectura en vez de competir con
   ella. Todo termina antes del segundo: pasado ese punto, una entrada deja de
   ser elegante y empieza a hacer esperar.
*/

@media (prefers-reduced-motion: no-preference) {
  .js .hero__title[data-animar="pendiente"] .palabra > i {
    translate: 0 105%;
  }

  .js .hero__title[data-animar="listo"] .palabra > i {
    translate: 0 0;
    transition: translate 0.62s cubic-bezier(0.22, 1, 0.36, 1);
    transition-delay: calc(var(--i) * 55ms);
  }

  .js .hero[data-entrada] .hero__lede,
  .js .hero[data-entrada] .hero__actions > *,
  .js .hero[data-entrada] .hero__brief li {
    opacity: 0;
    translate: 0 16px;
  }

  .js .hero[data-entrada="listo"] .hero__lede,
  .js .hero[data-entrada="listo"] .hero__actions > *,
  .js .hero[data-entrada="listo"] .hero__brief li {
    opacity: 1;
    translate: 0 0;
    transition: opacity 0.6s var(--ease), translate 0.6s var(--ease);
  }

  .js .hero[data-entrada="listo"] .hero__lede {
    transition-delay: 0.28s;
  }

  .js .hero[data-entrada="listo"] .hero__actions > :nth-child(1) {
    transition-delay: 0.4s;
  }

  .js .hero[data-entrada="listo"] .hero__actions > :nth-child(2) {
    transition-delay: 0.47s;
  }

  .js .hero[data-entrada="listo"] .hero__brief li:nth-child(1) {
    transition-delay: 0.5s;
  }

  .js .hero[data-entrada="listo"] .hero__brief li:nth-child(2) {
    transition-delay: 0.6s;
  }

  .js .hero[data-entrada="listo"] .hero__brief li:nth-child(3) {
    transition-delay: 0.7s;
  }
}

.hero__lede {
  margin-top: 1.6rem;
  font-size: clamp(1.05rem, 1.5vw, 1.22rem);
  color: var(--text-dim);
  max-width: 46ch;
  line-height: 1.6;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  margin-top: 2.4rem;
}

/* Columna derecha del hero. Ocupa el sitio donde iria una fotografia, pero
   con las tres capacidades escritas: dice mas que una imagen de archivo. */
.hero__brief {
  border-top: 1px solid var(--line);
}

.hero__brief li {
  padding-block: 1.2rem;
  border-bottom: 1px solid var(--line);
}

.hero__brief h2 {
  font-size: 1.05rem;
  font-weight: 560;
  letter-spacing: -0.015em;
}

.hero__brief p {
  margin-top: 0.35rem;
  color: var(--text-dim);
  font-size: 0.93rem;
  line-height: 1.55;
}

@media (max-width: 900px) {
  .hero {
    grid-template-columns: 1fr;
    min-height: 0;
    padding-block: 3rem 4rem;
  }

  /* En movil el resumen va despues de la llamada a la accion, no antes. */
  .hero__brief {
    margin-top: 0.5rem;
  }
}

/* Apilados y con anchos distintos, los dos botones parecen desalineados.
   En pantalla estrecha ocupan lo mismo. */
@media (max-width: 520px) {
  .hero__actions {
    flex-direction: column;
    align-items: stretch;
  }

  /* Todos los campos del formulario ocupan el ancho completo; un boton de
     enviar a media caja rompe esa columna. */
  [data-contact-form] button[type="submit"] {
    width: 100%;
  }
}

/* --- Hero editorial (paginas interiores) --------------------------------- */

.pagehead {
  padding-block: clamp(3.5rem, 9vh, 6.5rem) clamp(2.5rem, 6vh, 4rem);
  border-bottom: 1px solid var(--line);
}

.pagehead h1 {
  font-size: clamp(2.3rem, 5.2vw, 3.9rem);
  letter-spacing: -0.04em;
  max-width: 18ch;
}

.pagehead .lede {
  margin-top: 1.4rem;
}

.crumb {
  display: flex;
  gap: 0.55rem;
  align-items: center;
  margin-bottom: 1.5rem;
  font-family: var(--font-mono);
  font-size: 0.76rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.crumb a:hover {
  color: var(--text-dim);
}

/* --- Filas de enlace grandes (dos lineas de negocio) --------------------- */

.lines {
  border-top: 1px solid var(--line);
}

.line-row {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr) auto;
  gap: clamp(1.5rem, 4vw, 4rem);
  align-items: center;
  padding-block: clamp(2.5rem, 5vw, 3.75rem);
  border-bottom: 1px solid var(--line);
  transition: background-color 0.35s var(--ease);
}

/*
   Barrido rojo que entra desde la izquierda al pasar por encima. Se pinta con
   un pseudoelemento a sangre completa en vez de con background-position para
   poder animar solo scaleX, que la GPU resuelve sola.
*/
.line-row::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(90deg, var(--accent-wash), transparent 55%);
  scale: 0 1;
  transform-origin: 0 50%;
  transition: scale 0.5s var(--ease);
}

.line-row {
  position: relative;
  isolation: isolate;
}

.line-row > * {
  position: relative;
  z-index: 1;
}

@media (hover: hover) and (pointer: fine) {
  .line-row:hover::before {
    scale: 1 1;
  }

  /* El titulo avanza un poco, como invitando a entrar. */
  .line-row:hover .line-row__title {
    translate: 6px 0;
  }

  .line-row__title {
    transition: translate 0.4s var(--ease);
  }

  .line-row:hover .line-row__title svg {
    color: var(--accent);
  }

  .line-row__title svg {
    transition: color 0.3s var(--ease);
  }
}

@media (prefers-reduced-motion: reduce) {
  .line-row::before {
    display: none;
  }

  .line-row:hover {
    background: rgba(255, 255, 255, 0.03);
  }
}

.line-row__title {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  font-size: clamp(1.6rem, 3.1vw, 2.35rem);
  letter-spacing: -0.03em;
}

.line-row__title svg {
  width: 1.5rem;
  height: 1.5rem;
  flex: none;
  color: var(--text);
}

.line-row p {
  color: var(--text-dim);
  max-width: 52ch;
}

.line-row__go {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  flex: none;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  color: var(--text-dim);
  transition: background-color 0.25s var(--ease), color 0.25s var(--ease),
    border-color 0.25s var(--ease);
}

.line-row__go svg {
  width: 1.15rem;
  height: 1.15rem;
}

.line-row:hover .line-row__go {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: #ffffff;
}

@media (max-width: 820px) {
  .line-row {
    grid-template-columns: 1fr auto;
    gap: 0.9rem 1.25rem;
  }

  /* Colocacion explicita. Sin ella, el parrafo ocupa las dos columnas, se va
     a la segunda fila y empuja la flecha a una tercera, donde queda suelta y
     desconectada del titulo. */
  .line-row__title {
    grid-column: 1;
    grid-row: 1;
  }

  .line-row__go {
    grid-column: 2;
    grid-row: 1;
    width: 42px;
    height: 42px;
  }

  .line-row p {
    grid-column: 1 / -1;
    grid-row: 2;
  }

  /* En tactil no hay hover, asi que el circulo va ya marcado. */
  .line-row__go {
    border-color: var(--accent);
    color: var(--accent);
  }
}

/* --- Cadena de ataque tecleandose de fondo -------------------------------- */
/*
   El codigo se teclea con CSS puro: cada linea es un bloque con overflow
   oculto cuyo ancho crece de 0 a N caracteres con steps(N). No hay ni un
   setInterval escribiendo letra a letra, que obligaria a tocar el DOM
   decenas de veces por segundo.

   site.js solo mide cuantos caracteres tiene cada linea y escribe --n y el
   retardo. El resto lo hace el navegador.

   Se dispara una vez, al entrar en pantalla. En bucle seria un distractor
   permanente a media pagina.
*/

.hackeo {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  border-block: 1px solid var(--line);
  background: var(--ink);
  padding-block: clamp(4rem, 10vh, 7rem);
}

.hackeo__codigo {
  position: absolute;
  inset: 0;
  z-index: 0;
  margin: 0;
  padding: clamp(1.5rem, 4vw, 3rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: clamp(0.62rem, 1.05vw, 0.86rem);
  line-height: 1.9;
  color: var(--accent);
  /* Visible de verdad: el efecto consiste en ver el codigo escribiendose.
     Se compensa apartandolo del texto y velando la mitad izquierda. */
  opacity: 0.55;
  pointer-events: none;
  user-select: none;
  /* El codigo arranca pasada la mitad, donde ya no hay texto debajo. */
  padding-left: 53%;
}

.hackeo__codigo span {
  display: block;
  white-space: pre;
  overflow: hidden;
  width: max-content;
}

/* Velo horizontal: opaco sobre la columna de texto y transparente sobre la
   del codigo. Asi el titular conserva su contraste sin tener que apagar el
   codigo, que es lo que se quiere ver. */
.hackeo::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    rgba(13, 13, 13, 0.98) 0%,
    rgba(13, 13, 13, 0.96) 40%,
    rgba(13, 13, 13, 0.45) 58%,
    transparent 76%
  );
}

/* Se difumina el borde derecho para que las lineas largas no acaben
   cortadas en seco contra el filo de la seccion. */
.hackeo::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(90deg, transparent 82%, var(--ink) 100%);
}

/*
   El contenedor conserva el ancho de .shell y son los hijos los que se
   estrechan.

   Estrechar el contenedor no vale: lleva tambien la clase .shell, que trae
   margin-inline auto, asi que al reducirle el ancho se centraba en la seccion
   en vez de quedarse pegado a la izquierda, y acababa metiendose justo debajo
   del codigo.
*/
.hackeo__frente {
  position: relative;
  z-index: 2;
}

.hackeo__frente h2 {
  font-size: clamp(2rem, 5vw, 3.4rem);
  letter-spacing: -0.04em;
  max-width: 15ch;
}

.hackeo__frente > p {
  margin-top: 1.2rem;
  color: var(--text-dim);
  max-width: 44ch;
  font-size: clamp(1rem, 1.5vw, 1.1rem);
}

/* Selector completo en lugar de !important: gana por especificidad a
   ".hackeo__frente > p" sin ensuciar la cascada. */
.hackeo__frente > p.hackeo__nota {
  margin-top: 0.9rem;
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.04em;
  color: var(--text-faint);
}

.hackeo .btn {
  margin-top: 2rem;
}

/* El tecleo. Sin JavaScript escribiendo: solo ancho creciendo por pasos. */
@media (prefers-reduced-motion: no-preference) {
  .js .hackeo__codigo[data-teclear] span {
    width: 0;
  }

  /* --pasos lo fija site.js: tantos pasos como caracteres en un comando, uno
     solo en una linea de salida para que aparezca entera de golpe. */
  .js .hackeo__codigo[data-teclear="visto"] span {
    animation: teclear 0.7s steps(var(--pasos, 30)) forwards;
    animation-delay: var(--d, 0ms);
  }
}

/* El destino tiene que ser una medida concreta: "max-content" no se puede
   interpolar. Con tipografia monoespaciada, N caracteres son exactamente
   N unidades ch, asi que la linea acaba justo en su ultimo caracter. */
@keyframes teclear {
  to {
    width: calc(var(--n, 30) * 1ch);
  }
}

/* En pantalla estrecha no caben dos columnas: el codigo pasa detras del
   texto, mucho mas apagado, y el velo se vuelve vertical. */
@media (max-width: 900px) {
  .hackeo__codigo {
    padding-left: clamp(1.25rem, 5vw, 3rem);
    justify-content: flex-start;
    padding-top: 1.5rem;
    opacity: 0.3;
  }

  .hackeo::before {
    background: linear-gradient(
      180deg,
      rgba(13, 13, 13, 0.5) 0%,
      rgba(13, 13, 13, 0.92) 34%,
      rgba(13, 13, 13, 0.97) 100%
    );
  }

  .hackeo::after {
    background: linear-gradient(90deg, transparent 70%, var(--ink) 100%);
  }
}

/* --- Proceso: titulo lateral fijo + pasos apilados ------------------------ */

.process {
  display: grid;
  grid-template-columns: 0.75fr 1.25fr;
  gap: clamp(2rem, 6vw, 5rem);
}

.process__aside {
  position: sticky;
  top: calc(68px + 3rem);
  align-self: start;
}

.process__aside h2 {
  font-size: clamp(1.9rem, 3.4vw, 2.7rem);
}

.process__aside p {
  margin-top: 1.1rem;
  color: var(--text-dim);
  max-width: 32ch;
}

.step {
  padding-block: 2.1rem;
  border-top: 1px solid var(--line);
}

.step:last-child {
  border-bottom: 1px solid var(--line);
}

/*
   El paso que estas leyendo se marca solo. Comunica en que punto de la
   secuencia vas, que es justo lo que la seccion explica; no es adorno.
   El resto se queda algo apagado, nunca por debajo del contraste AA.
*/
.step h3 {
  font-size: 1.32rem;
  letter-spacing: -0.02em;
  transition: color 0.45s var(--ease);
}

.step::before {
  content: "";
  position: absolute;
  left: 0;
  top: -1px;
  width: 0;
  height: 1px;
  background: var(--accent);
  transition: width 0.55s var(--ease);
}

.step {
  position: relative;
}

/*
   Todo el juego de atenuar y resaltar vive dentro de este bloque.

   Es importante que la regla que APAGA los pasos inactivos este aqui dentro y
   no fuera: quien pide movimiento reducido no recibe el marcado por scroll,
   asi que si la atenuacion se aplicara igual, los cuatro titulos se quedarian
   grises para siempre y nunca se encenderia ninguno.
*/
@media (prefers-reduced-motion: no-preference) {
  .js .step[data-activo="true"]::before {
    width: 100%;
  }

  .js .step[data-activo="true"] h3 {
    color: var(--text);
  }

  .js .step:not([data-activo="true"]) h3 {
    color: var(--text-dim);
  }
}

.step p {
  margin-top: 0.7rem;
  color: var(--text-dim);
  max-width: 58ch;
}

@media (max-width: 860px) {
  .process {
    grid-template-columns: 1fr;
  }

  .process__aside {
    position: static;
  }
}

/* --- Declaracion a sangre completa + cita -------------------------------- */

.statement {
  background: var(--surface);
  border-block: 1px solid var(--line);
}

.statement__quote {
  font-size: clamp(1.5rem, 3.2vw, 2.3rem);
  line-height: 1.32;
  letter-spacing: -0.028em;
  max-width: 21ch;
  font-weight: 500;
}

.statement__grid {
  display: grid;
  grid-template-columns: 1.2fr 0.8fr;
  gap: clamp(2rem, 6vw, 5rem);
  align-items: end;
}

.attribution {
  font-size: 0.92rem;
  line-height: 1.55;
}

.attribution strong {
  display: block;
  font-weight: 560;
}

.attribution span {
  color: var(--text-faint);
}

@media (max-width: 820px) {
  .statement__grid {
    grid-template-columns: 1fr;
    align-items: start;
    gap: 2rem;
  }
}

/* --- Incidente en curso ---------------------------------------------------- */
/*
   Bloque deliberadamente distinto al resto: instrucciones numeradas y secas,
   sin frase ingeniosa. Es la seccion que alguien leera con prisa y nervioso,
   y ademas rompe la repeticion de "cita grande a la izquierda" que antes se
   repetia igual en las tres paginas.
*/

.urgente {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: clamp(2rem, 6vw, 4.5rem);
  align-items: start;
}

.urgente h2 {
  font-size: clamp(1.7rem, 3vw, 2.3rem);
}

.urgente > div > p {
  margin-top: 1rem;
  color: var(--text-dim);
  max-width: 34ch;
}

.urgente .btn {
  margin-top: 1.6rem;
}

.pasos {
  counter-reset: paso;
}

.pasos li {
  position: relative;
  counter-increment: paso;
  padding-left: 3.1rem;
  padding-block: 1.15rem;
  border-top: 1px solid var(--line);
  color: var(--text-dim);
  font-size: 0.97rem;
  line-height: 1.55;
}

.pasos li:last-child {
  border-bottom: 1px solid var(--line);
}

/* El numero va en rojo porque aqui si ordena una secuencia de verdad. */
.pasos li::before {
  content: counter(paso);
  position: absolute;
  left: 0;
  top: 1.05rem;
  width: 1.9rem;
  height: 1.9rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--accent);
  border-radius: 50%;
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 0.85rem;
}

.pasos b {
  display: block;
  color: var(--text);
  font-weight: 560;
  margin-bottom: 0.2rem;
}

@media (max-width: 860px) {
  .urgente {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
}

/* --- Hechos verificables sobre este mismo sitio --------------------------- */

.facts {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: clamp(2rem, 6vw, 5rem);
  align-items: start;
}

.facts h2 {
  font-size: clamp(1.8rem, 3.2vw, 2.5rem);
}

.facts__intro {
  margin-top: 1.1rem;
  color: var(--text-dim);
  max-width: 38ch;
}

.fact-list {
  display: grid;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
}

.fact-list li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.85rem;
  align-items: baseline;
  padding: 1.15rem 1.4rem;
  background: var(--surface);
  font-size: 0.95rem;
}

.fact-list svg {
  width: 1rem;
  height: 1rem;
  color: var(--text);
  translate: 0 2px;
}

.fact-list b {
  font-weight: 560;
}

.fact-list span {
  color: var(--text-dim);
}

@media (max-width: 860px) {
  .facts {
    grid-template-columns: 1fr;
  }
}

/* --- Servicios en rejilla mixta (pagina de ciberseguridad) ---------------- */

.svc-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.25rem;
}

/* La primera celda ocupa el ancho completo y lleva un fondo tintado,
   para que la rejilla tenga jerarquia y no cuatro cajas iguales. */
.svc-grid > :first-child {
  grid-column: 1 / -1;
  background:
    radial-gradient(120% 160% at 88% 8%, var(--accent-wash), transparent 62%),
    var(--surface);
}

.svc {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  padding: clamp(1.6rem, 3vw, 2.4rem);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  transition: border-color 0.3s var(--ease);
}

/*
   Realce que sigue al cursor. site.js escribe --mx y --my con la posicion del
   raton dentro de la tarjeta y aqui solo se pinta un degradado en ese punto.

   Se limita a punteros finos con hover: en un movil no hay cursor que seguir,
   y ahorra montar el escuchador donde no sirve de nada.
*/
@media (hover: hover) and (pointer: fine) {
  .svc::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.35s var(--ease);
    background: radial-gradient(
      16rem circle at var(--mx, 50%) var(--my, 50%),
      rgba(229, 72, 77, 0.09),
      transparent 62%
    );
  }

  .svc:hover {
    border-color: var(--line-strong);
  }

  .svc:hover::after {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .svc::after {
    display: none;
  }
}

.svc__icon {
  width: 2.6rem;
  height: 2.6rem;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  border: 1px solid var(--line-strong);
  color: var(--text);
  margin-bottom: 0.4rem;
}

.svc__icon svg {
  width: 1.3rem;
  height: 1.3rem;
}

.svc h3 {
  font-size: 1.32rem;
  letter-spacing: -0.022em;
}

.svc p {
  color: var(--text-dim);
  font-size: 0.97rem;
  max-width: 56ch;
}

.svc ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin-top: 0.35rem;
}

.svc li {
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.03em;
  color: var(--text-dim);
  padding: 0.32rem 0.65rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--ink);
}

@media (max-width: 780px) {
  .svc-grid {
    grid-template-columns: 1fr;
  }
}

/* --- Bloque partido texto + figura (usar como maximo 2 seguidos) --------- */

.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 6vw, 4.5rem);
  align-items: center;
}

.split h2 {
  font-size: clamp(1.8rem, 3.2vw, 2.5rem);
}

.split p {
  margin-top: 1.1rem;
  color: var(--text-dim);
  max-width: 52ch;
}

/* Panel de apoyo en la columna derecha de un bloque partido. Ocupa el sitio
   que tendria una fotografia, con una lista corta que sostiene el titular. */
.panel-list {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  padding: clamp(1.4rem, 3vw, 2rem);
}

.panel-list h3 {
  font-size: 0.98rem;
  font-weight: 560;
  letter-spacing: -0.01em;
  margin-bottom: 0.35rem;
}

.panel-list li {
  padding-block: 0.85rem;
  border-bottom: 1px solid var(--line);
  color: var(--text-dim);
  font-size: 0.94rem;
  line-height: 1.5;
}

.panel-list li:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

@media (max-width: 860px) {
  .split {
    grid-template-columns: 1fr;
  }
}

/* --- Entregables en columnas agrupadas ----------------------------------- */

.deliverables {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: clamp(1.5rem, 4vw, 3rem);
  margin-top: 2.5rem;
}

/* Separador de grupo, no contorno de control: usa la linea tenue. */
.deliverables section {
  border-top: 1px solid var(--line);
  padding-top: 1.25rem;
}

.deliverables h3 {
  font-size: 1.05rem;
  margin-bottom: 0.9rem;
}

.deliverables li {
  color: var(--text-dim);
  font-size: 0.94rem;
  padding-block: 0.4rem;
}

/* --- Tarifas orientativas -------------------------------------------------- */
/* Tres columnas de anchos distintos a proposito: la rejilla perfectamente
   simetrica es lo que hace que una pagina parezca salida de una plantilla. */

.tarifas {
  display: grid;
  grid-template-columns: 1.1fr 1fr 0.9fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  margin-top: 2.75rem;
}

.tarifas > div {
  border-top: 2px solid var(--line-strong);
  padding-top: 1.25rem;
}

.tarifas dt {
  font-size: 0.79rem;
  font-family: var(--font-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.tarifas__cifra {
  margin: 0.55rem 0 0.7rem;
  font-size: clamp(1.45rem, 2.8vw, 1.9rem);
  font-weight: 560;
  letter-spacing: -0.03em;
  color: var(--text);
}

.tarifas dd {
  margin: 0;
  color: var(--text-dim);
  font-size: 0.93rem;
  line-height: 1.55;
}

.tarifas__nota {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  color: var(--text-dim);
  font-size: 0.95rem;
  max-width: 62ch;
}

@media (max-width: 780px) {
  .tarifas {
    grid-template-columns: 1fr;
    gap: 1.75rem;
  }
}

/* --- Preguntas frecuentes ------------------------------------------------ */

.faq {
  max-width: 780px;
  margin-inline: auto;
}

.faq details {
  border-bottom: 1px solid var(--line);
}

.faq summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1.5rem;
  padding-block: 1.4rem;
  cursor: pointer;
  font-size: 1.08rem;
  font-weight: 500;
  letter-spacing: -0.015em;
  list-style: none;
  transition: color 0.2s var(--ease);
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary:hover {
  color: var(--accent);
}

.faq summary::after {
  content: "";
  flex: none;
  width: 11px;
  height: 11px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  rotate: 45deg;
  translate: 0 -3px;
  transition: rotate 0.25s var(--ease);
}

.faq details[open] summary::after {
  rotate: -135deg;
  translate: 0 2px;
}

.faq details p {
  color: var(--text-dim);
  padding-bottom: 1.5rem;
  max-width: 66ch;
}

/* --- Banda de contacto final --------------------------------------------- */

.cta-band {
  border-top: 1px solid var(--line);
  background:
    radial-gradient(80% 120% at 50% 0%, var(--accent-wash), transparent 68%),
    var(--ink);
  text-align: center;
}

.cta-band h2 {
  font-size: clamp(2rem, 4.6vw, 3.2rem);
}

.cta-band p {
  margin: 1.1rem auto 0;
  color: var(--text-dim);
  max-width: 48ch;
}

.cta-band__mail {
  display: inline-block;
  margin-top: 2rem;
  font-size: clamp(1.35rem, 3.4vw, 2.1rem);
  font-weight: 560;
  letter-spacing: -0.03em;
  border-bottom: 2px solid var(--line-strong);
  padding-bottom: 0.3rem;
  transition: border-color 0.25s var(--ease), color 0.25s var(--ease);
}

.cta-band__mail:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* --- WhatsApp ------------------------------------------------------------- */

.section-wa {
  padding-top: clamp(2rem, 5vh, 3rem);
}
/*
   En rojo de marca, no en el verde de WhatsApp. Meter el verde corporativo de
   otra empresa en una pagina que solo usa un color romperia el sistema entero
   y ademas parcheria un plugin pegado. El icono ya identifica el canal.
*/

.wa {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(1rem, 3vw, 1.6rem);
  align-items: center;
  padding: clamp(1.35rem, 3vw, 1.9rem);
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  background:
    radial-gradient(130% 180% at 0% 0%, var(--accent-wash), transparent 60%),
    var(--surface);
}

.wa__icon {
  width: 3rem;
  height: 3rem;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--accent-strong);
  color: #ffffff;
}

.wa__icon svg {
  width: 1.6rem;
  height: 1.6rem;
}

.wa h2 {
  font-size: 1.1rem;
  letter-spacing: -0.015em;
}

.wa p {
  margin-top: 0.3rem;
  color: var(--text-dim);
  font-size: 0.92rem;
  line-height: 1.5;
}

/* El numero, grande y pulsable. En movil es un enlace tel: de hecho. */
.wa__num {
  display: inline-block;
  margin-top: 0.75rem;
  font-family: var(--font-mono);
  font-size: clamp(1.05rem, 2.6vw, 1.3rem);
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--accent);
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s var(--ease);
}

.wa__num:hover {
  border-bottom-color: var(--accent);
}

@media (max-width: 520px) {
  .wa {
    grid-template-columns: 1fr;
    gap: 0.9rem;
  }
}

/* Boton de WhatsApp dentro de la banda de contacto final. */
.cta-band__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  justify-content: center;
  margin-top: 2.25rem;
}

@media (max-width: 520px) {
  .cta-band__actions {
    flex-direction: column;
    align-items: stretch;
  }
}

/* --- Formulario ---------------------------------------------------------- */

.contact-layout {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: clamp(2.5rem, 7vw, 5.5rem);
  align-items: start;
}

.field {
  display: grid;
  gap: 0.5rem;
  margin-bottom: 1.6rem;
}

.field label {
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--text);
}

.field label .req {
  color: var(--accent);
  margin-left: 0.15rem;
}

.field .hint {
  font-size: 0.82rem;
  color: var(--text-faint);
}

.field input,
.field textarea,
.field select {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  padding: 0.82rem 0.95rem;
  font-size: 0.97rem;
  color: var(--text);
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}

.field textarea {
  min-height: 150px;
  resize: vertical;
}

/* Contraste del texto tenue sobre --surface por encima de AA. */
.field ::placeholder {
  color: var(--text-faint);
  opacity: 1;
}

.field input:hover,
.field textarea:hover,
.field select:hover {
  border-color: var(--text-faint);
}

.field input:focus,
.field textarea:focus,
.field select:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--surface-2);
}

.field .error {
  font-size: 0.85rem;
  color: var(--accent);
  display: none;
}

.field[data-invalid="true"] input,
.field[data-invalid="true"] textarea {
  border-color: var(--accent);
}

.field[data-invalid="true"] .error {
  display: block;
}

/* Señuelo antirrobots. No se usa display:none porque algunos robots lo
   detectan y saltan el campo; asi queda fuera de la pantalla pero presente. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.consent {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.75rem;
  align-items: start;
  font-size: 0.88rem;
  color: var(--text-dim);
  margin-bottom: 1.9rem;
}

/* Casilla propia. La nativa se dibuja como un cuadro blanco y en un tema
   oscuro canta muchisimo. Se mantiene el <input type="checkbox"> real, asi
   que el teclado, el lector de pantalla y el formulario funcionan igual. */
.consent input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: 1.4rem;
  height: 1.4rem;
  margin: 0;
  display: grid;
  place-content: center;
  border: 1px solid var(--line-strong);
  border-radius: 5px;
  background: var(--surface);
  cursor: pointer;
  transition: background-color 0.15s var(--ease), border-color 0.15s var(--ease);
}

.consent input[type="checkbox"]:hover {
  border-color: var(--text-faint);
}

/* La marca de verificacion, dibujada con dos bordes girados. */
.consent input[type="checkbox"]::before {
  content: "";
  width: 0.36rem;
  height: 0.66rem;
  border: solid #ffffff;
  border-width: 0 2px 2px 0;
  rotate: 45deg;
  translate: 0 -1.5px;
  scale: 0;
  transition: scale 0.12s var(--ease);
}

.consent input[type="checkbox"]:checked {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
}

.consent input[type="checkbox"]:checked::before {
  scale: 1;
}

/* Cuando el campo se marca como invalido, el borde tiene que verse. */
.consent input[type="checkbox"][aria-invalid="true"] {
  border-color: var(--accent);
}

.consent a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Estados del envio: reposo, enviando, enviado, error. */
.form-status {
  display: none;
  gap: 0.7rem;
  align-items: start;
  margin-top: 1.5rem;
  padding: 1rem 1.15rem;
  border-radius: var(--r-sm);
  font-size: 0.92rem;
  line-height: 1.55;
  border: 1px solid var(--line-strong);
  background: var(--surface);
}

.form-status[data-state="ok"],
.form-status[data-state="fail"] {
  display: flex;
}

.form-status[data-state="ok"] {
  border-color: var(--text-faint);
}

.form-status[data-state="fail"] {
  border-color: var(--accent-strong);
}

.form-status svg {
  width: 1.1rem;
  height: 1.1rem;
  flex: none;
  translate: 0 3px;
}

.form-status[data-state="ok"] svg {
  color: var(--text);
}

.form-status[data-state="fail"] svg {
  color: var(--accent);
}

.form-status a {
  color: var(--accent);
  text-decoration: underline;
}

button[data-busy="true"] {
  pointer-events: none;
  opacity: 0.72;
}

button[data-busy="true"] .spin {
  display: inline-block;
  animation: spin 0.8s linear infinite;
}

button .spin {
  display: none;
}

@keyframes spin {
  to {
    rotate: 360deg;
  }
}

@media (prefers-reduced-motion: reduce) {
  button[data-busy="true"] .spin {
    animation-duration: 2.4s;
  }
}

/* Panel lateral de contacto */
.contact-aside {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  padding: clamp(1.6rem, 3vw, 2.2rem);
}

.contact-aside dt {
  font-family: var(--font-mono);
  font-size: 0.73rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 0.35rem;
}

.contact-aside dd {
  margin: 0 0 1.5rem;
  font-size: 0.98rem;
  color: var(--text);
}

.contact-aside dd:last-of-type {
  margin-bottom: 0;
}

.contact-aside dd a:hover {
  color: var(--accent);
}

.contact-aside code {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--text-dim);
  word-break: break-all;
}

@media (max-width: 900px) {
  .contact-layout {
    grid-template-columns: 1fr;
  }
}

/* --- Zonas pulsables en pantalla tactil ----------------------------------- */
/*
   La WCAG 2.5.8 pide 24 x 24 px como minimo para cualquier cosa que se pulse.
   Los enlaces dentro de una frase estan exentos, pero los de una lista y los
   controles de formulario no, y con el dedo se falla de verdad.

   Medido antes de esto: la casilla de consentimiento era de 17 x 17 y los
   enlaces del pie de 17 de alto.
*/

@media (max-width: 900px) {
  .footer__col li a,
  .footer__base a,
  .contact-aside dd a,
  .crumb a,
  .routes a,
  .wa__num {
    display: inline-flex;
    align-items: center;
    min-height: 26px;
  }

  .footer__col li + li {
    margin-top: 0.35rem;
  }

  .consent {
    gap: 0.85rem;
  }

  .consent input {
    width: 1.5rem;
    height: 1.5rem;
    margin-top: 0;
  }

  /* Con el dedo, un menu de 0.95rem de alto se falla. */
  .nav a:not(.btn) {
    padding-block: 1.05rem;
  }

  /* La miga de pan en mayusculas se queda corta a 12 px en el movil. */
  .crumb {
    font-size: 0.82rem;
  }
}

/* --- Texto legal ---------------------------------------------------------- */

.prose {
  max-width: 72ch;
}

.prose h2 {
  font-size: 1.45rem;
  margin-top: 2.75rem;
  margin-bottom: 0.9rem;
}

.prose h3 {
  font-size: 1.08rem;
  margin-top: 1.75rem;
  margin-bottom: 0.5rem;
}

.prose p,
.prose li {
  color: var(--text-dim);
  margin-bottom: 0.9rem;
}

.prose ul {
  list-style: disc;
  padding-left: 1.3rem;
  margin-bottom: 1.2rem;
}

.prose a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.prose strong {
  color: var(--text);
  font-weight: 560;
}

/* Hueco de dato legal aun por rellenar. Discreto a proposito: se distingue
   del texto normal para que no pase por un dato real, pero sin el rojo de
   alarma que hacia parecer la pagina "en obras". */
.todo {
  color: var(--text-faint);
  font-style: italic;
}


/* --- Utilidades finales --------------------------------------------------- */

/* Sin estilos en linea: la CSP del sitio no permite style-src inline.
   Va al final del fichero y lleva la etiqueta delante para empatar en
   especificidad con ".split p" y ganar por orden de aparicion. */
p.statement__cta {
  margin-top: 1.5rem;
  color: inherit;
}
