/* ============================================
   LUNEXUS — Componentes compartidos
   ============================================ */

/* Antes llevaba una rayita (::before, 22px) delante del texto — pedido
   explícito 2026-08-13: quitarla, en todo el sitio (el eyebrow es un solo
   componente compartido, así que un cambio acá alcanza para las 11 páginas). */
.eyebrow {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-accent);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

/* ---------- Subrayado a mano ---------- */
/* Trazo dibujado a mano bajo una palabra clave — pedido explícito
   2026-08-11 ("que no se vea hecho con IA"), inspirado en Notion. Uso
   deliberadamente escaso: una palabra por vista como máximo, nunca una
   frase completa ni un uso repetido en cada sección — ver
   docs/DESIGN-SYSTEM.md, misma lógica de "menos elementos generan más
   jerarquía" que ya rige el resto del sitio. Se dibuja solo al entrar en
   pantalla (misma clase .is-revealed que ya usa scroll-reveal.js), no en
   loop ni al hover — es un acento tipográfico, no una animación decorativa. */
.hand-underline { position: relative; white-space: nowrap; }
.hand-underline svg {
  position: absolute;
  left: -2%;
  bottom: -0.1em;
  width: 104%;
  height: 0.3em;
  overflow: visible;
}
.hand-underline path {
  fill: none;
  stroke: var(--color-brand);
  stroke-width: 4;
  stroke-linecap: round;
  stroke-dasharray: 170;
  /* Visible por defecto — igual que el resto del contenido sin JS de
     scroll-reveal (ver assets/js/scroll-reveal.js): nunca se espera a que
     algo "aparezca" para poder leerlo. */
  stroke-dashoffset: 0;
}
/* Solo si scroll-reveal.js activó .js-reveal Y esta palabra vive dentro de
   una sección [data-reveal]: se dibuja recién cuando esa sección entra en
   pantalla, mismo mecanismo que el resto del sitio. */
.js-reveal [data-reveal] .hand-underline path {
  stroke-dashoffset: 170;
  transition: stroke-dashoffset var(--duration-slow) var(--ease-out) 150ms;
}
.js-reveal [data-reveal].is-revealed .hand-underline path {
  stroke-dashoffset: 0;
}

/* ---------- Ambient network background ---------- */
.network-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}
.network-bg svg { position: absolute; opacity: 0.14; }

/* ---------- LUX — compañero permanente ----------
   Ver docs/brand/LUX-GUIDELINES.md §11. Un único elemento, inyectado y
   controlado por completo por assets/js/lux-companion.js — nunca se mueve de
   posición entre secciones, solo cambia qué imagen muestra. z-index 40: por
   debajo del nav (50/60/100 en este archivo y en base.css), nunca por
   encima de la navegación.

   Pedido explícito 2026-08-11 (ver bitácora de LUX-GUIDELINES.md): deja de
   ser puramente decorativo — ahora es un link a WhatsApp (pointer-events:
   auto, ya no "none"), con reacción al hover. Sigue sin moverse nunca de
   posición: lo único nuevo es que ahora se le puede hacer click y que
   reacciona al cursor, no que aparezca en otro lugar.

   Estados (mutuamente excluyentes — "una acción a la vez", pedido explícito):
   .is-visible     controla la entrada (aparece "desde un costado" una vez,
                   al cargar la página) — después queda siempre visible.
   .is-breathing   respiración sutil (--lux-breathe, en el <img>) — SOLO en
                   reposo (idle); se retira en cualquier otro modo, incluido
                   el hover (ver assets/js/lux-companion.js).
   .is-mode-falling / .is-mode-climbing   escalan levemente la imagen
                   (transform en el <img>, nunca en el wrapper) — al volver a
                   reposo, la transición de vuelta a scale(1) es el
                   "aterrizaje suave" pedido, sin una animación aparte.
   .is-tilting     hover activo — el <img> gira en 3D siguiendo el cursor
                   (JS setea rotateX/rotateY inline, ver attachHoverTilt()).
   .is-bubble-visible   aviso "¿Hablamos?" visible — una vez sola al cargar
                   (automático) o mientras haya hover/foco. */
.lux-companion {
  position: fixed;
  right: var(--space-6);
  bottom: var(--space-6);
  z-index: 40;
  display: block;
  cursor: pointer;
  perspective: 700px;
  opacity: 0;
  transform: translateX(40px);
  transition: opacity var(--duration-slow) var(--ease-out), transform var(--duration-slow) var(--ease-out);
  will-change: opacity, transform;
}
.lux-companion.is-visible {
  opacity: 1;
  transform: translateX(0);
}
.lux-companion img {
  display: block;
  /* Alto fijo (no el ancho): cada pose tiene una proporción real distinta
     (ver components/Lux.php) — fijar el alto es lo que garantiza que todas
     se vean "del mismo tamaño" pedido, en vez de variar según la pose activa.
     ~151px ≈ 4cm a 96px/pulgada (referencia CSS estándar) — piso explícito,
     no se reduce en mobile (pedido explícito, difiere de la regla general
     de LUX-GUIDELINES.md §6 de reducir bajo 860px). */
  width: auto;
  height: 151px;
  transform: scale(1);
  transform-style: preserve-3d;
  transition: transform var(--duration-base) var(--ease-out);
}
.lux-companion.is-mode-falling img,
.lux-companion.is-mode-climbing img {
  transform: scale(1.05);
}
/* Mientras hay hover, assets/js/lux-companion.js escribe rotateX/rotateY
   inline en cada mousemove — este transition (más largo, con rebote) es lo
   que hace que el giro "persiga" al cursor en vez de saltar de golpe, y que
   vuelva a plano con el mismo rebote al salir. */
.lux-companion.is-tilting img {
  transition: transform 420ms var(--ease-spring);
}

.lux-bubble {
  position: absolute;
  right: calc(100% + var(--space-3));
  /* Antes 14px (altura de los pies) — pedido explícito 2026-08-11: a la
     altura de la mano en lux-senalando.webp (~60% de los 151px de alto del
     companion, medido sobre el arte), para que el dedo señale realmente
     hacia la burbuja y no hacia un punto vacío más abajo. */
  bottom: 78px;
  white-space: nowrap;
  background: var(--color-text-dark);
  color: var(--color-bg-light);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 14px;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-2);
  opacity: 0;
  transform: translateX(6px) scale(0.94);
  transition: opacity var(--duration-base) var(--ease-spring), transform var(--duration-base) var(--ease-spring);
}
.lux-bubble::after {
  content: '';
  position: absolute;
  right: -5px;
  bottom: 16px;
  width: 10px;
  height: 10px;
  background: var(--color-text-dark);
  transform: rotate(45deg);
}
.lux-companion.is-bubble-visible .lux-bubble,
.lux-companion:hover .lux-bubble,
.lux-companion:focus-visible .lux-bubble {
  opacity: 1;
  transform: translateX(0) scale(1);
}
@media (max-width: 860px) {
  .lux-bubble { font-size: 13px; }
}

/* Respiración — única animación en loop de todo el componente, y solo activa
   en reposo. Duración deliberadamente lenta (ambiental, no una transición de
   UI): no reutiliza --duration-fast/base/slow (esos son para cambios de
   estado puntuales, ver tokens.css), es su propio ritmo. */
@keyframes lux-breathe {
  0%, 100% { transform: translateY(0) scale(1); }
  50%      { transform: translateY(-3px) scale(1.02); }
}
.lux-companion.is-breathing img {
  animation: lux-breathe 3600ms var(--ease-in-out) infinite;
}

@media (max-width: 860px) {
  /* Solo se ajusta el margen a los bordes, nunca el tamaño (pedido
     explícito: "no más pequeño que eso" en ninguna página). */
  .lux-companion { right: var(--space-4); bottom: var(--space-4); }
}

/* ---------- Navbar ---------- */
header.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(10, 15, 12, 0.88);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--color-border);
}
.nav-inner {
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 18px 32px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.logo { display: flex; align-items: center; gap: 10px; }
.logo img { height: 30px; width: auto; }
.logo-word { font-family: var(--font-heading); font-weight: 700; font-size: 19px; color: var(--color-text); }
.logo-word .x { color: var(--color-brand); }
nav.links { display: flex; align-items: center; gap: 34px; }
nav.links a {
  font-size: 14.5px;
  font-weight: 500;
  color: var(--color-text-muted);
  transition: color var(--duration-fast) var(--ease-out);
}
nav.links a:hover, nav.links a.active { color: var(--color-text); }
/* Selector calificado "nav.links .nav-cta" a propósito (no ".nav-cta" solo):
   "nav.links a" (arriba) tiene más especificidad que una sola clase por sus
   2 selectores de elemento, y le ganaría el color de texto al botón —
   mismo problema que se detectó y corrigió en .nav-whatsapp. */
nav.links .nav-cta {
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--color-brand);
  color: var(--color-text-dark);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 14.5px;
  padding: 0 22px;
  border-radius: 12px;
  transition: background var(--duration-fast) var(--ease-out), transform var(--duration-base) var(--ease-out);
}
nav.links .nav-cta:hover { background: var(--color-brand-hover); color: var(--color-text); }
nav.links .nav-cta:active { transform: scale(0.98); }

/* Botón de WhatsApp del navbar — mismo alto que .nav-cta a propósito
   (ambos usan height:44px + box-sizing:border-box, heredado del reset
   global), para que se vean como un mismo grupo de acción.
   Selector calificado como "nav.links .nav-whatsapp" (no ".nav-whatsapp"
   solo) a propósito: "nav.links a" (arriba) también le pondría su color
   gris al ícono vía currentColor si no se le gana en especificidad. */
nav.links .nav-whatsapp {
  height: 44px;
  width: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: 12px;
  color: var(--color-accent);
  transition: background var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out), transform var(--duration-base) var(--ease-out);
}
.nav-whatsapp svg { width: 20px; height: 20px; }
nav.links .nav-whatsapp:hover { border-color: var(--color-accent); background: rgba(115, 166, 61, 0.12); }
nav.links .nav-whatsapp:active { transform: scale(0.98); }

/* Botón hamburguesa — no existe en los mockups originales (el menú móvil quedaba roto).
   Se agrega respetando el mismo lenguaje visual: radios, bordes y color del sistema. */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: 10px;
  cursor: pointer;
  position: relative;
  z-index: 60;
  transition: border-color var(--duration-fast) var(--ease-out), transform var(--duration-base) var(--ease-out);
}
.nav-toggle:active { transform: scale(0.95); }
.nav-toggle-bar,
.nav-toggle-bar::before,
.nav-toggle-bar::after {
  content: '';
  display: block;
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: var(--color-text);
  transition: transform var(--duration-base) var(--ease-in-out), opacity var(--duration-fast) var(--ease-out), background var(--duration-fast) var(--ease-out);
}
.nav-toggle-bar::before { position: absolute; transform: translateY(-6px); }
.nav-toggle-bar::after { position: absolute; transform: translateY(6px); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar::before { transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar::after { transform: rotate(-45deg); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 15.5px;
  padding: var(--space-4) var(--space-6);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  cursor: pointer;
  /* Propiedades explícitas en vez de "all": color/fondo cambian rápido,
     el press (transform) es un poco más lento — ver docs/DESIGN-SYSTEM.md §2.6.
     ease-spring (no ease-out) en transform: es el botón "magnético" de
     assets/js/interactions.js (data-magnetic en .btn-primary/.btn-light) —
     pedido explícito de movimiento más fluido, 2026-08-11. */
  transition: background var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out), box-shadow var(--duration-base) var(--ease-out), transform 260ms var(--ease-spring);
}
.btn:active { transform: scale(0.98); }
.btn-primary { background: var(--color-brand); color: var(--color-text-dark); }
.btn-primary:hover { background: var(--color-brand-hover); box-shadow: var(--shadow-highlight); }
.btn-secondary { background: transparent; border-color: var(--color-border); color: var(--color-text); }
.btn-secondary:hover { border-color: var(--color-accent); color: var(--color-accent); }
.btn-light { background: var(--color-text-dark); color: var(--color-bg-light); }
/* Hallazgo de Fase 4: era la única variante de .btn sin :hover — existía
   la transición de color en la clase base, pero nunca un estado de
   llegada (mismo tipo de bug que H10 en Fase 1). Se resuelve hacia
   --color-brand-hover, no hacia un gris nuevo: todo botón sólido del
   sitio "entra" en la familia del verde de marca al pasar el mouse,
   sea cual sea su color de reposo — es el mismo lenguaje que ya usa
   .btn-primary, no uno inventado para esta variante. */
.btn-light:hover { background: var(--color-brand-hover); color: var(--color-text); }

/* ---------- Cards ---------- */
.card {
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  position: relative;
}
/* Brillo ambiental que sigue el cursor — pedido explícito 2026-08-11
   ("muy dinámico"). Deliberadamente separado de --shadow-2/elevación: ese
   token sigue reservado a tarjetas que son un link completo (plan-card,
   case-card — ver docs/DESIGN-SYSTEM.md §2.5, "la mayoría del sitio se
   mantiene plano a propósito"). Esto es solo luz ambiental, no una señal de
   "esto es clicable" — por eso se puede aplicar a tarjetas informativas
   (.card) y a .flow-card sin contradecir esa regla. --spot-x/--spot-y los
   escribe assets/js/interactions.js en mousemove; sin JS o con
   reduced-motion, quedan en 50%/50% y el glow simplemente no se activa
   (nunca hay listener, ver interactions.js). */
.card::before,
.flow-card::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  opacity: 0;
  background: radial-gradient(260px circle at var(--spot-x, 50%) var(--spot-y, 50%), rgba(145, 185, 103, 0.14), transparent 70%);
  transition: opacity var(--duration-base) var(--ease-out);
  pointer-events: none;
}
.card:hover::before,
.flow-card:hover::before { opacity: 1; }
.icon-box {
  width: 48px;
  height: 48px;
  border-radius: var(--radius-md);
  background: rgba(115, 166, 61, 0.12);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-accent);
  margin-bottom: var(--space-5);
}
.icon-box svg { width: 24px; height: 24px; }
.section-light .icon-box { background: rgba(115, 166, 61, 0.1); }
/* título → párrafo dentro de una card: mismo valor (--space-4) en todo el
   sitio — ver también .plan-card p, .comparison-card p, .step-row p. Antes
   eran 4 valores distintos (8/10/10/12px) para el mismo rol. */
.card .card-description { color: var(--color-text-muted); margin-top: var(--space-4); font-size: 15px; }
.section-light .card-description { color: var(--color-text-dark-mut); }
.card.is-on-white { background: #fff; border-color: #E4E8E2; }

/* ---------- Footer ---------- */
footer {
  background: var(--color-bg-elevated);
  border-top: 1px solid var(--color-border);
  padding: var(--space-16) 0 var(--space-8);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: var(--space-10);
  padding-bottom: var(--space-10);
}
.footer-grid h4 { font-size: 14px; color: var(--color-text); margin-bottom: var(--space-4); }
.footer-grid a, .footer-grid p { color: var(--color-text-muted); font-size: 14.5px; display: block; margin-bottom: var(--space-3); }
.footer-grid a { transition: color var(--duration-fast) var(--ease-out); }
.footer-grid a:hover { color: var(--color-accent); }
.footer-bottom {
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-6);
  display: flex;
  justify-content: space-between;
  font-size: 13.5px;
  color: var(--color-text-muted);
}

/* ---------- Tag / pill ---------- */
.tag {
  display: inline-block;
  font-family: var(--font-heading);
  font-size: 12.5px;
  font-weight: 600;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  background: rgba(145, 185, 103, 0.12);
  color: var(--color-accent-soft);
  letter-spacing: 0.03em;
}

/* ---------- Tag sobre fondo claro (section-light) ---------- */
.tag-on-light { background: rgba(115, 166, 61, 0.12); color: #3A6B1F; }

/* ---------- CTA de cierre de sección (componente CtaSection) ---------- */
.cta-section { text-align: center; }
.cta-section p { margin-top: var(--space-5); color: var(--color-text-muted); }
.section-light.cta-section p { color: var(--color-text-dark-mut); }
/* CTA único después de texto: mismo valor en todo el sitio — ver también
   .page-hero .btn, .servicios-selector-panel .btn. Antes eran 26/28px sueltos. */
.cta-section .btn { margin-top: var(--space-6); }

/* Modificadores opcionales — cada mockup usa una combinación distinta,
   no son el default porque la mayoría de las páginas usan el párrafo simple. */
.cta-section.has-emphasis p { font-size: 18px; }
.cta-section.is-narrow p {
  max-width: var(--cta-narrow, 520px);
  margin-left: auto;
  margin-right: auto;
}

/* ---------- CTA con LUX a la izquierda (opción 'lux') ----------
   Pedido explícito 2026-08-12, exclusivo del CTA final de servicios.php.
   Deja de estar centrado: LUX en su propia columna, el texto se alinea a
   la izquierda (heredado de text-align, sin reglas nuevas por elemento). */
.cta-section.has-lux { text-align: left; }
.cta-section-grid {
  display: flex;
  align-items: center;
  gap: var(--space-10);
}
.cta-section-lux { flex: none; }
.cta-section-lux img { display: block; }
.cta-section-content { flex: 1 1 auto; }

@media (max-width: 860px) {
  .cta-section-grid { flex-direction: column; text-align: center; }
  .cta-section.has-lux { text-align: center; }
  .cta-section-lux img { margin: 0 auto; }
}

/* ---------- Lista de features con check ----------
   Antes parte del componente ServiceRow (fila "zigzag" texto+card, 3
   instancias en servicios.php). Ese layout se reemplazó el 2026-08-12 por
   el selector lista+tarjeta que gira (ver .servicios-selector-* más abajo)
   — components/ServiceRow.php se eliminó. Esta lista de features sigue
   viva porque el panel nuevo la reutiliza tal cual, mismo nombre de clase
   para no duplicar la regla. */
.service-row-features { margin-top: var(--space-6); display: flex; flex-direction: column; gap: var(--space-3); }
.service-row-features li { display: flex; gap: var(--space-2); align-items: flex-start; }
.service-row-features .check-mark { color: var(--color-accent); }

/* ---------- Hero de página interna (componente PageHero) ---------- */
.page-hero { padding-top: var(--space-20); padding-bottom: var(--space-16); }
.page-hero h1 { margin-top: var(--space-4); }
.page-hero h1.is-reduced { font-size: clamp(2.2rem, 4vw, 3.4rem); }
.page-hero-lead { margin-top: var(--space-5); font-size: 18px; line-height: 1.6; color: var(--color-text-muted); max-width: 560px; }
.page-hero .btn { margin-top: var(--space-6); }
.page-hero-back { font-size: 14px; color: var(--color-text-muted); }
.page-hero.has-back-link .eyebrow { margin-top: var(--space-5); }

/* ---------- Card de plan, clicable (componente PlanCard — hub de Soporte) ---------- */
.plan-card {
  display: block;
  /* perspective + rotateX/rotateY: giro 3D que sigue el cursor, pedido
     explícito 2026-08-11 ("más 3D, movimientos más fluidos") — solo en las
     tarjetas que ya eran un link completo (ver nota debajo de
     .plan-card:hover), nunca en las informativas. --tilt-x/--tilt-y los
     escribe assets/js/interactions.js; sin JS quedan en 0deg. */
  transform: perspective(1000px) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
  transition: border-color var(--duration-fast) var(--ease-out), transform 380ms var(--ease-spring), box-shadow var(--duration-base) var(--ease-out);
}
/* Hover/active ANTES de .is-highlighted a propósito: misma especificidad
   (dos clases cada uno), así que el orden en el archivo decide — el plan
   destacado debe conservar su borde de marca al pasar el mouse, no
   cambiar al verde de énfasis como los demás. Corrige el hallazgo H10
   (la transición existía, pero nunca tenía un color de destino). */
/* Elevación en hover: .plan-card es la tarjeta entera actuando como link
   (toda la superficie es clicable) — es de las dos únicas "tarjetas"
   genuinamente interactivas del sitio, junto a .case-card.is-published.
   Por eso es la que recibe la señal de "esto va a hacer algo". Las demás
   tarjetas (feature, misión, módulo, comparación) son informativas y se
   mantienen planas — ver docs/DESIGN-SYSTEM.md §2.5. */
.plan-card:hover, .plan-card:focus-visible {
  border-color: var(--color-accent);
  transform: perspective(1000px) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg)) translateY(-4px);
  box-shadow: var(--shadow-2);
}
/* El press "aplana" la elevación de vuelta (en vez de sumarse a ella) —
   se siente como si la tarjeta se hundiera al presionarla, no como si
   flotara más alto. */
.plan-card:active { transform: perspective(1000px) translateY(0) scale(0.98); }
.plan-card p { margin-top: var(--space-4); color: var(--color-text-muted); font-size: 14.5px; }
.plan-card-price-label { margin-top: var(--space-6); font-size: 14px; color: var(--color-text-muted); }
.plan-card-price { margin-top: var(--space-1); display: flex; align-items: baseline; gap: var(--space-2); }
.plan-card-amount { font-family: var(--font-heading); font-weight: 800; font-size: 32px; }
.plan-card-period { color: var(--color-text-muted); font-size: 14px; }
/* CTA dentro de una card: mismo valor que .module-card .btn — antes 22px en
   ambas, ahora tokenizado a --space-6 (24px). */
.plan-card-cta { margin-top: var(--space-6); width: 100%; justify-content: center; }
/* El plan destacado es "más importante" de forma permanente, no solo al
   interactuar con él — por eso lleva un halo de marca en reposo (no un
   estado de hover). Reutiliza la misma lógica de resplandor sutil del
   hero de Home (.orbit-core), no inventa un lenguaje visual nuevo. */
.plan-card.is-highlighted { border-color: var(--color-brand); position: relative; box-shadow: var(--shadow-highlight); }
/* No es el espacio "título → párrafo" del resto del sitio — es el despeje
   necesario para que el h3 no choque con el tag "Más elegido" (posición
   absoluta, ver .plan-card-tag). Antes era 6px aquí y 14px en la variante
   equivalente de .module-card, para el mismo problema — se unifican ambas
   en el mismo valor porque no había ninguna razón real para que difirieran. */
.plan-card.is-highlighted h3 { margin-top: var(--space-3); }
/* Al hacer hover sobre el destacado, la retroalimentación de interacción
   reemplaza temporalmente el halo — el usuario necesita saber "esto es
   clicable" más de lo que necesita seguir viendo "esta es la opción
   recomendada" en ese instante. */
.plan-card.is-highlighted:hover, .plan-card.is-highlighted:focus-visible { box-shadow: var(--shadow-2); }
/* top:-14px es un offset de posición (cuánto asoma el badge sobre el borde
   de la card), no una separación de la escala de espaciado — se deja como
   valor propio a propósito. left sí es espaciado real (respiro desde el
   borde izquierdo) y usa el token. */
.plan-card-tag { position: absolute; top: -14px; left: var(--space-8); }

/* ---------- Card de módulo (componente ModuleCard — detalle de plan) ---------- */
.module-card-price { margin-top: var(--space-4); display: flex; align-items: baseline; gap: var(--space-2); }
.module-card-amount { font-family: var(--font-heading); font-weight: 800; font-size: 36px; }
.module-card-period { color: var(--color-text-muted); }
.module-card p { margin-top: var(--space-4); color: var(--color-text-muted); font-size: 15px; }
.module-card .btn { margin-top: var(--space-6); width: 100%; justify-content: center; }
/* Mismo halo que .plan-card.is-highlighted, pero sin estado de hover:
   .module-card no es un link (solo su botón interno lo es), así que la
   tarjeta en sí no debe reaccionar a nada — Filosofía de Diseño #6. */
.module-card.is-highlighted { border-color: var(--color-brand); position: relative; box-shadow: var(--shadow-highlight); }
/* Mismo despeje que .plan-card.is-highlighted h3, misma razón (tag "Más
   elegido" con posición absoluta) — ver el comentario ahí. */
.module-card.is-highlighted h3 { margin-top: var(--space-3); }
.module-card-tag { position: absolute; top: -14px; left: var(--space-8); }

/* Variante compacta: usada cuando el plan tiene 3 módulos en vez de 2
   (soporte-premium.php), con una escala tipográfica ligeramente menor.
   Deliberadamente un paso por debajo de los valores generales de arriba —
   no es descuido, es la misma proporción a una escala más chica. */
.module-card.is-compact .module-card-price { margin-top: var(--space-3); }
.module-card.is-compact .module-card-amount { font-size: 32px; }
.module-card.is-compact .module-card-period { font-size: 14px; }
.module-card.is-compact p { margin-top: var(--space-3); font-size: 15px; }
.module-card.is-compact .btn { margin-top: var(--space-5); }

/* ---------- Card de caso (componente CaseCard) ---------- */
.case-card-title { margin-top: var(--space-4); }
.case-card.is-published {
  display: block;
  /* Mismo giro 3D que .plan-card y por la misma razón — ver esa nota. */
  transform: perspective(1000px) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
  transition: border-color var(--duration-fast) var(--ease-out), transform 380ms var(--ease-spring), box-shadow var(--duration-base) var(--ease-out);
}
/* Mismo criterio que .plan-card: es la tarjeta entera actuando como link,
   una de las dos únicas tarjetas interactivas del sitio — recibe la
   misma elevación en hover por la misma razón. */
.case-card.is-published:hover, .case-card.is-published:focus-visible {
  border-color: var(--color-accent);
  transform: perspective(1000px) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg)) translateY(-4px);
  box-shadow: var(--shadow-2);
}
.case-card.is-published:active { transform: perspective(1000px) translateY(0) scale(0.98); }

/* ---------- Responsive: navbar y footer ---------- */
@media (max-width: 860px) {
  .nav-toggle { display: flex; }

  nav.links {
    display: none;
    position: fixed;
    top: 67px;
    left: 0;
    right: 0;
    bottom: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    background: var(--color-bg);
    border-top: 1px solid var(--color-border);
    padding: 8px 32px 32px;
    overflow-y: auto;
  }
  nav.links.is-open { display: flex; }
  nav.links a {
    width: 100%;
    padding: 16px 0;
    border-bottom: 1px solid var(--color-border);
    font-size: 16px;
  }
  /* nav.links a (arriba) le pone padding/border-bottom a TODOS sus <a>
     hijos, incluyendo estos dos botones — se anulan explícitamente aquí
     porque tienen su propio look (no son links de texto en lista). */
  nav.links .nav-cta,
  nav.links .nav-whatsapp {
    width: 100%;
    padding-left: 0;
    padding-right: 0;
    border-bottom: none;
    justify-content: center;
  }
  nav.links .nav-cta {
    margin-top: 20px;
    text-align: center;
  }
  nav.links .nav-whatsapp { margin-top: 12px; }

  .footer-grid { padding-bottom: var(--space-6); }
  .footer-bottom { flex-direction: column; gap: var(--space-2); }
}
