/* ============================================================================
   TUXANI — Landing pública (Fase 0). Oscuro premium "agro cósmico".
   Depende de tokens.css.
   ========================================================================== */

body { overflow-x: hidden; }
.nv-wrap { max-width: 1180px; margin: 0 auto; padding: 0 20px; }
.nv-kicker { font-family: var(--nv-f-mono); font-size: 11px; text-transform: uppercase;
  letter-spacing: .24em; color: var(--nv-savia); }
.nv-tenue { color: var(--nv-tenue); }
.nv-grad-text { background: var(--nv-grad); -webkit-background-clip: text; background-clip: text; color: transparent; }

/* ---- Nav ---- */
.nv-top { position: sticky; top: 0; z-index: 50; display: flex; align-items: center; gap: 14px;
  padding: 12px 20px; background: color-mix(in srgb, var(--nv-abismo) 78%, transparent);
  backdrop-filter: blur(14px); border-bottom: 1px solid var(--nv-linea); }
.nv-brand { display: flex; align-items: center; gap: 11px; margin-right: auto; }
.nv-brand canvas { width: 38px; height: 38px; filter: drop-shadow(0 0 12px rgba(47,169,140,.4)); }
.nv-brand b { font-family: var(--nv-f-display); font-weight: 800; font-size: 18px; letter-spacing: -.01em; }
.nv-navlinks { display: flex; gap: 6px; align-items: center; }
/* 14px de relleno vertical (preflight M-4): esta regla es `.nv-navlinks a`
   (0,1,1) y ganaba a `.nv-btn` (0,1,0), asi que el CTA «Entrar» se quedaba en
   33px de alto por mucho que se subiera `.nv-btn`. Medido en el navegador. */
.nv-navlinks a { font: 600 13.5px/1 var(--nv-f-body); color: var(--nv-tenue); text-decoration: none;
  padding: 14px 13px; border-radius: var(--nv-r-pill); transition: var(--nv-dur-fast);
  display: inline-flex; align-items: center; min-height: 44px; }
.nv-navlinks a:hover { color: var(--nv-texto); background: color-mix(in srgb, var(--nv-savia) 12%, transparent); }
/* preflight P09 N-1 (2a ronda, 2026-09-04): mismo choque de especificidad que
   el de arriba, pero de COLOR, no de alto, y mucho peor: `.nv-navlinks a`
   (0,1,1) le pinta `--nv-tenue` (gris apagado) al CTA «Entrar», que además es
   `.nv-btn-primary` (0,1,0) con fondo `--nv-savia`. Contraste medido en
   navegador: 1,10:1 en claro, 1,65:1 en oscuro -- el botón principal de la
   portada, casi invisible en los dos temas. `A-1` (quitar el tema forzado) no
   lo causó: en oscuro ya fallaba antes; lo que hizo fue volver alcanzable la
   variante clara, que estaba igual de rota y nadie podía ver. */
.nv-navlinks a.nv-btn-primary { color: var(--nv-sobre-savia); }
/* preflight P09 N-1, arreglo del `:hover` que el commit anterior dejó a
   medias (encontrado por P13, el escéptico, midiendo en Chrome real): al
   pasar el ratón, `.nv-navlinks a:hover` (0,2,1) le gana en FONDO a
   `.nv-btn-primary:hover` (0,2,0) -- el sólido `--nv-savia-hi` se sustituye
   por un lavado casi transparente, y el texto `--nv-sobre-savia` (pensado
   para ir sobre el sólido) queda casi invisible sobre ese lavado en los DOS
   temas. Este selector junta fondo y color en una sola regla con
   especificidad más alta (0,3,1) que cualquiera de las otras dos, así que
   gana sin importar el orden en el archivo. Contraste verificado:
   12,36:1 en oscuro, 8,16:1 en claro. */
.nv-navlinks a.nv-btn-primary:hover { background: var(--nv-savia-hi); color: var(--nv-sobre-savia); }
@media (max-width: 720px) { .nv-navlinks .nv-hide-sm { display: none; } }
/* A 320px la portada se desbordaba 5px (preflight M-3): `.nv-top` con 20px de
   relleno a cada lado deja 280 de caja, y `.nv-navlinks` necesita 181 empezando
   en x=143 — el CTA «Entrar» terminaba en 324 y quedaba mordido por el borde.
   Con 10px de relleno la caja pasa a 300 y cabe. A 375 y por encima no ocurría,
   por eso el corte va en 400. */
@media (max-width: 400px) {
  .nv-top { padding: 12px 10px; gap: 8px; }
  .nv-navlinks { gap: 4px; }
}

/* 15px de relleno vertical (preflight M-4): con la fuente de 14px el botón
   llega a 44px de alto. Medía 33 — el CTA «Entrar» incluido. */
.nv-btn { font: 700 14px/1 var(--nv-f-body); border-radius: var(--nv-r-md); padding: 15px 20px;
  cursor: pointer; border: 1px solid transparent; transition: var(--nv-dur-fast); text-decoration: none;
  display: inline-flex; align-items: center; gap: 8px; }
.nv-btn-cosecha { background: var(--nv-grad); color: #04140E; box-shadow: 0 10px 30px rgba(47,169,140,.3); }
.nv-btn-cosecha:hover { transform: translateY(-1px); box-shadow: 0 14px 38px rgba(47,169,140,.42); }
.nv-btn-primary { background: var(--nv-savia); color: var(--nv-sobre-savia); }
.nv-btn-primary:hover { background: var(--nv-savia-hi); }
.nv-btn-ghost { background: transparent; border-color: var(--nv-linea-fuerte); color: var(--nv-texto); }
.nv-btn-ghost:hover { background: color-mix(in srgb, var(--nv-savia) 12%, transparent); }

/* ---- Hero ---- */
.nv-hero { position: relative; overflow: hidden; text-align: center; padding: 60px 20px 40px; }
#nv-cosmos { position: absolute; inset: 0; z-index: 0; }
.nv-veil { position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(1000px 520px at 50% 6%, rgba(47,169,140,.16), transparent 70%),
    linear-gradient(180deg, transparent 62%, var(--nv-abismo)); }
.nv-hero-in { position: relative; z-index: 2; max-width: 860px; margin: 0 auto; }
.nv-hero canvas.nv-planet { width: 264px; height: 264px; margin: 4px auto 8px; display: block; }
.nv-display { font-size: clamp(38px, 7vw, 74px); line-height: 1.02; margin: 8px 0 16px; }
.nv-lede { font-size: clamp(15px, 2.3vw, 20px); color: var(--nv-tenue); max-width: 620px; margin: 0 auto 28px; }
.nv-cta-row { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.nv-meta { display: flex; gap: 26px; justify-content: center; flex-wrap: wrap; margin-top: 34px;
  font-family: var(--nv-f-mono); font-size: 11.5px; letter-spacing: .06em; color: var(--nv-tenue); }
.nv-meta b { color: var(--nv-texto); }

/* ---- Secciones ---- */
/* `padding: 56px 0` anulaba el `0 20px` de `.nv-wrap` (misma especificidad,
   gana el que va después en la hoja) en TODA sección con las dos clases —
   hero, relief, honestidad y la nueva de puertas. Medido a 375px el 2026-08-25
   armando la sección de puertas: el contenido pegaba contra el borde de la
   pantalla en todo el sitio, no solo ahí. Se restaura el lateral sin tocar el
   vertical. */
.nv-block { padding: 56px 20px; }
.nv-h2 { font-size: clamp(24px, 4vw, 38px); margin-bottom: 10px; }
.nv-sub { color: var(--nv-tenue); font-size: 15px; max-width: 680px; margin-bottom: 28px; }
.nv-grid { display: grid; gap: 16px; }
.nv-g3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 820px) { .nv-g3 { grid-template-columns: 1fr; } }
.nv-card { background: var(--nv-superficie); border: 1px solid var(--nv-linea);
  border-radius: var(--nv-r-md); padding: 20px; box-shadow: var(--nv-sh-1); }
.nv-card h4 { font-size: 16px; margin-bottom: 8px; display: flex; align-items: center; gap: 9px; }
.nv-card p { font-size: 13.5px; color: var(--nv-tenue); margin: 0; }
/* Las tarjetas de "Los 4 módulos principales" (2026-09-09) son <a> de
   verdad, no <div role="button">: sin esto el navegador les pone
   subrayado azul de link por defecto en todo el texto de adentro. */
a.nv-card { display: block; color: inherit; text-decoration: none; }
/* `.nv-dot`, `.nv-bento` y `.nv-feat` vivían aquí y se fueron con el muro de 12
   tarjetas que reemplazaron las 13 puertas (2026-08-25). Eran del bento y de
   nadie más —comprobado en todo `web/` y `web-publico/`—, así que quedarse
   habría dejado reglas que no pinta nadie. `.nv-card` SÍ se queda: la usan las
   6 tarjetas de "Lo que te quita de encima". */

/* ---- Pasos ---- */
/* CORREGIDO 2026-09-09: el selector decía `h4`, pero el HTML real
   (index.html) usa `<h3>` para el número de paso — el margen nunca
   aplicaba y "01" quedaba pegado al texto ("01Habla con la IA"). */
.nv-step h3 .nv-n { font-family: var(--nv-f-mono); color: var(--nv-savia); margin-right: 6px; }

/* ---- Precios ---- */
.nv-price-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
@media (max-width: 720px) { .nv-price-grid { grid-template-columns: 1fr; } }
.nv-price .nv-amt { font-family: var(--nv-f-mono); font-size: 30px; font-weight: 700; margin: 6px 0; }
.nv-price .nv-amt small { font-size: 13px; color: var(--nv-tenue); font-weight: 400; }
/* Referencia en USD bajo el precio en COP (2026-09-09) — chica, muda, nunca
   compite con el número principal: el cobro real sigue siendo en USD, esto
   es solo contexto de poder de compra. */
.nv-price .nv-price-usd { font-size: 12.5px; color: var(--nv-tenue); margin: 0 0 10px; }
.nv-price.nv-hl { border-color: var(--nv-linea-fuerte);
  background: linear-gradient(180deg, color-mix(in srgb, var(--nv-cosecha) 9%, var(--nv-superficie)), var(--nv-superficie)); }
.nv-price ul { list-style: none; padding: 0; margin: 12px 0 0; }
.nv-price li { font-size: 13px; color: var(--nv-tenue); padding: 5px 0 5px 20px; position: relative; }
.nv-price li::before { content: "✓"; position: absolute; left: 0; color: var(--nv-savia); }

/* ---- Footer ---- */
.nv-foot { border-top: 1px solid var(--nv-linea); margin-top: 30px; padding: 30px 20px;
  color: var(--nv-tenue); font-size: 12.5px; }
.nv-foot .nv-wrap { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 14px; align-items: center; }
.nv-reveal { opacity: 0; transform: translateY(14px); transition: opacity .6s var(--nv-ease), transform .6s var(--nv-ease); }
.nv-reveal.nv-in { opacity: 1; transform: none; }

/* ---- Tarjetas de módulo clicables + modal / hoja de todos los módulos ----
   Sin ilustración ni video propios todavía (docs/PENDIENTES_HILO_NUEVO.md §3):
   solo icono real (NVIcon) + texto real (m.<id> / m.<id>.d), nada inventado. */
.nv-mod-card { cursor: pointer; transition: transform var(--nv-dur) var(--nv-ease), border-color var(--nv-dur) var(--nv-ease); }
.nv-mod-card:hover, .nv-mod-card:focus-visible { transform: translateY(-3px); border-color: var(--nv-linea-fuerte); }
.nv-mod-more { color: var(--nv-savia); text-decoration: underline; text-underline-offset: 3px; }
.nv-mod-more:hover, .nv-mod-more:focus-visible { color: var(--nv-savia-hi); }

/* ---- Las 13 puertas (rediseño de menú, 2026-08-25) ------------------------
   Cada tarjeta lleva su color en `--nv-p` (lo pone mod-sheet.js desde la tabla
   PUERTAS). El color pinta el ICONO y una banda superior; NUNCA texto de
   lectura: varios de los trece tonos (#748F1E, #B98A1E, #D2860F) no llegan a
   4,5:1 sobre blanco, así que el título va en --nv-texto y el subtítulo en
   --nv-tenue, que sí cumplen en los dos temas.

   ⚠️ La tarjeta es un <button>, y un <button> NO hereda ni el color ni la
   fuente del documento: sin `color: var(--nv-texto)` y `font: inherit`
   explícitos sale con el gris de sistema del navegador —negro sobre fondo
   noche en tema oscuro—, que es el mismo bug de contraste que ya se cazó en la
   Fase 1 dentro de la app. */
.nv-puertas { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
@media (max-width: 940px) { .nv-puertas { grid-template-columns: repeat(3, 1fr); } }
/* Dos columnas se aguantan hasta 360 px, y eso es a propósito: en una sola,
   trece tarjetas con ícono, título, subtítulo y chips son un scroll larguísimo
   —la lista larga de la que veníamos huyendo—. Debajo de 360 px el título de
   la puerta más larga («¿Qué Puedo Hacer en mi Terreno?») ya no cabe en dos
   renglones, así que ahí sí se pasa a una. */
@media (max-width: 720px) { .nv-puertas { grid-template-columns: repeat(2, 1fr); gap: 10px; } }
@media (max-width: 720px) { .nv-puerta { padding: 14px 12px 13px; }
  .nv-puerta-ic { width: 44px; height: 44px; border-radius: 12px; }
  .nv-puerta-ic svg { width: 26px; height: 26px; } }
@media (max-width: 360px) { .nv-puertas { grid-template-columns: 1fr; } }

.nv-puerta { position: relative; overflow: hidden; display: flex; flex-direction: column; gap: 7px;
  padding: 18px 16px 16px; text-align: left; cursor: pointer;
  background: var(--nv-superficie); border: 1px solid var(--nv-linea); border-radius: var(--nv-r-lg);
  color: var(--nv-texto); font: inherit;
  transition: transform var(--nv-dur) var(--nv-ease), border-color var(--nv-dur) var(--nv-ease),
              box-shadow var(--nv-dur) var(--nv-ease); }
/* La banda de color: es lo que hace que trece tarjetas se lean como trece
   puertas distintas y no como trece cajas iguales. Se enciende al pasar. */
/* 🔴 SUBIDA EL 2026-09-07: de 3px al 55 % a 6px a plena opacidad.
   El comentario de arriba decía que esta banda «es lo que hace que trece
   tarjetas se lean como trece puertas distintas»… y estaba puesta al 55 % de
   opacidad sobre 3 píxeles, o sea que en reposo no se veía y solo aparecía al
   pasar el ratón — que en un teléfono no pasa NUNCA. Medido el mismo día: el
   95 % del texto de esta página era blanco o gris.
   Es el sitio donde el color puede ir fuerte sin riesgo: no lleva texto ni
   ícono encima, así que no hay contraste que romper. El chip del ícono NO se
   toca por lo contrario — ver el bloque de `.nv-puerta-ic` justo abajo. */
.nv-puerta::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 6px;
  background: var(--nv-p, var(--nv-savia)); transition: opacity var(--nv-dur-fast); }
.nv-puerta:hover, .nv-puerta:focus-visible { transform: translateY(-3px);
  border-color: color-mix(in srgb, var(--nv-p, var(--nv-savia)) 55%, var(--nv-linea));
  box-shadow: 0 14px 34px rgba(0, 0, 0, .28); }
.nv-puerta:hover::before, .nv-puerta:focus-visible::before { opacity: 1; }

/* TINTE, NO COLOR PLANO — misma solución que la Fase 1 en `.nv-h6-ic` de la
   app, y por partida doble aquí:
   (a) con trece tonos, dos de ellos claros, un chip a plena saturación pediría
       un ícono blanco y dejaría dos puertas casi invisibles;
   (b) los dibujos de ESTE `icons.js` (el de la landing) no usan `currentColor`:
       llevan el gradiente de marca cosido al `stroke`. O sea que `color` sobre
       el ícono NO lo tiñe, y sin el chip las trece tarjetas saldrían con el
       mismo dibujo verde — justo lo que este rediseño viene a quitar. El color
       de la puerta lo lleva el CHIP, que sí es nuestro. `icons.js` no se toca
       desde aquí: es de otro dueño y lo usan el resto de secciones. */
/* 🔴 CORREGIDO EL 2026-09-08: EL CHIP PASA DE TINTE A COLOR PLENO.
   El comentario de aquí arriba decía que este `icons.js` no podía teñirse
   porque lleva el degradado de marca cosido al `stroke`. ESO YA NO ES CIERTO:
   `assets/js/icons.js:421` tiene modo `mono` desde hace tiempo y cambia
   `url(#nvIG)`/`url(#nvIA)` por `currentColor`. El comentario envejeció mal y
   nadie volvió a mirar.

   Y el tinte del 14 % NO ERA INOCUO, estaba roto: medido el contraste del peor
   color del ícono (el lima #B7CC00 del degradado) sobre el peor de los trece
   chips, en TEMA CLARO, daba 1,46:1 — con 3:1 de mínimo para un gráfico. O sea
   que en el landing en claro había íconos que casi no se veían. Y subir el
   tinte lo empeoraba (30 % -> 1,14).

   La solución es la misma que ya se aplicó en la app: chip a COLOR PLENO con
   el ícono en tinta oscura (`--nv-sobre-puerta`). Con la paleta nueva el peor
   caso de los trece es 4,30:1 sobre el tono plano. `mod-sheet.js` pide el
   ícono en modo `mono` para que obedezca a `color`. Las dos piezas hacen falta:
   chip pleno con ícono degradado sería un borrón, y modo mono sobre el tinte
   del 14 % sería un ícono oscuro sobre un lavado — invisible. */
.nv-puerta-ic { width: 52px; height: 52px; flex-shrink: 0; display: grid; place-items: center;
  margin-bottom: 3px; border-radius: 14px;
  background: var(--nv-p, var(--nv-savia));
  border: 1px solid color-mix(in srgb, var(--nv-p, var(--nv-savia)) 78%, #000000);
  color: var(--nv-sobre-puerta, #0B140F); }
.nv-puerta-ic svg { display: block; }
.nv-puerta-t { font-family: var(--nv-f-display); font-size: 15px; line-height: 1.25; color: var(--nv-texto); }
.nv-puerta-sub { font-size: 12.5px; line-height: 1.45; color: var(--nv-tenue); }
.nv-puerta-chips { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 5px; }
.nv-puerta-chip { font-family: var(--nv-f-mono); font-size: 10px; line-height: 1.4; color: var(--nv-tenue);
  border: 1px solid var(--nv-linea); background: var(--nv-suelo); padding: 3px 8px; border-radius: 999px; }
.nv-puerta-chip-mas { border-style: dashed; }

/* ---- Módulos de ejemplo dentro del modal de una puerta ---- */
.nv-modal-mods:empty { display: none; }
.nv-modal-mods { display: grid; gap: 8px; margin-bottom: 22px; text-align: left; }
.nv-modal-mas { font-family: var(--nv-f-mono); font-size: 11px; color: var(--nv-tenue); margin: 2px 0 0; text-align: center; }
/* Mismo chip tintado de la tarjeta, para que se reconozca la puerta que se
   acaba de abrir. Solo en `.nv-modal-puerta`: la ficha de un módulo suelto se
   queda con su ícono a pelo y su halo verde, exactamente como estaba. */
.nv-modal-puerta .nv-modal-ic { width: 96px; height: 96px; display: grid; place-items: center;
  border-radius: 24px;
  background: color-mix(in srgb, var(--nv-p, var(--nv-savia)) 14%, var(--nv-superficie));
  border: 1px solid color-mix(in srgb, var(--nv-p, var(--nv-savia)) 32%, transparent); }
.nv-modal-puerta .nv-modal-ic svg { width: 56px; height: 56px; filter: none; }

.nv-modal-ov { position: fixed; inset: 0; background: rgba(4, 20, 14, .72); backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center; z-index: 200; padding: 24px;
  animation: nv-fade var(--nv-dur) var(--nv-ease); }
.nv-modal-ov[hidden] { display: none; }
@keyframes nv-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes nv-pop { from { opacity: 0; transform: translateY(10px) scale(.97); } to { opacity: 1; transform: none; } }

.nv-modal { background: var(--nv-superficie); border: 1px solid var(--nv-linea-fuerte); border-radius: var(--nv-r-lg);
  box-shadow: var(--nv-sh-2); max-width: 440px; width: 100%; padding: 32px; position: relative;
  animation: nv-pop var(--nv-dur) var(--nv-ease); text-align: center; }
.nv-modal-ic { width: 84px; height: 84px; margin: 0 auto 18px; color: var(--nv-p, var(--nv-savia));
  animation: nv-ic-in .55s var(--nv-ease) both, nv-ic-float 4.5s ease-in-out .55s infinite; }
.nv-modal-ic svg { width: 100%; height: 100%; filter: drop-shadow(0 0 16px rgba(47, 169, 140, .38)); }
@keyframes nv-ic-in { from { opacity: 0; transform: scale(.55) rotate(-14deg); } to { opacity: 1; transform: none; } }
@keyframes nv-ic-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@media (prefers-reduced-motion: reduce) { .nv-modal-ic { animation: none; } }
.nv-modal-t { margin-bottom: 10px; }
.nv-modal-d { color: var(--nv-tenue); font-size: 14.5px; line-height: 1.55; margin-bottom: 22px; }
.nv-modal-x { position: absolute; top: 14px; right: 14px; width: 32px; height: 32px; border-radius: var(--nv-r-pill);
  border: 1px solid var(--nv-linea); background: transparent; color: var(--nv-tenue); cursor: pointer; }
.nv-modal-x:hover { color: var(--nv-texto); border-color: var(--nv-linea-fuerte); }

.nv-sheet { background: var(--nv-superficie); border: 1px solid var(--nv-linea-fuerte); border-radius: var(--nv-r-lg);
  box-shadow: var(--nv-sh-2); max-width: 880px; width: 100%; max-height: 82vh; overflow-y: auto; padding: 32px;
  position: relative; animation: nv-pop var(--nv-dur) var(--nv-ease); }
.nv-sheet-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
@media (max-width: 720px) { .nv-sheet-grid { grid-template-columns: repeat(2, 1fr); } }
.nv-sheet-item { display: flex; align-items: center; gap: 10px; padding: 12px; border-radius: var(--nv-r-md);
  border: 1px solid var(--nv-linea); background: var(--nv-suelo); cursor: pointer; text-align: left;
  color: inherit; font: inherit; transition: border-color var(--nv-dur-fast); }
.nv-sheet-item:hover, .nv-sheet-item:focus-visible { border-color: var(--nv-linea-fuerte); }
.nv-sheet-item .nv-sheet-ic { width: 22px; height: 22px; flex-shrink: 0; color: var(--nv-savia); }
.nv-sheet-item .nv-sheet-ic svg { width: 100%; height: 100%; }
.nv-sheet-item span { font-size: 13.5px; }
/* Encabezado de familia dentro de la hoja. Ocupa la fila entera: es lo que
   convierte 36 botones sueltos en un mapa por puerta. La barrita de color es
   la misma que la de la tarjeta, para que se reconozca de dónde vino. */
.nv-sheet-fam { grid-column: 1 / -1; display: flex; align-items: center; gap: 9px;
  font-family: var(--nv-f-mono); font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--nv-tenue); margin: 16px 0 2px; }
.nv-sheet-fam:first-child { margin-top: 0; }
.nv-sheet-fam::before { content: ""; width: 3px; height: 13px; border-radius: 2px; flex-shrink: 0;
  background: var(--nv-p, var(--nv-savia)); }
.nv-sheet-fam::after { content: ""; flex: 1; height: 1px; background: var(--nv-linea); }

/* ============================================================================
   "Lo que te quita de encima" — 6 tarjetas clickeables + modal de proceso animado.
   Aprobado por Daniel 2026-08-19 (artifact "Hero: segunda ronda") tras revisión con
   copywriting-psychologist + ui-ux-pro-max + frontend-design. Cada modal ilustra su
   propio mecanismo real (SVG + CSS, sin video/imagen), animación continua SOLO
   mientras el modal está abierto (se apaga al cerrar y con prefers-reduced-motion).
   ========================================================================== */
.nv-relief-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
@media (max-width: 720px) { .nv-relief-grid { grid-template-columns: 1fr; } }
.nv-relief-card { cursor: pointer; transition: transform var(--nv-dur) var(--nv-ease), border-color var(--nv-dur) var(--nv-ease), box-shadow var(--nv-dur) var(--nv-ease); }
.nv-relief-card:hover, .nv-relief-card:focus-visible { transform: translateY(-3px); border-color: var(--nv-linea-fuerte);
  box-shadow: 0 14px 34px rgba(0,0,0,.28); }
.nv-relief-tag { font-family: var(--nv-f-mono); font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--nv-dorado); margin-bottom: 10px; }
.nv-relief-quien { display: inline-block; margin-top: 10px; font-family: var(--nv-f-mono); font-size: 10.5px;
  color: var(--nv-cielo); border: 1px solid color-mix(in srgb, var(--nv-cielo) 35%, transparent); padding: 3px 9px; border-radius: 999px; }
.nv-relief-more { display: flex; align-items: center; gap: 6px; margin-top: 14px; font-family: var(--nv-f-mono);
  font-size: 11px; color: var(--nv-savia-hi); }
.nv-relief-more::after { content: "▸"; transition: transform var(--nv-dur-fast); }
.nv-relief-card:hover .nv-relief-more::after, .nv-relief-card:focus-visible .nv-relief-more::after { transform: translateX(3px); }

/* ---- Franja "más módulos" (reusa el mecanismo real de mod-sheet.js vía .nv-mod-card) ---- */
.nv-chips { text-align: center; margin-top: 36px; padding-top: 30px; border-top: 1px dashed var(--nv-linea-fuerte); }
.nv-chip-row { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; max-width: 720px; margin: 0 auto; }
/* Las 11 fichas son `role="button"` y median 30px de alto (preflight M-4). */
.nv-chip { font-family: var(--nv-f-mono); font-size: 11px; color: var(--nv-tenue); border: 1px solid var(--nv-linea);
  background: var(--nv-suelo); padding: 11px 14px; border-radius: 999px; cursor: pointer; transition: var(--nv-dur-fast);
  display: inline-flex; align-items: center; min-height: 44px; }
.nv-chip:hover, .nv-chip:focus-visible { color: var(--nv-texto); border-color: var(--nv-savia); }

/* ---- Honestidad ---- */
.nv-honest { text-align: center; }
.nv-honest .nv-h2 { max-width: 720px; margin-left: auto; margin-right: auto; }
.nv-honest p { color: var(--nv-tenue); font-size: 14.5px; max-width: 620px; margin: 0 auto 10px; line-height: 1.6; }

/* ---- Modal de proceso (distinto del modal simple de módulo: más ancho, con ilustración y pasos) ---- */
/* `visibility: hidden` (preflight M-1). Estos seis modales se ocultaban SOLO
   con `opacity:0` + `pointer-events:none`, que bloquea el ratón pero NO el
   tabulador: sus 6 botones de cierre seguían recibiendo foco dentro de un
   contenedor marcado `aria-hidden="true"` — la violación explícita «aria-hidden
   no debe contener elementos enfocables». `visibility` es animable, así que la
   transición de apertura se conserva; va en la lista de `transition` para que
   al cerrar espere a que termine el desvanecido. El patrón correcto ya existía
   en el modal simple de `mod-sheet.js` (`[hidden]{display:none}`, línea 182). */
.nv-rm-ov { position: fixed; inset: 0; background: rgba(4, 20, 14, .72); backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center; z-index: 200; padding: 24px;
  opacity: 0; pointer-events: none; visibility: hidden;
  transition: opacity var(--nv-dur) var(--nv-ease), visibility var(--nv-dur); }
.nv-rm-ov.open { opacity: 1; pointer-events: auto; visibility: visible; }
.nv-rm-box { width: 100%; max-width: 600px; max-height: 88vh; overflow-y: auto; background: var(--nv-suelo);
  border: 1px solid var(--nv-linea-fuerte); border-radius: var(--nv-r-lg); box-shadow: var(--nv-sh-2);
  transform: translateY(16px) scale(.98); transition: transform var(--nv-dur) var(--nv-ease); }
.nv-rm-ov.open .nv-rm-box { transform: translateY(0) scale(1); }
.nv-rm-head { display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 20px 24px; border-bottom: 1px solid var(--nv-linea); }
.nv-rm-head .nv-rm-tag { font-family: var(--nv-f-mono); font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--nv-dorado); display: block; margin-bottom: 6px; }
.nv-rm-head h3 { font-size: 18px; margin: 0; }
/* 44x44 (preflight M-4): los seis cierres de modal median 33x33. */
.nv-rm-x { flex-shrink: 0; width: 44px; height: 44px; border-radius: var(--nv-r-pill); border: 1px solid var(--nv-linea-fuerte);
  background: transparent; color: var(--nv-tenue); cursor: pointer; display: grid; place-items: center; font-size: 15px;
  transition: var(--nv-dur-fast); }
.nv-rm-x:hover { color: var(--nv-texto); border-color: var(--nv-savia); }
.nv-rm-illo { padding: 26px 20px 6px; display: flex; align-items: center; justify-content: center; }
.nv-rm-illo svg { width: 100%; max-width: 440px; height: auto; display: block; }
.nv-rm-body { padding: 6px 24px 26px; }
.nv-rm-body p.nv-rm-lead { color: var(--nv-tenue); font-size: 13.5px; margin: 0 0 16px; }
.nv-rm-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.nv-rm-steps li { display: flex; gap: 12px; align-items: flex-start; font-size: 13.5px; color: var(--nv-texto); line-height: 1.5; }
.nv-rm-steps .nv-rm-n { flex-shrink: 0; width: 22px; height: 22px; border-radius: 6px; background: var(--nv-superficie-2);
  border: 1px solid var(--nv-linea-fuerte); display: grid; place-items: center; font-family: var(--nv-f-mono);
  font-size: 11px; color: var(--nv-cosecha); margin-top: 1px; }
.nv-illo-lbl { font-family: var(--nv-f-mono); font-size: 10px; fill: var(--nv-tenue); }
.nv-illo-lbl-end { fill: var(--nv-cosecha); }
.nv-illo-glow { filter: drop-shadow(0 0 9px rgba(183,204,0,.45)); }

/* ---- Mecanismos de animación — cada tarjeta ilustra su propio proceso, en bucle
   MIENTRAS el modal está abierto (clase .play en .nv-rm-box), nunca decorativo suelto. ---- */
.nv-stream-path { fill: none; stroke: var(--nv-cosecha); stroke-width: 2.5; stroke-linecap: round; stroke-dasharray: 8 8; opacity: .9; }
.nv-rm-box.play .nv-stream-path { animation: nv-dashflow 1s linear infinite; }
@keyframes nv-dashflow { to { stroke-dashoffset: -32; } }

.nv-illo-pkg { offset-path: path("M118,92 C200,50 260,50 342,92"); offset-rotate: 0deg; offset-distance: 50%; }
.nv-rm-box.play .nv-illo-pkg { animation: nv-travel 3s ease-in-out infinite alternate; }
@keyframes nv-travel { 0% { offset-distance: 3%; } 100% { offset-distance: 97%; } }

.nv-illo-scan { transform: translateY(0); }
.nv-rm-box.play .nv-illo-scan { animation: nv-scan 1.6s ease-in-out infinite alternate; }
@keyframes nv-scan { 0% { transform: translateY(-22px); } 100% { transform: translateY(22px); } }
.nv-illo-alert { opacity: 0; } .nv-illo-check { opacity: 1; }
.nv-rm-box.play .nv-illo-alert { animation: nv-alertfade 3.2s ease-in-out infinite; }
.nv-rm-box.play .nv-illo-check { animation: nv-checkfade 3.2s ease-in-out infinite; }
@keyframes nv-alertfade { 0%, 42% { opacity: 1; } 55%, 100% { opacity: 0; } }
@keyframes nv-checkfade { 0%, 42% { opacity: 0; } 55%, 100% { opacity: 1; } }

.nv-illo-receipt { opacity: 1; transform: translateX(70px); }
.nv-rm-box.play .nv-illo-receipt { animation: nv-conveyor 2.4s linear infinite; }
.nv-illo-receipt:nth-of-type(2) { animation-delay: .8s; }
.nv-illo-receipt:nth-of-type(3) { animation-delay: 1.6s; }
@keyframes nv-conveyor { 0% { transform: translateX(0); opacity: 0; } 10% { opacity: 1; }
  88% { opacity: 1; } 100% { transform: translateX(230px); opacity: 0; } }

.nv-illo-wl { stroke: var(--nv-savia-hi); stroke-width: 1.6; stroke-linecap: round; fill: none; stroke-dasharray: 26; stroke-dashoffset: 0; }
.nv-rm-box.play .nv-illo-wl1 { animation: nv-write 2.6s ease-in-out infinite; }
.nv-rm-box.play .nv-illo-wl2 { animation: nv-write 2.6s ease-in-out infinite .35s; }
.nv-rm-box.play .nv-illo-wl3 { animation: nv-write 2.6s ease-in-out infinite .7s; }
@keyframes nv-write { 0% { stroke-dashoffset: 26; } 35%, 100% { stroke-dashoffset: 0; } }

.nv-illo-ring { fill: none; stroke: var(--nv-cosecha); stroke-width: 2; opacity: 0; }
.nv-rm-box.play .nv-illo-ring1 { animation: nv-ping 1.8s ease-out infinite; }
.nv-rm-box.play .nv-illo-ring2 { animation: nv-ping 1.8s ease-out infinite .9s; }
@keyframes nv-ping { 0% { r: 5; opacity: .6; } 100% { r: 24; opacity: 0; } }
.nv-illo-sat { opacity: 1; }
.nv-rm-box.play .nv-illo-sat { animation: nv-satpulse 2.4s ease-in-out infinite; }
.nv-illo-sat:nth-of-type(2) { animation-delay: .6s; }
.nv-illo-sat:nth-of-type(3) { animation-delay: 1.2s; }
@keyframes nv-satpulse { 0%, 100% { opacity: .5; } 50% { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .nv-rm-box.play .nv-stream-path, .nv-rm-box.play .nv-illo-pkg, .nv-rm-box.play .nv-illo-scan,
  .nv-rm-box.play .nv-illo-alert, .nv-rm-box.play .nv-illo-check, .nv-rm-box.play .nv-illo-receipt,
  .nv-rm-box.play .nv-illo-wl1, .nv-rm-box.play .nv-illo-wl2, .nv-rm-box.play .nv-illo-wl3,
  .nv-rm-box.play .nv-illo-ring1, .nv-rm-box.play .nv-illo-ring2, .nv-rm-box.play .nv-illo-sat { animation: none; }
  .nv-illo-receipt { opacity: 1; transform: translateX(70px); }
}

/* ---- Modal de proceso en móvil — bug real (Daniel, esposa): letras e ilustración
   se probaron solo en escritorio. El SVG tiene viewBox fijo (460x184) con texto en
   unidades de usuario (10px); en un modal angosto ese texto se escala junto con el
   contenedor y queda ilegible. Arreglo: menos padding lateral (más ancho real para
   el SVG) + tope de ancho más alto + tamaño de fuente del SVG un poco mayor, para
   que el texto no dependa solo del escalado del contenedor. ---- */
@media (max-width: 640px) {
  .nv-rm-ov { padding: 10px; }
  .nv-rm-box { max-height: 92vh; }
  .nv-rm-head { padding: 16px 16px; }
  .nv-rm-head h3 { font-size: 17px; }
  .nv-rm-illo { padding: 16px 6px 2px; }
  .nv-rm-illo svg { max-width: 100%; }
  .nv-rm-body { padding: 4px 16px 22px; }
  .nv-rm-body p.nv-rm-lead { font-size: 14.5px; }
  .nv-rm-steps li { font-size: 14.5px; }
  .nv-illo-lbl { font-size: 12px; }
}


/* ═══ ENLACE «SALTAR AL CONTENIDO» (preflight M-10) ═══════════════════════════
   Primer elemento enfocable del documento. Fuera de la pantalla hasta que
   recibe foco — no `display:none`, que lo sacaría del orden de tabulación y lo
   dejaría inservible, que es justo el error que se comete siempre con esto. */
.nv-skip { position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--nv-savia); color: var(--nv-sobre-savia);
  font: 700 14px/1 var(--nv-f-body); padding: 14px 18px; border-radius: 0 0 var(--nv-r-md) 0;
  text-decoration: none; }
.nv-skip:focus { left: 0; }
/* RTL (ar, he, ur, ku, fa): con left:-9999px la página se desborda 10.000 px por la
   izquierda (el lado que se desplaza en rtl) y sale en blanco. Se esconde por la derecha. */
html[dir="rtl"] .nv-skip { left: auto; right: -9999px; border-radius: 0 0 0 var(--nv-r-md); }
html[dir="rtl"] .nv-skip:focus { right: 0; }
/* 44px de alto tambien aqui: es un control como cualquier otro (M-4). */
.nv-skip { display: inline-flex; align-items: center; min-height: 44px; }

/* Los tres enlaces legales del pie median 20px de alto — por debajo de los
   24x24 que exige WCAG 2.2 AA (SC 2.5.8). Mismo criterio que B-9 aplica a las
   paginas legales. Preflight M-4. */
.nv-foot-legal { display: flex; flex-wrap: wrap; gap: 4px 18px; margin-top: 10px; }
.nv-foot-legal a { display: inline-flex; align-items: center; min-height: 24px;
  padding: 4px 0; color: var(--nv-tenue); font-size: 13px; }
.nv-foot-legal a:hover { color: var(--nv-texto); }

/* ---------- LAS FICHAS DE MÓDULO, CON EL COLOR DE SU FAMILIA (2026-09-07) ----
   Las once fichas de la franja «más módulos» eran todas del mismo gris
   (`--nv-tenue`): el mismo muro plano que la app tenía por dentro. Ahora cada
   una lleva el color de su puerta, que `mod-sheet.js` le pone en `--nv-p`
   leyendo la MISMA tabla `PUERTAS` — sin segunda lista que se desincronice.

   🔴 EL COLOR VA AL BORDE Y AL PUNTO, NUNCA AL TEXTO, Y ESTO SE MIDIÓ.
   Los trece tonos dan entre 3,03 y 5,39 sobre blanco: como TEXTO no llegan al
   4,5:1 que pide WCAG en tema claro. Como elemento gráfico el mínimo es 3:1 y
   sí lo cumplen los trece. Por eso el rótulo sube a `--nv-texto` (que antes era
   `--nv-tenue`, gris apagado) y el color se queda en el borde y en el punto.

   El punto de color hace el trabajo de reconocimiento a distancia: con once
   fichas en fila, el ojo agrupa por color antes de leer una sola palabra. */
.nv-chip-color {
  color: var(--nv-texto);
  border-color: color-mix(in srgb, var(--nv-p, var(--nv-savia)) 55%, var(--nv-linea));
  padding-left: 11px;
}
.nv-chip-color::before {
  content: "";
  width: 7px; height: 7px; border-radius: 999px; margin-right: 8px;
  background: var(--nv-p, var(--nv-savia));
  flex-shrink: 0;
}
.nv-chip-color:hover, .nv-chip-color:focus-visible {
  border-color: var(--nv-p, var(--nv-savia));
  background: color-mix(in srgb, var(--nv-p, var(--nv-savia)) 10%, var(--nv-suelo));
}
