:root {
  --ink-950: #17122d;
  --ink-900: #241b49;
  --ink-800: #35266b;
  --amber-500: #f4b942;
  --amber-400: #ffc95c;
  --coral-500: #f47c6c;
  --mint-500: #36b69a;
  --paper: #fbfaf7;
  --surface: #ffffff;
  --surface-raised: #ffffff;
  --surface-soft: #f3f0ea;
  --surface-inverse: #17122d;
  --text: #201a34;
  --text-muted: #6f687c;
  --text-on-dark: #fbf9ff;
  --border: #e5e0eb;
  --border-strong: #ccc3d8;
  --focus: #f4b942;
  --danger: #b93846;
  --success: #247d69;
  --shadow-sm: 0 8px 24px rgba(32, 20, 55, .07);
  --shadow-md: 0 20px 50px rgba(32, 20, 55, .12);
  --shadow-glow: 0 28px 80px rgba(244, 185, 66, .2);
  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 24px;
  --radius-xl: 36px;
  /* Espaciado: reticula de 4px. Faltaban los pasos con guion y por eso cada regla
     se inventaba el suyo: habia 5, 7, 9, 11, 13, 22, 26 y 62px sueltos. */
  --space-0-25: 2px;
  --space-0-5: 4px;
  --space-1: 8px;
  --space-1-5: 12px;
  --space-2: 16px;
  --space-2-5: 20px;
  --space-3: 24px;
  --space-4: 32px;
  --space-5: 40px;
  --space-6: 48px;
  --space-8: 64px;
  --space-10: 80px;
  --space-12: 96px;
  --font-display: "Segoe UI Variable Display","Aptos Display","Segoe UI",system-ui,sans-serif;
  --font-body: "Segoe UI Variable Text","Aptos","Segoe UI",system-ui,sans-serif;
  --ease: cubic-bezier(.2,.8,.2,1);

  /* Escala tipografica: 11 pasos, solo los dos ultimos escalan con el ancho.
     El porque de cada peldaño, en DESIGN-SYSTEM.md §1. */
  --fs-1: .6875rem;   /* 11px · micro: sellos, HZ, unidades */
  --fs-2: .75rem;     /* 12px · pie, metadatos, pildoras */
  --fs-3: .8125rem;   /* 13px · texto secundario, interfaz densa */
  --fs-4: .875rem;    /* 14px · interfaz por defecto */
  --fs-5: 1rem;       /* 16px · cuerpo */
  --fs-6: 1.125rem;   /* 18px · cuerpo destacado, entradilla */
  --fs-7: 1.375rem;   /* 22px · titulo de tarjeta */
  --fs-8: 1.75rem;    /* 28px · titulo de seccion */
  --fs-9: 2.25rem;    /* 36px · cifra grande */
  --fs-display: clamp(1.9rem, 4.4vw, 3.2rem);
  --fs-hero: clamp(2.3rem, 5.6vw, 4.2rem);

  --lh-plana: 1;      /* cifras y sellos: sin interlineado que las separe */
  --lh-corta: 1.15;   /* titulos */
  --lh-media: 1.4;    /* interfaz */
  --lh-larga: 1.6;    /* parrafos de lectura */

  --peso-normal: 400;
  --peso-medio: 600;
  --peso-fuerte: 750;
  --peso-maximo: 800;

  /* Escala cromatica: cada banda de frecuencia tiene su color, y siempre el mismo,
     en tarjeta, reproductor e historial. DESIGN-SYSTEM.md §2. */
  --banda-sueno-fg: #4a3aa8;      /* violeta profundo · dormir, descansar */
  --banda-sueno-bg: #eeeaff;
  --banda-calma-fg: #1f6b64;      /* verde azulado · calmar, respirar */
  --banda-calma-bg: #e2f3f0;
  --banda-enfoque-fg: #8a4d10;    /* ambar quemado · concentrarse */
  --banda-enfoque-bg: #fdefd8;
  --banda-energia-fg: #a33a4e;    /* granate · activar, animo */
  --banda-energia-bg: #fdeaee;

  /* ── Radios ────────────────────────────────────────────────────────────────
     Habia 20 valores unicos. Cinco pasos y una constante para lo circular. */
  --radius-xs: 4px;
  --radius-full: 999px;

  /* ── Elevacion ─────────────────────────────────────────────────────────────
     Habia 11 sombras. Tres niveles y un resplandor de marca, y se acabo.
     --shadow-xs es para lo que se apoya (pildoras, campos); no existia y por eso
     habia seis sombras casi-iguales inventadas ahi mismo. */
  --shadow-xs: 0 1px 2px rgba(32, 20, 55, .06);
  --shadow-boton: 0 10px 24px rgba(53, 38, 107, .2);
  --shadow-boton-alta: 0 14px 30px rgba(53, 38, 107, .3);
  --shadow-ambar: 0 10px 34px rgba(244, 185, 66, .45);
  --shadow-sobre-oscuro: 0 30px 80px rgba(0, 0, 0, .25);
  --shadow-barra: 0 18px 50px rgba(0, 0, 0, .32);
  /* Halos: no son sombra de elevacion, son señal de estado. Van aparte para que
     nadie los use como si fueran profundidad. */
  --halo-activo: 0 0 0 4px rgba(54, 182, 154, .22);
  --halo-suave: 0 0 0 5px rgba(54, 182, 154, .12);

  /* Movimiento: tres duraciones y una curva. Mas variedad no da mas calidad, da
     una app en la que cada cosa tarda algo distinto sin motivo. `--dur-toque` es
     corto a proposito: pasados ~120ms deja de sentirse como respuesta al dedo.
     Todo esto lo anula `prefers-reduced-motion`. DESIGN-SYSTEM.md §5. */
  --dur-toque: 110ms;
  --dur-base: 200ms;
  --dur-lenta: 340ms;
  /* Salida rapida al principio y frenada suave: es la curva del movimiento de
     interfaz, la que hace que algo parezca que responde en vez de que arranca. */
  --ease-salida: cubic-bezier(.16,1,.3,1);

  --badge-pro-bg: #ece6ff;
  --badge-pro-fg: #2d205b;
  --badge-pro-border: #c9bafd;
  --badge-quantum-bg: #ffe5df;
  --badge-quantum-fg: #7a352d;
  --badge-quantum-border: #ffb7aa;
  /* Era #0284c7, un cian que sobrevivio a la migracion a tinta/ambar/coral y no
     pertenece a ninguna paleta de la marca. Violeta de marca, 7.1:1 sobre su fondo. */
  --badge-category-bg: #efeafd;
  --badge-category-fg: #453083;
  --trial-banner-bg: #fff1c9;
  --trial-banner-fg: #4a3510;
  --trial-banner-border: #f5d374;
  --evidence-chip-bg: #fff2cd;
  --evidence-chip-fg: #785721;
  --evidence-chip-border: #f3d27c;
  --hz-tag-bg: #fff1c9;
  --hz-tag-fg: #59411b;
  --lock-pill-bg: #ffe2dd;
  --lock-pill-fg: #6d332d;
  --status-error-bg: #fff0f2;
  --status-error-fg: #991b1b;
  --status-error-border: #f3c0c6;
  --status-success-bg: #eaf8f4;
  --status-success-fg: #065f46;
  --status-success-border: #afe1d5;
}

[data-theme="dark"] {
  --paper: #100c20;
  --surface: #1a1430;
  --surface-raised: #231a40;
  --surface-soft: #2b2247;
  --text: #f8f5ff;
  --text-muted: #b7afc6;
  --border: #3c315a;
  --border-strong: #584a78;
  --shadow-xs: 0 1px 2px rgba(0, 0, 0, .3);
  --shadow-sm: 0 8px 24px rgba(0, 0, 0, .25);
  --shadow-md: 0 20px 50px rgba(0, 0, 0, .34);

  /* La escala cromatica, en oscuro. No son los mismos colores aclarados: sobre
     fondo casi negro un tinte claro se lava y pierde identidad. Cada banda lleva
     su propio par medido contra su fondo, no contra el papel. */
  --banda-sueno-fg: #c3b6ff;
  --banda-sueno-bg: #2c2258;
  --banda-calma-fg: #86ded1;
  --banda-calma-bg: #163b38;
  --banda-enfoque-fg: #ffd79a;
  --banda-enfoque-bg: #43310f;
  --banda-energia-fg: #ffb0be;
  --banda-energia-bg: #4a1f2a;

  --badge-pro-bg: #32255e;
  --badge-pro-fg: #e2d9ff;
  --badge-pro-border: #5b469e;
  --badge-quantum-bg: #522520;
  --badge-quantum-fg: #ffd8d2;
  --badge-quantum-border: #8c4238;
  /* Mismo cian huerfano que en el tema claro. Violeta claro de marca, 8.4:1. */
  --badge-category-bg: #322659;
  --badge-category-fg: #d6c9ff;
  --trial-banner-bg: #473315;
  --trial-banner-fg: #ffecb3;
  --trial-banner-border: #805c26;
  --evidence-chip-bg: #443516;
  --evidence-chip-fg: #ffe8a3;
  --evidence-chip-border: #755b25;
  --hz-tag-bg: #443516;
  --hz-tag-fg: #ffe8a3;
  --lock-pill-bg: #4c2622;
  --lock-pill-fg: #ffd4cf;
  --status-error-bg: #3f1a1d;
  --status-error-fg: #fecdd3;
  --status-error-border: #881337;
  --status-success-bg: #11382b;
  --status-success-fg: #a7f3d0;
  --status-success-border: #065f46;
  /* Los dos de abajo solo estaban definidos en el tema claro. Sobre fondo casi
     negro se quedaban en 3.4:1, por debajo del minimo legible. */
  --success: #5fd0b4;
  --danger: #ff8f9c;
}

/* Cifras tabulares: sin esto un 1 ocupa menos que un 8 y el numero SALTA al
   cambiar de sesion. Lo dan las fuentes del sistema: 0 KB. DESIGN-SYSTEM.md §1. */
.preview-frequency, .price, .plan-price, .timer-display, .hz-tag,
.stats-grid, .admin-metrics,
input[type="number"], td, th {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* Enlace de salto. No se oculta con `display:none` ni con `visibility:hidden`:
   eso lo sacaria tambien del orden de tabulacion y no serviria de nada. Se saca
   de la pantalla con `transform`, que es lo unico que no lo quita del foco. */
.saltar-al-contenido {
  position: fixed; top: var(--space-1); left: var(--space-1); z-index: 100;
  padding: var(--space-1-5) var(--space-2);
  color: var(--text-on-dark); background: var(--ink-900);
  border-radius: var(--radius-sm); font-size: var(--fs-4); font-weight: var(--peso-fuerte);
  text-decoration: none;
  transform: translateY(-200%);
  transition: transform var(--dur-base) var(--ease-salida);
}
.saltar-al-contenido:focus-visible { transform: translateY(0); }

* { box-sizing: border-box; margin: 0; padding: 0; }
html {
  overflow-x: clip;
  scroll-behavior: smooth;
  /* Corta el rebote elastico al llegar al final. Instalada como PWA, ese rebote
     deja ver el fondo del navegador por debajo del contenido y es de las cosas
     que mas delatan que no es una app. No usa `none` en el eje X porque eso
     tambien mataria el gesto de "atras" por deslizamiento. */
  overscroll-behavior-y: none;
}
body {
  min-width: 320px;
  /* `100dvh` sigue a la barra del navegador movil cuando aparece y desaparece;
     `100vh` se queda con la altura maxima y deja un hueco al final. Los dos, en
     este orden: un navegador que no entienda `dvh` descarta esa linea y se queda
     con la de arriba. Con una sola se quedaria sin altura minima. */
  min-height: 100vh;
  min-height: 100dvh;
  overflow-x: clip;
  background:
    radial-gradient(circle at 10% 0, rgba(244,185,66,.12), transparent 30rem),
    radial-gradient(circle at 90% 25%, rgba(244,124,108,.1), transparent 28rem),
    var(--paper);
  color: var(--text);
  font-family: var(--font-body);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
body::before {
  position: fixed;
  inset: 0;
  z-index: -1;
  content: "";
  pointer-events: none;
  opacity: .28;
  background-image: repeating-radial-gradient(ellipse at 50% 5%, transparent 0 34px, rgba(53,38,107,.07) 35px 36px);
  mask-image: linear-gradient(to bottom, #000, transparent 70%);
}
button, input { font: inherit; }
button { color: inherit; }
button, a { -webkit-tap-highlight-color: transparent; }
button:focus-visible, a:focus-visible, input:focus-visible, summary:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
}
svg { width: 1.25em; height: 1.25em; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.svg-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.hidden { display: none !important; }

/* `theme-boot.js` añade esta pista antes del primer pintado. Un visitante nuevo
   ve la landing inmediatamente; una sesión guardada espera la validación sin
   mostrar por un instante la portada equivocada. */
.session-hint #landingView { visibility: hidden; }

.button-danger {
  background: color-mix(in srgb, var(--danger) 12%, var(--surface-raised));
  border-color: var(--danger);
  color: var(--danger);
}
.button-danger:hover { background: var(--danger); color: white; }

.plan-features-compact { margin-bottom: 0; }
.billing-cancel-button { margin-top: var(--space-2); }
.payments-history { margin-top: var(--space-2); }
.payments-title { margin-bottom: var(--space-1); }
.payments-empty { color: var(--text-muted); font-size: var(--fs-2); }
.payment-skeleton-row { height: var(--space-2-5); margin-bottom: var(--space-1); }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
.shell { width: min(1180px, calc(100% - 40px)); margin-inline: auto; }

h1, h2, h3, h4 { font-family: var(--font-display); letter-spacing: -.035em; line-height: 1.1; }
p { color: var(--text-muted); }
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  color: var(--ink-800);
  font: 800 var(--fs-2)/1 var(--font-display);
  letter-spacing: .13em;
  text-transform: uppercase;
}
[data-theme="dark"] .eyebrow { color: var(--amber-400); }
.eyebrow > span { width: 20px; height: 2px; border-radius: var(--radius-xs); background: var(--coral-500); }
.eyebrow-light { color: var(--amber-400); }

/* UN sistema de boton, no dos. Los `.btn-` de las tarjetas del catalogo eran
   planos y no se parecian al primario de la portada. Se traen a la misma base y
   NO se renombra ninguna: las escribe el JS. DESIGN-SYSTEM.md §6.2. */
.button,
.btn-primary, .btn-secondary, .btn-plan-action {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  border: 1px solid transparent;
  border-radius: var(--radius-full);
  padding: var(--space-1-5) var(--space-2);
  font-family: var(--font-display);
  font-weight: 750;
  font-size: var(--fs-4);
  cursor: pointer;
  transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease), background var(--dur-base) var(--ease);
}
/* El `:hover` va detras de `(hover:hover)` a proposito. En una pantalla tactil no
   existe "pasar por encima": el navegador aplica el `:hover` al tocar y lo deja
   puesto hasta que tocas otra cosa, asi que el boton se quedaba levantado despues
   de pulsarlo. Aqui solo entra donde hay raton de verdad. */
@media (hover: hover) and (pointer: fine) {
  .button:hover:not(:disabled),
  .btn-primary:hover:not(:disabled), .btn-secondary:hover:not(:disabled),
  .btn-plan-action:hover:not(:disabled) { transform: translateY(-2px); }
}
/* Lo que SI hay en un movil es el momento del dedo apoyado, y no habia ninguna
   respuesta: pulsabas y no pasaba nada hasta que terminaba el JavaScript. Es lo
   que mas delata a una web disfrazada de app. Se hunde con `scale`, que va por
   el compositor y no obliga a recalcular el diseño. */
.button:active:not(:disabled),
.btn-primary:active:not(:disabled), .btn-secondary:active:not(:disabled),
.btn-plan-action:active:not(:disabled) { transform: scale(.96); transition-duration: var(--dur-toque); }
.button:disabled, .btn-primary:disabled, .btn-secondary:disabled,
.btn-plan-action:disabled { opacity: .58; cursor: not-allowed; }

/* Un primario y solo uno. `.btn-primary` y `.btn-upgrade` entran aqui: son el
   mismo trabajo (la accion que se quiere que pulses) en otra pantalla. */
.button-primary, .btn-primary, .btn-upgrade { color: #fff; background: linear-gradient(135deg, var(--ink-800), #4a3292); box-shadow: var(--shadow-boton); }
.button-primary:hover:not(:disabled), .btn-primary:hover:not(:disabled),
.btn-upgrade:hover:not(:disabled) { box-shadow: var(--shadow-boton-alta); }
.button-secondary { color: var(--ink-900); background: var(--amber-500); }
/* El fantasma: borde y superficie, sin peso. `.btn-secondary` es esto. */
.button-ghost, .btn-secondary { background: var(--surface); border-color: var(--border); color: var(--text); }
/* Estado "ya lo tienes": no es un boton apagado, es informacion. Sin sombra, sin
   elevacion al pasar, y el cursor lo dice. */
.btn-current { color: var(--text-muted); background: var(--surface-soft); border-color: var(--border); cursor: default; }
.button-accent { color: var(--ink-950); background: linear-gradient(135deg, var(--amber-500), var(--coral-500)); }
.button-large { min-height: 54px; padding-inline: var(--space-3); }
.button-block { width: 100%; }
.button.compact { min-height: 38px; padding: var(--space-1) var(--space-1-5); }
.icon-button {
  width: 44px; height: 44px; display: inline-grid; place-items: center;
  border: 1px solid var(--border); border-radius: 50%; background: var(--surface); cursor: pointer;
}
.text-link { border: 0; background: transparent; color: inherit; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; font-weight: 650; }

.site-header {
  min-height: 88px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}
.brand { display: inline-flex; align-items: center; gap: var(--space-1-5); color: var(--text); text-decoration: none; }
.brand img { width: 48px; height: 48px; object-fit: contain; }
.brand span { display: flex; flex-direction: column; }
.brand strong { font: 800 var(--fs-6)/1.2 var(--font-display); letter-spacing: -.03em; }
.brand small { color: var(--text-muted); font-size: var(--fs-2); }
.site-actions, .app-header-actions { display: flex; align-items: center; gap: var(--space-1-5); }

.hero {
  min-height: 650px;
  display: grid;
  grid-template-columns: 1.08fr .92fr;
  align-items: center;
  gap: var(--space-8);
  padding-block: var(--space-6) var(--space-8);
}
.hero h1 { max-width: 690px; margin: var(--space-2-5) 0; font-size: var(--fs-hero); letter-spacing: -.075em; }
.hero-lead { max-width: 650px; font-size: var(--fs-6); }
.hero-actions { display: flex; flex-wrap: wrap; gap: var(--space-1-5); margin-top: var(--space-4); }
/* Los dos botones del hero competian: el ambar de "Escuchar muestra" pesa mas que
   el violeta de "Empezar prueba Pro", asi que la accion secundaria le ganaba la
   atencion a la que cobra. Dos primarios es no tener ninguno. La muestra pasa a
   fantasma: sigue estando, sigue siendo facil de encontrar, y deja de gritar. */
.hero-actions .button-secondary { color: var(--text); background: var(--surface); border-color: var(--border-strong); }
.hero-actions .button-secondary svg { color: var(--coral-500); }
.hero-note { margin-top: var(--space-2); font-size: var(--fs-3); }
.hero-product { position: relative; min-height: 550px; display: grid; place-items: center; isolation: isolate; }
.resonance-orbit {
  position: absolute; border: 1px solid rgba(53,38,107,.18); border-radius: 50%; z-index: -1;
  animation: breathe 6s var(--ease) infinite alternate;
}
.orbit-one { width: 520px; height: 520px; }
.orbit-two { width: 400px; height: 400px; animation-delay: -2s; }
.player-preview {
  position: relative;
  width: min(390px, 92vw);
  min-height: 510px;
  overflow: hidden;
  padding: var(--space-3);
  color: var(--text-on-dark);
  text-align: center;
  background:
    radial-gradient(circle at 50% 45%, rgba(244,185,66,.2), transparent 37%),
    linear-gradient(155deg, #302260, #17122d 70%);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-glow), 0 40px 90px rgba(23,18,45,.32);
}
.player-preview::before { position: absolute; inset: 0; content: ""; background: repeating-radial-gradient(circle at 50% 44%, transparent 0 52px, rgba(255,255,255,.06) 53px 54px); }
.preview-top { position: relative; display: flex; align-items: center; gap: var(--space-1); color: #d9d2e8; font: 700 var(--fs-1)/1 var(--font-display); letter-spacing: .1em; }
.preview-top .evidence-chip { margin-left: auto; }
.status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--mint-500); box-shadow: var(--halo-suave); }
.preview-mark { position: relative; display: grid; place-items: center; height: 210px; }
.preview-mark img { width: 170px; height: 170px; object-fit: contain; }
.preview-frequency { position: relative; color: #fff; font: 800 var(--fs-display)/1 var(--font-display); letter-spacing: -.07em; }
.preview-frequency small { color: var(--amber-400); font-size: var(--fs-5); }
.player-preview h2 { position: relative; margin: var(--space-1-5) 0 var(--space-1); font-size: var(--fs-7); }
.player-preview > p:not(.preview-frequency) { position: relative; color: #aaa1bd; font-size: var(--fs-4); }
.preview-progress { position: relative; height: 4px; margin: var(--space-3) 0; overflow: hidden; background: rgba(255,255,255,.15); border-radius: var(--radius-xs); }
.preview-progress span { display: block; width: 42%; height: 100%; background: linear-gradient(90deg,var(--coral-500),var(--amber-500)); }
.preview-play { position: relative; width: 62px; height: 62px; border: 0; border-radius: 50%; color: var(--ink-950); background: var(--amber-500); cursor: pointer; }

.trust-strip {
  display: grid;
  grid-template-columns: repeat(3,1fr);
  border-block: 1px solid var(--border);
}
.trust-strip > div { display: flex; align-items: center; gap: var(--space-1-5); padding: var(--space-3); border-right: 1px solid var(--border); }
.trust-strip > div:last-child { border: 0; }
.trust-strip svg { flex: 0 0 auto; color: var(--coral-500); font-size: var(--fs-7); }
.trust-strip span { display: flex; flex-direction: column; color: var(--text-muted); font-size: var(--fs-3); }
.trust-strip strong { color: var(--text); font-size: var(--fs-4); }

/* `content-visibility: auto` le dice al navegador que no pinte lo que esta fuera
   de la ventana. Dos cosas a la vez:

   1. La landing tiene 932 nodos y los pintaba todos en la primera carga, con la
      CPU a 4x. Esto es coste que no se paga hasta que hace falta.
   2. Las animaciones en bucle infinito -las orbitas del hero, el brillo de los
      esqueletos- SE DETIENEN al salir de pantalla. La regla dice que ninguna
      animacion puede correr en bucle fuera del viewport, y hasta ahora corrian.

   `contain-intrinsic-size` es obligatorio: sin el, el navegador asume alto cero
   para lo que no ha pintado, la barra de desplazamiento salta y el CLS -que hoy
   esta en 0- se rompe. El valor es una estimacion del alto tipico de una seccion;
   se corrige sola en cuanto se pinta una vez. */
.section { padding-block: var(--space-10); content-visibility: auto; contain-intrinsic-size: auto 900px; }
/* El hero NO lleva `content-visibility`: es lo primero que se ve y saltarselo no
   ahorra nada, solo retrasa el LCP. */
.section-heading { max-width: 720px; margin: 0 auto var(--space-6); text-align: center; }
.section-heading h2 { margin: var(--space-2) 0; font-size: var(--fs-display); }
.section-heading > p:last-child { font-size: var(--fs-6); }
.steps-grid { display: grid; grid-template-columns: repeat(3,1fr); gap: var(--space-2); }
.steps-grid article {
  min-height: 260px;
  position: relative;
  padding: var(--space-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
/* Estaba en `var(--border-strong)` (#ccc3d8) sobre blanco: 1,7:1 medido, cuando
   19px en peso 800 es texto grande y exige 3:1. Era el unico fallo de contraste
   real de la portada. `--text-muted` da 4,9:1 y ademas hace que el numero se lea
   como parte de la secuencia y no como marca de agua decorativa. */
.steps-grid article > span { position: absolute; top: var(--space-2-5); right: var(--space-2-5); color: var(--text-muted); font: var(--peso-maximo) var(--fs-7) var(--font-display); opacity: .65; }
.steps-grid svg { width: 42px; height: 42px; color: var(--coral-500); margin-bottom: var(--space-4); }
.steps-grid h3 { margin-bottom: var(--space-1-5); font-size: var(--fs-7); }
.steps-grid p { font-size: var(--fs-5); }

.agent-showcase { padding-block: var(--space-10); color: var(--text-on-dark); background: var(--surface-inverse); overflow: hidden; }
.agent-showcase-inner { display: grid; grid-template-columns: 1fr .9fr; align-items: center; gap: var(--space-8); }
.agent-showcase h2 { max-width: 650px; margin: var(--space-2) 0 var(--space-2-5); font-size: var(--fs-display); }
.agent-showcase p { color: #b9b0c9; }
.check-list { margin-top: var(--space-3); list-style: none; }
.check-list li { margin-top: var(--space-1-5); color: #ddd6e9; }
.check-list li::before { margin-right: var(--space-1-5); color: var(--amber-400); content: "✓"; }
.agent-dialog { position: relative; padding: var(--space-3); border: 1px solid rgba(255,255,255,.12); border-radius: var(--radius-xl); background: rgba(255,255,255,.06); box-shadow: var(--shadow-sobre-oscuro); }
.dialog-message { max-width: 88%; margin-bottom: var(--space-2); padding: var(--space-2) var(--space-2); border-radius: var(--radius-md); font-size: var(--fs-5); }
.dialog-message.user-msg { margin-left: auto; color: var(--ink-950); background: var(--amber-500); }
.dialog-message.agent-msg { color: #efeaf6; background: #30264d; border-top-left-radius: 5px; }
.dialog-source { margin-top: var(--space-2-5); padding-top: var(--space-2); border-top: 1px solid rgba(255,255,255,.12); color: #a8a0b8; font-size: var(--fs-2); }
.dialog-source span { margin-right: var(--space-1); color: var(--amber-400); font-weight: 700; }

.pricing-grid { display: grid; grid-template-columns: repeat(3,1fr); gap: var(--space-2); align-items: stretch; }
.price-card { position: relative; display: flex; flex-direction: column; min-height: 480px; padding: var(--space-4); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); }
.price-card.featured { transform: translateY(-12px); border: 2px solid var(--amber-500); box-shadow: var(--shadow-md); }
.recommended { position: absolute; top: -13px; right: 22px; padding: var(--space-1) var(--space-1-5); color: var(--ink-950); background: var(--amber-500); border-radius: var(--radius-full); font: 800 var(--fs-1) var(--font-display); letter-spacing: .08em; }
.plan-pill { align-self: flex-start; letter-spacing: .07em; }
.plan-name { color: var(--text); font-size: var(--fs-6); font-weight: 700; }
.admin-subtitle { margin: var(--space-2-5) 0 var(--space-1); font-size: var(--fs-5); font-weight: 700; color: var(--text); }
.admin-hint { margin: 0 0 var(--space-1-5); font-size: var(--fs-3); color: var(--text-muted); }
.admin-hint code { font-size: var(--fs-2); background: var(--surface-2, var(--badge-category-bg)); padding: var(--space-0-25) var(--space-0-5); border-radius: var(--radius-xs); }
.plan-detail-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-1-5); }
.plan-price { font-weight: 700; color: var(--success); }
.plan-subscription-label { font-size: var(--fs-4); color: var(--success); font-weight: 700; margin-bottom: var(--space-1); }
.plan-description { font-size: var(--fs-4); color: var(--text-muted); margin-bottom: var(--space-1-5); }
.favorite-button.is-active { color: var(--amber-500); }

/* Aviso breve para acciones que no tienen un `form-status` cerca, como marcar un
   favorito desde el reproductor o desde una tarjeta del catalogo. Antes esas
   acciones fallaban en silencio: la estrella se pintaba igual aunque el guardado
   no hubiera llegado al servidor. */
.app-toast {
  position: fixed; left: 50%; bottom: calc(78px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%); z-index: 60; max-width: min(92vw, 420px);
  display: flex; align-items: center; gap: var(--space-1);
  padding: var(--space-1-5) var(--space-2); border-radius: var(--radius-sm); font-size: var(--fs-3); text-align: left;
  color: var(--status-error-fg); background: var(--status-error-bg);
  border: 1px solid var(--status-error-border); box-shadow: var(--shadow-md);
}
.app-toast.success { color: var(--status-success-fg); background: var(--status-success-bg); border-color: var(--status-success-border); }
.price-card h3 { margin: var(--space-2-5) 0 var(--space-1-5); font-size: var(--fs-7); }
.price { min-height: 56px; color: var(--text); font: 800 var(--fs-8)/1.1 var(--font-display); }
.price small { display: block; margin-top: var(--space-0-5); color: var(--text-muted); font-size: var(--fs-2); }
.price-card ul { flex: 1; margin: var(--space-3) 0; padding: 0; list-style: none; }
.price-card li { position: relative; margin-bottom: var(--space-1-5); padding-left: var(--space-3); color: var(--text-muted); font-size: var(--fs-4); }
.price-card li::before { position: absolute; left: 0; color: var(--mint-500); content: "✓"; font-weight: 800; }

.faq-grid { max-width: 860px; margin-inline: auto; border-top: 1px solid var(--border); }
.faq-grid details { border-bottom: 1px solid var(--border); padding: var(--space-2-5) var(--space-0-5); }
.faq-grid summary { cursor: pointer; list-style: none; font: 750 var(--fs-5) var(--font-display); }
.faq-grid summary::after { float: right; content: "+"; color: var(--coral-500); font-size: var(--fs-7); }
.faq-grid details[open] summary::after { content: "−"; }
.faq-grid p { padding-top: var(--space-1-5); }

.site-footer { padding: var(--space-5) 0; color: var(--text-on-dark); background: var(--surface-inverse); }
.footer-inner { display: grid; grid-template-columns: 1fr 1.2fr auto; align-items: center; gap: var(--space-4); }
.brand-inverse { color: #fff; }
.brand-inverse small { color: #aca4bd; }
.site-footer p { color: #aaa2ba; font-size: var(--fs-3); }
/* Los tres enlaces legales median 20px de alto: se fallan con el pulgar y hay que
   apuntar. El relleno vertical los lleva a 44 sin mover el diseño, porque el `gap`
   negativo del margen los mantiene visualmente donde estaban. */
.site-footer nav { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-0-5) var(--space-2); margin: -var(--space-1-5) 0; color: #d9d3e4; font-size: var(--fs-3); }
.site-footer nav a { display: inline-flex; align-items: center; min-height: 44px; }

/* Application */
.app-shell { width: min(1240px, calc(100% - 32px)); margin: 0 auto; padding: var(--space-2) 0 var(--space-10); }
.app-header {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  min-height: 74px; padding: var(--space-1-5) var(--space-2); background: rgba(251,250,247,.8);
  border: 1px solid var(--border); border-radius: var(--radius-md); backdrop-filter: blur(18px); box-shadow: var(--shadow-sm);
}
[data-theme="dark"] .app-header { background: rgba(26,20,48,.82); }
/* A 390px los cinco controles del encabezado no caben en una fila: el escudo caia
   a una segunda linea y el encabezado se partia en dos alturas distintas. No es
   que sobre espacio, es que sobra un control. */
.app-header-actions { display: flex; align-items: center; gap: var(--space-1); flex: none; }
.device-status-badge { display: inline-flex; align-items: center; min-height: 36px; padding: var(--space-1) var(--space-1-5); border-radius: var(--radius-full); font: var(--peso-fuerte) var(--fs-2) var(--font-display); white-space: nowrap; }
@media (max-width: 560px) {
  /* En movil el sello del plan se queda con el nombre corto y el subtitulo de la
     marca desaparece: lo que importa arriba es saber en que plan estas y poder
     cambiar el tema, no leer "Tu espacio de escucha" en cada pantalla. */
  .app-header { min-height: 62px; padding: var(--space-1) var(--space-1-5); gap: var(--space-1); }
  .app-header .brand small { display: none; }
  .app-header .brand img { width: 36px; height: 36px; }
  .device-status-badge { min-height: 32px; font-size: var(--fs-1); }
}
.trial-banner { margin-top: var(--space-1-5); padding: var(--space-1-5) var(--space-2); color: var(--trial-banner-fg); background: var(--trial-banner-bg); border: 1px solid var(--trial-banner-border); border-radius: var(--radius-sm); text-align: center; font-weight: 700; font-size: var(--fs-3); }
.nav-tabs { display: grid; grid-template-columns: repeat(5,1fr); gap: var(--space-1); margin: var(--space-2) 0 var(--space-3); padding: var(--space-1); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md); box-shadow: var(--shadow-sm); }
.nav-tab { min-height: 48px; display: flex; align-items: center; justify-content: center; gap: var(--space-1); border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--text-muted); cursor: pointer; font: 700 var(--fs-3) var(--font-display); }
.nav-tab.active { color: #fff; background: var(--ink-800); }
.tab-content { display: none; }
.tab-content.active { display: block; animation: pestana-entra var(--dur-base) var(--ease-salida); }
@keyframes pestana-entra { from { opacity: 0; transform: translateY(6px); } }
.dashboard-grid, .account-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2-5); align-items: start; }
.panel, .player-panel {
  padding: var(--space-3); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
}
.panel h2 { margin: var(--space-1-5) 0 var(--space-1-5); font-size: var(--fs-8); }
.panel-intro { margin-bottom: var(--space-3); font-size: var(--fs-4); }
fieldset { border: 0; margin-bottom: var(--space-2-5); }
legend, .form-group label { margin-bottom: var(--space-1); font: 700 var(--fs-3) var(--font-display); }
.segmented { display: grid; grid-template-columns: repeat(3,1fr); gap: var(--space-1); padding: var(--space-0-5); background: var(--surface-soft); border-radius: var(--radius-sm); }
/* Cuatro opciones en una rejilla de tres dejaban la cuarta sola en la fila de
   abajo. 2x2 reparte el ancho y "Preparar descanso" cabe en una linea. */
.segmented--goal { grid-template-columns: repeat(2,1fr); }
.segmented--time { grid-template-columns: repeat(4,1fr); }
.segmented label { cursor: pointer; }
.segmented input { position: absolute; opacity: 0; outline: none; }
.segmented span { display: grid; place-items: center; min-height: 42px; padding: var(--space-1); border-radius: var(--radius-sm); color: var(--text-muted); font-size: var(--fs-3); font-weight: 700; }
.segmented span { transition: background var(--dur-base) var(--ease-salida), color var(--dur-base) var(--ease-salida), box-shadow var(--dur-base) var(--ease-salida), transform var(--dur-toque) var(--ease-salida); }
.segmented label:active span { transform: scale(.95); }
.segmented input:checked + span { color: var(--text); background: var(--surface); box-shadow: var(--shadow-sm); }
.segmented input:focus-visible + span { outline: 3px solid var(--focus); outline-offset: 2px; }
.result-area { margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--border); }
.result-area > p { margin: var(--space-1) 0 var(--space-2-5); }
.agent-heading { display: flex; align-items: center; gap: var(--space-1-5); }
.agent-heading img { object-fit: contain; }
.agent-heading h2 { margin: var(--space-0-25) 0 0; }
.agent-chat { height: 330px; display: flex; flex-direction: column; gap: var(--space-1-5); overflow-y: auto; padding: var(--space-2); background: var(--surface-soft); border: 1px solid var(--border); border-radius: var(--radius-md); }
.chat-msg { max-width: 88%; padding: var(--space-1-5) var(--space-2); border-radius: var(--radius-md); font-size: var(--fs-4); line-height: 1.5; }
.chat-msg.agent-msg { align-self: flex-start; color: var(--text); background: var(--surface); border: 1px solid var(--border); border-top-left-radius: 4px; }
.chat-msg.user-msg { align-self: flex-end; color: #fff; background: var(--ink-800); border-top-right-radius: 4px; }
.chat-msg.safety { border-color: #e6a8af; background: #fff0f2; }
.chat-msg.typing { color: var(--text-muted); }
.chat-msg .play-chat-rec-btn { display: flex; margin-top: var(--space-1-5); min-height: 36px; padding: var(--space-1) var(--space-1-5); }
.chat-form { display: flex; gap: var(--space-1); margin-top: var(--space-1-5); }
.chat-form input, .panel-title-row input, .form-group input {
  width: 100%; min-height: 46px; padding: var(--space-1-5) var(--space-1-5); color: var(--text); background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
}
.chat-form input { flex: 1; }

.player-panel { position: relative; max-width: 980px; margin-inline: auto; padding: var(--space-4); overflow: hidden; }
.player-info { padding-right: var(--space-8); }
.player-info h2 { margin: var(--space-1-5) 0 var(--space-1); font-size: var(--fs-display); }
.favorite-button { position: absolute; top: 28px; right: 28px; font-size: var(--fs-7); }
.visualizer-wrap { position: relative; height: 300px; display: grid; place-items: center; margin: var(--space-3) 0; overflow: hidden; background: linear-gradient(150deg,#2c2058,#141026); border-radius: var(--radius-lg); }
.visualizer-wrap::before { position: absolute; inset: -30%; content: ""; background: repeating-radial-gradient(circle,transparent 0 54px,rgba(244,185,66,.08) 55px 56px); }
#oscilloscopeCanvas { position: relative; width: 100%; height: 100%; }
.visualizer-center { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
.visualizer-center img { opacity: .35; }
.player-primary-actions { display: flex; align-items: center; gap: var(--space-2); }
.player-primary-actions .button { min-width: 220px; }
.timer-display { color: var(--text-muted); font-size: var(--fs-3); }
.control-grid { display: grid; grid-template-columns: repeat(3,1fr); gap: var(--space-2); margin: var(--space-4) 0 var(--space-2-5); }
.range-control { display: grid; grid-template-columns: 1fr auto; gap: var(--space-1-5); color: var(--text-muted); font-size: var(--fs-3); font-weight: 650; }
.control-grid output { color: var(--text); }
.range-control input { grid-column: 1/-1; width: 100%; height: 44px; accent-color: var(--coral-500); cursor: pointer; }
/* Las fichas de filtro se desbordaban a la derecha y "Binaurales" salia cortada,
   asi que parecia rota en vez de desplazable. Con desplazamiento horizontal y
   anclaje, se lee como una fila que continua. El relleno lateral negativo hace
   que la primera ficha empiece alineada con el resto del contenido y la ultima
   no se pegue al borde. */
.chip-row, .chip-scroller {
  display: flex; gap: var(--space-1); margin-top: var(--space-1-5);
  overflow-x: auto; scrollbar-width: none;
  scroll-snap-type: x proximity;
  padding-inline: var(--space-3); margin-inline: calc(var(--space-3) * -1);
}
.chip-row::-webkit-scrollbar, .chip-scroller::-webkit-scrollbar { display: none; }
.chip-row > *, .chip-scroller > * { flex: none; scroll-snap-align: start; }
.chip-row .button, .chip-scroller .button { min-height: 44px; padding: var(--space-1) var(--space-1-5); font-size: var(--fs-2); }
.timer-btn.active, .filter-chip.active { color: #fff; background: var(--ink-800); border-color: var(--ink-800); }
.panel-title-row { display: flex; justify-content: space-between; align-items: flex-end; gap: var(--space-3); margin-bottom: var(--space-2); }
.panel-title-row input { max-width: 300px; }
.auto-grid { display: grid; grid-template-columns: repeat(auto-fit,minmax(240px,1fr)); gap: var(--space-2); margin-top: var(--space-2-5); }
/* `min-height: 300px` + `space-between` era la causa del hueco muerto en medio de
   cada tarjeta: con una descripcion corta, el reparto empujaba el pie hasta los
   300px. En una rejilla de varias columnas eso igualaba alturas; en movil, donde
   la tarjeta es de ancho completo y solo hay una por fila, no igualaba nada y
   gastaba media pantalla por tarjeta. `gap` + `margin-top:auto` en el pie da la
   misma alineacion sin inventar altura. */
/* `position: relative` y `overflow: hidden` son para el filete de banda de arriba:
   sin ellos, la barra de color se sale del radio de la esquina. */
.program-card { position: relative; overflow: hidden; display: flex; flex-direction: column; gap: var(--space-0-5); padding: var(--space-2-5); background: var(--surface-raised); border: 1px solid var(--border); border-radius: var(--radius-md); transition: transform var(--dur-base) var(--ease),box-shadow var(--dur-base) var(--ease); }
/* El pie va dentro de un `<div>` sin clase que SI es hijo directo de la tarjeta.
   Ponerle `margin-top:auto` a `.card-actions` no hacia nada: no es un elemento
   flexible de `.program-card`, sino nieto. En movil da igual porque hay una
   tarjeta por fila, pero en la rejilla de escritorio es lo que alinea los botones
   de todas las tarjetas de una fila a la misma altura. */
.program-card > div:last-child { margin-top: auto; }
@media (hover: hover) and (pointer: fine) {
  .program-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
}
/* La tarjeta entera es pulsable, asi que responde entera. Se hunde menos que un
   boton porque una superficie grande con el mismo `scale` se percibe exagerada. */
.program-card:active { transform: scale(.985); transition-duration: var(--dur-toque); }
.program-card.card-locked { opacity: .78; }
.card-header { display: flex; justify-content: space-between; gap: var(--space-1); margin-bottom: var(--space-2); }
/* .65rem son 10,4px. A esa altura una etiqueta en mayusculas deja de leerse y
   pasa a ser textura. 11,4px es el minimo al que sigue siendo informacion. */
/* Pildoras: un cuerpo, y lo unico que cambia es el par de color. Eran once
   clases con once rellenos distintos para la misma forma. */
.badge, .hz-tag, .lock-pill, .plan-pill, .evidence-chip, .badge-category {
  display: inline-flex;
  align-items: center;
  gap: var(--space-0-5);
  padding: var(--space-0-5) var(--space-1-5);
  border: 1px solid transparent;
  border-radius: var(--radius-full);
  background: var(--surface-soft);
  color: var(--text-muted);
  font-family: var(--font-display);
  font-size: var(--fs-2);
  font-weight: var(--peso-fuerte);
  line-height: var(--lh-media);
  white-space: nowrap;
}
/* Va DESPUES de `.badge` a proposito. La etiqueta de categoria se pinta con
   `class="badge badge-category"`, y `.badge` se declaraba mas abajo: con la misma
   especificidad ganaba la ultima, asi que el color de categoria nunca llego a
   verse y todas las tarjetas mostraban la etiqueta en gris. Se creyo arreglado
   dos veces porque la clase SI estaba aplicada en el HTML; lo que fallaba era el
   orden en la hoja. Doblar la clase fija la especificidad y lo deja inmune al orden. */
/* Los pares de color. Van DESPUES del cuerpo: con igual especificidad gana la
   ultima regla, y por eso `.badge` pisaba a `.badge-category` y todas las
   categorias salian grises. Se doblo la clase para que gane la variante. */
.badge.badge-category, .badge-category { color: var(--badge-category-fg); background: var(--badge-category-bg); }
.hz-tag { color: var(--hz-tag-fg); background: var(--hz-tag-bg); }
.lock-pill { color: var(--lock-pill-fg); background: var(--lock-pill-bg); }
.evidence-chip { color: var(--evidence-chip-fg); background: var(--evidence-chip-bg); border-color: var(--evidence-chip-border); }
.badge-free { color: var(--text-muted); background: var(--surface-soft); border-color: var(--border); }
.badge-pro { color: var(--badge-pro-fg); background: var(--badge-pro-bg); border-color: var(--badge-pro-border); }
.badge-quantum { color: var(--badge-quantum-fg); background: var(--badge-quantum-bg); border-color: var(--badge-quantum-border); }

/* ── La escala cromatica aplicada ────────────────────────────────────────────
   Una sesion lleva su banda de color en las tres superficies donde aparece. El
   selector es por atributo para que valga tanto en el markup estatico como en el
   que pinta el JS el dia que emita `data-banda` (ver B4 del backlog). */
[data-banda="sueno"]   { --banda-fg: var(--banda-sueno-fg);   --banda-bg: var(--banda-sueno-bg); }
[data-banda="calma"]   { --banda-fg: var(--banda-calma-fg);   --banda-bg: var(--banda-calma-bg); }
[data-banda="enfoque"] { --banda-fg: var(--banda-enfoque-fg); --banda-bg: var(--banda-enfoque-bg); }
[data-banda="energia"] { --banda-fg: var(--banda-energia-fg); --banda-bg: var(--banda-energia-bg); }
/* La banda se declara en la TARJETA, y `--banda-fg` baja por herencia hasta la
   pildora. Asi el color viaja con la sesion y no hay que repetir el atributo en
   cada hijo: el mismo dato pinta el filete de arriba y la etiqueta de categoria. */
.badge[data-banda], .hz-tag[data-banda],
[data-banda] .badge-category { color: var(--banda-fg); background: var(--banda-bg); }
/* El filete de banda: una barra de 3px arriba de la tarjeta. Es lo que convierte
   el catalogo de lista en mapa. Si la tarjeta no declara banda, no hay filete —
   no aparece una barra gris de relleno. */
.program-card[data-banda]::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 3px;
  background: var(--banda-fg); border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.card-title { margin-bottom: var(--space-1); font-size: var(--fs-6); }
.card-desc { font-size: var(--fs-3); }
.card-meta { display: flex; flex-wrap: wrap; gap: var(--space-1-5); margin: var(--space-2) 0; color: var(--text-muted); font-size: var(--fs-2); }
.card-actions { display: flex; gap: var(--space-1); }
/* 44px de alto y de ancho: son los botones que mas se pulsan de la app —
   "Escuchar" y el "+" de favoritos— y estaban en 40x41. El "+" era el peor:
   cuadrado de 41px es justo el tamaño al que el pulgar falla y se acaba
   pulsando la tarjeta entera. */
.card-actions .button, .card-actions .btn-primary, .card-actions .btn-secondary { min-height: 44px; min-width: 44px; }
/* Los botones de tarjeta van un paso mas pequeños que los de portada: caben dos
   por fila a 320px sin romperse. Es lo unico que los diferencia; el aspecto lo
   heredan del sistema unico de arriba. */
.card-actions .btn-primary, .card-actions .btn-secondary { font-size: var(--fs-3); padding-inline: var(--space-2); }
.studio-panel { min-height: 560px; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--space-6) var(--space-3); color: #fff; text-align: center; background: radial-gradient(circle at 50% 45%,rgba(244,185,66,.14),transparent 30%),linear-gradient(150deg,#2d2058,#121023); border-radius: var(--radius-xl); }
.studio-panel h2 { margin: var(--space-2) 0; font-size: var(--fs-hero); }
.studio-panel > p { max-width: 620px; color: #b9b0c9; }
.studio-display { width: min(440px,100%); margin: var(--space-4) 0 var(--space-3); padding: var(--space-4); background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.13); border-radius: var(--radius-lg); }
.studio-display span, .studio-display small { display: block; color: #ada5bc; font-size: var(--fs-2); letter-spacing: .1em; }
.studio-display strong { display: block; margin: var(--space-1-5) 0; color: var(--amber-400); font: 800 var(--fs-display) var(--font-display); }
.studio-progress { height: 5px; margin-top: var(--space-2-5); overflow: hidden; background: rgba(255,255,255,.12); border-radius: var(--radius-xs); }
.studio-progress span { width: 0; height: 100%; background: var(--coral-500); }
.profile-card { text-align: center; }
.account-avatar { width: 86px; height: 86px; display: grid; place-items: center; margin: 0 auto var(--space-2); border-radius: 50%; color: #fff; background: var(--ink-800); font: 800 var(--fs-9) var(--font-display); }
.profile-card > p { margin: var(--space-1) 0 var(--space-1-5); }
.profile-card .plan-pill { align-self: auto; }
.stats-grid { display: grid; grid-template-columns: repeat(3,1fr); margin-top: var(--space-3); border-top: 1px solid var(--border); }
.stats-grid > div { display: flex; flex-direction: column; padding: var(--space-2-5) var(--space-1) 0; border-right: 1px solid var(--border); }
.stats-grid > div:last-child { border: 0; }
.stats-grid strong { font: 800 var(--fs-5) var(--font-display); }
.stats-grid span { color: var(--text-muted); font-size: var(--fs-2); }
.account-actions { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-top: var(--space-2-5); }
.plan-features-list { margin: var(--space-2) 0; list-style: none; }
.plan-features-list li { display: flex; gap: var(--space-1); margin-bottom: var(--space-1); color: var(--text-muted); font-size: var(--fs-3); }
.check-icon { color: var(--mint-500); font-weight: 800; }
.mobile-only-nav { display: none; }

/* Modals */
.modal-overlay {
  position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: var(--space-2);
  background: rgba(11,8,23,.72); backdrop-filter: blur(10px);
  animation: velo-entra var(--dur-base) var(--ease-salida);
}
@keyframes velo-entra { from { opacity: 0; } }
.modal-card {
  position: relative; width: min(500px,100%); max-height: min(90vh,850px); overflow-y: auto;
  padding: var(--space-4); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-md);
  /* Sube un poco y crece muy poco: lo justo para que se lea como que llega,
     no como que estaba ahi y alguien encendio la luz. */
  animation: modal-entra var(--dur-lenta) var(--ease-salida);
  /* Su propio scroll no arrastra el de la pagina de detras. */
  overscroll-behavior: contain;
}
@keyframes modal-entra { from { opacity: 0; transform: translateY(16px) scale(.97); } }
.modal-card h2 { margin: var(--space-1-5) 0 var(--space-2); font-size: var(--fs-8); }
.modal-card > p { margin-bottom: var(--space-2); }
.modal-close-btn { position: absolute; top: 13px; right: 15px; width: 42px; height: 42px; border: 0; background: transparent; color: var(--text-muted); cursor: pointer; font-size: var(--fs-8); }
.modal-brand { width: 76px; height: 76px; display: grid; place-items: center; margin-bottom: var(--space-2); background: var(--surface-soft); border-radius: var(--radius-md); }
.form-group { display: flex; flex-direction: column; margin-bottom: var(--space-2); }
.consent-row { display: flex; align-items: flex-start; gap: var(--space-1); margin-bottom: var(--space-2); color: var(--text-muted); font-size: var(--fs-2); }
.consent-row input { margin-top: var(--space-0-5); }
.form-status { min-height: var(--space-2); margin: var(--space-1) 0; padding: var(--space-1-5); border-radius: var(--radius-sm); font-size: var(--fs-3); }
.form-status:empty { padding: 0; }
.form-status.error { color: var(--status-error-fg); background: var(--status-error-bg); border: 1px solid var(--status-error-border); }
.form-status.success { color: var(--status-success-fg); background: var(--status-success-bg); border: 1px solid var(--status-success-border); }

/* El error nunca solo por color: icono + texto. Va en `::before` porque el JS
   escribe el mensaje con `textContent` y borraria un simbolo puesto en el markup. */
.app-toast::before,
.form-status.error::before, .form-status.success::before {
  flex: none; font-size: var(--fs-4); line-height: var(--lh-plana);
}
.app-toast::before { content: "⚠"; }
.app-toast.success::before { content: "✓"; }
.form-status.error::before { content: "⚠ "; }
.form-status.success::before { content: "✓ "; }

/* Estados vacios: los cuatro que habia eran texto suelto centrado, sin salida.
   Lo que el JS aun pinta con `style=` en linea, en DESIGN-BACKLOG.md B2. */
.catalog-empty {
  grid-column: 1 / -1;
  display: flex; flex-direction: column; align-items: center; gap: var(--space-1-5);
  padding: var(--space-6) var(--space-3);
  color: var(--text-muted); text-align: center;
  background: var(--surface-soft); border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
}
.catalog-empty::before {
  content: "◠"; display: block; font-size: var(--fs-9); line-height: var(--lh-plana);
  color: var(--border-strong);
}
.catalog-empty p { max-width: 34ch; font-size: var(--fs-4); }
.auth-modal-card > .text-link { display: block; margin: var(--space-1-5) auto; }
.auth-modal-card > .button-ghost { margin-top: var(--space-1-5); }
.option-stack { display: grid; gap: var(--space-1); }
.option-stack label { display: flex; gap: var(--space-1); padding: var(--space-1-5); background: var(--surface-soft); border-radius: var(--radius-sm); }
.modal-actions { display: flex; justify-content: flex-end; gap: var(--space-1); margin-top: var(--space-2-5); }
.safety-card { text-align: center; }
.safety-card > svg { width: 52px; height: 52px; color: var(--coral-500); }
.legal-card { width: min(720px,100%); }
.legal-card h3 { margin: var(--space-3) 0 var(--space-1); }
.legal-card ul { padding-left: var(--space-2-5); color: var(--text-muted); }
.legal-card li { margin-bottom: var(--space-1); }
.legal-page { padding-block: var(--space-4) var(--space-8); }
.legal-page > .brand { margin-bottom: var(--space-3); }
.legal-document { max-width: 820px; margin-inline: auto; }
.legal-document h1 { margin: var(--space-1-5) 0 var(--space-4); font-size: var(--fs-hero); }
.legal-document h2 { margin: var(--space-3) 0 var(--space-1); font-size: var(--fs-7); }
.legal-document ul { padding-left: var(--space-2-5); color: var(--text-muted); }
.legal-document li { margin-bottom: var(--space-1); }
.paywall-modal-card { width: min(940px,100%); }
.paywall-header { text-align: center; margin-bottom: var(--space-3); }
.paywall-header h2 { font-size: var(--fs-9); }
.paywall-plans-grid { display: grid; grid-template-columns: repeat(3,1fr); gap: var(--space-1-5); }
.paywall-plan-card { position: relative; display: flex; flex-direction: column; min-height: 400px; padding: var(--space-2-5); border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface-raised); }
.paywall-plan-card.plan-pro { border: 2px solid var(--amber-500); }
.paywall-plan-card h3 { margin: var(--space-2) 0 var(--space-1); }
.paywall-plan-card .plan-features-list { flex: 1; }
.plan-price { font: 800 var(--fs-7) var(--font-display); }
.plan-desc { margin-top: var(--space-1); font-size: var(--fs-3); }
.popular-ribbon { position: absolute; top: -11px; right: 15px; padding: var(--space-0-5) var(--space-1); color: var(--ink-950); background: var(--amber-500); border-radius: var(--radius-full); font: 800 var(--fs-1) var(--font-display); }
/* `.btn-plan-action` estaba en 42px de alto: cuatro por debajo del minimo tactil,
   en el boton que contrata el plan. Hereda 44 del sistema unico. */
.btn-plan-action { width: 100%; font-size: var(--fs-3); }
.security-guarantee { margin-top: var(--space-1-5); text-align: center; font-size: var(--fs-2); }

.bottom-nav {
  /* `calc`, no `max`. Con `max(10px, 34px)` en un iPhone con barra de inicio la
     nav se pegaba justo encima del indicador, sin aire. Lo que se quiere es
     "10px por encima de la zona segura", que es una suma, no un maximo. */
  position: fixed; left: 10px; right: 10px; bottom: calc(10px + env(safe-area-inset-bottom)); z-index: 500;
  align-items: center; justify-content: space-around; padding: var(--space-1); background: rgba(23,18,45,.94); border: 1px solid rgba(255,255,255,.13); border-radius: var(--radius-md); box-shadow: var(--shadow-barra); backdrop-filter: blur(14px);
  /* Una barra de navegacion no se selecciona ni se arrastra al mantener pulsado:
     eso es lo que delata que por debajo hay una pagina web. */
  -webkit-user-select: none; user-select: none;
}
/* .58rem son 9,3px: por debajo de lo que se lee de un vistazo con el pulgar
   encima. Las barras de pestañas nativas rondan los 10-11px. */
.bottom-nav-item { min-width: 54px; min-height: 48px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-0-25); border: 0; border-radius: var(--radius-sm); color: #a9a0bd; background: transparent; cursor: pointer; font: 650 var(--fs-1)/1 var(--font-display); letter-spacing: -.01em; }
.bottom-nav-item svg { font-size: var(--fs-7); }
.bottom-nav-item.active { color: var(--ink-950); background: var(--amber-500); }
/* La pastilla activa se desliza en vez de saltar de sitio. */
.bottom-nav-item { transition: color var(--dur-base) var(--ease-salida), background var(--dur-base) var(--ease-salida), transform var(--dur-toque) var(--ease-salida); }
.bottom-nav-item:active { transform: scale(.9); }

.admin-panel { max-width: 1180px; margin-inline: auto; }
.admin-metrics { display: grid; grid-template-columns: repeat(4,1fr); gap: var(--space-1-5); margin: var(--space-3) 0; }
.admin-metrics > div { padding: var(--space-2); border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface-soft); }
.admin-metrics span { display: block; color: var(--text-muted); font-size: var(--fs-2); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; }
.admin-metrics strong { display: block; margin-top: var(--space-1); font: 800 var(--fs-7) var(--font-display); }
.admin-table-wrap { max-width: 100%; overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius-md); }
.admin-table { width: 100%; min-width: 760px; border-collapse: collapse; background: var(--surface); }
.admin-table th, .admin-table td { padding: var(--space-2) var(--space-2); border-bottom: 1px solid var(--border); text-align: left; vertical-align: middle; }
.admin-table th { color: var(--text-muted); background: var(--surface-soft); font-size: var(--fs-2); text-transform: uppercase; letter-spacing: .05em; }
.admin-table td { font-size: var(--fs-4); }
.admin-table tbody tr:last-child td { border-bottom: 0; }
.admin-user-name { display: block; color: var(--text); font-weight: 750; }
.admin-user-email { display: block; color: var(--text-muted); font-size: var(--fs-2); }
.admin-plan-control { display: flex; align-items: center; gap: var(--space-1); }
.admin-plan-control select { min-height: 40px; padding: var(--space-1) var(--space-1-5); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text); background: var(--surface); }

/* ── Estados que faltaban ────────────────────────────────────────────────────
   Una app se juzga por lo que hace mientras NO tiene la respuesta todavia. Aqui
   no habia nada: la rejilla del catalogo se vaciaba y quedaba en blanco, y el
   agente decia "Pensando…" en texto plano, que parece que se colgo. */

/* Esqueletos: ocupan el sitio exacto que va a ocupar el contenido, asi que al
   llegar los datos nada salta. Un spinner centrado no consigue eso. */
.esqueleto {
  position: relative;
  overflow: hidden;
  background: var(--surface-soft);
  border-radius: var(--radius-md);
}
.esqueleto::after {
  position: absolute;
  inset: 0;
  content: "";
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.42), transparent);
  animation: brillo 1.35s infinite;
}
[data-theme="dark"] .esqueleto::after {
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.08), transparent);
}
@keyframes brillo { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

/* Los tres puntos del agente. Que se muevan dice "sigue trabajando"; un texto
   quieto durante seis segundos dice "se rompio". */
.puntos-escribiendo { display: inline-flex; align-items: center; gap: var(--space-0-5); margin-left: var(--space-1); vertical-align: middle; }
.puntos-escribiendo span {
  width: 5px; height: 5px; border-radius: 50%;
  background: currentColor; opacity: .35;
  animation: latido-punto 1.25s infinite;
}
.puntos-escribiendo span:nth-child(2) { animation-delay: .18s; }
.puntos-escribiendo span:nth-child(3) { animation-delay: .36s; }
@keyframes latido-punto { 0%,60%,100% { opacity: .3; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-3px); } }

/* Las tarjetas del catalogo entran escalonadas. El retraso lo pone el JS con
   `--i`; se corta a los 10 primeros para que la ultima no espere medio segundo. */
.program-card { animation: entrar-tarjeta var(--dur-lenta) var(--ease-salida) backwards; animation-delay: calc(var(--i, 0) * 40ms); }
@keyframes entrar-tarjeta { from { opacity: 0; transform: translateY(14px); } }

/* El aviso flotante aparecia y desaparecia de golpe, con `display:none`. */
.app-toast { animation: entrar-aviso var(--dur-base) var(--ease-salida); }
@keyframes entrar-aviso { from { opacity: 0; transform: translate(-50%, 14px); } }

/* Mientras suena audio, el boton respira al ritmo de una respiracion tranquila.
   Es el unico movimiento continuo de la app y esta puesto a proposito: da una
   señal permanente de que hay sonido saliendo aunque el telefono este en
   silencio o los auriculares desconectados.
   La clase `.playing` ya la ponia y quitaba el JavaScript desde siempre, pero no
   existia ninguna regla para ella: estaba muerta. */
.button.playing { animation: respirar-boton 3.6s var(--ease) infinite; }
@keyframes respirar-boton {
  0%, 100% { box-shadow: var(--shadow-boton); }
  50% { box-shadow: var(--shadow-ambar); }
}

/* `reveal` se quedo sin usos al pasar el cambio de pestaña a `pestana-entra`.
   Se retira en vez de dejarlo: un keyframe huerfano es lo que hace que la
   siguiente persona lo reutilice creyendo que es el que manda. */
@keyframes breathe { from { transform: scale(.96); opacity: .5; } to { transform: scale(1.04); opacity: 1; } }

@media (max-width: 900px) {
  .hero { grid-template-columns: 1fr; padding-top: var(--space-4); text-align: center; }
  .hero-copy .eyebrow { justify-content: center; }
  .hero-lead { margin-inline: auto; }
  .hero-actions { justify-content: center; }
  .hero-product { min-height: 520px; }

  /* ── El arreglo de conversion de esta fase ─────────────────────────────────
     En escritorio el hero es de dos columnas y la tarjeta del reproductor -"432
     Hz, Pausa de llegada"- se ve junto al titular. Es lo mas persuasivo de la
     pagina: es el producto, no una promesa sobre el producto.

     Al colapsar a una columna, esa tarjeta caia DEBAJO del titular, de la
     entradilla de cinco lineas, de dos botones y de una nota. En un movil eso es
     media pantalla de scroll antes de ver nada del producto. En el dispositivo
     donde vive este producto, el producto era invisible.

     `order` reordena la columna sin tocar el HTML: titular, PRODUCTO, y despues
     el argumento. El lector de pantalla y el orden de tabulacion siguen el DOM,
     que no cambia, asi que esto no rompe la navegacion por teclado. */
  .hero-copy { display: contents; }
  .hero-copy .eyebrow { order: 1; }
  .hero h1 { order: 2; }
  .hero-product { order: 3; }
  /* La accion va ANTES del argumento. En escritorio se lee titular → argumento →
     boton porque hay sitio para los tres de un vistazo. En una columna de 390px
     no lo hay, y la entradilla son cinco lineas: dejarla en medio empujaba el
     boton de prueba fuera de la primera pantalla. Quien ya esta convencido por
     el titular y por la tarjeta no necesita leer el parrafo para pulsar. */
  .hero-actions { order: 4; margin-top: var(--space-2-5); }
  .hero-lead { order: 5; margin-top: var(--space-1); }
  .hero-note { order: 6; }

  /* Subir la tarjeta no basta: a tamaño de escritorio se come la pantalla entera
     y empuja el boton de prueba fuera. El objetivo es que quepan LAS DOS COSAS —
     el producto y la accion— en el primer golpe de vista, asi que la tarjeta se
     compacta: el logotipo pasa de 170 a 104px y desaparece la orbita decorativa,
     que en una columna estrecha no se lee como profundidad, se lee como ruido. */
  .hero-product { min-height: 0; }
  /* Las orbitas decorativas se quitan: en una columna estrecha no se leen como
     profundidad, se leen como ruido detras del contenido. */
  .resonance-orbit { display: none; }
  .agent-showcase-inner { grid-template-columns: 1fr; }
  .steps-grid, .pricing-grid { grid-template-columns: 1fr; }
  .price-card { min-height: auto; }
  .price-card.featured { transform: none; }
  .footer-inner { grid-template-columns: 1fr; }
  .dashboard-grid, .account-grid { grid-template-columns: 1fr; }
  .paywall-plans-grid { grid-template-columns: 1fr; }
}

@media (max-width: 720px) {
  .shell { width: min(100% - 24px,1180px); }
  .site-header { min-height: 74px; }
  .brand small { display: none; }
  /* El boton de tema estaba oculto justo en movil, que es donde la app se usa de
     noche y donde no hay otra forma de cambiarlo. Se queda, algo mas estrecho. */
  .site-actions .icon-button { width: 40px; height: 40px; font-size: var(--fs-5); }
  /* 40px se queda corto para el pulgar; 44 es el minimo de las guias de iOS y
     Android. El ancho se recupera apretando el relleno lateral, no la altura. */
  /* 40px se queda corto para el pulgar; 44 es el minimo de las guias de iOS y
     Android. El ancho se recupera apretando el relleno lateral, no la altura.
     `nowrap` porque "Probar 14 días" partia en dos lineas y descuadraba la fila. */
  .site-actions .button { min-height: 44px; padding: var(--space-1) var(--space-1-5); font-size: var(--fs-2); white-space: nowrap; }
  .site-actions { gap: var(--space-1); flex-shrink: 0; }
  /* La coletilla bajo el nombre no cabe cuando el encabezado lleva cuatro cosas. */
  .site-header .brand small { display: none; }
  .site-header .brand img { width: 38px; height: 38px; }
  /* El nombre cede primero: el logo ya identifica la marca, y lo que no puede
     encogerse son los dos botones que llevan a registrarse. */
  .site-header .brand { min-width: 0; }
  .site-header .brand strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .hero { min-height: auto; gap: var(--space-2-5); padding-bottom: var(--space-6); }
  .hero h1 { font-size: var(--fs-hero); }
  /* Estas cinco reglas mantenian la tarjeta a tamaño de escritorio (470px de alto
     minimo) en una pantalla de 844. Con la tarjeta ya subida sobre la entradilla,
     eso empujaba el boton de prueba fuera del primer golpe de vista: se veia el
     producto pero no la accion. Compactada, caben las dos cosas. */
  .hero-product { min-height: 0; }
  .player-preview { min-height: 0; padding: var(--space-2-5); }
  .preview-mark { height: 112px; }
  .preview-mark img { width: 100px; height: 100px; }
  .preview-progress { margin: var(--space-2) 0; }
  .preview-play { width: 52px; height: 52px; }
  .trust-strip { grid-template-columns: 1fr; }
  .trust-strip > div { border-right: 0; border-bottom: 1px solid var(--border); }
  .section { padding-block: var(--space-8); }
  .app-shell { width: min(100% - 20px,1240px); padding-bottom: var(--space-12); }
  .app-header { align-items: flex-start; }
  .app-header .brand strong { font-size: var(--fs-4); }
  .app-header-actions { flex-wrap: wrap; justify-content: flex-end; }
  .app-header-actions .icon-button { width: 44px; height: 44px; }
  .device-status-badge { min-height: 34px; font-size: var(--fs-2); }
  .desktop-nav { display: none; }
  .mobile-only-nav { display: flex; }
  .hero-product { overflow: clip; }
  .resonance-orbit { max-width: calc(100vw - 48px); max-height: calc(100vw - 48px); }
  .panel, .player-panel { padding: var(--space-2-5); border-radius: var(--radius-md); }
  .visualizer-wrap { height: 220px; border-radius: var(--radius-md); }
  .control-grid { grid-template-columns: 1fr; }
  .panel-title-row { align-items: stretch; flex-direction: column; }
  .panel-title-row input { max-width: none; }
  .chip-scroller { flex-wrap: nowrap; overflow-x: auto; padding-bottom: var(--space-0-5); scrollbar-width: thin; }
  .chip-scroller > * { flex: 0 0 auto; }
  .stats-grid { grid-template-columns: 1fr 1fr 1fr; }
  .admin-metrics { grid-template-columns: 1fr 1fr; }
  .modal-card { padding: var(--space-3) var(--space-2); }
}

@media (max-width: 412px) {
  /* Por debajo de esto no caben logo + nombre + tres controles sin que algo se
     parta. Se va el nombre escrito, que es lo unico redundante: el simbolo de
     al lado dice lo mismo. Verificado a 360 y 390px. */
  .site-header .brand strong { display: none; }
}

@media (max-width: 440px) {
  .site-actions .button-ghost { display: inline-flex; }
  .hero-actions { flex-direction: column; }
  .hero-actions .button { width: 100%; }
  /* Estos dos `min-height` eran el ultimo resto de la tarjeta de escritorio: la
     mantenian en 415px de alto aunque el contenido ocupara 300, con 80px de vacio
     al fondo. La tarjeta ahora mide lo que mide su contenido. */
  .hero-product { min-height: 0; }
  .player-preview { min-height: 0; padding: var(--space-2-5); border-radius: var(--radius-lg); }
  .preview-top .evidence-chip { display: none; }
  .preview-frequency { font-size: var(--fs-9); }
  .app-header { padding: var(--space-1) var(--space-1-5); }
  .app-header .brand img { width: 38px; height: 38px; }
  .app-header-actions { gap: var(--space-0-5); }
  /* El de la prueba de sonido sí sobra en una barra estrecha; el de instalar NO.
     Estaba oculto justo en el único sitio donde se instala una PWA. */
  .app-header-actions #quickSoundTestBtn { display: none !important; }
  .app-header-actions #pwaInstallBtn { padding-inline: var(--space-1-5); }

  /* Los segmentados se quedan en fila.
     Colapsarlos a una columna convertía el check-in —la acción diaria, tres
     preguntas— en tres pantallas de scroll. "Baja/Media/Alta" cabe de sobra en
     390px: son ~115px por opción. Lo que no cabe es el texto largo, y eso se
     resuelve bajando el tamaño y dejando que parta en dos líneas, no apilando. */
  .segmented span { padding-inline: var(--space-0-25); font-size: var(--fs-2); line-height: 1.2; text-align: center; }
  .segmented--time { grid-template-columns: repeat(4,1fr); }
  .chat-form { flex-direction: column; }
  .chat-form .button { width: 100%; }
  .player-primary-actions { align-items: stretch; flex-direction: column; }
  .player-primary-actions .button { width: 100%; min-width: 0; }
  .modal-actions { flex-direction: column-reverse; }
  .modal-actions .button { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

/* ── Widget del especialista en la landing ──────────────────────────────────
   Flotante, por encima de la página pero por debajo de los modales. Usa los
   tokens de arriba para que no parezca un injerto de otra app. */
.pa-widget {
  position: fixed;
  right: var(--space-3);
  bottom: var(--space-3);
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-1);
  font-family: var(--font-body);
}
.pa-widget.pa-hidden { display: none; }
/* A 390px el lanzador ocupaba casi el ancho entero y tapaba el parrafo del hero.
   Un invitador flotante tiene que verse; taparle al visitante lo que esta leyendo
   es otra cosa. Se compacta, sin perder la etiqueta: un circulo con un icono no
   invita a nada. */
@media (max-width: 560px) {
  .pa-widget { right: var(--space-2); bottom: var(--space-2); }
  .pa-launcher { padding: var(--space-1) var(--space-2); font-size: var(--fs-3); gap: var(--space-1); }
}

.pa-launcher {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1-5) var(--space-2-5);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-full);
  background: var(--surface-inverse);
  color: var(--text-on-dark);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  box-shadow: var(--shadow-md);
  transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .pa-launcher:hover { transform: translateY(-2px); box-shadow: var(--shadow-glow); }
}
.pa-launcher:active { transform: scale(.95); transition-duration: var(--dur-toque); }
.pa-launcher:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
.pa-launcher-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--mint-500);
  box-shadow: var(--halo-activo);
}
.pa-widget.pa-open .pa-launcher { display: none; }

.pa-panel {
  width: min(380px, calc(100vw - var(--space-3) * 2));
  max-height: min(560px, calc(100vh - var(--space-5)));
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.pa-panel[hidden] { display: none; }

.pa-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--surface-inverse);
  color: var(--text-on-dark);
}
.pa-head-title { margin: 0; font-weight: 600; font-size: var(--fs-5); }
.pa-head-sub { margin: var(--space-0-25) 0 0; font-size: var(--fs-3); opacity: .72; }
.pa-close {
  border: 0; background: transparent; color: inherit;
  font-size: var(--fs-8); line-height: 1; cursor: pointer; padding: 0 var(--space-0-5); opacity: .8;
}
.pa-close:hover { opacity: 1; }
.pa-close:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--radius-sm); }

.pa-log {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: var(--space-3);
  display: flex; flex-direction: column; gap: var(--space-2);
  background: var(--paper);
}
.pa-msg { max-width: 88%; }
.pa-msg p { margin: 0; padding: var(--space-1-5) var(--space-2); border-radius: var(--radius-md); font-size: var(--fs-5); line-height: 1.5; }
.pa-msg-agent { align-self: flex-start; }
.pa-msg-agent p { background: var(--surface); border: 1px solid var(--border); color: var(--text); }
.pa-msg-user { align-self: flex-end; }
.pa-msg-user p { background: var(--ink-800); color: var(--text-on-dark); }
.pa-pending p { opacity: .6; font-style: italic; }

.pa-rec {
  margin-top: var(--space-1);
  padding: var(--space-2);
  border: 1px solid var(--border);
  border-left: 3px solid var(--amber-500);
  border-radius: var(--radius-md);
  background: var(--surface);
}
.pa-rec-name { margin: 0 !important; padding: 0 !important; font-weight: 600; font-size: var(--fs-5) !important; background: none !important; border: 0 !important; }
.pa-rec-meta { margin: var(--space-0-25) 0 var(--space-2) !important; padding: 0 !important; font-size: var(--fs-3) !important; color: var(--text-muted); background: none !important; border: 0 !important; }
.pa-rec-cta { width: 100%; }

.pa-chips { display: flex; flex-wrap: wrap; gap: var(--space-1); padding: 0 var(--space-3) var(--space-2); background: var(--paper); }
.pa-chip {
  border: 1px solid var(--border-strong); background: var(--surface);
  border-radius: var(--radius-full); padding: var(--space-1) var(--space-1-5); font: inherit; font-size: var(--fs-3);
  color: var(--text-muted); cursor: pointer;
}
.pa-chip:hover { color: var(--text); border-color: var(--ink-800); }
.pa-chip:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

.pa-form { display: flex; gap: var(--space-1); padding: var(--space-2) var(--space-3) var(--space-1); border-top: 1px solid var(--border); }
.pa-input {
  flex: 1 1 auto; min-width: 0;
  padding: var(--space-1-5) var(--space-2); font: inherit; font-size: var(--fs-5);
  border: 1px solid var(--border-strong); border-radius: var(--radius-md);
  background: var(--surface); color: var(--text);
}
.pa-input:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; border-color: var(--ink-800); }
.pa-send {
  flex: 0 0 auto; width: 44px; border: 0; border-radius: var(--radius-md);
  background: var(--ink-800); color: var(--text-on-dark); cursor: pointer;
}
.pa-send svg { width: 20px; height: 20px; }
.pa-send:hover { background: var(--ink-950); }
.pa-send:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

.pa-legal { margin: 0; padding: 0 var(--space-3) var(--space-2); font-size: var(--fs-2); color: var(--text-muted); }

/* En móvil el PANEL ocupa el ancho útil. El LANZADOR no.
   Con `align-items: stretch` el invitador medía 358 de 390 px, o sea que se leía
   como un segundo boton a nueve pixeles del de "Empezar prueba Pro". Dos cosas del
   mismo tamaño, una encima de otra, compiten: el visitante no sabe cuál es la
   accion. El panel abierto sí debe ocupar el ancho; el lanzador se cierra a su
   contenido y se va a la esquina, que es donde un invitador flotante no estorba. */
@media (max-width: 560px) {
  .pa-widget { right: var(--space-2); left: var(--space-2); bottom: var(--space-2); align-items: flex-end; }
  .pa-launcher { align-self: flex-end; }
  .pa-panel { width: 100%; max-height: calc(100vh - var(--space-4)); }
}

@media (prefers-reduced-motion: reduce) {
  .pa-launcher { transition: none; }
  .pa-launcher:hover { transform: none; }
}

/* Nota del plan gratuito dentro del chat: explica qué añade Pro sin bloquear nada. */
.chat-upsell {
  margin: var(--space-2) 0 0;
  padding: var(--space-2);
  border-radius: var(--radius-md);
  border: 1px dashed var(--border-strong);
  background: var(--surface-soft);
  font-size: var(--fs-3);
  line-height: 1.5;
  color: var(--text-muted);
}
.chat-upsell-btn {
  display: block;
  margin-top: var(--space-1);
  font-size: var(--fs-3);
}
