/* =============================================================
   COMPONENTS — botones, tarjetas, formulario, estados
============================================================= */

/* ---- Botones ---- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 600;
  padding: 14px 26px;
  border-radius: var(--radius-sm);
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}

.btn--primary {
  color: #041018;
  background: var(--color-cyan);
  box-shadow: var(--shadow-glow-cyan);
}

@media (hover: hover) {
  .btn--primary:hover {
    background: #7dd3fc;
    transform: translateY(-2px);
  }
}

.btn--ghost {
  color: var(--color-ink);
  border: 1px solid var(--color-border-strong);
}

/* Hover del CTA secundario en naranja — distingue claramente del
   primario (cian) y le da al nuevo acento corporativo un rol de
   "foco puntual" consistente con el resto del sitio. */
@media (hover: hover) {
  .btn--ghost:hover {
    border-color: var(--color-accent-orange);
    color: var(--color-accent-orange);
    transform: translateY(-2px);
  }
}

.btn:active {
  transform: translateY(0);
}

.btn svg {
  width: 16px;
  height: 16px;
  transition: transform var(--dur-fast) var(--ease-out);
}

@media (hover: hover) {
  .btn:hover svg { transform: translateX(3px); }
}

/* ---- Diagrama de servicios (4 pilares, refactor 2026-07-29) ----
   Antes: 4 tarjetas planas en un grid de hairlines de 1px (sin jerarquía
   ni metáfora de flujo). Ahora: nodos independientes con borde propio,
   conectados por flechas reales en el DOM (.services-diagram__arrow, ver
   layout.css para el contenedor .services-diagram) que se "encienden" al
   interactuar con el nodo anterior — la interactividad refuerza la
   metáfora de flujo, no es un hover suelto. min-height sube de 260px a
   300px para reservar SIEMPRE el espacio de .service-card__detail
   (revelado en hover/foco más abajo): la tarjeta nunca cambia de alto al
   interactuar, así las flechas/arco conectores no se desalinean. */
.service-card {
  position: relative;
  /* flex-basis:auto (no "0") en la base — .services-diagram apila en
     columna bajo 1100px (ver layout.css), donde el eje principal del
     flex item es la ALTURA. "auto" deja que cada tarjeta se dimensione
     por su propio contenido; min-height abajo sigue siendo el piso.
     BUG fix (2026-07-29 ronda 4, encontrado al verificar el pilar 04 en
     navegador headless a 375/390/428px): con "flex: 1 1 0" (basis:0) el
     motor de flex ignora el tamaño del contenido al calcular la altura
     hipotética del item y la resuelve clampeada por min-height —
     resultado: la tarjeta queda fija en EXACTAMENTE 300px sin importar
     cuánto texto tenga, y el contenido que no entra (pilar 04, el más
     largo, en viewports angostos donde las tags envuelven a 2 líneas)
     se desborda por debajo del borde de la tarjeta en vez de empujarla
     a crecer. flex-basis:0 solo tiene sentido en la fila horizontal de
     escritorio (repartir ANCHO en partes iguales) — se reactiva ahí
     abajo, en el breakpoint que ya usa .services-diagram para pasar a
     flex-direction:row. */
  flex: 1 1 auto;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  min-height: 300px;
  display: flex;
  flex-direction: column;
  transition: background var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}

@media (min-width: 1100px) {
  .service-card {
    /* Fix de overflow horizontal (verificado en navegador headless,
       2026-07-29): los flex items tienen min-width:auto por defecto, que
       se calcula sobre el contenido MÁS ANCHO sin wrap (ej. una tag
       larga como "Infraestructura y Seguridad"), impidiendo que la
       tarjeta se achique por debajo de eso — con 4 nodos + 3 flechas en
       fila el diagrama se desbordaba del viewport en vez de repartirse
       en 1fr parejos. flex-basis:0 (en vez de "auto") es lo que permite
       repartir el ANCHO disponible en partes exactamente iguales entre
       las 4 tarjetas, sin importar que su contenido tenga distinto
       largo — necesario solo aquí, en la fila horizontal; ver la regla
       base arriba para por qué "auto" es lo correcto en la columna
       vertical de mobile/tablet. */
    flex: 1 1 0;
    min-width: 0;
  }
}

/* El naranja del nodo activo reutiliza el MISMO rol semántico "estás
   aquí" que ya tiene en el rail de índice y la pill de estado (ver
   tokens.css) — coherencia de sistema en vez de introducir otro color
   suelto para "nodo enfocado". Ronda 4 (2026-07-29, feedback: la
   interacción se sentía plana): se suma un glow de box-shadow —
   reutiliza --shadow-glow-signal, ya definido en tokens.css pero sin
   ningún consumidor hasta ahora — en vez de un color/sombra nuevo.
   box-shadow y no filter/backdrop-filter a propósito: mismo criterio de
   performance que se aplica en TV Box (ver persona), barato en cualquier
   GPU aunque este sitio no tenga TV Box como target explícito. */
@media (hover: hover) {
  .service-card:hover {
    background: var(--color-surface-2);
    border-color: var(--color-signal);
    transform: translateY(-3px);
    box-shadow: var(--shadow-glow-signal);
  }
}

/* :focus (no solo :focus-visible) — un tap en touch/TV-remote también
   debe revelar el detalle del nodo; el anillo de foco en sí lo resuelve
   :focus-visible en base.css, esto es la reacción visual del propio nodo. */
.service-card:focus {
  background: var(--color-surface-2);
  border-color: var(--color-signal);
  transform: translateY(-3px);
  box-shadow: var(--shadow-glow-signal);
}

/* position:relative + el ::before de abajo: halo circular detrás de la
   numeración, el mismo lenguaje de "foco puntual" que --color-signal-dim
   ya usa en .status-pill (tokens.css) — reutilizado aquí en vez de
   inventar un tono nuevo. display:inline-block para que el ::before
   absoluto tome como referencia SOLO la caja del número, no la fila
   completa del padre. */
.service-card__num {
  position: relative;
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: var(--tracking-wide);
  color: var(--color-ink-faint);
  margin-bottom: var(--space-5);
  transition: color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}

.service-card__num::before {
  content: '';
  position: absolute;
  inset: -8px -10px;
  border-radius: 999px;
  background: var(--color-signal-dim);
  opacity: 0;
  transform: scale(0.6);
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
  z-index: -1;
}

@media (hover: hover) {
  .service-card:hover .service-card__num {
    color: var(--color-signal);
    transform: scale(1.08);
  }

  .service-card:hover .service-card__num::before {
    opacity: 1;
    transform: scale(1);
  }
}

.service-card:focus .service-card__num {
  color: var(--color-signal);
  transform: scale(1.08);
}

.service-card:focus .service-card__num::before {
  opacity: 1;
  transform: scale(1);
}

.service-card h3 {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 700; /* ronda 3: 500→700 — Montserrat solo tiene 400/700 cargados localmente */
  color: var(--color-ink);
  margin-bottom: var(--space-3);
  letter-spacing: var(--tracking-tight);
}

/* ---- Descripción del pilar ----
   BUG fix (2026-07-29, reportado por el cliente en el pilar 04): esta
   regla vivía como ".service-card p" — un selector genérico por tag que
   TAMBIÉN matcheaba a ".service-card__detail" más abajo (también
   implementado como <p>, ver index.html). ".service-card p" tiene mayor
   especificidad (0,1,1) que ".service-card__detail" (0,1,0), así que por
   cascada pisaba silenciosamente el color/font-size/margin-top que
   ".service-card__detail" intentaba fijar — el más dañino era
   margin-top: auto, que dentro del mismo contenedor flex-column hacía
   competir a AMBOS elementos por el espacio libre repartido de forma
   impredecible, apretando el texto del detalle contra el número del
   pilar en el nodo 04 (texto más largo). Fix: clase explícita en vez de
   acoplarse al tag genérico — cero ambigüedad de cascada, sin subir
   especificidad ni usar !important. */
.service-card__desc {
  font-size: 0.9rem;
  line-height: var(--lh-normal);
  color: var(--color-ink-muted);
  margin-top: auto;
}

/* Fila de tags/capacidades por pilar — mismo patrón visual que
   .project-card__tags (pill con borde, mono, uppercase), reutilizado
   aquí en vez de inventar un estilo nuevo (pedido explícito). */
.service-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

.service-card__tags li {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-muted);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 4px 10px;
}

/* ---- Detalle de conexión — revelado en hover/foco (2026-07-29) ----
   Texto que explica hacia qué pilar "fluye" cada nodo (refuerza la
   metáfora de diagrama con CONTENIDO, no solo con estilo). Reserva su
   espacio SIEMPRE — anima solo opacity+transform, nunca max-height ni
   display, así la tarjeta no cambia de alto al revelarse (ver min-height
   arriba). Sigue en el árbol de accesibilidad en todo momento (nunca
   aria-hidden): un lector de pantalla lo recibe igual que el resto del
   contenido, sin depender de hover/foco para "existir" — lo que cambia
   con la interacción es solo su presentación visual.

   Ronda 4 (2026-07-29): su margin-top/color/font-size ya no compiten con
   ".service-card p" — ese selector genérico se renombró a
   ".service-card__desc" (ver arriba) precisamente porque también
   matcheaba este elemento por ser un <p>. Ver ese comentario para el
   diagnóstico completo del bug reportado en el pilar 04. */
.service-card__detail {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: var(--tracking-wide);
  color: var(--color-accent-teal-deep);
  margin-top: var(--space-3);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}

.service-card__detail strong {
  color: var(--color-ink);
  font-weight: 700;
}

@media (hover: hover) {
  .service-card:hover .service-card__detail {
    opacity: 1;
    transform: translateY(0);
  }
}

.service-card:focus .service-card__detail {
  opacity: 1;
  transform: translateY(0);
}

/* ---- Flecha conectora entre nodos ----
   Elemento real del DOM (span + svg), hermano entre cada par de
   .service-card dentro de .services-diagram (ver layout.css) — no un
   pseudo-elemento posicionado en absoluto. Al vivir en el flujo normal,
   se reordena solo entre el layout vertical (mobile/tablet, flechas hacia
   abajo) y horizontal (desktop ≥1100px, flechas hacia la derecha) sin
   recalcular coordenadas. aria-hidden: decorativa — el orden real de
   lectura de los 4 pilares ya lo da el DOM de los .service-card
   (role="listitem"), un lector de pantalla no necesita "escuchar" la
   flecha para entender la secuencia. */
.services-diagram__arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  color: var(--color-signal);
  opacity: 0.5;
  transition: opacity var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out);
}

.services-diagram__arrow svg {
  width: 22px;
  height: 22px;
  transform: rotate(90deg); /* flujo vertical por defecto (mobile/tablet) — apunta hacia abajo */
}

@media (min-width: 1100px) {
  .services-diagram__arrow svg {
    transform: rotate(0deg); /* flujo horizontal — apunta a la derecha */
  }
}

/* La flecha se "enciende" en teal — el acento de "flujo/conexión" del
   diagrama (ver tokens.css), deliberadamente distinto del naranja
   "estás aquí" del propio nodo — cuando el nodo ANTERIOR (el que empuja
   el flujo hacia este) está en hover o foco.

   Ronda 4 (2026-07-29, feedback: "la interacción se siente simple, solo
   opacity+transform del detalle"): se suma un "empuje" continuo mientras
   el nodo anterior sigue activo — la flecha no solo se enciende, sigue
   moviéndose en la dirección del flujo (abajo en mobile/tablet, a la
   derecha en desktop ≥1100px, mismo breakpoint que la rotación del ícono
   arriba) reforzando la metáfora de "empuja hacia el siguiente pilar" en
   vez de solo cambiar de color. @keyframes en animations.css — misma
   convención del archivo (transform únicamente, sin filter/blur, barato
   en cualquier GPU). Se define aquí la variante vertical por defecto y
   se cambia a la horizontal en el breakpoint de escritorio. */
@media (hover: hover) {
  .service-card:hover + .services-diagram__arrow {
    opacity: 1;
    color: var(--color-accent-teal-deep);
    animation: services-arrow-flow-y var(--dur-slow) var(--ease-in-out) infinite;
  }
}

.service-card:focus + .services-diagram__arrow {
  opacity: 1;
  color: var(--color-accent-teal-deep);
  animation: services-arrow-flow-y var(--dur-slow) var(--ease-in-out) infinite;
}

@media (min-width: 1100px) {
  @media (hover: hover) {
    .service-card:hover + .services-diagram__arrow {
      animation-name: services-arrow-flow-x;
    }
  }

  .service-card:focus + .services-diagram__arrow {
    animation-name: services-arrow-flow-x;
  }
}

/* ---- Acento del badge "vuelve a 01" al llegar al último pilar (mobile/
   tablet, <1100px) ---- Equivalente mobile del bloque :has() de abajo,
   pero sin necesitarlo: .services-diagram__cycle-mobile es hermano
   INMEDIATO del pilar 04 en el DOM (ver index.html), así que el
   selector adyacente `+` de toda la vida alcanza. */
@media (max-width: 1099px) {
  @media (hover: hover) {
    .service-card:nth-of-type(4):hover + .services-diagram__cycle-mobile svg,
    .service-card:nth-of-type(4):hover + .services-diagram__cycle-mobile span {
      opacity: 1;
    }
  }

  .service-card:nth-of-type(4):focus + .services-diagram__cycle-mobile svg,
  .service-card:nth-of-type(4):focus + .services-diagram__cycle-mobile span {
    opacity: 1;
  }
}

/* ---- Acento del arco de ciclo al llegar al último pilar (escritorio) ----
   Progressive enhancement con :has() (soporte amplio en navegadores
   evergreen 2026; sin soporte, el arco simplemente se queda con su
   animación ambiental ya existente — nunca deja de comunicar el ciclo,
   solo pierde este refuerzo puntual). El arco (.services-diagram__cycle,
   ver layout.css) vive ANTES que los .service-card en el DOM, así que un
   selector de hermanos (~/+) no alcanza desde el pilar 04 — de ahí
   :has() sobre el contenedor en vez de reestructurar el DOM. */
@media (min-width: 1100px) {
  .services-diagram:has(.service-card:nth-of-type(4):hover) .services-diagram__cycle-path,
  .services-diagram:has(.service-card:nth-of-type(4):focus) .services-diagram__cycle-path {
    opacity: 1;
    stroke-width: 2.25;
  }

  .services-diagram:has(.service-card:nth-of-type(4):hover) .services-diagram__cycle-arrowhead-icon,
  .services-diagram:has(.service-card:nth-of-type(4):focus) .services-diagram__cycle-arrowhead-icon,
  .services-diagram:has(.service-card:nth-of-type(4):hover) .services-diagram__cycle-label,
  .services-diagram:has(.service-card:nth-of-type(4):focus) .services-diagram__cycle-label {
    opacity: 1;
  }
}

.services-cta a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink);
  border-bottom: 1px solid var(--color-border-strong);
  padding-bottom: 4px;
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}

@media (hover: hover) {
  .services-cta a:hover {
    color: var(--color-accent-orange);
    border-color: var(--color-accent-orange);
  }
}

/* ---- Fila de proyecto (caso de trabajo real, con captura propia) ----
   Ronda 6 (2026-07-29, feedback explícito de Frank: "debe ser igual
   como el ejemplo... con más interacción"): se reconstruye sobre el
   bento grid de la ronda 5 para acercarse mucho más al bloque exacto
   "Evidence, not theatre." (`.section.section--rule` → `.case-grid` /
   `.case-card`) de aiagency-599.pages.dev, verificado renderizándolo
   con Playwright (layout, CSS real vía network response, e interacción
   en vivo con mouse.move — no solo HTML/CSS en reposo). Adoptado casi
   1:1: filas a todo el ancho separadas por `border-top` (no cards en
   caja con fondo propio), grid 7fr/5fr con imagen/cuerpo alternados
   por fila (`nth-of-type(2n)`), cuerpo envuelto en un recuadro de 1px
   (`.project-card__body`) sin relleno, tipografía del nombre de caso
   mucho más grande y dominante, y el mismo gesto de imagen
   (`saturate(.78)→1` + `scale(1.025)` en hover) ya adaptado en ronda 5.
   Lo nuevo de esta ronda: 1) cifra grande — la referencia usa un
   resultado de negocio inventado (ej. "41% faster exception
   resolution"); eso NO se replica (prohibido fabricar métricas —
   restricción explícita de Frank), pero SÍ se replica el gesto
   tipográfico con datos reales y neutrales ya presentes en el copy de
   cada caso (recuentos verificables: "3" sitios del ecosistema Grupo
   Crear, "2" plataformas del Colegio, "3" pasos del cotizador ABS —
   ver `.project-card__stat` más abajo); Comuniads y Restaurant Digital
   deliberadamente NO tienen esta cifra porque no existe un recuento
   real de 2+ piezas que mostrar sin forzarlo — ver nota en
   `.project-card__stat` y memoria del agente para el detalle; 2) color
   de acento por fila vía `--accent` inline (mismo mecanismo literal que
   `style="--accent: #c7f36b"` de la referencia), que ahora tiñe la
   cifra, el chip numerado en hover Y el anillo del cursor personalizado
   al pasar sobre la fila (ver cursor.js) — esto último es una extensión
   propia, sin equivalente en aiagency, pensada para reforzar
   "interacción" reutilizando el cursor magnético que ya existía en el
   sitio en vez de crear un sistema paralelo; 3) parallax de la foto que
   sigue al cursor dentro del panel de medios (ver issets/js/projects.js),
   además del saturate/scale ya existente — la referencia no tiene esto,
   es la segunda extensión propia para "más interacción". El gradiente
   temático de fondo por caso (ronda 2/5) se mantiene como color de
   "loading" bajo cada imagen. */
.project-card {
  position: relative;
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-6);
}

.project-card + .project-card {
  margin-top: var(--space-7);
}

.project-card__media {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: var(--radius-sm);
  background: linear-gradient(150deg, #0a0e1a, #10141f);
}

/* Variedad temática por caso (color de "loading" bajo la foto) — 6
   combinaciones sobre la misma paleta ya existente (cian, naranja-señal,
   azul, azul profundo, una quinta mezcla cian+naranja para el 5º caso, y
   naranja de nuevo para el 6º — ver nota junto a nth-of-type(6) más abajo). */
.project-card:nth-of-type(1) .project-card__media {
  background: radial-gradient(circle at 26% 22%, rgba(56, 189, 248, 0.34), transparent 62%),
              linear-gradient(150deg, #0a0e1a, #10141f);
}
.project-card:nth-of-type(2) .project-card__media {
  background: radial-gradient(circle at 74% 28%, rgba(255, 106, 3, 0.2), transparent 60%),
              linear-gradient(150deg, #0a0e1a, #10141f);
}
.project-card:nth-of-type(3) .project-card__media {
  background: radial-gradient(circle at 38% 72%, rgba(96, 165, 250, 0.3), transparent 60%),
              linear-gradient(150deg, #0a0e1a, #10141f);
}
.project-card:nth-of-type(4) .project-card__media {
  background: radial-gradient(circle at 62% 66%, rgba(57, 87, 162, 0.45), transparent 60%),
              linear-gradient(150deg, #0a0e1a, #10141f);
}
.project-card:nth-of-type(5) .project-card__media {
  background: radial-gradient(circle at 50% 50%, rgba(255, 106, 3, 0.16), transparent 65%),
              radial-gradient(circle at 15% 85%, rgba(56, 189, 248, 0.22), transparent 60%),
              linear-gradient(150deg, #0a0e1a, #10141f);
}
/* 6º caso (ronda 7): Célula Publicidad, agencia partner — mismo
   naranja corporativo que el caso 2 (Colegio), reutilizado a
   propósito: solo hay 4 tokens de acento en la paleta para 6 filas
   (ver memoria del agente, ronda 6), y naranja da mejor contraste con
   el cian de la fila inmediatamente anterior (caso 5) que repetir cian. */
.project-card:nth-of-type(6) .project-card__media {
  background: radial-gradient(circle at 30% 30%, rgba(255, 106, 3, 0.22), transparent 60%),
              linear-gradient(150deg, #0a0e1a, #10141f);
}

/* Foto real del proyecto — cubre todo el panel de medios. Desaturada en
   reposo (mismo gesto que .case-media img de la referencia) y a
   saturación/brillo plenos en hover/foco, SOLO donde hay hover real
   (pointer fino): en touch (TV/mobile sin hover) se muestra siempre a
   color pleno porque ahí no existe forma de "revelar" el estado — dejar
   la captura permanentemente apagada se leería como una imagen de mala
   calidad, no como una interacción. */
/* --shot-scale/--parallax-* son escritas por issets/js/projects.js
   (solo hover:hover + pointer:fine, y solo si NO hay prefers-reduced-
   motion — el script ni siquiera agrega los listeners en ese caso). El
   fallback de :hover/:focus-within de abajo cubre foco por teclado y
   cualquier caso donde JS no llegue a correr; el translate por defecto
   es 0px así que sin JS el resultado es idéntico al de la ronda 5. */
.project-card__shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.4) brightness(0.9);
  transform: scale(var(--shot-scale, 1.02)) translate3d(var(--parallax-x, 0px), var(--parallax-y, 0px), 0);
  transition: filter var(--dur-slow) var(--ease-out);
}

@media (hover: hover) {
  .project-card:hover .project-card__shot,
  .project-card:focus-within .project-card__shot {
    filter: saturate(1.05) brightness(1);
  }
}

/* Fallback de --shot-scale para foco por teclado / navegadores sin JS
   (con mouse+JS activo, projects.js sobreescribe --shot-scale inline en
   cada tick y esta regla queda sin efecto por especificidad). Se exige
   también no-preference de movimiento reducido: sin esto, hover con
   mouse bajo prefers-reduced-motion:reduce igual escalaba la imagen de
   golpe (sin transición, ya que --dur-fast/linear solo cubre `filter`)
   — con la condición agregada, bajo movimiento reducido la imagen
   nunca cambia de tamaño, solo de color (mismo criterio que projects.js). */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .project-card:hover .project-card__shot,
  .project-card:focus-within .project-card__shot {
    --shot-scale: 1.06;
  }
}

@media (hover: none) {
  .project-card__shot {
    filter: saturate(0.94) brightness(0.98);
    transform: scale(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .project-card__shot {
    transition: filter var(--dur-fast) linear;
  }
}

/* Chip numerado — reemplaza el ghost-num transparente de las rondas
   anteriores (pensado para el fondo oscuro liso de los iconos SVG; sobre
   una foto real a 0.07 de opacidad se pierde por completo). Mismo
   lenguaje visual que .status-pill/.project-card__tags (píldora mono
   con borde), ahora con fondo sólido para quedar legible sobre
   cualquier captura. */
.project-card__ghost-num {
  position: absolute;
  top: var(--space-3);
  left: var(--space-3);
  z-index: 1;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: var(--tracking-wide);
  line-height: 1;
  color: var(--color-ink);
  background: rgba(6, 7, 12, 0.72);
  border: 1px solid rgba(238, 242, 247, 0.16);
  border-radius: 999px;
  padding: 5px 11px;
  pointer-events: none;
  user-select: none;
  transition: color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}

/* Acento por fila — el chip se enciende con el color de la fila
   (--accent, inline en cada .project-card, ver index.html) al pasar el
   cursor, en vez de naranja fijo — refuerza junto con la cifra grande
   y el tinte del cursor (cursor.js) que cada caso tiene su propia
   identidad de color, no solo el ghost-num aislado como en ronda 5. */
@media (hover: hover) {
  .project-card:hover .project-card__ghost-num {
    color: var(--accent, var(--color-accent-orange));
    border-color: var(--accent, var(--color-accent-orange));
  }
}

/* ---- Capturas hermanas (ecosistema/piezas adicionales) ----
   Tira de 1-2 miniaturas superpuestas al pie del panel de medios, solo en
   los casos con más de una captura de respaldo (Grupo Crear, Colegio,
   ABS Security — ver index.html). Prueba visual de una afirmación
   concreta del texto (ej. "portal aparte", "ecosistema de 3 sitios"),
   no decoración. Llevan alt real (son informativas) pero NO son
   focusables — no hay una acción/enlace real detrás todavía, así que
   agregar un foco sin acción sería un callejón sin salida para teclado/
   D-pad (ver restricción de accesibilidad del sitio). */
.project-card__siblings {
  position: absolute;
  left: var(--space-3);
  right: var(--space-3);
  bottom: var(--space-3);
  z-index: 1;
  display: flex;
  gap: var(--space-2);
}

.project-card__siblings--single {
  max-width: 220px;
}

.project-card__sibling {
  position: relative;
  flex: 1;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(238, 242, 247, 0.18);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.45);
  background: #0a0e1a;
}

.project-card__sibling img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.55) brightness(0.85);
  transition: filter var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}

/* Captura vertical (ej. pantalla de login estilo mobile) — recortarla en
   cover la dejaría casi ilegible; se ve completa con letterbox oscuro. */
.project-card__sibling--contain img {
  object-fit: contain;
}

.project-card__sibling span {
  position: absolute;
  left: 6px;
  bottom: 5px;
  right: 6px;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.9);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (hover: hover) {
  .project-card:hover .project-card__sibling img {
    filter: saturate(1) brightness(1);
    transform: scale(1.05);
  }
}

@media (hover: none) {
  .project-card__sibling img {
    filter: saturate(0.92) brightness(0.96);
  }
}

/* Recuadro de 1px sin relleno (eco de `.case-content{border:1px solid
   var(--line)}` de la referencia) — antes el color/fondo del panel
   vivía en `.project-card` (caja elevada); ahora el "marco" es solo
   del cuerpo, la foto queda a sangre completa sin borde propio. */
.project-card__body {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  flex: 1;
}

/* Pulso de llegada al navegar desde un logo de #clientes (ronda 8,
   2026-07-29) — CSS puro vía :target, sin JS: el <a> de #clientes
   apunta a un id="caso-*" en la fila correspondiente; el navegador ya
   hace scroll suave (scroll-behavior:smooth, base.css) y agrega
   :target automáticamente al llegar. scroll-margin-top compensa el
   header fijo para que la fila no quede tapada al aterrizar. El pulso
   usa var(--accent) de la propia fila (heredada por .project-card__body
   desde el <article>), así que el color coincide con el logo que se
   acaba de tocar. Bajo prefers-reduced-motion la regla global de
   base.css ya colapsa animation-duration a 0.01ms — no hace falta
   gatear esto aparte. */
.project-card {
  scroll-margin-top: 110px;
}

.project-card:target .project-card__body {
  animation: case-target-pulse 1.8s var(--ease-out);
}

@keyframes case-target-pulse {
  0% { box-shadow: 0 0 0 3px var(--accent, var(--color-signal)); }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/* Fila de meta partida (sector | tipo) — eco del kicker de dos lados de
   la referencia (dos etiquetas mono en los extremos sobre cada caso). */
.project-card__meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}

.project-card__sector {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--accent, var(--color-signal));
}

.project-card__meta-extra {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-faint);
  text-align: right;
  white-space: nowrap;
}

/* Nombre del caso — mucho más grande que el resto del sitio (antes
   usaba el mismo --fs-h3 que .service-card, clamp 1.15rem-1.5rem). Se
   fija un tamaño propio para esta sección, sin tocar el token
   compartido, acercándose al peso tipográfico de `.case-content h3`
   de la referencia (clamp 3.5rem-7.5rem) sin llegar a esa escala:
   el cuerpo de esta tarjeta también carga meta+cifra+facts+tags
   (mucho más denso que el case-content minimalista de aiagency), así
   que una escala tan extrema habría dejado poco espacio al resto. */
.project-card h3 {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.4vw + 1.4rem, 2.75rem);
  font-weight: 700; /* ronda 3: 500→700 — Montserrat solo tiene 400/700 cargados localmente */
  line-height: 0.98;
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
}

/* ---- Cifra grande (equivalente honesto de .case-result) ----
   Ronda 6: la referencia muestra un resultado de negocio inventado
   ("41% faster exception resolution") — eso está expresamente
   prohibido en este proyecto. En vez de descartar el patrón completo
   (como en ronda 5), se replica el gesto tipográfico con un RECUENTO
   real y neutral que ya vive en el copy de cada caso (no es una cifra
   nueva): "3" sitios del ecosistema Grupo Crear, "2" plataformas del
   Colegio (sitio + portal con login), "3" pasos del cotizador ABS.
   Comuniads y Restaurant Digital no llevan `.project-card__stat` en el
   HTML — no hay un recuento real de 2+ piezas en esos dos casos y
   forzar un "1" no aporta información, así que se omite en vez de
   rellenar el patrón artificialmente (ver memoria del agente). */
.project-card__stat {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.project-card__stat strong {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 2.4vw + 1.6rem, 4rem);
  font-weight: 700;
  line-height: 0.9;
  letter-spacing: var(--tracking-tight);
  color: var(--accent, var(--color-signal));
}

.project-card__stat span {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-faint);
  max-width: 16ch;
}

.project-card__facts {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.project-card__facts dt {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-faint);
  margin-bottom: 2px;
}

.project-card__facts dd {
  font-size: 0.875rem;
  line-height: var(--lh-normal);
  color: var(--color-ink-muted);
}

.project-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-3);
}

.project-card__tags li {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-muted);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 4px 10px;
}

/* ---- Enlace(s) de salida al sitio real (ronda 7, 2026-07-29) ----
   Pedido explícito de Frank: las filas ya no son solo casos ilustrados,
   ahora enlazan al sitio real en producción. Patrón inspirado en el
   "VIEW DEPLOYMENT ↗" de la referencia aiagency-599 (ver ronda 5/6 —
   antes deliberadamente omitido por no tener URLs confirmadas), pero
   como texto discreto al pie del cuerpo en vez de envolver toda la fila
   en un único <a>: Grupo Crear tiene 3 URLs distintas dentro de una
   misma fila (imposible con un solo enlace envolvente), y envolver el
   <article> completo habría arriesgado el parallax/cursor-tint del
   panel de medios ya validado en ronda 6. Cada .project-card__link es
   focusable de forma independiente — sigue el mismo flujo de tab que
   el resto del cuerpo (meta → h3 → facts → tags → enlaces). */
.project-card__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  margin-top: var(--space-2);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
}

.project-card__link {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink);
  padding-bottom: 2px;
  background-image: linear-gradient(var(--accent, var(--color-signal)), var(--accent, var(--color-signal)));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}

.project-card__link span {
  color: var(--accent, var(--color-signal));
}

@media (hover: hover) {
  .project-card__link:hover {
    color: var(--accent, var(--color-signal));
    background-size: 100% 1px;
  }
}

.project-card__link:focus-visible {
  color: var(--accent, var(--color-signal));
  background-size: 100% 1px;
}

/* ---- Grid alternado 7fr/5fr por fila, imagen/cuerpo cruzados en pares ----
   Ronda 6: reemplaza el caso especial "flagship" (única fila ancha en
   un grid 2x2) por el mismo patrón que TODAS las filas usan en la
   referencia (`.case-card{grid-template-columns:7fr 5fr} :nth-child(2n){
   grid-template-columns:5fr 7fr} :nth-child(2n) .case-media{order:2}`).
   Ya no hay distinción de layout para el primer caso (Grupo Crear) —
   ocupa la fila impar #1 igual que cualquier otro. */
@media (min-width: 900px) {
  .project-card {
    display: grid;
    grid-template-columns: 7fr 5fr;
    align-items: stretch;
    gap: var(--space-6);
  }

  .project-card:nth-of-type(2n) {
    grid-template-columns: 5fr 7fr;
  }

  .project-card:nth-of-type(2n) .project-card__media {
    order: 2;
  }

  .project-card__media {
    aspect-ratio: auto;
  }

  .project-card__body {
    padding: var(--space-7);
  }
}

/* ---- Carrusel de logos de clientes — logos reales (ronda 8), ahora
   en marquee fluido (ronda 9, 2026-07-29) ----
   Frank: "la interacción de los logos no es muy apta, usar carrusel
   fluido". Se descartó por completo el patrón anterior (grid estático
   + halo ambiental "respirando" + atracción magnética) — ver
   layout.css para la estructura del carrusel (.client-marquee/
   __viewport/__track/__set). Este bloque define únicamente el
   contenido de cada celda (.client-badge/.client-logo*), que ahora
   vive dentro de esa banda en vez de una grilla.

   Se elimina --accent-glow-rgb (ya no hay halo ambiental que tintar):
   --accent (los mismos tokens AA de ronda 8) sigue usándose para el
   borde/sombra de hover y para el subrayado + color de la flecha del
   caption — ambos son solo TEXTO/BORDE, sin requisito de contraste
   distinto al ya verificado en ronda 8. */
.client-badge {
  flex: 0 0 auto;
  width: clamp(196px, 22vw, 248px);
  border-inline-end: 1px solid var(--color-border);
  scroll-snap-align: start;
}

.client-logo {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-5);
}

/* Caja de tamaño uniforme para los 6 logos, aunque sus proporciones
   originales sean muy distintas (el lockup de Grupo Crear/Canoser/
   Crear Asociados es ~4.3:1, el de Célula ~2.2:1) — SIN CAMBIOS
   respecto a ronda 8: mismo ancho/alto de contenedor para los 6,
   object-fit:contain adentro evita deformar cualquiera, --logo-bg
   (override inline por logo en index.html — blanco en 4 de los 6,
   navy en Comuniads, negro en Célula) resuelve el "letterbox". */
.client-logo__frame {
  --logo-bg: #ffffff;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 5 / 2;
  background: var(--logo-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-4);
  overflow: hidden;
  transition: border-color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out);
}

.client-logo__frame img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  transition: transform var(--dur-base) var(--ease-out);
}

/* Nombre del cliente + flecha "→" (no "↗": a diferencia de
   .project-card__link, este enlace NO abre una pestaña nueva, navega
   dentro de la misma página hacia el caso en #proyectos). Mismo gesto
   de subrayado que crece en hover/focus que .project-card__link. */
.client-logo__caption {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-faint);
  text-align: center;
  padding-bottom: 2px;
  background-image: linear-gradient(var(--accent, var(--color-signal)), var(--accent, var(--color-signal)));
  background-repeat: no-repeat;
  background-position: 50% 100%;
  background-size: 0% 1px;
  transition: background-size var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}

.client-logo__caption span {
  color: var(--accent, var(--color-signal));
}

/* Hover/foco de un logo individual — feedback más contenido que en
   ronda 8 (sin halo/glow): borde + sombra de acento + zoom leve del
   logo. La señal PRINCIPAL de "estás sobre un logo" es que el
   carrusel entero se detiene (ver .client-marquee--live:hover en
   layout.css) — este highlight es un refuerzo secundario, no el
   único indicador. */
@media (hover: hover) {
  .client-logo:hover .client-logo__frame {
    border-color: var(--accent, var(--color-signal));
    transform: scale(1.045);
    box-shadow: 0 14px 28px rgba(28, 26, 21, 0.16);
  }

  .client-logo:hover .client-logo__frame img {
    transform: scale(1.06);
  }

  .client-logo:hover .client-logo__caption {
    color: var(--color-ink-muted);
    background-position: 0 100%;
    background-size: 100% 1px;
  }
}

.client-logo:focus-visible .client-logo__frame {
  border-color: var(--accent, var(--color-signal));
  transform: scale(1.045);
  box-shadow: 0 14px 28px rgba(28, 26, 21, 0.16);
}

.client-logo:focus-visible .client-logo__frame img {
  transform: scale(1.06);
}

.client-logo:focus-visible .client-logo__caption {
  color: var(--color-ink-muted);
  background-position: 0 100%;
  background-size: 100% 1px;
}

/* ---- Formulario de contacto ---- */
.contact-form-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: var(--shadow-card);
}

@media (min-width: 640px) {
  .contact-form-card { padding: var(--space-7); }
}

.field-group {
  margin-bottom: var(--space-4);
}

.field-group label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-muted);
  margin-bottom: var(--space-2);
}

.field-group input,
.field-group textarea {
  width: 100%;
  font-family: var(--font-body);
  font-size: 15px; /* >=16px evita zoom iOS; 15px + padding cumple igual, ver nota abajo */
  color: var(--color-ink);
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  outline: none;
  transition: border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}

/* Campo "Cuéntame tu situación" — único <textarea> del formulario, mismo
   patrón visual que los <input> (label + campo + field-error-msg). */
.field-group textarea {
  resize: vertical;
  min-height: 110px;
  line-height: var(--lh-normal);
}

@media (max-width: 480px) {
  .field-group input,
  .field-group textarea { font-size: 16px; } /* evita zoom automático en iOS Safari */
}

.field-group input::placeholder,
.field-group textarea::placeholder {
  color: var(--color-ink-faint);
}

.field-group input:focus,
.field-group textarea:focus {
  border-color: var(--color-cyan);
  background: rgba(56, 189, 248, 0.05);
  box-shadow: 0 0 0 3px rgba(56, 189, 248, 0.12);
}

.field-group input.field-error,
.field-group textarea.field-error {
  border-color: var(--color-danger);
}

.field-group input.field-error:focus,
.field-group textarea.field-error:focus {
  box-shadow: 0 0 0 3px rgba(248, 113, 113, 0.15);
}

.field-error-msg {
  display: none;
  font-size: 0.75rem;
  color: var(--color-danger);
  margin-top: var(--space-2);
}

.field-error-msg.show {
  display: block;
}

.btn-submit {
  width: 100%;
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 600;
  color: #041018;
  background: var(--color-cyan);
  border-radius: var(--radius-sm);
  padding: 14px 20px;
  margin-top: var(--space-3);
  box-shadow: var(--shadow-glow-cyan);
  transition: background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}

@media (hover: hover) {
  .btn-submit:hover {
    background: #7dd3fc;
    transform: translateY(-1px);
  }
}

.btn-submit:active {
  transform: translateY(0);
}

.form-note {
  font-size: 0.7rem;
  color: var(--color-ink-faint);
  margin-top: var(--space-3);
  text-align: center;
}

/* ---- Estado de éxito ---- */
.form-success {
  display: none;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
  padding-block: var(--space-4);
}

.form-success.show {
  display: flex;
}

.success-icon {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: rgba(52, 211, 153, 0.1);
  border: 1px solid rgba(52, 211, 153, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-success);
  font-size: 22px;
}

.success-title {
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 700; /* ronda 3: 500→700 — Montserrat solo tiene 400/700 cargados localmente */
  color: var(--color-ink);
}

.success-body {
  font-size: 0.9rem;
  color: var(--color-ink-muted);
  line-height: var(--lh-normal);
}

/* ---- Pill de estado "en línea" ---- */
.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-signal);
  background: var(--color-signal-dim);
  border: 1px solid rgba(255, 106, 3, 0.35);
  padding: 6px 12px;
  border-radius: 999px;
  margin-bottom: var(--space-5);
}

.status-pill__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-signal);
  animation: pulse-dot 2.2s ease-in-out infinite;
}

/* ---- LinkedIn link footer ---- */
.social-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition: color var(--dur-fast) var(--ease-out);
}

.social-link svg {
  width: 16px;
  height: 16px;
  fill: currentColor;
}

@media (hover: hover) {
  .social-link:hover { color: var(--color-cyan); }
}

/* =============================================================
   PÁGINA DE POLÍTICA DE PRIVACIDAD (ADR-03)
============================================================= */
.privacy-main {
  padding-top: calc(var(--space-10) + var(--space-6));
  padding-bottom: var(--space-10);
}

.privacy-section__inner {
  max-width: 820px;
}

.privacy-header {
  margin-bottom: var(--space-8);
  padding-bottom: var(--space-7);
  border-bottom: 1px solid var(--color-border);
}

.privacy-title {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  font-weight: 700;
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
  margin-bottom: var(--space-5);
}

.privacy-intro {
  font-size: var(--fs-lead);
  line-height: var(--lh-normal);
  color: var(--color-ink-muted);
  margin-bottom: var(--space-4);
}

.privacy-updated {
  font-size: var(--fs-small);
  color: var(--color-ink-faint);
  font-style: italic;
}

.privacy-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
}

.privacy-article {
  padding: var(--space-6);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.privacy-article__title {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 700;
  color: var(--color-cyan);
  margin-bottom: var(--space-4);
  line-height: var(--lh-snug);
}

.privacy-article__text {
  font-size: var(--fs-body);
  line-height: var(--lh-normal);
  color: var(--color-ink-muted);
  margin-bottom: var(--space-4);
}

.privacy-article__text:last-child {
  margin-bottom: 0;
}

.privacy-list {
  list-style: disc;
  padding-left: var(--space-5);
  margin-bottom: var(--space-4);
  color: var(--color-ink-muted);
  line-height: var(--lh-normal);
}

.privacy-list li {
  margin-bottom: var(--space-2);
}

.privacy-list li::marker {
  color: var(--color-cyan);
}

.privacy-footer {
  margin-top: var(--space-8);
  padding-top: var(--space-7);
  border-top: 1px solid var(--color-border);
  color: var(--color-ink-muted);
  font-size: var(--fs-body);
  line-height: var(--lh-normal);
}

.privacy-footer p {
  margin-bottom: var(--space-3);
}

.privacy-footer a {
  color: var(--color-cyan);
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color var(--dur-fast) var(--ease-out);
}

@media (hover: hover) {
  .privacy-footer a:hover { color: var(--color-blue); }
}

.privacy-back {
  margin-top: var(--space-6);
}

.privacy-back .btn--secondary {
  color: var(--color-ink);
  border: 1px solid var(--color-border-strong);
  padding: 12px 22px;
  border-radius: var(--radius-sm);
  display: inline-flex;
  transition: border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}

@media (hover: hover) {
  .privacy-back .btn--secondary:hover {
    border-color: var(--color-cyan);
    color: var(--color-cyan);
    transform: translateY(-2px);
  }
}

/* Link a política de privacidad en formulario y footer */
.privacy-link {
  color: var(--color-cyan);
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color var(--dur-fast) var(--ease-out);
}

@media (hover: hover) {
  .privacy-link:hover { color: var(--color-blue); }
}

.privacy-consent {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin: var(--space-5) 0;
  padding: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.privacy-consent input[type="checkbox"] {
  width: 18px;
  height: 18px;
  margin-top: 2px;
  accent-color: var(--color-cyan);
  flex-shrink: 0;
}

.privacy-consent label {
  font-size: 0.9rem;
  line-height: var(--lh-normal);
  color: var(--color-ink-muted);
}

.privacy-consent label a {
  color: var(--color-cyan);
  text-decoration: underline;
}

.form-privacy-note {
  font-size: 0.875rem;
  line-height: var(--lh-normal);
  color: var(--color-ink-muted);
  margin-top: var(--space-4);
  text-align: center;
}

.form-privacy-note .privacy-link {
  color: var(--color-cyan);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* =============================================================
   BANNER DE CONSENTIMIENTO DE COOKIES (ADR-04)
============================================================= */
/*
 * Banner flotante compacto en desktop, barra inferior en mobile.
 * Por defecto muestra texto corto + dos botones + link "Personalizar".
 * Al personalizar se despliegan las categorías y el botón Guardar.
 */
.cookie-banner {
  position: fixed;
  left: var(--space-3);
  right: var(--space-3);
  bottom: var(--space-3);
  z-index: 9999;
  max-width: 420px;
  margin: 0 auto;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.55);
  padding: var(--space-4);
  font-size: 0.9rem;
}

@media (min-width: 520px) {
  .cookie-banner {
    left: auto;
    right: var(--space-5);
    bottom: var(--space-5);
    margin: 0;
  }
}

.cookie-banner__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.cookie-banner__title {
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
  margin: 0;
}

.cookie-banner__text {
  font-size: 0.85rem;
  line-height: var(--lh-normal);
  color: var(--color-ink-muted);
  margin: 0 0 var(--space-2) 0;
}

.cookie-banner__link {
  font-size: 0.8rem;
  color: var(--color-cyan);
  text-decoration: underline;
  text-underline-offset: 3px;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out);
}

@media (hover: hover) {
  .cookie-banner__link:hover { color: #7dd3fc; }
}

.cookie-banner__options {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
}

.cookie-banner__options[hidden] {
  display: none;
}

.cookie-banner__option {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.85rem;
  color: var(--color-ink);
  cursor: pointer;
}

.cookie-banner__option input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--color-cyan);
  flex-shrink: 0;
}

.cookie-banner__option input[type="checkbox"]:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.cookie-banner__actions {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.cookie-banner__actions .btn {
  flex: 1 1 0;
  justify-content: center;
  padding: 10px 14px;
  font-size: 0.8rem;
}

.cookie-banner__actions .btn[hidden] {
  display: none;
}

/* Link de revocación de cookies en footer */
.cookie-preferences-link {
  color: var(--color-ink-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out);
}

@media (hover: hover) {
  .cookie-preferences-link:hover { color: var(--color-cyan); }
}
