/* =============================================================
   NIMBO — sistema visual
   =============================================================
   IDEA: el sitio como una pieza de equipo de estudio. Chasis
   oscuro, reglas finas, mucho aire, y los productos presentados
   como objetos bajo luz.

   Tres reglas de las que sale todo lo demas. Son las mismas que
   gobiernan la interfaz del plugin (docs/SKIN_NIMBO.md), y por eso
   el sitio y el producto por fin se parecen:

     1. La profundidad la hacen capas de fondo, no sombras
        difusas. Cada superficie esta un escalon por encima de la
        anterior y se separa con una linea de 1 px, no con blur.
     2. El color se reserva para lo que tiene un valor o un
        estado. Lo demas es chasis y texto.
     3. El movimiento es mecanico: recorridos cortos, easing
        rapido, las cosas encajan. Nada rebota.

   DOS PALETAS CON DOS TRABAJOS. El naranja sigue siendo la marca y
   manda en todo lo interactivo. Los colores del plugin —teal,
   magenta, amarillo— solo salen donde significan algo: una familia
   de control, un estado de campo, una etiqueta de precio. Antes
   ambas competian en cada seccion que mostraba una captura.
   ============================================================= */

:root {
    /* Chasis — cinco escalones, no un negro plano */
    --ink-950: #08080A;
    --ink-900: #0C0C10;
    --ink-800: #131319;
    --ink-700: #1B1B23;
    --ink-600: #24242E;
    --line: #2E2E3A;
    --line-soft: #21212A;

    /* Texto: blanco calido, nunca #fff puro (quema en OLED) */
    --text: #F2F0EA;
    --text-2: #A8A5AE;
    /* Subido de #6F6D77: sobre el chasis daba 3.8:1 y no llegaba al
       minimo AA para texto normal. Ahora 5.5:1. */
    --text-3: #8A8792;

    /* NARANJA: el color de la marca. Es el que la gente reconoce, y
       manda en todo lo interactivo — botones, enlaces, navegacion,
       foco. */
    --orange: #FF6A00;
    --orange-deep: #C24E00;

    /* Acentos del plugin. NO son decoracion: cada uno significa algo
       (familia de control, estado de un campo) y solo aparecen donde
       ese significado existe. Asi el naranja no compite con ellos. */
    --teal: #2FB894;
    --teal-deep: #1F8A70;
    --magenta: #E85AA8;
    --magenta-deep: #C23C86;
    --yellow: #F5E14C;

    /* Superficies de producto: el papel de la interfaz del plugin */
    --paper: #EFE9DC;
    --paper-card: #FFFCF4;
    --paper-ink: #100E0A;

    --accent: var(--orange);

    /* VT323 deja de ser la voz del sitio y pasa a ser el rotulo
       tecnico: kickers, etiquetas, cifras. Como la serigrafia de
       un panel. El texto normal va en la sans del sistema, que en
       Mac es SF Pro y en Windows Segoe UI Variable. */
    --font-tec: 'VT323', ui-monospace, monospace;

    /* La fuente del logotipo. Es la MISMA que el plugin lleva
       compilada dentro (assets/fonts/Jost-300-Light.ttf) y la misma
       de las laminas de marca, para que el nombre se lea igual en la
       cabecera, en la interfaz del plugin y en un post. */
    --font-marca: 'Jost', 'Helvetica Neue', Helvetica, Arial, sans-serif;
    --font: -apple-system, BlinkMacSystemFont, 'Segoe UI Variable Text',
        'Segoe UI', Inter, system-ui, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    /* Movimiento mecanico: entra rapido, frena seco */
    --ease: cubic-bezier(.2, .8, .2, 1);
    --ease-out: cubic-bezier(.16, 1, .3, 1);
    --t-fast: .18s;
    --t: .32s;

    --r: 4px;
    --pad: clamp(1.25rem, 4vw, 3rem);
    --max: 1180px;
}

/* =============================================================
   BASE
   ============================================================= */
*,
*::before,
*::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* El atributo hidden gana a cualquier display de aqui.
   El navegador trae [hidden]{display:none}, pero es una regla SUYA y
   pierde contra cualquier regla nuestra que ponga display — da igual la
   especificidad. Por eso .checkout{display:flex} dejaba a la vista una
   caja escrita <div class="checkout" hidden> en el HTML, y por eso
   .vc-price-line{display:flex} habria ignorado el hidden que le pone
   checkout.js el dia del lanzamiento.
   Es un fallo que solo se ve en la pagina equivocada el dia equivocado,
   asi que se arregla en la base y para todo el sitio. */
[hidden] {
    display: none !important;
}

html {
    scroll-behavior: smooth;
    -webkit-text-size-adjust: 100%;
}

body {
    background: var(--ink-900);
    color: var(--text);
    font-family: var(--font);
    font-size: 1rem;
    line-height: 1.6;
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

img {
    max-width: 100%;
    display: block;
}

a {
    color: inherit;
}

::selection {
    background: var(--accent);
    color: var(--ink-950);
}

/* =============================================================
   FONDO
   =============================================================
   El negro plano es lo que delata una plantilla. Aqui hay tres
   capas: una rejilla tecnica de dos frecuencias, un halo tenue
   arriba (como si la pagina estuviera iluminada desde el
   encabezado) y grano finisimo POR ENCIMA de todo el contenido.

   El grano es un SVG en data: URI — ni una peticion mas, y pasa
   la CSP del sitio (img-src 'self' data:). Es lo que le quita el
   acabado de plastico a una superficie oscura. */
.bg-grid {
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background-image:
        radial-gradient(120% 70% at 50% -10%, rgba(255, 106, 0, .07), transparent 60%),
        linear-gradient(rgba(255, 255, 255, .022) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, .022) 1px, transparent 1px),
        linear-gradient(rgba(255, 255, 255, .05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, .05) 1px, transparent 1px);
    background-size: 100% 100%, 44px 44px, 44px 44px, 264px 264px, 264px 264px;
}

/* El tunel 3D del hero. Va en el mismo plano que .bg-grid (z-index -1)
   y despues en el DOM, asi que pinta encima de la rejilla y debajo de
   absolutamente todo el contenido. El grano de body::after le cae por
   arriba igual que al resto, que es lo que lo integra con la pagina en
   vez de dejarlo como un video pegado.

   Sin alto propio: hereda el del viewport por inset. El canvas se
   dimensiona desde JS con el devicePixelRatio. */
.tunel {
    position: fixed;
    inset: 0;
    z-index: -1;
    display: block;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

body::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 9990;
    pointer-events: none;
    opacity: .04;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    background-size: 200px 200px;
}

/* =============================================================
   TIPOGRAFIA
   ============================================================= */
h1,
h2,
h3,
h4 {
    font-weight: 700;
    line-height: 1.04;
    letter-spacing: -.03em;
    text-wrap: balance;
}

p {
    text-wrap: pretty;
}

/* El rotulo tecnico: pequeno, espaciado, en VT323. Es la unica
   supervivencia del look viejo, y ahora funciona porque contrasta
   con la sans en vez de competir con ella. */
.hero-kicker,
.vc-eyebrow,
.card-price,
.price-meta,
.vc-price-meta,
.badge,
.card-tag,
.vc-format,
.form-label,
.legal-updated,
.footer,
.nav-link,
.btn,
.vc-chain-orig-lbl,
.vc-soon,
.product-subtitle,
.amount,
.vc-price-line,
.vc-cta-title {
    font-family: var(--font-tec);
    letter-spacing: .06em;
    text-transform: uppercase;
}

.text-accent {
    color: var(--accent);
}

code {
    font-family: var(--font-mono);
    font-size: .88em;
    background: var(--ink-700);
    border: 1px solid var(--line);
    border-radius: 3px;
    padding: .12em .4em;
}

/* =============================================================
   CURSOR
   =============================================================
   La mira verde de antes era ruido. Ahora es un punto con
   mix-blend-mode: difference, que se lee sobre cualquier fondo
   —incluido el crema de las capturas— sin tener que saber que hay
   debajo. Se agranda sobre lo interactivo. */
.cursor,
.cursor-follower {
    position: fixed;
    top: 0;
    left: 0;
    pointer-events: none;
    z-index: 9998;
    border-radius: 50%;
    mix-blend-mode: difference;
    will-change: transform;
    transition: opacity .18s var(--ease);
}

.cursor {
    width: 7px;
    height: 7px;
    background: #fff;
    margin: -3.5px 0 0 -3.5px;
}

.cursor-follower {
    width: 34px;
    height: 34px;
    margin: -17px 0 0 -17px;
    border: 1px solid rgba(255, 255, 255, .6);
    transition: width var(--t) var(--ease), height var(--t) var(--ease),
        margin var(--t) var(--ease), background-color var(--t) var(--ease),
        opacity .18s var(--ease);
}

.cursor-follower.active {
    width: 58px;
    height: 58px;
    margin: -29px 0 0 -29px;
    background: rgba(255, 255, 255, .18);
}

/* El puntero de adorno se aparta de las capturas de producto.
   Va con mix-blend-mode: difference, que es lo que le da contraste sobre el
   fondo negro del sitio; pero sobre el papel crema de la interfaz de un plugin
   la diferencia se invierte y sale un aro negro duro con un punto dentro, justo
   encima del producto. Dentro de la imagen deja de leerse como un cursor y pasa
   a parecer una pieza mas de la interfaz, o suciedad pegada a la captura.
   El puntero de verdad del sistema no se oculta en ningun sitio, asi que aqui no
   se pierde nada: simplemente manda el del sistema mientras el raton esta encima
   de la imagen. */
body:has(.vc-shot:hover) .cursor,
body:has(.vc-shot:hover) .cursor-follower {
    opacity: 0;
}

@media (pointer: coarse),
(hover: none) {

    .cursor,
    .cursor-follower {
        display: none !important;
    }
}

/* =============================================================
   ENCABEZADO
   ============================================================= */
.header {
    position: fixed;
    inset: 0 0 auto 0;
    z-index: 100;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    padding: .9rem var(--pad);
    background: color-mix(in srgb, var(--ink-950) 82%, transparent);
    backdrop-filter: blur(14px) saturate(1.3);
    -webkit-backdrop-filter: blur(14px) saturate(1.3);
    border-bottom: 1px solid var(--line-soft);
    view-transition-name: cabecera;
}

/* La nube y el nombre son UNA marca, no dos elementos sueltos: el
   color lo pone el enlace y los dos lo heredan, asi el hover los
   tine a la vez en vez de encender solo una mitad. */
.marca {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    color: var(--text);
    /* Un logotipo no se subraya. Mientras aqui dentro solo hubo un
       SVG no hizo falta decirlo —el subrayado del navegador no pinta
       sobre un SVG— pero el nombre es texto y si lo lleva. */
    text-decoration: none;
    transition: color var(--t) var(--ease);
}

.marca:hover {
    color: var(--accent);
}

/* El trazo de nube que llevan el plugin y todo el material de NIMBO.
   Antes aqui habia una foto dentro de un marco de 1 px: el marco
   existia para recortar la foto, y sin foto no tiene nada que
   encuadrar. En vector y en currentColor, el naranja del hover lo
   hereda igual que cualquier otro elemento interactivo. */
.logo {
    width: 46px;
    height: auto;
    transition: transform var(--t) var(--ease);
    view-transition-name: logo;
}

/* Se inclina la nube, no el conjunto: una palabra torcida se lee
   como un fallo de maquetacion, no como un gesto. */
.marca:hover .logo {
    transform: scale(1.06) rotate(-2deg);
}

/* El logotipo va en Jost 300, la fuente de la marca. El espaciado
   sale de las laminas: alli es 12 sobre un cuerpo de 128, o sea
   .094em, y en em se mantiene igual a cualquier tamano. */
.logotipo {
    font-family: var(--font-marca);
    font-weight: 300;
    font-size: 1.3rem;
    letter-spacing: .094em;
    line-height: 1;
    /* El espaciado deja un hueco suelto detras de la ultima letra
       que descoloca el conjunto medio pixel a la izquierda. */
    margin-right: -.094em;
}

.nav {
    display: flex;
    gap: .25rem;
    flex-wrap: wrap;
}

.nav-link {
    position: relative;
    font-size: 1.15rem;
    color: var(--text-2);
    text-decoration: none;
    padding: .4rem .7rem;
    border-radius: var(--r);
    transition: color var(--t-fast) var(--ease), background-color var(--t-fast) var(--ease);
}

/* Subrayado que crece desde el centro. Barato y se nota. */
.nav-link::after {
    content: '';
    position: absolute;
    left: 50%;
    right: 50%;
    bottom: .15rem;
    height: 1px;
    background: var(--accent);
    transition: left var(--t) var(--ease), right var(--t) var(--ease);
}

.nav-link:hover {
    color: var(--text);
    background: var(--ink-700);
}

.nav-link:hover::after {
    left: .7rem;
    right: .7rem;
}

/* =============================================================
   BOTONES
   ============================================================= */
.btn {
    --btn-bg: transparent;
    --btn-fg: var(--text);
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    padding: .85rem 1.6rem;
    font-size: 1.2rem;
    text-decoration: none;
    cursor: pointer;
    color: var(--btn-fg);
    background: var(--btn-bg);
    border: 1px solid var(--line);
    border-radius: var(--r);
    overflow: hidden;
    isolation: isolate;
    transition: transform var(--t) var(--ease), border-color var(--t) var(--ease),
        color var(--t) var(--ease);
}

/* El relleno sube desde abajo al pasar por encima */
.btn::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    background: var(--accent);
    transform: translateY(101%);
    transition: transform var(--t) var(--ease-out);
}

.btn:hover {
    color: var(--ink-950);
    border-color: var(--accent);
}

.btn:hover::before {
    transform: translateY(0);
}

.btn:active {
    transform: scale(.98);
}

.btn-primary {
    --btn-bg: var(--accent);
    --btn-fg: var(--ink-950);
    border-color: var(--accent);
}

.btn-primary::before {
    background: var(--text);
}

.btn-secondary {
    --btn-bg: transparent;
}

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

.btn-disabled {
    opacity: .35;
    pointer-events: none;
}

/* =============================================================
   ESTRUCTURA
   ============================================================= */
.main-content {
    padding-top: clamp(80px, 12vh, 110px);
}

.section {
    max-width: var(--max);
    margin: 0 auto clamp(3rem, 9vw, 6.5rem);
    padding: 0 var(--pad);
    scroll-margin-top: 110px;
}

.section-title {
    font-size: clamp(1.9rem, 5.2vw, 3.1rem);
    margin-bottom: clamp(1.5rem, 4vw, 2.5rem);
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .6rem;
}

/* Regla fina que sale del titular hasta el borde: da anchura a la
   pagina y ordena la lectura sin dibujar una caja. */
.section-title::after {
    content: '';
    flex: 1;
    min-width: 2rem;
    height: 1px;
    background: linear-gradient(90deg, var(--line), transparent);
    transform: translateY(-.35em);
}

/* =============================================================
   HERO
   ============================================================= */
.hero {
    max-width: var(--max);
    margin: 0 auto clamp(3rem, 9vw, 6rem);
    padding: clamp(2.5rem, 8vw, 6rem) var(--pad) clamp(2rem, 5vw, 3.5rem);
    text-align: left;
}

.hero-kicker {
    font-size: 1.15rem;
    color: var(--accent);
    margin-bottom: 1.25rem;
}

.hero-title {
    font-size: clamp(2.8rem, 11vw, 7rem);
    margin-bottom: 1.5rem;
}

/* La bandera y el mundo del titular. Van medidos en `em`, no en px:
   asi crecen y menguan con el clamp() de arriba y nunca se
   descuadran de la linea de texto en ningun ancho de pantalla.

   Las dos alturas son distintas a proposito. La bandera es un
   rectangulo y se alinea con la altura de las mayusculas; el mundo
   es un circulo, y un circulo de la misma altura SE VE mas pequeno
   que una letra cuadrada, asi que se le da algo mas. */
.hero-glifo {
    display: inline-block;
    width: auto;
    vertical-align: baseline;
}

.hero-bandera {
    height: .62em;
    /* El borde de 4 px del original es casi negro: sobre el chasis
       oscuro desapareceria y la bandera flotaria sin contorno. */
    stroke: var(--line);
}

.hero-mundo {
    height: .82em;
    /* Hereda el naranja de la marca, el mismo que llevaba la palabra
       acentuada del titular anterior. */
    color: var(--accent);
    margin-bottom: -.06em;
}

.hero-sub {
    font-size: clamp(1.05rem, 2.2vw, 1.3rem);
    color: var(--text-2);
    max-width: 46ch;
    margin-bottom: 2.5rem;
}

.hero-actions {
    display: flex;
    gap: .9rem;
    flex-wrap: wrap;
}

.badges {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    margin-top: 3rem;
    padding-top: 2rem;
    border-top: 1px solid var(--line-soft);
}

.badge {
    font-size: 1rem;
    color: var(--text-3);
    border: 1px solid var(--line-soft);
    border-radius: 999px;
    padding: .35rem .9rem;
}

.badge strong {
    color: var(--text);
    font-weight: 400;
}

/* =============================================================
   TARJETAS
   ============================================================= */
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
    gap: 1rem;
}

.card {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: 1.75rem;
    background: linear-gradient(180deg, var(--ink-800), var(--ink-900));
    border: 1px solid var(--line-soft);
    border-radius: 10px;
    overflow: hidden;
    transition: transform var(--t) var(--ease), border-color var(--t) var(--ease);
}

/* Luz que sigue al puntero. Las coordenadas las escribe motion.js
   como variables; sin puntero encima el gradiente es invisible. */
.card::before {
    content: '';
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity var(--t) var(--ease);
    background: radial-gradient(320px circle at var(--mx, 50%) var(--my, 0%),
            rgba(255, 106, 0, .1), transparent 65%);
}

.card:hover {
    transform: translateY(-4px);
    border-color: var(--line);
}

.card:hover::before {
    opacity: 1;
}

.card-content {
    display: flex;
    flex-direction: column;
    flex: 1;
    position: relative;
}

.card-icon {
    font-size: 1.9rem;
    margin-bottom: 1rem;
    filter: saturate(.9);
}

.card-title {
    font-size: 1.6rem;
    margin-bottom: .5rem;
}

.card-price {
    font-size: 1.1rem;
    color: var(--accent);
    margin-bottom: .9rem;
}

.card-price small {
    font-size: .85em;
    color: var(--text-3);
}

.card-desc {
    color: var(--text-2);
    font-size: .97rem;
    margin-bottom: 1.75rem;
}

.card .btn {
    margin-top: auto;
}

.card-tag {
    position: absolute;
    top: 1rem;
    right: 1rem;
    z-index: 1;
    font-size: .95rem;
    padding: .18rem .7rem;
    border-radius: 999px;
    border: 1px solid;
}

.card-tag--free {
    color: var(--teal);
    border-color: var(--teal-deep);
    background: color-mix(in srgb, var(--teal) 12%, transparent);
}

/* Para lo que acaba de salir. En naranja, que es el color de "esto cuesta
   dinero" en el resto del sitio — el mismo que la caja de compra. */
.card-tag--nuevo {
    color: var(--orange);
    border-color: color-mix(in srgb, var(--orange) 45%, transparent);
    background: color-mix(in srgb, var(--orange) 12%, transparent);
}

.card-tag--soon {
    color: var(--yellow);
    border-color: color-mix(in srgb, var(--yellow) 45%, transparent);
    background: color-mix(in srgb, var(--yellow) 10%, transparent);
}

/* =============================================================
   FICHA DE PRODUCTO
   ============================================================= */
.product-layout {
    display: grid;
    grid-template-columns: 1.05fr 1fr;
    gap: clamp(1.5rem, 4vw, 3rem);
    align-items: start;
}

.product-images {
    display: grid;
    gap: 1rem;
    position: sticky;
    top: 110px;
}

.product-images img {
    width: 100%;
    border-radius: 8px;
    border: 1px solid var(--line);
    background: var(--ink-800);
}

.product-img--primary {
    box-shadow: 0 24px 60px -24px rgba(0, 0, 0, .9);
}

.product-info {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}

.product-subtitle {
    font-size: 1.15rem;
    color: var(--text-3);
}

.product-price {
    font-size: 1.5rem;
    padding-bottom: 1.25rem;
    border-bottom: 1px solid var(--line-soft);
}

.amount {
    color: var(--accent);
    font-size: 1.9rem;
}

.price-meta {
    display: block;
    font-size: 1rem;
    color: var(--text-3);
    margin-top: .4rem;
}

.product-desc {
    color: var(--text-2);
    font-size: .98rem;
    padding: 1.25rem;
    background: var(--ink-800);
    border: 1px solid var(--line-soft);
    border-left: 2px solid var(--orange-deep);
    border-radius: var(--r);
}

.product-desc strong {
    color: var(--text);
}

/* =============================================================
   FORMULARIOS
   ============================================================= */
.download-form {
    display: flex;
    flex-direction: column;
    gap: .8rem;
    padding: 1.5rem;
    background: var(--ink-800);
    border: 1px solid var(--line);
    border-radius: 10px;
}

.form-label {
    font-size: 1.05rem;
    color: var(--accent);
}

.input-y2k {
    width: 100%;
    padding: .85rem 1rem;
    font-family: var(--font);
    font-size: .98rem;
    color: var(--text);
    background: var(--ink-950);
    border: 1px solid var(--line);
    border-radius: var(--r);
    transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}

.input-y2k::placeholder {
    color: var(--text-3);
}

.input-y2k:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}

textarea.input-y2k {
    resize: vertical;
    min-height: 110px;
    line-height: 1.5;
}

select.input-y2k option {
    background: var(--ink-800);
    color: var(--text);
}

select.input-y2k:invalid {
    color: var(--text-3);
}

/* Honeypot: invisible para personas, irresistible para bots. Sin
   display:none, que algunos bots detectan y esquivan. */
.hp-field {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.consent-row {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    font-size: .88rem;
    color: var(--text-2);
    cursor: pointer;
}

.consent-row input {
    margin-top: .25rem;
    width: 17px;
    height: 17px;
    accent-color: var(--accent);
    flex-shrink: 0;
}

.consent-row a {
    color: var(--accent);
}

.form-msg {
    margin-top: 1rem;
    padding: .85rem 1rem;
    border: 1px solid;
    border-radius: var(--r);
    font-size: .95rem;
    /* checkout.js escribe con textContent, no con innerHTML, asi que
       sus saltos de linea son \n de verdad y el CSS los tiene que
       respetar. Los mensajes de download-gate.js usan <br> y no les
       afecta: pre-line no cambia nada donde no hay saltos. */
    white-space: pre-line;
}

.form-msg--working,
.form-msg--ok {
    color: var(--teal);
    border-color: var(--teal-deep);
    background: color-mix(in srgb, var(--teal) 10%, transparent);
}

.form-msg--error {
    color: var(--magenta);
    border-color: var(--magenta-deep);
    background: color-mix(in srgb, var(--magenta) 10%, transparent);
}

/* "Todavia no esta a la venta" no es un fallo, es una noticia. En
   magenta de error parecia que la pagina estaba rota. */
.form-msg--info {
    color: var(--text-2);
    border-color: var(--line);
    background: var(--ink-900);
}

/* Aviso fijo escrito en el HTML, no un mensaje del formulario. Mismo
   aspecto neutro que .form-msg--info pero sin la clase .form-msg,
   porque download-gate.js reclama el primer .form-msg del contenedor
   para sus avisos y sobreescribiria este texto. */
.nota-pausa {
    margin-bottom: 1rem;
    padding: .85rem 1rem;
    font-size: .95rem;
    color: var(--text-2);
    background: var(--ink-900);
    border: 1px solid var(--line);
    border-left: 2px solid var(--yellow);
    border-radius: var(--r);
}

/* =============================================================
   CHECKOUT
   =============================================================
   El boton lo pinta PayPal dentro de un iframe, asi que su aspecto
   no se puede estilar desde aqui: se elige con el objeto style de
   paypal.Buttons() en checkout.js. Lo que si es nuestro es la caja
   que lo rodea, y va deliberadamente distinta del formulario de
   descarga —borde naranja, no gris— porque una es la accion que
   cuesta dinero y la otra no. */
.checkout {
    display: flex;
    flex-direction: column;
    gap: .9rem;
    padding: 1.5rem;
    background: var(--ink-800);
    border: 1px solid var(--line);
    border-left: 2px solid var(--orange);
    border-radius: 10px;
}

/* -------------------------------------------------------------
   EL PRECIO
   -------------------------------------------------------------
   NO va en VT323 como el resto de la caja, y es la unica excepcion.
   Esa fuente esta hecha de lineas de un pixel y tiene UN solo grosor:
   por muy grande que se ponga nunca pesa, y el precio quedaba flotando
   entre el boton amarillo de PayPal y el celeste de Mercado Pago, que
   son dos bloques de color macizo.
   Asi que usa la misma fuente y el mismo peso que los titulares de la
   pagina —700/800, interletraje negativo— que es lo que si tiene cuerpo.

   Y el degradado: el mismo naranja de la marca en el centro, aclarado
   arriba y quemado abajo. Da volumen sin cambiar el color. */
.checkout-precio {
    font-family: var(--font);
    font-weight: 800;
    font-size: 3.5rem;
    line-height: 1;
    letter-spacing: -.035em;
    /* Cifras de ancho fijo: si no, el precio "baila" al cambiar de
       15.990 a 24.990 y en una animacion o un cambio de idioma se nota. */
    font-variant-numeric: tabular-nums;
    color: var(--accent);
}

/* EL PRECIO VA EN NARANJA PLANO, y antes no.
   Tenia un degradado de cuatro paradas recortado sobre el texto
   (#FFCF9A -> #FF9540 -> naranja -> #A84300) con una sombra corta
   debajo. La ultima parada es un marron oscuro, y en un numero grande
   ese tramo final no se lee como volumen: se lee como si la cifra
   tuviera una textura sucia justo donde termina.

   Con el degradado se fueron dos cosas que solo existian para
   sostenerlo: el @supports que comprobaba background-clip —hacia falta
   porque pintar texto con degradado obliga a color:transparent, y en un
   navegador sin recorte el precio DESAPARECIA— y el bloque de
   forced-colors, que lo devolvia a naranja plano en el alto contraste
   de Windows. Sin degradado no hay nada que devolver: ya es plano en
   todas partes, que es justo lo que se buscaba. */

.checkout-precio:empty {
    display: none;
}

/* EL PRECIO DE ANTES, TACHADO, al lado del rebajado. Lo pinta
   checkout.js solo cuando el SERVIDOR dice que aplico un cupon.

   Mas pequeno y en el gris tenue: el numero que hay que leer es el que
   se paga, y este solo esta para que se vea que el otro es mas bajo. En
   el mismo tamano competirian y habria que mirar dos veces cual es
   cual. */
.checkout-precio-antes {
    font-size: .42em;
    font-weight: 600;
    letter-spacing: 0;
    color: var(--text-3);
    text-decoration: line-through;
    vertical-align: middle;
    white-space: nowrap;
}

/* El precio en dolares, debajo del de pesos y mucho mas discreto. Los dos
   tienen que estar —quien paga en dolares no deberia calcular de cabeza—
   pero solo uno puede ser EL precio, y en una tienda chilena es el peso. */
.checkout-precio-otra {
    margin: -.55rem 0 0;
    font-family: var(--font-tec);
    font-size: 1.05rem;
    letter-spacing: .04em;
    color: var(--text-3);
}

/* La oferta de lanzamiento, debajo del precio grande. En amarillo y no
   en naranja a proposito: el naranja es la marca y no caduca, y esto es
   lo unico de la caja que si. Regla 2 del sistema — el color se reserva
   para lo que tiene un estado. */
.vc-price-launch {
    font-family: var(--font-tec);
    font-size: 1rem;
    letter-spacing: .04em;
    line-height: 1.2;
    color: var(--yellow);
}

/* PayPal necesita un ancho real para decidir el tamano del boton.
   Sin min-height la caja da un salto cuando el iframe aparece. */
.checkout-boton {
    min-height: 48px;
}

/* -------------------------------------------------------------
   LA SEGUNDA PUERTA: MERCADO PAGO
   -------------------------------------------------------------
   En su celeste de marca y no en el naranja del sitio, que es la unica
   vez que aqui se usa un color ajeno. Es deliberado: en Chile ese boton
   se reconoce antes de leerlo, y quien no reconoce con que esta pagando
   no pulsa. La forma, la tipografia y el relleno que sube al pasar por
   encima siguen siendo los de la casa.

   El texto lleva el precio en pesos dentro, porque es la unica accion de
   la pagina que cobra esa cantidad. */
.checkout-mp {
    --btn-bg: #00A5E4;
    --btn-fg: #06202B;
    border-color: #00A5E4;
    font-family: var(--font-tec);
    letter-spacing: .03em;
}

.checkout-mp::before {
    background: #FFFFFF;
}

/* Deshabilitado mientras se abre el checkout: sin esto se puede pulsar
   tres veces y abrir tres pagos mientras la pestaña todavia no se ha
   ido. */
.checkout-mp[disabled] {
    opacity: .55;
    cursor: progress;
    transform: none;
}

/* El "o" entre las dos puertas. Tenue a proposito: separa, no compite. */
.checkout-o {
    display: flex;
    align-items: center;
    gap: .7rem;
    margin: -.15rem 0;
    font-family: var(--font-tec);
    font-size: .95rem;
    letter-spacing: .1em;
    color: var(--text-3);
}

.checkout-o::before,
.checkout-o::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--line);
}

.checkout-sandbox {
    font-family: var(--font-tec);
    font-size: 1.05rem;
    letter-spacing: .04em;
    color: var(--paper-ink);
    background: var(--yellow);
    padding: .45rem .7rem;
    border-radius: var(--r);
    text-align: center;
}

/* Cuando una pasarela cobra y la otra no, el aviso deja de ser amarillo
   tranquilizador y pasa a magenta: el amarillo de esta caja significa
   "estas a salvo", y en ese caso no lo estas. */
.checkout-sandbox--mezcla {
    background: var(--magenta);
    color: var(--paper-card);
}

.checkout-descarga {
    margin-top: .2rem;
}

/* Cuando el plugin viene en dos versiones salen dos botones seguidos, y
   con .2rem entre ellos parecen uno partido. */
.checkout-descarga + .checkout-descarga {
    margin-top: .55rem;
}

/* -------------------------------------------------------------
   LA LICENCIA
   -------------------------------------------------------------
   En teal y no en naranja: el naranja de la caja es "esto cuesta
   dinero" y aqui ya se pago. Este es el bloque que hay que guardar,
   y va antes del boton de descarga porque el archivo se puede pedir
   otra vez y esto no. */
.checkout-licencia {
    padding: 1.1rem;
    background: var(--ink-900);
    border: 1px solid var(--teal-deep);
    border-left: 2px solid var(--teal);
    border-radius: var(--r);
}

.checkout-licencia-titulo {
    font-family: var(--font-tec);
    font-size: 1.15rem;
    letter-spacing: .06em;
    color: var(--teal);
    margin-bottom: .7rem;
}

/* Monoespaciada de verdad, no la pixelada de la interfaz: esto es
   base64 y hay que poder distinguir una l de un 1 y una O de un 0 si
   alguien decide copiarlo a mano. */
.checkout-licencia-texto {
    display: block;
    width: 100%;
    box-sizing: border-box;
    padding: .7rem;
    font-family: var(--font-mono);
    font-size: .8rem;
    line-height: 1.5;
    color: var(--text);
    background: var(--ink-800);
    border: 1px solid var(--line);
    border-radius: var(--r);
    /* Sin ajuste de linea: el bloque ya viene cortado a 64 caracteres
       para sobrevivir al correo, y verlo tal cual es como se comprueba
       de un vistazo que esta entero. */
    white-space: pre;
    overflow-x: auto;
    resize: vertical;
}

.checkout-licencia-botones {
    display: flex;
    flex-wrap: wrap;
    gap: .6rem;
    margin-top: .8rem;
}

.checkout-licencia-botones .btn {
    padding: .6rem 1.1rem;
    font-size: 1rem;
}

.checkout-licencia-como {
    margin-top: .8rem;
    font-size: .9rem;
    line-height: 1.5;
    color: var(--text-2);
}

/* "Te lo mande al correo tambien". Discreto: es tranquilizador, no una
   accion, y no debe competir con el boton de descarga. */
.checkout-correo {
    font-size: .9rem;
    line-height: 1.5;
    color: var(--text-2);
}

/* El mismo aviso, pero el que pinta download-gate.js debajo de los
   botones de la demo. Alli no hay una caja flex con su hueco entre
   hijos, como en la de compra, y sin esto quedaba pegado al ultimo
   boton. */
.gate-correo {
    margin-top: 1rem;
}

/* "¿Estas en tu computador?", encima de los botones de descarga cuando
   el correo ya salio. Separa las dos cosas: lo que acaba de recibir y
   lo que puede hacer aqui mismo si no esta en el telefono. */
.gate-ahora {
    margin: 1.25rem 0 .6rem;
    font-size: .9rem;
    line-height: 1.5;
    color: var(--text-2);
}

/* Se cobro pero la firma fallo. En amarillo de aviso, no en magenta de
   error: el pago SI salio y el archivo SI se entrega, lo que falta es
   una pieza que llega despues. */
.checkout-licencia--falta {
    font-size: .95rem;
    line-height: 1.6;
    color: var(--text);
    border-color: var(--line);
    border-left-color: var(--yellow);
}

/* =============================================================
   FAQ
   ============================================================= */
.faq-item {
    border-bottom: 1px solid var(--line-soft);
}

.faq-item summary {
    display: flex;
    align-items: center;
    gap: .8rem;
    padding: 1.15rem .25rem;
    font-size: 1.05rem;
    font-weight: 600;
    cursor: pointer;
    list-style: none;
    transition: color var(--t-fast) var(--ease);
}

.faq-item summary::-webkit-details-marker {
    display: none;
}

.faq-item summary::before {
    content: '';
    width: 9px;
    height: 9px;
    flex-shrink: 0;
    border-right: 1.5px solid var(--accent);
    border-bottom: 1.5px solid var(--accent);
    transform: rotate(-45deg);
    transition: transform var(--t) var(--ease);
}

.faq-item[open] summary::before {
    transform: rotate(45deg);
}

.faq-item summary:hover {
    color: var(--accent);
}

.faq-item p {
    padding: 0 .25rem 1.25rem 1.9rem;
    color: var(--text-2);
    font-size: .96rem;
    max-width: 72ch;
}

.faq-item a {
    color: var(--accent);
}

/* =============================================================
   TABLAS
   ============================================================= */
.compare {
    width: 100%;
    border-collapse: collapse;
    font-size: .95rem;
}

.compare th,
.compare td {
    border-bottom: 1px solid var(--line-soft);
    padding: .8rem .6rem;
    text-align: left;
}

.compare thead th {
    color: var(--accent);
    font-family: var(--font-tec);
    font-size: 1.1rem;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.compare td.yes {
    color: var(--accent);
    text-align: center;
}

.compare td.no {
    color: var(--text-3);
    text-align: center;
}

/* =============================================================
   PAGINA LEGAL
   ============================================================= */
.legal {
    max-width: 68ch;
    color: var(--text-2);
}

.legal h3 {
    font-size: 1.3rem;
    color: var(--text);
    margin: 2.5rem 0 .75rem;
}

.legal p,
.legal li {
    margin-bottom: .8rem;
}

.legal ul {
    padding-left: 1.2rem;
}

.legal a {
    color: var(--accent);
}

.legal-updated {
    font-size: 1rem;
    color: var(--text-3);
    margin-bottom: 2rem;
}

/* =============================================================
   PIE
   ============================================================= */
.footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 1rem;
    max-width: var(--max);
    margin: 0 auto;
    padding: 2.5rem var(--pad);
    border-top: 1px solid var(--line-soft);
    font-size: 1rem;
    color: var(--text-3);
}

.footer-links {
    display: flex;
    gap: 1.5rem;
}

.footer-links a {
    color: var(--text-3);
    text-decoration: none;
    transition: color var(--t-fast) var(--ease);
}

.footer-links a:hover {
    color: var(--accent);
}

/* =============================================================
   MOVIMIENTO
   =============================================================
   1) TRANSICION ENTRE PAGINAS. Una regla y el navegador hace el
      fundido cruzado entre documentos; los elementos con
      view-transition-name (logo y cabecera) se transforman en vez
      de parpadear. Donde no esta soportado, navega normal.
   2) REVELADOS LIGADOS AL SCROLL, en CSS puro. Si el navegador no
      soporta animation-timeline, el .visible que pone script.js
      hace el mismo trabajo; y si tampoco hay JS, la regla @supports
      de mas abajo deja todo visible. Tres redes: la pagina nunca
      se queda en blanco. */

/* SOLO CON RATON, y esto no es un capricho de diseno.
   Para hacer el fundido, el navegador CONGELA una captura de la
   pagina que dejas y la deja en pantalla hasta que la siguiente
   esta lista para pintar. Mientras esa foto esta puesta no se
   puede tocar ni deslizar nada: no es la pagina, es una imagen.
   En un navegador normal dura milisegundos y no se nota.
   Dentro del navegador que traen Instagram y Facebook si se nota,
   y a veces no la sueltan nunca: te quedas mirando una foto de la
   pagina anterior, das a un enlace y no pasa nada, y la unica
   salida es cerrar. Es justo lo que pasaba viniendo de la bio.
   Perder un fundido de 0,28 s no le importa a nadie. Perder a
   quien entro desde Instagram si, que es por donde entra casi
   todo el mundo. Asi que en tactil se navega a pelo. */
@view-transition {
    navigation: none;
}

@media (pointer: fine) and (hover: hover) {
    @view-transition {
        navigation: auto;
    }
}

::view-transition-old(root) {
    animation: vt-salir .28s var(--ease) both;
}

::view-transition-new(root) {
    animation: vt-entrar .38s var(--ease-out) both;
}

@keyframes vt-salir {
    to {
        opacity: 0;
        transform: translateY(-8px);
    }
}

@keyframes vt-entrar {
    from {
        opacity: 0;
        transform: translateY(14px);
    }
}

/* El estado de reposo es VISIBLE. Nada de opacity:0 por defecto.
   Una animacion que no arranca no puede dejar la pagina en blanco,
   que es justo lo que paso en este sitio con el IntersectionObserver.

   Las animaciones solo entran cuando <html> lleva la clase .motion,
   que pone el JS despues de comprobar que puede. Y si aun asi algo
   se quedase invisible, el vigia de script.js quita .motion y todo
   vuelve a verse. Tres redes:
     1. Sin JS       -> no hay .motion  -> visible
     2. Sin soporte  -> @supports no aplica -> transicion normal
     3. Con las dos y aun asi invisible -> el vigia lo desactiva */
.object-reveal {
    opacity: 1;
}

html.motion .object-reveal {
    opacity: 0;
    transform: translateY(22px);
    transition: opacity .6s var(--ease-out), transform .6s var(--ease-out);
}

html.motion .object-reveal.visible {
    opacity: 1;
    transform: none;
}

@supports (animation-timeline: view()) {
    html.motion .object-reveal {
        opacity: 1;
        transform: none;
        transition: none;
        animation: revelar linear both;
        animation-timeline: view();
        animation-range: entry 5% cover 22%;
    }
}

@keyframes revelar {
    from {
        opacity: 0;
        transform: translateY(26px);
    }
}

/* Barra de progreso de lectura, sin una linea de JS */
.progreso {
    position: fixed;
    top: 0;
    left: 0;
    height: 2px;
    width: 100%;
    z-index: 101;
    pointer-events: none;
    transform-origin: 0 50%;
    background: linear-gradient(90deg, var(--accent), var(--magenta));
    animation: progreso linear both;
    animation-timeline: scroll(root block);
}

@keyframes progreso {
    from {
        transform: scaleX(0);
    }

    to {
        transform: scaleX(1);
    }
}

/* =============================================================
   RESPONSIVE
   ============================================================= */
@media (max-width: 860px) {
    .product-layout {
        grid-template-columns: 1fr;
    }

    .product-images {
        position: static;
    }
}

@media (max-width: 620px) {
    .header {
        padding: .7rem 1rem;
    }

    /* En pantalla estrecha se queda la nube sola. El nombre ocupa 80
       px que le hacen falta al menu: con tres enlaces —el dia que
       vuelva DRUMKITS— la barra se parte en dos lineas y la cabecera
       dobla de alto. La nube sola sigue siendo la marca, y el enlace
       lleva aria-label, asi que quien no ve la pagina sigue oyendo
       "NIMBO, ir al inicio". */
    .logotipo {
        display: none;
    }

    .nav {
        gap: 0;
    }

    .nav-link {
        font-size: 1.05rem;
        padding: .35rem .5rem;
    }

    .hero-actions .btn {
        width: 100%;
    }

    .footer {
        flex-direction: column;
        text-align: center;
    }
}

/* Quien pide menos movimiento se queda sin efectos, pero con toda
   la informacion: nada depende de una animacion para verse. */
@media (prefers-reduced-motion: reduce) {

    *,
    *::before,
    *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }

    .object-reveal {
        opacity: 1 !important;
        transform: none !important;
    }

    @view-transition {
        navigation: none;
    }
}

/* =============================================================
   NIMBO VOCAL CHAIN — ficha
   =============================================================
   Todo bajo .vc. La ficha usa el mismo sistema que el resto y
   solo anade lo que es suyo: la cadena de diez bloques, las
   tablas de datos y el marco de las capturas.
   ============================================================= */
.vc-hero {
    padding-top: clamp(1rem, 4vw, 2.5rem);
}

.vc-eyebrow {
    font-size: 1.1rem;
    color: var(--accent);
    margin-bottom: 1.25rem;
}

.vc-title {
    font-size: clamp(2.4rem, 8.5vw, 5.4rem);
    margin-bottom: 1.5rem;
}

.vc-title .text-accent {
    color: var(--text-3);
}

.vc-lead {
    font-size: clamp(1.05rem, 2.2vw, 1.28rem);
    color: var(--text-2);
    max-width: 54ch;
    margin-bottom: 2.5rem;
}

.vc-lead strong {
    color: var(--text);
    font-weight: 600;
}

/* ---------- Capturas del plugin ----------
   La interfaz es crema y contorno de tinta: sobre el chasis
   oscuro se sostiene sola. El marco solo la separa del fondo y le
   da la sombra de un objeto apoyado.
   La inclinacion 3D la calcula motion.js escribiendo --rx/--ry;
   sin puntero encima valen 0 y la imagen esta plana. */
.vc-shot {
    margin: 0 0 2.5rem;
    perspective: 1100px;
}

.vc-shot img {
    width: 100%;
    height: auto;
    border-radius: 10px;
    border: 1px solid var(--line);
    background: var(--paper);
    box-shadow: 0 30px 70px -30px rgba(0, 0, 0, .95);
    transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
    transition: transform var(--t) var(--ease);
    will-change: transform;
}

/* La secuencia NO lleva el marco de la captura: ni borde, ni fondo de
   papel, ni sombra. Sus fotogramas ya traen el #08080A de la pagina y
   su propia luz, asi que enmarcarlos dibujaria una caja alrededor de
   un negro que deberia ser invisible. Lo que parece flotar es el
   plugin, no el rectangulo. */
/* La pieza se sale del ancho de lectura. A 1180 px menos padding se
   quedaba pequena, y lo que se esta ensenando ES el producto: manda
   el, no la columna de texto.

   El tope son 1280 px porque es el ancho real de los fotogramas: mas
   alla se estarian escalando hacia arriba y el texto de la interfaz
   —que es lo que hay que poder leer— se emborrona. Mas grande de lo
   que era, y nitido. */
.vc-shot {
    width: min(100vw - 2rem, 1280px);
    margin-left: 50%;
    translate: -50% 0;
}

.vc-shot .vc-secuencia {
    display: block;
    width: 100%;
    height: auto;
    /* SIN imagen de fondo. Los fotogramas ahora llevan alfa, asi que
       un fondo aqui se veria A TRAVES de ellos: se colaria el plugin
       montado por detras del despiece. El respaldo lo da el propio
       JS, que pide el ultimo fotograma primero y lo pinta en cuanto
       llega. */
    background: transparent;
    /* La caja se reserva desde el principio: las imagenes se piden
       tarde a proposito y sin esto la pagina pegaria un salto. */
    aspect-ratio: 16 / 9;
}

.vc-shot-cap {
    margin-top: .9rem;
    font-size: .9rem;
    color: var(--text-3);
}

/* ---------- Formatos ---------- */
.vc-formats {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    list-style: none;
    margin-bottom: 2.5rem;
}

.vc-format {
    font-size: 1rem;
    color: var(--text-2);
    border: 1px solid var(--line-soft);
    border-radius: 999px;
    padding: .35rem .9rem;
    text-transform: none;
}

.vc-format span {
    color: var(--text-3);
}

/* ---------- Precio ---------- */
.vc-price {
    padding: 1.5rem 0;
    margin-bottom: 2.5rem;
    border-top: 1px solid var(--line-soft);
    border-bottom: 1px solid var(--line-soft);
}

.vc-price-line {
    font-size: 1.6rem;
    display: flex;
    align-items: center;
    gap: .8rem;
    flex-wrap: wrap;
}

.vc-soon {
    font-size: 1.05rem;
    color: var(--yellow);
    border: 1px solid color-mix(in srgb, var(--yellow) 45%, transparent);
    background: color-mix(in srgb, var(--yellow) 10%, transparent);
    border-radius: 999px;
    padding: .2rem .8rem;
}

.vc-price-meta {
    font-size: 1rem;
    color: var(--text-3);
    margin-top: .5rem;
}

/* ---------- Lista de espera ---------- */
.vc-cta {
    padding: 1.75rem;
    background: linear-gradient(180deg, var(--ink-800), var(--ink-900));
    border: 1px solid var(--line);
    border-radius: 12px;
    scroll-margin-top: 110px;
}

.vc-cta-title {
    font-size: 1.3rem;
    color: var(--accent);
    margin-bottom: .5rem;
}

.vc-cta-sub {
    font-size: .95rem;
    color: var(--text-2);
    max-width: 56ch;
    margin-bottom: 1.5rem;
}

.vc-cta .vc-form {
    border: 0;
    background: transparent;
    padding: 0;
}

/* ---------- Aviso bajo cada campo ----------
   Tres estados distintos a proposito: error en magenta (bloquea),
   aviso en amarillo (solo sugiere, porque el detector de dominios
   parecidos es una heuristica) y ok en teal. */
.vc-field-msg {
    font-size: .88rem;
    line-height: 1.45;
    margin-top: -.35rem;
}

.vc-field-msg:empty {
    display: none;
}

.vc-field-msg--error {
    color: var(--magenta);
}

.vc-field-msg--aviso {
    color: var(--yellow);
}

.vc-field-msg--ok {
    color: var(--teal);
}

.input-y2k.is-error {
    border-color: var(--magenta);
}

.input-y2k.is-aviso {
    border-color: var(--yellow);
}

.vc-fix {
    font: inherit;
    font-size: .88rem;
    cursor: pointer;
    color: var(--ink-950);
    background: var(--yellow);
    border: 0;
    border-radius: 3px;
    padding: .1rem .45rem;
}

.vc-fix:hover {
    background: var(--text);
}

/* ---------- Prosa ---------- */
.vc-prose p,
.vc-prose--tight {
    color: var(--text-2);
    font-size: 1.02rem;
    max-width: 68ch;
    margin-bottom: 1rem;
}

.vc-prose strong {
    color: var(--text);
    font-weight: 600;
}

.vc-prose--tight {
    margin-bottom: 2rem;
}

/* ---------- La cadena ----------
   Lista ordenada, que es lo que es. Una columna en movil, dos en
   escritorio, sin que ninguna tabla desborde. */
.vc-chain {
    display: grid;
    gap: .75rem;
    list-style: none;
}

.vc-chain-item {
    display: flex;
    gap: 1rem;
    padding: 1.15rem;
    background: var(--ink-800);
    border: 1px solid var(--line-soft);
    border-radius: 8px;
    transition: border-color var(--t) var(--ease), transform var(--t) var(--ease);
}

.vc-chain-item:hover {
    border-color: var(--line);
    transform: translateX(3px);
}

.vc-chain-n {
    flex: 0 0 2.4rem;
    height: 2.4rem;
    display: grid;
    place-items: center;
    font-family: var(--font-tec);
    font-size: 1.3rem;
    color: var(--teal);
    background: color-mix(in srgb, var(--teal) 12%, transparent);
    border: 1px solid var(--teal-deep);
    border-radius: 6px;
}

.vc-chain-n--alt {
    font-size: .95rem;
    color: var(--text-3);
    background: transparent;
    border-color: var(--line);
}

.vc-chain-name {
    font-family: var(--font-tec);
    font-size: 1.35rem;
    letter-spacing: .04em;
    margin-bottom: .5rem;
}

/* De que plugin comercial sale cada bloque. Va visible, no
   escondido: es la respuesta a "que emula". Solo texto — ni un
   logo, ni una captura, ni tipografias de marca ajena. */
.vc-chain-orig {
    font-size: .95rem;
    color: var(--text);
    margin-bottom: .6rem;
    padding: .5rem .7rem;
    background: var(--ink-700);
    border-left: 2px solid var(--magenta);
    border-radius: 0 var(--r) var(--r) 0;
}

.vc-chain-orig span {
    color: var(--text-3);
}

.vc-chain-orig-lbl {
    display: block;
    font-size: .85rem;
    color: var(--magenta) !important;
}

.vc-chain-orig--propio {
    border-left-color: var(--teal-deep);
}

.vc-chain-orig--propio .vc-chain-orig-lbl {
    color: var(--teal) !important;
}

.vc-chain-circuit {
    font-size: .88rem;
    color: var(--text-3);
    margin-bottom: .5rem;
}

.vc-chain-what {
    font-size: .96rem;
    color: var(--text-2);
}

.vc-chain-ctrl {
    display: inline-block;
    margin-top: .7rem;
    font-family: var(--font-tec);
    font-size: 1rem;
    letter-spacing: .06em;
    color: var(--teal);
    border: 1px solid var(--teal-deep);
    border-radius: 999px;
    padding: .1rem .7rem;
}

.vc-chain-ctrl--none {
    color: var(--text-3);
    border-color: var(--line);
    font-family: var(--font);
    font-size: .82rem;
    letter-spacing: 0;
}

/* ---------- Listas ---------- */
.vc-list {
    list-style: none;
    margin: 1rem 0;
}

.vc-list li {
    position: relative;
    padding-left: 1.5rem;
    margin-bottom: .8rem;
    color: var(--text-2);
    font-size: 1rem;
    max-width: 70ch;
}

.vc-list li::before {
    content: '';
    position: absolute;
    left: 0;
    top: .62em;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--teal);
}

.vc-list strong {
    color: var(--text);
}

/* ---------- Tablas de datos ---------- */
.vc-scroll {
    overflow-x: auto;
    margin: 1.25rem 0;
    border: 1px solid var(--line-soft);
    border-radius: 8px;
}

.vc-data {
    width: 100%;
    border-collapse: collapse;
    font-variant-numeric: tabular-nums;
}

.vc-data th,
.vc-data td {
    padding: .85rem 1rem;
    text-align: left;
    border-bottom: 1px solid var(--line-soft);
}

.vc-data tr:last-child th,
.vc-data tr:last-child td {
    border-bottom: 0;
}

.vc-data thead th {
    font-family: var(--font-tec);
    font-size: 1.05rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--accent);
    background: var(--ink-800);
}

.vc-data tbody th {
    color: var(--text);
    font-weight: 600;
    font-size: .95rem;
}

.vc-data td {
    color: var(--text-2);
    font-size: .95rem;
}

.vc-data .vc-td-orig {
    color: var(--text);
    font-weight: 600;
}

.vc-data .vc-td-orig span {
    display: block;
    font-weight: 400;
    font-size: .85rem;
    color: var(--text-3);
}

.vc-data caption {
    caption-side: bottom;
    padding: .7rem 1rem;
    font-size: .84rem;
    color: var(--text-3);
    text-align: left;
}

.vc-data--spec th {
    width: 34%;
}

/* ---------- Aviso legal ----------
   Texto literal: no se reescribe. */
.vc-legal {
    margin-top: 1.5rem;
    padding: 1.1rem 1.25rem;
    background: var(--ink-800);
    border: 1px solid var(--line-soft);
    border-radius: 8px;
    scroll-margin-top: 110px;
}

.vc-legal p {
    font-size: .9rem;
    color: var(--text-3);
    max-width: 78ch;
}

/* ---------- Cierre ---------- */
.vc-close {
    text-align: left;
}

@media (min-width: 860px) {
    .vc-chain {
        grid-template-columns: 1fr 1fr;
    }
}

@media (max-width: 620px) {
    .vc-cta {
        padding: 1.25rem;
    }

    .vc-chain-item {
        padding: .9rem;
        gap: .75rem;
    }

    .vc-data th,
    .vc-data td {
        padding: .6rem .7rem;
        font-size: .9rem;
    }
}

/* =============================================================
   MODIFICADORES Y GANCHOS SUELTOS
   =============================================================
   .interactive no lleva estilo a proposito: es solo el gancho que
   usa el JS para el cursor y el sonido. */

/* Un hijo de flex no encoge por debajo de su contenido salvo que
   se le diga. Sin esto, un nombre largo dentro de la cadena
   desborda la tarjeta. */
.vc-chain-body {
    flex: 1;
    min-width: 0;
}

/* La segunda captura de una ficha es contexto, no el retrato */
.product-img--secondary {
    opacity: .82;
    transition: opacity var(--t) var(--ease);
}

.product-img--secondary:hover {
    opacity: 1;
}

.product-price--free .amount {
    color: var(--teal);
}

.vc-data--ref tbody th {
    font-family: var(--font-tec);
    font-size: 1.05rem;
    letter-spacing: .05em;
    color: var(--text-3);
    width: 3rem;
}

.vc-price-line--close {
    margin: 1.5rem 0 .5rem;
}

/* =============================================================
   OBJETIVOS TACTILES
   =============================================================
   44x44 px es el minimo con el que un dedo acierta sin pelearse.
   La navegacion se quedaba en 38 y los enlaces del pie en 26, y la
   mitad del trafico de este sitio llega por movil.

   Se resuelve con min-height y centrado, no agrandando la letra:
   el area crece, el diseno no cambia. */
.nav-link,
.footer-links a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
}

/* El logo mide 46x28 px a proposito, asi que el area la pone el
   enlace que lo envuelve. */
.header>a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
}

/* El checkbox de consentimiento mide 17 px, pero va dentro de un
   <label> que envuelve tambien el texto: se toca toda la fila. Se
   le da altura minima para que esa fila nunca quede por debajo del
   umbral. */
.consent-row {
    min-height: 44px;
    align-items: center;
}

/* =============================================================
   VOCAL SPACE — LOS REELS Y LA VENTA
   =============================================================
   Todo lo de aqui abajo es de vocal-space.html y lleva prefijo
   .vs- para no pisar a .vc-, que es lo que comparten las tres
   fichas de producto.

   LOS VIDEOS SON LOS REELS DE INSTAGRAM tal cual, en 9:16. Ese
   formato es el problema de diseno de esta hoja: puestos al ancho
   de la columna medirian mas de dos pantallas de alto y nadie
   llegaria al final. Por eso van SIEMPRE en una caja estrecha, y
   en pantalla ancha al lado del texto que argumentan en vez de
   debajo. */

/* ---------- La secuencia arrastrada por el scroll ---------- */
.vs-seq {
    /* Aire arriba y abajo. Sin el margen inferior la animacion quedaba pegada
       al parrafo siguiente —0 px medidos— y las dos cosas se leian como una
       sola. Los cuadros son transparentes por los bordes, asi que la figura
       "acaba" antes de donde dice su caja: hace falta mas hueco del que
       pareceria. */
    margin: 1.5rem auto 3rem;
    /* Apaisada, porque sin el suelo del render el sujeto lo es: las cuatro
       voces alrededor de la cabeza miden 1000x630. Se puede ir mas ancha que
       cuando arrastraba el bloque vertical entero, y 780 px es donde la
       esfera mas pequeña —la voz 4— todavia se ve claramente separada de la
       cabeza. El tope real son los 1080 px del render: por encima se estaria
       escalando hacia arriba. */
    width: min(100%, 780px);
}

.vs-seq-lienzo {
    display: block;
    width: 100%;
    height: auto;
    /* NI BORDE, NI FONDO, NI SOMBRA, igual que el despiece del hero: los
       cuadros llevan alfa y se difuminan a transparente por los bordes, y
       enmarcarlos dibujaria una caja alrededor de algo que tiene que
       parecer que flota. */
    background: transparent;
}

.vs-seq .vc-shot-cap {
    text-align: center;
    max-width: 34ch;
    margin-inline: auto;
}

/* ---------- La oferta del hero ----------
   El precio y la prueba, en la primera pantalla. Puesto el 9 de
   octubre de 2026 porque el trafico pagado de Meta aterrizaba sin
   nada que tocar: el precio quedaba a 911 px y el boton de la
   prueba a 1678, en una pantalla de 812.

   NO ES UNA CAJA, y es lo que la distingue de .checkout y de
   .vs-demo. Las dos cajas de esta pagina tienen fondo, borde y
   relleno porque estan sueltas en mitad del scroll y necesitan decir
   donde empiezan. Esta va pegada al texto del hero: encerrarla
   dibujaria un recuadro entre el titular y el producto. Solo la
   separa del parrafo una linea fina — arriba en escritorio, abajo en
   un telefono, que es donde queda el parrafo en cada caso. */
.vs-oferta {
    /* El ancho de una columna y no el de la pagina. A todo lo ancho, en
       escritorio el boton era una barra de 1084 px: mas larga que el
       parrafo que tiene encima y que cualquier otra cosa del hero. En
       un telefono no cambia nada, la pantalla es mas estrecha que esto. */
    max-width: 30rem;
    margin-bottom: 2.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--line-soft);
}

/* Cifra y "pago unico" en la misma linea, alineados por la base del
   texto: es como lo lee el ojo, "24.990 pago unico", sin saltar. */
.vs-oferta-precio {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: .25rem .8rem;
    margin-bottom: .2rem;
}

/* La cifra, con el tratamiento de la de la caja de compra: la fuente
   de los titulares y no VT323 —que tiene un solo grosor y no pesa
   por grande que se ponga— y cifras de ancho fijo. Mas pequena que
   alla (2.2 contra 3.5) a proposito: aqui manda el titular y el
   precio acompana; en la caja de compra el precio ES lo que se mira.
   Salio a 2.6 y gritaba mas que "CON ESTEROIDES.", que va en gris:
   lo primero que se miraba de la pagina era el numero. */
.vs-oferta-clp {
    font-family: var(--font);
    font-weight: 800;
    font-size: 2.2rem;
    line-height: 1;
    letter-spacing: -.035em;
    font-variant-numeric: tabular-nums;
    color: var(--accent);
}

/* Como .vc-price-meta, que dice lo mismo en la caja de compra: VT323
   en mayusculas y con el espaciado de todas las etiquetas del sitio. */
/* El precio de antes, tachado, junto al rebajado del hero. Lo pinta
   checkout.js solo cuando el servidor confirma el cupon. Mas pequeno y
   tenue: el numero que hay que leer es el que se paga. */
.vs-oferta-antes {
    font-family: var(--font-tec);
    font-size: 1.05rem;
    letter-spacing: .04em;
    color: var(--text-3);
    text-decoration: line-through;
    white-space: nowrap;
}

.vs-oferta-pago {
    font-family: var(--font-tec);
    font-size: 1.05rem;
    line-height: 1.15;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-2);
}

/* El <br> de la etiqueta solo existe para el telefono; la doble barra,
   para el escritorio. */
.vs-oferta-pago br {
    display: none;
}

.vs-oferta-usd {
    font-family: var(--font-tec);
    font-size: 1.05rem;
    line-height: 1.3;
    letter-spacing: .04em;
    color: var(--text-3);
    margin-bottom: 1.25rem;
}

/* LO QUE DICE checkout.js EN data-precio-eco. Vacio = preguntando,
   y entonces no se toca nada: se ve el precio escrito en el HTML. */
[data-precio-eco="listo"] .vs-oferta-usd:empty,
[data-precio-eco="sin-precio"] .vs-oferta-precio,
[data-precio-eco="sin-precio"] .vs-oferta-usd,
[data-precio-eco="vuelta"] {
    display: none;
}

/* EL BOTON VA EN TEAL Y NO EN NARANJA. El naranja es la marca y en
   esta pagina esta reservado a la accion que cobra: la caja de compra
   y su borde izquierdo. Esto no cobra —es la prueba— y la caja a la
   que lleva ya se presenta en teal (.vs-demo-title). En naranja seria
   el mismo color para pagar y para probar, y ademas la misma accion
   de dos colores segun la altura de la pagina.

   RELLENO Y NO CONTORNO, al reves que el boton de la caja de la demo.
   Alli dentro ya se sabe donde se esta; aqui es lo unico pulsable de
   la primera pantalla, para gente que acaba de tocar un boton que
   decia Descargar. Un contorno sobre fondo oscuro no se lee como un
   boton a la primera. */
.btn-prueba {
    --btn-bg: var(--teal);
    --btn-fg: var(--ink-950);
    border-color: var(--teal);
}

/* El barrido de :hover va al blanco del texto y no al naranja que
   hereda de .btn: naranja entrando sobre teal son dos colores
   saturados chocando. Lo mismo que hace .btn-primary. */
.btn-prueba::before {
    background: var(--text);
}

.btn-prueba:hover {
    border-color: var(--text);
}

/* "sin tarjeta" PEGADO AL BOTON: centrado debajo y a .4rem, para que
   se lea como parte de el y no como una linea mas de la pagina. */
.vs-oferta-nota {
    margin-top: .4rem;
    text-align: center;
    font-family: var(--font-tec);
    font-size: 1.05rem;
    line-height: 1.3;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--teal);
}

/* ═══ GRATIS DONDE ESTABA EL PRECIO ══════════════════════════════
   Lo mas grande del hero era "$24.990" justo encima de un boton que
   dice GRATIS, y gana el numero: quien llegaba del anuncio creia que le
   cobraban por probarlo. El 15-oct-2026 el hueco grande pasa a decir lo
   que de verdad se ofrece ahi.

   EL PRECIO SOLO SALE CUANDO EL PRECIO ES LA OFERTA, o sea con cupon.
   Lo decide el mismo data-con-cupon que pone checkout.js, asi que las
   dos caras se excluyen sin que haya un instante con las dos.

   Y EL CASO NORMAL NO NECESITA JAVASCRIPT: sin el atributo -que es como
   nace el HTML- ya se ve GRATIS y el precio esta escondido. El salto
   solo puede ocurrir en la visita con cupon, que es la rara. */
.vs-oferta:not([data-con-cupon]) .vs-oferta-precio,
.vs-oferta:not([data-con-cupon]) .vs-oferta-usd {
    display: none;
}

[data-con-cupon] .vs-oferta-gratis {
    display: none;
}

/* La misma forma que el precio al que sustituye: cifra y etiqueta en una
   linea, alineadas por la base del texto. Ver .vs-oferta-precio. */
.vs-oferta-gratis {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: .25rem .8rem;
    margin-bottom: .2rem;
}

/* Y el mismo peso visual que tenia el precio, para que el ojo encuentre
   algo donde esperaba encontrarlo. En teal y no en naranja: es el color
   con el que el sitio dice "esto no cuesta" —el boton de la prueba y
   "sin tarjeta" ya van en el— y el naranja es el de pagar. */
.vs-oferta-gratis-grande {
    font-family: var(--font);
    font-weight: 800;
    font-size: 2.2rem;
    line-height: 1;
    letter-spacing: -.02em;
    color: var(--teal);
}

/* ═══ EL HERO CUANDO SE LLEGA CON UN CUPON ═══════════════════════
   Lo marca checkout.js con data-con-cupon en cuanto ve ?oferta= en la
   direccion, antes de preguntar nada al servidor: asi no hay parpadeo
   —primero el formulario y un segundo despues los botones de pago—, que
   en el hero es lo que mas se nota.

   LO QUE CAMBIA ES EL ORDEN, NO EL HTML. La caja de pago vive despues
   del .form-msg de la demo porque download-gate.js se queda con el
   primero que encuentra (ver el comentario de vocal-space.html), asi
   que el orden de la pantalla lo pone `order` y no el documento. Por
   eso el bloque pasa a flex aqui y solo aqui: fuera de este estado la
   pagina sigue siendo exactamente la de siempre. */
[data-con-cupon] {
    display: flex;
    flex-direction: column;
}

[data-con-cupon] .vs-oferta-precio { order: 1 }
[data-con-cupon] .vs-oferta-usd    { order: 2 }
[data-con-cupon] .vs-oferta-compra { order: 3 }
[data-con-cupon] .vs-oferta-probar { order: 4 }
[data-con-cupon] .vs-oferta-form   { order: 5 }
[data-con-cupon] > .form-msg       { order: 6 }
[data-con-cupon] .vs-oferta-como   { order: 7 }

/* La caja de pago del hero no es una caja: el hero no lleva recuadros
   —es la regla de toda esta seccion— asi que se le quita el marco que
   trae .checkout y quedan solo los botones. */
.vs-oferta-compra {
    padding: 0;
    background: none;
    border: 0;
    border-radius: 0;
    gap: .6rem;
}

/* La prueba, plegada. Quien llega con el cupon ya dejo su correo: el
   formulario entero ahi arriba le pide otra vez lo que ya hizo. Se
   despliega pulsando la linea, y entonces vuelve tambien el "te
   mandamos el enlace al correo", que explica ese formulario y no la
   compra. */
[data-con-cupon] .vs-oferta-form,
[data-con-cupon] .vs-oferta-como {
    display: none;
}

[data-con-cupon][data-prueba-abierta] .vs-oferta-form {
    display: flex;
}

[data-con-cupon][data-prueba-abierta] .vs-oferta-como {
    display: block;
}

[data-con-cupon][data-prueba-abierta] .vs-oferta-probar {
    display: none;
}

/* La linea que despliega la prueba. Centrada como "sin tarjeta" y el
   resto de lo que va debajo del boton, y sin color de boton: lo que
   tiene que destacar es el pago. Esto es la salida para quien reciba el
   enlace reenviado sin haber probado el plugin nunca. */
.vs-oferta-probar {
    margin-top: .5rem;
    padding: .35rem 0;
    background: none;
    border: 0;
    color: var(--text-3);
    font-family: var(--font);
    font-size: .92rem;
    line-height: 1.45;
    text-align: center;
    cursor: pointer;
}

.vs-oferta-probar span {
    text-decoration: underline;
    text-underline-offset: .2em;
}

.vs-oferta-probar:hover {
    color: var(--text-2);
}

/* COMO LLEGA EL PLUGIN, debajo de "sin tarjeta". En el gris del texto
   secundario y no en teal: "sin tarjeta" es la promesa y tiene que
   seguir siendo lo que mas pesa debajo del boton; esto solo explica.
   Centrado bajo el boton, como ella. */
.vs-oferta-como {
    margin-top: .55rem;
    text-align: center;
    font-size: .92rem;
    line-height: 1.45;
    color: var(--text-3);
}

/* ---------- La oferta en un telefono ----------
   AQUI SUBE ENCIMA DEL PARRAFO, y el HTML no se toca: su orden es el
   de escritorio. La razon son las medidas. Dentro de Instagram la
   pantalla util ronda los 670 px; el cartel del pixel tapa los
   ultimos ~150 en la primera visita, que es TODA visita que viene de
   un anuncio; y el parrafo solo ya acaba a 455. Debajo de el, el
   boton caia detras del cartel. Encima, termina hacia los 395 y se ve
   entero incluso en un iPhone SE.

   :has(.vs-oferta) es para que esto solo le pase al hero que tiene
   oferta. .vc-hero tambien es el de vocal-chain.html, que no vende.

   Pasar a flex no cambia ningun espacio: ningun par de hermanos del
   hero tiene margen por los dos lados, asi que no habia margenes que
   se solaparan y que flex dejara de solapar. */
@media (max-width: 620px) {
    .vc-hero:has(.vs-oferta) {
        display: flex;
        flex-direction: column;
        padding-top: 0;
    }

    .vc-hero:has(.vs-oferta) .vs-oferta {
        order: 1;
    }

    .vc-hero:has(.vs-oferta) .vc-lead {
        order: 2;
    }

    .vc-hero:has(.vs-oferta) .vs-oferta~* {
        order: 3;
    }

    /* Lo que se aprieta para que quepa, sin tocar un solo texto: el
       interlineado del antetitulo —que en un telefono va en dos lineas
       y a 1.6 dejaba un hueco entre ellas como de dos parrafos— y los
       margenes entre antetitulo, titular y precio. */
    .vc-hero:has(.vs-oferta) .vc-eyebrow {
        line-height: 1.3;
        margin-bottom: .9rem;
    }

    .vc-hero:has(.vs-oferta) .vc-title {
        margin-bottom: 1.1rem;
    }

    .vs-oferta {
        padding-top: 0;
        border-top: 0;
        padding-bottom: 1.4rem;
        border-bottom: 1px solid var(--line-soft);
        margin-bottom: 1.4rem;
    }

    /* La etiqueta en dos lineas AL LADO de la cifra, y no en una
       tercera debajo: "$24.990 pago unico, sin suscripcion" no cabe
       en una fila de 335 px. Centrada y no por la base, porque con dos
       lineas la base de la primera dejaria la segunda colgando. */
    .vs-oferta-precio {
        align-items: center;
        flex-wrap: nowrap;
    }

    .vs-oferta-pago br {
        display: inline;
    }

    .vs-oferta-sep {
        display: none;
    }

    .vs-oferta-usd {
        margin-bottom: .8rem;
    }

    /* 50 px de alto y no los 60 de un .btn: la altura de linea que
       hereda (1.6) solo anade aire dentro del boton, y en esta pantalla
       cada fila cuenta. Sigue por encima de los 44 de area tactil. */
    .btn-prueba {
        line-height: 1.2;
    }

    /* El caso que marca el limite es un iPhone SE dentro de Instagram:
       553 px de pantalla y el cartel del pixel empezando en 398. Con el
       interlineado de siempre, "sin tarjeta" acababa en 400. */
    .vs-oferta-nota {
        margin-top: .35rem;
        line-height: 1.15;
    }
}

/* EL FORMULARIO DEL HERO. Puesto el 10 de octubre de 2026: antes aqui
   habia un boton que llevaba al formulario de mas abajo, y ese salto
   era un paso de mas justo donde se decide. Ahora el hueco donde se
   escribe el correo esta donde se toma la decision.

   SIN CAJA, como el resto de .vs-oferta: lo que lo separa del texto de
   arriba es la misma linea fina, no un recuadro. Un formulario metido
   en un marco dentro del hero parte la pantalla en dos. */
.vs-oferta-form {
    display: flex;
    flex-direction: column;
    gap: .6rem;
}

/* "sin tarjeta" vive dentro del formulario, asi que su margen de arriba
   lo pone el gap de la columna y no hace falta el suyo. */
.vs-oferta-form .vs-oferta-nota {
    margin-top: 0;
}

/* La etiqueta del campo existe para quien usa lector de pantalla, y no
   se ve: al lado del titular y del precio, un "> TU CORREO:" encima de
   un hueco con marcador de posicion es una linea que no añade nada.
   No se usa display:none —eso tambien lo esconde del lector— sino el
   recorte de un pixel de siempre. */
.sr-solo {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* El hueco del correo, mas alto que el de la caja de abajo. Aqui se
   escribe con una mano, de pie y mirando el telefono: 52 px es el alto
   del boton que tiene debajo, y los dos juntos se leen como una sola
   pieza. */
.vs-oferta-form .input-y2k {
    padding: .95rem 1rem;
    font-size: 1rem;
}

/* El mensaje del campo solo ocupa sitio cuando dice algo. Sin esto deja
   un hueco entre el correo y el boton que los separa sin motivo. */
.vs-oferta-form .vc-field-msg:empty {
    display: none;
}

/* El consentimiento, mas discreto que en la caja de abajo: ahi es parte
   del formulario y aqui es letra pequena bajo una decision que ya se
   tomo. */
.vs-oferta-form .consent-row {
    font-size: .82rem;
    line-height: 1.4;
    color: var(--text-3);
}

/* ---------- Pantallas bajas: el iPhone SE dentro de Instagram ----------
   553 px de alto utiles y el cartel del pixel empezando en 398. Ahi la
   linea de "te mandamos el enlace" caia detras del cartel hasta que lo
   cerraban. Se aprieta lo que no es texto —el aire del antetitulo, del
   titular y del precio— y entra entera.

   Por ALTO y no por ancho: un telefono normal de 390x844 tiene sitio de
   sobra y no tiene por que ir apretado. */
@media (max-width: 620px) and (max-height: 600px) {
    .vc-hero:has(.vs-oferta) .vc-eyebrow {
        margin-bottom: .6rem;
    }

    .vc-hero:has(.vs-oferta) .vc-title {
        margin-bottom: .8rem;
    }

    .vs-oferta-usd {
        margin-bottom: .45rem;
    }

    .vs-oferta-como {
        margin-top: .4rem;
    }

    /* Unos pixeles de respiro entre el boton y el cartel del pixel: sin
       ellos el boton acaba justo donde empieza el cartel y cualquier
       fuente que caiga distinta lo mete debajo. */
    .vc-hero:has(.vs-oferta) .vc-eyebrow {
        margin-bottom: .45rem;
    }

    /* EL FORMULARIO DEL HERO OCUPA MAS QUE EL BOTON QUE HABIA ANTES —un
       hueco, un boton y el aire entre ellos— y en esta pantalla eso
       dejaba el boton DETRAS del cartel del pixel, que es justo lo que
       no puede pasar: es lo unico que hay que pulsar.
       EL SITIO SE SACA DE LO QUE NO SE TOCA: el antetitulo y el titular.
       Se probo recortando el relleno del hueco y del boton y NO se hace:
       bajaba el area tactil a 43 px, por debajo de los 44 que respeta
       todo el sitio. Antes se encoge la letra que solo se lee. */
    .vs-oferta-form {
        gap: .45rem;
    }

    .vc-hero:has(.vs-oferta) .vc-eyebrow {
        font-size: 1rem;
        line-height: 1.25;
    }

    .vc-hero:has(.vs-oferta) .vc-title {
        font-size: 2rem;
        line-height: 1.05;
    }
}

/* ---------- La prueba de siete dias ----------
   Misma caja que .vc-cta, que es la que ocupaba este sitio cuando
   la pagina pedia correos para la lista de espera. Ahora pide el
   correo para lo mismo —bajarse algo— y no habia razon para que
   pareciera otra cosa. */
.vs-demo {
    /* El enlace del cierre trae aqui. Sin esto la caja se mete debajo de la
       cabecera fija, que es lo mismo que usan .section y .vc-cta. */
    scroll-margin-top: 110px;
    margin-top: 2rem;
    padding: 1.75rem;
    background: linear-gradient(180deg, var(--ink-800), var(--ink-900));
    border: 1px solid var(--line);
    border-radius: 12px;
}

.vs-demo-title {
    font-family: var(--font-tec);
    font-size: 1.3rem;
    letter-spacing: .04em;
    color: var(--teal);
    margin-bottom: .5rem;
}

/* TEAL Y NO NARANJA, y es lo unico de esta pagina que se sale del
   color de la marca a proposito: justo encima esta el boton de
   pago, que es naranja. Dos llamadas del mismo color compiten y la
   de arriba pierde — la que cobra. En teal se lee como la
   alternativa que es. */
.vs-demo-sub {
    font-size: .95rem;
    color: var(--text-2);
    max-width: 56ch;
    margin-bottom: 1.5rem;
}

.vs-demo .download-form {
    border: 0;
    background: transparent;
    padding: 0;
}

/* ---------- Ficha tecnica plegada ---------- */
.vs-specs {
    border: 1px solid var(--line-soft);
    border-radius: 10px;
    background: var(--ink-900);
}

.vs-specs>summary {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .8rem;
    padding: 1.15rem 1.25rem;
    font-family: var(--font-tec);
    font-size: 1.2rem;
    letter-spacing: .05em;
    color: var(--text-2);
    cursor: pointer;
    list-style: none;
    /* 44px de area tactil, como el resto de la pagina. */
    min-height: 44px;
    transition: color var(--t-fast) var(--ease);
}

.vs-specs>summary::-webkit-details-marker {
    display: none;
}

.vs-specs>summary::before {
    content: '';
    width: 9px;
    height: 9px;
    flex-shrink: 0;
    border-right: 1.5px solid var(--accent);
    border-bottom: 1.5px solid var(--accent);
    transform: rotate(-45deg);
    transition: transform var(--t) var(--ease);
}

.vs-specs[open]>summary::before {
    transform: rotate(45deg);
}

.vs-specs>summary:hover {
    color: var(--accent);
}

.vs-specs-hint {
    font-family: var(--font);
    font-size: .88rem;
    letter-spacing: 0;
    color: var(--text-3);
}

.vs-specs .vc-scroll {
    padding: 0 1.25rem 1.25rem;
}

.vs-specs-sub {
    padding: .5rem 1.25rem .75rem;
    font-family: var(--font-tec);
    font-size: 1.1rem;
    letter-spacing: .05em;
    color: var(--text-3);
}

/* ---------- La salida del cierre ---------- */
.vs-close-alt {
    margin-top: 1.25rem;
    font-size: .95rem;
    color: var(--text-2);
}

/* EL AREA TACTIL SE HACE CON PADDING, NO CON ALTURA. La primera
   version era inline-flex con min-height:44px para llegar al minimo
   que respeta el resto del sitio, y salieron DOS rayas debajo del
   enlace: el subrayado del navegador pegado al texto, y el
   border-bottom de aqui caido al fondo de una caja de 44 px.

   Asi no pasa. En un elemento en linea el padding vertical NO mueve
   la maqueta ni el subrayado, pero SI agranda la zona que responde al
   dedo — que era lo unico que se buscaba. El subrayado lo pone el
   navegador, que ya sabe pegarlo al texto. */
.vs-close-alt a {
    color: var(--teal);
    /* .85rem por arriba y por abajo sobre 18 px de texto dan 45 px de zona
       sensible: por encima de los 44 que respeta el resto del sitio. Con .7
       se quedaba en 40. */
    padding-block: .85rem;
    text-underline-offset: .22em;
}

/* =============================================================
   PANTALLAS MUY ESTRECHAS (320 px)
   =============================================================
   A 320 px la pagina se iba 51 px de lado y se podia arrastrar en
   horizontal. No era de ninguna ficha en concreto: son la barra de
   arriba y los enlaces del pie, que estan en TODAS las paginas.

   Los tres culpables, medidos:
     · el enlace "< VOLVER AL INICIO", que a 1.05rem mide 155 px y
       no cabe al lado del logo
     · .footer-links, cuatro enlaces en una fila que no dobla
     · el parrafo del copyright, que no encoge

   320 px no es un movil raro: es un iPhone SE y buena parte de los
   Android baratos, y por ahi entra la mitad del trafico del sitio.
   Una pagina que se arrastra de lado se siente rota aunque se lea
   entera. */
@media (max-width: 380px) {

    .header {
        padding-inline: .75rem;
    }

    /* El menu puede encoger. Sin esto un hijo de flex se planta en
       el ancho de su texto y empuja la barra entera. */
    .nav,
    .nav-link {
        min-width: 0;
    }

    .nav-link {
        font-size: .95rem;
        padding-inline: .25rem;
    }

    .footer {
        padding-inline: 1rem;
    }

    /* Cuatro enlaces no caben en una linea de 320 px. Que doblen. */
    .footer-links {
        flex-wrap: wrap;
        justify-content: center;
        gap: .5rem 1.15rem;
    }

    /* Y que nada de dentro pueda ser mas ancho que la pantalla. */
    .footer p {
        max-width: 100%;
    }
}

/* =============================================================
   LOS CAMPOS QUE APARECEN AL ESCRIBIR EL CORREO
   =============================================================
   El bloque nace con [hidden] en el HTML y lo destapa
   download-gate.js. Aqui solo se le pone la entrada, para que no
   salte de golpe: aparecer es un cambio grande en una caja que la
   persona esta mirando.

   El .download-form es flex con gap, asi que este div seria UN hijo
   y sus campos se amontonarian sin separacion. Por eso repite el
   mismo display y el mismo gap: por dentro se ordena igual que si
   los campos colgaran directamente del formulario. */
.gate-extra {
    display: flex;
    flex-direction: column;
    gap: .8rem;
    animation: gate-abre var(--t) var(--ease) both;
}

@keyframes gate-abre {
    from {
        opacity: 0;
        transform: translateY(-6px);
    }
}

/* Quien pide menos movimiento lo recibe puesto, sin el deslizamiento.
   Aparecer no es decorativo —son los campos que hacen falta para
   enviar—, asi que la animacion se quita y el bloque se queda. */
@media (prefers-reduced-motion: reduce) {
    .gate-extra {
        animation: none;
    }
}
