/* ══════════════════════════════════════════════════════════════
   EPIC — DESIGN TOKENS
   Dark = default (navy profundo, NUNCA negro puro). [data-theme="light"] = claro.
   Fuentes: Poppins (headings) + DM Sans (body), Google Fonts.
   Liquid Glass "iOS bubble": edge lensing, brillo especular, squircle grande.
   ══════════════════════════════════════════════════════════════ */

/* Las fuentes (Poppins + DM Sans) ya NO se cargan por @import serial aquí: se movieron a
   <link rel="preload"/stylesheet> en el <head> de index.html para que descarguen en paralelo con
   este CSS y no en cadena después de parsearlo (dieta de arranque en frío, brecha 12 de
   docs/VEREDICTO-NIVEL-1.md). Las font-family de --font / --font-heading se declaran abajo intactas. */

:root{
  color-scheme:dark;

  /* ════════════════════════════════════════════════════════════════════
     R1 · SISTEMA SEMÁNTICO (roles primero, valores después)
     ────────────────────────────────────────────────────────────────────
     Contrato completo: docs/design-system.md. Regla dura: todo color futuro
     sale de un ROL de esta sección, nunca un hex suelto en un componente.
     Los tokens legacy (--cyan, --bg, --muted, --gold, --glass, --border...)
     se CONSERVAN abajo pero ahora se derivan de estos roles, para que la app
     viva renderice idéntica o sutilmente mejor tras R1 (cero rotura). R3
     migrará los módulos de los legacy a los roles, módulo por módulo.

     Dirección (docs/DIRECCION-DISENO-PROPIA.md): premium PERO cálido, nivel
     Calm/Oura de confort. Base oscura profunda como RAÍZ (no negro puro),
     azul eléctrico como hilo de marca, oro champagne SOLO para logro/élite,
     colores de score INTACTOS como colores de DATO. Menos contraste duro.
     ════════════════════════════════════════════════════════════════════ */

  /* ── ROL · Fondo y profundidad ──
     La base es un navy profundo tibio (no un azul frío puro): un toque de
     calidez baja la fatiga visual del uso diario sin dejar de ser premium.
     --bg-root es la raíz absoluta de marca (#04101F), --bg es la superficie
     de página. --bg-deep es el pozo (headers, sheets, dock sólido). */
  --bg-root:#04101F;
  --bg:#0B143C;
  --bg-deep:#04121F;
  --navy:#0E1B4D;
  --navy-deep:#0B143C;

  /* ── ROL · Superficies (jerarquía de elevación, no "tarjeta dentro de tarjeta") ──
     --surface: contenedor base sobre el fondo (glass sutil).
     --surface-2: segundo nivel puntual (fila destacada, input); MÁXIMO un
     paso más — R3 prohíbe anidar más de 1 nivel de card.
     --surface-glass: la translucidez viva de Liquid Glass sobre el contenido.
     --surface-solid: cuando el blur no puede degradar (headers/dock/sheets). */
  --surface:rgba(255,255,255,.04);
  --surface-2:rgba(255,255,255,.025);
  --surface-glass:rgba(255,255,255,.04);
  --surface-solid:rgba(14,27,60,.55);

  /* ── ROL · Cromo del shell (header sticky + dock) ──
     Fondo casi opaco del header y el dock para que su legibilidad NO dependa del blur
     (P0-3). Son TOKENS para que floten en dark/light/system-light/alto-contraste en un
     solo lugar; .hd/.dock los consumen. --hd-bg-solid es el fallback sin backdrop-filter. */
  --hd-bg:rgba(4,16,31,.94);
  --hd-bg-solid:#04101F;
  --dock-bg:rgba(4,16,31,.94);
  --dock-bg-solid:#04101F;
  --dock-badge-ring:rgba(4,16,31,.95);

  /* ── ROL · Texto (jerarquía tibia, contraste AA sobre el fondo real) ──
     --text principal, --text-dim secundario, --text-faint terciario/hint.
     El blanco de marca lleva una gota de azul (#F2F4FF) para no vibrar. */
  --text:#F2F4FF;
  --text-dim:rgba(255,255,255,.5);
  --text-faint:rgba(255,255,255,.28);
  --text-ghost:rgba(255,255,255,.18);

  /* ── ROL · Marca (azul eléctrico = hilo conductor de EPIC) ──
     --brand es el azul de acción/CTA (#1A6BF5, paleta oficial), --brand-soft
     el hover (#4F8EF7), --brand-strong el navy de tinta. --brand-glow es el
     halo bioluminiscente cian de la imaginería científica (uso puntual, hero).
     Nota R3: hoy los módulos usan --cyan (#37C8F0) como acento de facto; R1
     NO lo voltea (sería cambio visual), solo define el rol para migrar luego. */
  --brand:#1A6BF5;
  --brand-soft:#4F8EF7;
  --brand-strong:#0E1B4D;
  --brand-glow:#37C8F0;
  --brand-glow-hi:#6FE3FF;

  /* ── ROL · Acento élite (oro champagne) — SOLO logro/celebración, jamás fondo ── */
  --accent-elite:#C8A45D;

  /* ── ROL · Estados semánticos (feedback, no decoración) ──
     --ok éxito, --warn atención, --error fallo (único rojo permitido de marca),
     --info neutral informativo. Cada uno con su versión de superficie tenue. */
  --ok:#34D399;
  --ok-strong:#4ADE80;
  --warn:#FFB800;
  --error:#DC2626;
  --error-text:#FF8181;
  --info:#4F8EF7;

  /* ── ROL · Datos de score (INTACTOS: paleta por producto = paleta por dato) ──
     Estos NO son decoración: son la etiqueta del empaque vuelta lenguaje de
     datos. Nunca se migran a un "azul de marca"; cada score conserva su color. */
  --score-readiness:#1A6BF5;
  --score-strain:#3B4FD8;   /* COREX cobalto */
  --score-sleep:#7FD4D0;    /* CREANOVA aqua */
  --score-momentum:#FFD43B; /* PUMPX mango */
  --score-fuel:#8DC63F;     /* BIOMAG lima */

  /* ── ROL · Bordes y foco ── */
  --border:rgba(255,255,255,.07);
  --border-strong:rgba(255,255,255,.12);
  --focus-ring:var(--brand-glow);

  /* ════════════════════════════════════════════════════════════════════
     LEGACY → derivado de los roles de arriba (compatibilidad viva).
     Estos nombres los consumen HOY los módulos (--cyan 189 usos, --muted 149,
     --border 102, --glass 97, --text 75, --gold 64...). Se mantienen con su
     valor resuelto ACTUAL (cero cambio visual) pero apuntando al rol cuando el
     valor coincide. R3 los va reemplazando por el rol directo, módulo a módulo.
     ════════════════════════════════════════════════════════════════════ */
  --cyan:var(--brand-glow);        /* #37C8F0 — acento de facto actual */
  --cyan-bio:var(--brand-glow-hi); /* #6FE3FF */
  --blue:var(--brand);             /* #1A6BF5 */
  --blue-soft:var(--brand-soft);   /* #4F8EF7 */
  --gold:#FFB800;                  /* dorado de racha (distinto del champagne élite) */
  --champagne:var(--accent-elite); /* #C8A45D */
  --green:var(--ok);               /* #34D399 */
  --green-ok:var(--ok-strong);     /* #4ADE80 — antes solo fallback inline en retos/suscripcion */
  --red-error:var(--error);        /* #DC2626 */

  /* Superficies legacy → rol de superficie */
  --glass:var(--surface);          /* rgba(255,255,255,.04) */
  --glass-2:var(--surface-2);      /* rgba(255,255,255,.025) */
  --glass-solid:var(--surface-solid);
  --muted:var(--text-dim);
  --soft:var(--text-faint);
  --faint:var(--text-ghost);

  /* ── Acentos por producto EPIC (data-driven, igual que los scores) ── */
  --sku-corex:var(--score-strain);
  --sku-pumpx:var(--score-momentum);
  --sku-creanova:var(--score-sleep);
  --sku-biomag:var(--score-fuel);

  /* ── ROL · Tipografía (Poppins display + DM Sans cuerpo + mono para datos) ──
     --font-mono da a los números de dato (pesos, reps, códigos) ancho tabular
     estable; antes solo existía como fallback inline en retos/admin. */
  --font:'DM Sans',-apple-system,BlinkMacSystemFont,'SF Pro Display','Segoe UI',sans-serif;
  --font-heading:'Poppins','DM Sans',-apple-system,BlinkMacSystemFont,'SF Pro Display','Segoe UI',sans-serif;
  --font-mono:ui-monospace,'SF Mono','DM Sans',Menlo,Consolas,monospace;

  /* ── ROL · Escala tipográfica fluida (clamp) ── Poppins display / DM Sans cuerpo.
     Los tamaños ya vividos en componentes (login-title, mega-num, hd-title) se
     conservan; estos tokens son el vocabulario canónico para R2/R3. */
  /* AUDITORIA-MOVIL Ola 4: techo tipográfico en móvil (los textos gigantes se achican GLOBAL sin
     tocar copy). vw reducido para que en 390px no dispare 50px+ por número/título. */
  --fs-display-xl:clamp(2rem,9vw,3.4rem);    /* mega número de score / hero */
  --fs-display-l:clamp(1.75rem,6.4vw,2.4rem);/* título de pantalla grande */
  --fs-display-m:clamp(1.25rem,4.8vw,1.5rem);/* título de paso / sección grande */
  --fs-title:1.25rem;                        /* hd-title, título de card */
  --fs-subtitle:1rem;                        /* subtítulo, opción */
  --fs-body:0.9375rem;                       /* cuerpo base (15px) */
  --fs-body-sm:0.8125rem;                    /* cuerpo secundario (13px) */
  --fs-caption:0.75rem;                      /* micro label (12px) */
  --fs-micro:0.6875rem;                      /* etiqueta de sistema (11px) */
  --lh-tight:1.15;                           /* display / titulares */
  --lh-snug:1.35;                            /* subtítulos */
  --lh-body:1.5;                             /* cuerpo (DM Sans ~1.5 de marca) */
  --tracking-display:-0.02em;                /* titulares apretados */
  --tracking-label:0.14em;                   /* etiquetas MAYÚSCULAS de sistema */
  --tracking-caps:0.06em;                    /* MAYÚSCULAS de cuerpo */
  --weight-body:400;
  --weight-medium:500;
  --weight-semibold:600;
  --weight-bold:700;
  --weight-display:800;

  /* ── ROL · Spacing en rejilla de 4px (ritmo único de toda la app) ── */
  --s-1:4px;
  --s-2:8px;
  --s-3:12px;
  --s-4:16px;
  --s-5:20px;
  --s-6:24px;
  --s-7:32px;
  --s-8:40px;
  --s-9:56px;
  --s-10:72px;

  /* ── Radios (squircle system, firma EPIC) ── */
  --r-sm:14px;
  --r-md:18px;
  --r-lg:22px;
  --r-xl:24px;
  --r-pill:100px;
  --r-xs:10px;    /* legacy: chips/badges pequeños que ya lo consumen */

  /* ── ROL · Elevación (sombra SUTIL en 2-3 niveles, nunca sombra enorme dura) ──
     --elev-1 reposo (card en fondo), --elev-2 elevado (sheet/toast), --elev-3
     flotante (FAB/CTA). Cada nivel: ambiente + contacto (2 capas), nunca una
     sola sombra negra plana. El glass suma su propio par ambient/contact. */
  --elev-1:0 8px 28px rgba(0,0,0,.28);
  --elev-2:0 -8px 40px rgba(0,0,0,.4);
  --elev-3:0 14px 38px rgba(0,0,0,.34);
  --shadow-glass-ambient:0 24px 60px -20px rgba(0,0,0,.5);
  --shadow-glass-contact:0 2px 6px rgba(0,0,0,.22);

  /* Legacy de sombra → rol de elevación (valor idéntico) */
  --shadow-card:var(--elev-1);
  --shadow-sheet:var(--elev-2);
  --shadow-cta:0 14px 38px rgba(0,200,240,.27),inset 0 1px 0 rgba(255,255,255,.2);
  --glow-cyan:0 0 32px rgba(0,200,240,.4);
  --glow-cyan-lg:0 0 40px rgba(0,200,240,.35);

  /* ── Glass elevado: doble sombra (ambiente + contacto) + edge lensing ── */
  --glass-edge-light:linear-gradient(135deg,rgba(255,255,255,.55) 0%,rgba(255,255,255,.14) 22%,rgba(255,255,255,.03) 45%,rgba(255,255,255,0) 62%,rgba(255,255,255,.07) 100%);
  --glass-sweep:linear-gradient(115deg,transparent 20%,rgba(255,255,255,.16) 46%,rgba(255,255,255,.28) 50%,rgba(255,255,255,.16) 54%,transparent 80%);
  /* Edge lensing compacto (chips, opciones, teclas) — mismo principio, halo más contenido */
  --edge-lens-sm:linear-gradient(135deg,rgba(255,255,255,.4) 0%,rgba(255,255,255,.08) 30%,rgba(255,255,255,0) 55%,rgba(255,255,255,.05) 100%);
  /* Brillo del barrido del skeleton (estado de carga canónico, Emil). Un solo tono de sheen
     para TODA la app: coherencia = se siente una sola pieza de vidrio esperando datos. */
  --skeleton-sheen:rgba(255,255,255,.09);

  /* ── Champagne (élite / celebración, DESIGN-DIRECTION §6) ── */
  --champagne-soft:rgba(200,164,93,.24);
  --champagne-glow:0 0 44px rgba(200,164,93,.4);

  /* ── ROL · Motion (duraciones + curvas; nunca persistir transforms, lección P0-3) ──
     --dur-fast feedback de presión, --dur-base transición estándar, --dur-slow
     entrada orquestada. Curva de la casa (--ease) para entradas; --ease-exit
     más seca para salidas (asimetría deliberada: entrar se nota, salir es rápido). */
  --dur-fast:120ms;
  --dur-base:240ms;
  --dur-slow:380ms;
  --ease:cubic-bezier(.16,1,.3,1);       /* curva de la casa (entrada serena) */
  --ease-out:cubic-bezier(.22,1,.36,1);  /* salida suave; curva del crossfade skeleton->contenido
                                            y de la entrada del modal de actualización (Emil: fuerte,
                                            arranca rápido, sin ease-in). NO cambiar el valor sin ADR:
                                            lo consumen decenas de transiciones en todo el sitio. */
  --ease-in-out:cubic-bezier(.65,0,.35,1);
  --ease-drawer:cubic-bezier(.32,.72,0,1);/* sheets/drawers */
  --ease-exit:cubic-bezier(.4,0,1,1);    /* salida seca */

  /* ── Layout ── */
  --h-pad:clamp(18px,5.5vw,32px);
  --max-w:560px;
  --dock-h:64px;
  /* ── Escritorio (>=1024px, ola 3): ancho de lectura ampliado + riel lateral.
     --rail-w es el ancho del dock convertido en riel lateral fijo; --max-w-desktop
     es el techo de .screen-wrap en pantallas anchas, con clamp (BLUEPRINT-REDISENO
     §3.2 exacto) para que crezca proporcional al viewport en vez de saltar de golpe
     a 1120px justo pasando el breakpoint (a 1024px, 92vw=942px < 1120px, así que el
     contenido sigue respirando en vez de forzar un ancho fijo prematuro). Ambos
     consumidos solo dentro de @media(min-width:1024px). ── */
  --max-w-desktop:clamp(560px,92vw,1120px);
  --rail-w:96px;

  /* ── Safe areas (iPhone) ── */
  --safe-t:env(safe-area-inset-top,0px);
  --safe-b:env(safe-area-inset-bottom,0px);
  --safe-l:env(safe-area-inset-left,0px);
  --safe-r:env(safe-area-inset-right,0px);

  /* ── Gutter horizontal seguro: padding lateral de contenido + inset de safe-area.
     Fuente única de contención lateral de la app. Todo el contenido de pantalla
     respira contra este valor; nada pega en los bordes del iPhone (notch/landscape
     incluidos). Ver .screen-wrap en app.css. ── */
  --gutter-l:calc(var(--h-pad) + var(--safe-l));
  --gutter-r:calc(var(--h-pad) + var(--safe-r));

  /* ── Escala tipográfica instalable (default = 1) ── */
  --font-scale:1;

  /* ════════════════════════════════════════════════════════════════════
     OLA 0 · FUNDACIÓN 3D (REDISENO-TOTAL-PLAN §2.1) — ADITIVO, cero consumo
     todavía: las utilidades existen, ninguna ola de módulo las consume aún
     (diff de screenshots root = 0). Las olas A-D las cablean después.
     Regla dura: perspective/preserve-3d SOLO en componentes hoja, JAMÁS en
     ancestros de .sheet/#menu/.hd (lección containing-block del drawer).
     ════════════════════════════════════════════════════════════════════ */

  /* ── ROL · Escena 3D (CSS) ── */
  --scene-perspective:1100px;   /* contenedor .depth-stage */
  --tilt-max:5deg;              /* tope de rotateX/Y en tilt táctil (6deg en packshots de Tienda) */
  --depth-back:-40px;           /* capa hundida (rejillas, fondos de gráfica) */
  --depth-mid:0px;
  --depth-front:24px;           /* capa que flota (número héroe, packshot) */
  --parallax-drift:8px;         /* desplazamiento máx de capas decorativas con scroll */

  /* ── ROL · Estado (puente ADR 0001, para que CSS pinte sin JS) ──
     [data-estado="exigir|sostener|recuperar|calibrando"] en el contenedor del
     orbe setea --estado-color. Colores IDÉNTICOS a los del dock por zona y a
     los de fx.nucleo3d.setEstado (mismo esquema de tres colores + reposo). */
  --estado-color:var(--brand-glow);            /* default sostener */
  --estado-exigir:var(--ok);                   /* #34D399 */
  --estado-sostener:var(--brand-glow);         /* #37C8F0 */
  --estado-recuperar:var(--warn);              /* #FFB800 */
  --estado-calibrando:var(--score-readiness);  /* #1A6BF5, reposo honesto */

  /* ── ROL · Material Liquid Glass v2 (rim refractivo / edge lensing / specular)
     SOLO para el protagonista de cada pantalla (utilidad .glass-protagonist,
     máx 1 por pantalla). --shadow-contact es la sombra de CONTACTO de objetos
     (packshots con tilt), distinta de la elevación de card. ── */
  --glass-inner-glow:radial-gradient(120% 90% at 50% -20%,rgba(255,255,255,.08),transparent 55%);
  --glass-refract-rim:conic-gradient(from 210deg,rgba(255,255,255,.35),rgba(111,227,255,.12) 25%,transparent 40%,rgba(255,255,255,.06) 70%,rgba(255,255,255,.3));
  --glass-specular:linear-gradient(135deg,rgba(255,255,255,.5) 0%,rgba(255,255,255,.12) 20%,transparent 46%);
  --shadow-contact:0 2px 10px -2px rgba(0,0,0,.5);  /* sombra de CONTACTO para objetos (packshots) */

  /* ── ROL · Gramática de motion (6 verbos, REDISENO-TOTAL-PLAN §2.2) ──
     Springs interruptibles (fx.spring) para ASENTAR; estas duraciones son el
     presupuesto de los verbos basados en keyframes (EMERGER/TRASLADAR/BARRER/
     RESPIRAR/REVELAR). ASENTAR no usa duración: es física real en rAF. */
  --dur-emerger:340ms;   /* EMERGER: pantalla llega con dirección y profundidad */
  --dur-trasladar:380ms; /* TRASLADAR (FLIP): este objeto ES el mismo que viste allá */
  --dur-barrer:700ms;    /* BARRER: confirmado/completado (sweep) */
  --dur-revelar:300ms;   /* REVELAR: hay una capa más profunda debajo */
  --breathe-min:4s;      /* RESPIRAR: piso del ciclo (confianza alta = más rápido) */
  --breathe-max:7s;      /* RESPIRAR: techo del ciclo (confianza baja = más lento) */
}

/* ══ ACCESIBILIDAD INSTALABLE — atributos en <html> ══ */
/* [data-font-scale="lg|xl"]: escala tipográfica global sin romper layout (usa rem/clamp existentes) */
/* Se escala html (no body): rem se ancla a html, así que escalar solo body dejaba fuera
   todo lo que usa rem/clamp en rem (ej. .mega-num, tamaños en clamp(...rem...)). */
html[data-font-scale="lg"]{ --font-scale:1.14; }
html[data-font-scale="xl"]{ --font-scale:1.3; }
html[data-font-scale="lg"],
html[data-font-scale="xl"]{ font-size:calc(16px * var(--font-scale)); }

/* [data-onehand="1"]: baja elementos de acción a la zona del pulgar (mitad inferior de pantalla) */
html[data-onehand="1"] .fab{
  bottom:calc(var(--dock-h) + var(--safe-b) + 84px);
}
html[data-onehand="1"] .hd-right .icon-btn{
  transform:translateY(2px);
}

/* [data-colorblind="1"]: además del color, agrega forma/patrón — activado por .cb-pattern en el propio elemento */
html[data-colorblind="1"] .cb-pattern{
  position:relative;
}
html[data-colorblind="1"] .cb-pattern::after{
  content:attr(data-cb-glyph);
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  font-size:.85em; font-weight:800; opacity:.9; pointer-events:none; mix-blend-mode:overlay;
}
html[data-colorblind="1"] .cb-pattern[data-cb-shape="dash"]::before{
  content:''; position:absolute; inset:0; pointer-events:none; border-radius:inherit;
  background-image:repeating-linear-gradient(45deg,rgba(255,255,255,.16) 0 3px,transparent 3px 8px);
}
html[data-colorblind="1"] .cb-pattern[data-cb-shape="dot"]::before{
  content:''; position:absolute; inset:0; pointer-events:none; border-radius:inherit;
  background-image:radial-gradient(rgba(255,255,255,.22) 1px,transparent 1.4px);
  background-size:7px 7px;
}
html[data-colorblind="1"] .cb-pattern[data-cb-shape="ring"]::before{
  content:''; position:absolute; inset:14%; pointer-events:none; border-radius:50%;
  border:2px dashed rgba(255,255,255,.4);
}

/* ══ LIGHT THEME — activar con data-theme="light" en <html> ══
   Se flipan los ROLES semánticos (los legacy heredan por alias); además se
   conservan los overrides legacy explícitos para módulos que aún leen el
   nombre viejo directo (R3 los migra). Valores idénticos a antes de R1. */
html[data-theme="light"]{
  color-scheme:light;
  /* roles */
  --bg:#F5F7FA;
  --bg-root:#F5F7FA;
  --bg-deep:#EFF0F5;
  --text:#0A0A14;
  --text-dim:rgba(10,10,20,.62);
  --text-faint:rgba(10,10,20,.22);
  --text-ghost:rgba(10,10,20,.14);
  --surface:rgba(255,255,255,.72);
  --surface-2:rgba(255,255,255,.88);
  --surface-glass:rgba(255,255,255,.72);
  --surface-solid:rgba(255,255,255,.92);
  --border:rgba(10,20,40,.09);
  --border-strong:rgba(10,20,40,.16);
  --elev-1:0 8px 28px rgba(10,10,30,.08);
  --elev-2:0 -8px 34px rgba(10,10,30,.12);
  /* cromo del shell en claro: superficie clara equivalente (antes el header/dock se quedaban navy) */
  --hd-bg:rgba(245,247,250,.96);
  --hd-bg-solid:#F5F7FA;
  --dock-bg:rgba(245,247,250,.96);
  --dock-bg-solid:#F5F7FA;
  --dock-badge-ring:rgba(245,247,250,.95);
  /* legacy explícitos (sin cambio de valor) */
  --muted:rgba(10,10,20,.62);
  --soft:rgba(10,10,20,.22);
  --faint:rgba(10,10,20,.14);
  --glass:rgba(255,255,255,.72);
  --glass-2:rgba(255,255,255,.88);
  --glass-solid:rgba(255,255,255,.92);
  --shadow-card:0 8px 28px rgba(10,10,30,.08);
  --shadow-sheet:0 -8px 34px rgba(10,10,30,.12);
}
html[data-theme="light"] body{
  background:#F5F7FA;
  background-image:
    radial-gradient(ellipse 70% 40% at 10% -5%,rgba(0,200,240,.07),transparent 65%),
    radial-gradient(ellipse 55% 35% at 92% 5%,rgba(77,141,255,.05),transparent 65%);
}
html[data-theme="light"] .logo-invert{ filter:brightness(0); }

/* ══ V3 · SEGUIR EL SISTEMA — data-theme="system" (DIRECCION-ELITE §5) ══
   Ola 2 (shell) escribe data-theme="system" en <html> cuando el usuario nunca eligió tema
   explícito, y agrega el matchMedia('(prefers-color-scheme: dark)') listener para reflejar
   cambios del SO en vivo. Aquí solo resolvemos las variables: mismo par de bloques que
   data-theme="light"/dark, condicionados al media query en vez de al atributo directo. */
@media(prefers-color-scheme:light){
  html[data-theme="system"]{
    color-scheme:light;
    /* roles */
    --bg:#F5F7FA;
    --bg-root:#F5F7FA;
    --bg-deep:#EFF0F5;
    --text:#0A0A14;
    --text-dim:rgba(10,10,20,.62);
    --text-faint:rgba(10,10,20,.22);
    --text-ghost:rgba(10,10,20,.14);
    --surface:rgba(255,255,255,.72);
    --surface-2:rgba(255,255,255,.88);
    --surface-glass:rgba(255,255,255,.72);
    --surface-solid:rgba(255,255,255,.92);
    --border:rgba(10,20,40,.09);
    --border-strong:rgba(10,20,40,.16);
    --elev-1:0 8px 28px rgba(10,10,30,.08);
    --elev-2:0 -8px 34px rgba(10,10,30,.12);
    /* cromo del shell en claro (seguir sistema): antes header/dock se quedaban navy en OS claro */
    --hd-bg:rgba(245,247,250,.96);
    --hd-bg-solid:#F5F7FA;
    --dock-bg:rgba(245,247,250,.96);
    --dock-bg-solid:#F5F7FA;
    --dock-badge-ring:rgba(245,247,250,.95);
    /* legacy explícitos (sin cambio de valor) */
    --muted:rgba(10,10,20,.62);
    --soft:rgba(10,10,20,.22);
    --faint:rgba(10,10,20,.14);
    --glass:rgba(255,255,255,.72);
    --glass-2:rgba(255,255,255,.88);
    --glass-solid:rgba(255,255,255,.92);
    --shadow-card:0 8px 28px rgba(10,10,30,.08);
    --shadow-sheet:0 -8px 34px rgba(10,10,30,.12);
  }
  html[data-theme="system"] body{
    background:#F5F7FA;
    background-image:
      radial-gradient(ellipse 70% 40% at 10% -5%,rgba(0,200,240,.07),transparent 65%),
      radial-gradient(ellipse 55% 35% at 92% 5%,rgba(77,141,255,.05),transparent 65%);
  }
  html[data-theme="system"] body::before{ display:none; }
  html[data-theme="system"] body::after{ display:none; }
  html[data-theme="system"]::before{ opacity:.015; }
  html[data-theme="system"] .logo-invert{ filter:brightness(0); }
}
/* prefers-color-scheme:dark bajo data-theme="system" no necesita override: hereda los
   valores dark de :root tal cual (mismos que el default sin atributo). */

/* ══ V2 · ALTO CONTRASTE — data-contrast="high" en <html> (DIRECCION-ELITE §5, #96) ══
   Fondos más oscuros, texto blanco puro, bordes visibles 2px, SIN glass translúcido.
   Combinable con data-theme="dark|light|system": se aplica encima en ambos casos.
   Toggle real en Ajustes -> Accesibilidad lo escribe Ola 2 (shell). */
html[data-contrast="high"]{
  /* roles: texto blanco puro, superficies sólidas, bordes visibles */
  --text:#FFFFFF;
  --text-dim:rgba(255,255,255,.82);
  --text-faint:rgba(255,255,255,.6);
  --text-ghost:rgba(255,255,255,.4);
  --border:rgba(255,255,255,.55);
  --border-strong:rgba(255,255,255,.85);
  --surface:#0B1830;
  --surface-2:#0B1830;
  --surface-glass:#0B1830;
  --surface-solid:#0B1830;
  --elev-1:0 0 0 2px rgba(255,255,255,.55);
  --elev-2:0 -2px 0 2px rgba(255,255,255,.55);
  /* legacy explícitos (sin cambio de valor) */
  --muted:rgba(255,255,255,.82);
  --soft:rgba(255,255,255,.6);
  --faint:rgba(255,255,255,.4);
  --glass:#0B1830;
  --glass-2:#0B1830;
  --glass-solid:#0B1830;
  --shadow-card:0 0 0 2px rgba(255,255,255,.55);
  --shadow-sheet:0 -2px 0 2px rgba(255,255,255,.55);
}
html[data-contrast="high"]{
  --bg:#04121F;
  --bg-root:#04121F;
  --bg-deep:#020A12;
  --navy:#0B1830;
  --navy-deep:#080F24;
  /* cromo del shell en alto contraste: 100% opaco (el blur ya se apaga con !important abajo) */
  --hd-bg:#04121F;
  --hd-bg-solid:#04121F;
  --dock-bg:#04121F;
  --dock-bg-solid:#04121F;
  --dock-badge-ring:#04121F;
}
html[data-contrast="high"] body::before,
html[data-contrast="high"] body::after,
html[data-contrast="high"]::before{ display:none; } /* sin halos ni grano: máxima legibilidad */
/* Glass = plano y opaco, bordes 2px sólidos, cero blur (el blur reduce contraste de borde) */
html[data-contrast="high"] .glass-card,
html[data-contrast="high"] .opt,
html[data-contrast="high"] .chip,
html[data-contrast="high"] .mas-item,
html[data-contrast="high"] .field input,
html[data-contrast="high"] .sheet,
html[data-contrast="high"] .toast,
html[data-contrast="high"] .dock,
html[data-contrast="high"] .hd{
  border-width:2px!important;
  border-color:var(--border-strong)!important;
  backdrop-filter:none!important;
  -webkit-backdrop-filter:none!important;
}
html[data-contrast="high"] .glass-card::before,
html[data-contrast="high"] .glass-card::after,
html[data-contrast="high"] .glass-edge::before,
html[data-contrast="high"] .opt::after,
html[data-contrast="high"] .chip::after,
html[data-contrast="high"] .mas-item::after,
html[data-contrast="high"] .field::after,
html[data-contrast="high"] .btn-ghost::after,
html[data-contrast="high"] .glass-sweep::after{ display:none; } /* sin sweep, sin lensing: bordes reales, no luz simulada */
html[data-contrast="high"] .btn-primary{
  background:var(--blue); box-shadow:none; border:2px solid #FFFFFF;
}
html[data-contrast="high"] .btn-primary::after{ display:none; }
html[data-contrast="high"] .instrument::before,
html[data-contrast="high"] .instrument::after{ opacity:.9; }
html[data-theme="light"][data-contrast="high"]{
  /* roles */
  --text:#000000;
  --text-dim:rgba(0,0,0,.82);
  --border:rgba(0,0,0,.55);
  --border-strong:rgba(0,0,0,.85);
  --bg:#FFFFFF;
  --bg-root:#FFFFFF;
  --bg-deep:#FFFFFF;
  --surface:#FFFFFF;
  --surface-2:#FFFFFF;
  --surface-glass:#FFFFFF;
  --surface-solid:#FFFFFF;
  /* cromo del shell en claro + alto contraste: blanco opaco */
  --hd-bg:#FFFFFF;
  --hd-bg-solid:#FFFFFF;
  --dock-bg:#FFFFFF;
  --dock-bg-solid:#FFFFFF;
  --dock-badge-ring:#FFFFFF;
  /* legacy explícitos */
  --muted:rgba(0,0,0,.82);
  --glass:#FFFFFF;
  --glass-2:#FFFFFF;
  --glass-solid:#FFFFFF;
}
html[data-theme="light"][data-contrast="high"] .btn-primary{ border-color:#000000; }

/* ══ OLA 0 · Alto contraste apaga TODO el material 3D/refractivo (§2.4) ══
   Sin rim refractivo, sin specular, sin profundidad, sin tilt, sin respiración:
   bordes reales y legibilidad clínica. Se pega sobre light/dark/system igual. */
html[data-contrast="high"]{
  --glass-inner-glow:none;
  --glass-refract-rim:none;
  --glass-specular:none;
  --shadow-contact:none;
  --scene-perspective:none;   /* .depth-stage no genera perspectiva -> capas planas */
  --depth-back:0px; --depth-mid:0px; --depth-front:0px; --parallax-drift:0px;
  --tilt-max:0deg;            /* fx.tilt lee este tope: 0 = sin inclinación */
}
html[data-contrast="high"] .depth-stage{ perspective:none!important; }
html[data-contrast="high"] .glass-protagonist::before,
html[data-contrast="high"] .glass-protagonist::after{ display:none!important; }
html[data-contrast="high"] .breathe,
html[data-contrast="high"] .breathe--calm{ animation:none!important; }

/* ══ RESET BASE ══ */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;height:100%}
body{
  background:var(--bg);color:var(--text);font-family:var(--font);
  -webkit-font-smoothing:antialiased;overflow-x:hidden;
  transition:background .4s;
  min-height:100dvh;
  -webkit-tap-highlight-color:transparent;
  overscroll-behavior-y:none;
}
body::before{
  content:'';position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(ellipse 70% 40% at 15% -8%,rgba(55,200,240,.10),transparent 60%),
    radial-gradient(ellipse 60% 35% at 100% 0%,rgba(26,107,245,.08),transparent 60%);
}
html[data-theme="light"] body::before{ display:none; }

/* ══ ATMÓSFERA — halo navy de profundidad + grano fino SVG (DESIGN-DIRECTION §4) ══ */
/* Se suma detrás de body::before (cian/azul ya existente); no lo reemplaza. */
body::after{
  content:'';position:fixed;inset:0;z-index:-2;pointer-events:none;
  background:radial-gradient(ellipse 130% 75% at 50% -6%,var(--navy-deep) 0%,var(--bg) 58%,var(--bg-deep) 100%);
}
html[data-theme="light"] body::after{ display:none; }

/* Grano fino independiente: opacity literal .02-.03 (DESIGN-DIRECTION §4), capa propia para no depender de blend-mode */
html::before{
  content:'';position:fixed;inset:0;z-index:-2;pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:160px 160px;
  opacity:.025;
  mix-blend-mode:overlay;
}
html[data-theme="light"]::before{ opacity:.015; }

/* .halo — halo bioluminiscente cian sutil detrás de un instrumento hero (usar en un contenedor position:relative) */
.halo{ position:relative; isolation:isolate; --halo-color:55,200,240; }
.halo::before{
  content:'';position:absolute;z-index:-1;pointer-events:none;
  inset:-38% -30%;
  background:radial-gradient(circle at 50% 42%,rgba(var(--halo-color),.22) 0%,rgba(var(--halo-color),.09) 32%,transparent 68%);
  filter:blur(2px);
  animation:haloBreathe 6.5s var(--ease-in-out) infinite;
}
@keyframes haloBreathe{
  0%,100%{ opacity:.75; transform:scale(1); }
  50%{ opacity:1; transform:scale(1.05); }
}
@media(prefers-reduced-motion:reduce){
  .halo::before{ animation:none; }
}
/* Halo tintado por score/producto — usar junto a .halo, ej: <div class="halo halo--strain"> */
.halo--readiness{ --halo-color:26,107,245; }
.halo--strain{ --halo-color:59,79,216; }
.halo--sleep{ --halo-color:127,212,208; }
.halo--momentum{ --halo-color:255,212,59; }
.halo--fuel{ --halo-color:141,198,63; }
.halo--champagne{ --halo-color:200,164,93; }
h1,h2,h3,h4{font-family:var(--font-heading)}
button,input,select,textarea{font-family:inherit;color:inherit}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
::-webkit-scrollbar{width:0;height:0}

.logo-invert{ filter:brightness(0) invert(1); }

/* ══ TOUCH TARGETS — evita el delay de 300ms de doble-tap-zoom en elementos táctiles ══ */
button,a.btn,.btn,.chip,.opt,.dock-item,.icon-btn{ touch-action:manipulation; }

/* ══ REDUCED-MOTION = CALMADO, NUNCA MUERTO (AUDITORIA-MOVIL Ola 1B) ══
   El nuke global anterior (*{animation-duration:.01ms}) convertía la app en una foto: mataba
   TAMBIÉN las degradaciones bellas (el fade de pantalla caía a 0.01ms = invisible; el flash del
   confetti a 0.01ms = nunca se ve). Ahora reducimos lo DECORATIVO pero conservamos el movimiento
   ESENCIAL en su versión calmada:
     - <video> NUNCA se toca (el Núcleo respira siempre; la reproducción de media no la bloquea
       prefers-reduced-motion en ningún navegador).
     - [data-motion="esencial"] queda EXENTO del recorte de duración: es el opt-in explícito para
       transiciones/animaciones que deben seguir vivas y calmadas (fade de pantalla, flash del
       confetti, respiración del halo del Núcleo fallback, crossfades de fx.flip).
   Todo lo demás (parallax, tilt, sweep especular, staggers largos, ripple) sigue muerto: se
   colapsa a ~0. Las reglas @media(reduce) por-componente que ya degradan a fadeIn/none siguen
   aplicando y su duración (>=120ms) YA no la pisa este bloque. */
@media(prefers-reduced-motion:reduce){
  *:not(video):not([data-motion="esencial"]){animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
  /* Movimiento esencial calmado: las transiciones de pantalla del shell degradan a un fade real
     (fadeIn .2s definido más abajo por-componente) que sigue vivo porque el elemento lleva la
     clase de transición marcada esencial; el shell la etiqueta al montar. */
  [data-motion="esencial"]{scroll-behavior:auto!important}
}

/* ══ GLASS CARD — unidad estructural base (edge lensing + brillo especular) ══ */
.glass-card{
  background:var(--glass);
  border:1px solid var(--border);
  border-radius:var(--r-lg);
  padding:20px 22px;
  position:relative;
  overflow:hidden;
  box-shadow:var(--shadow-card),var(--shadow-glass-ambient),var(--shadow-glass-contact);
  backdrop-filter:blur(18px) saturate(1.3);
  -webkit-backdrop-filter:blur(18px) saturate(1.3);
  transition:transform .2s var(--ease),box-shadow .3s var(--ease);
}
.glass-card::before{
  content:'';position:absolute;inset:0;
  background:linear-gradient(135deg,rgba(255,255,255,.07) 0%,transparent 55%);
  pointer-events:none;
}
.glass-card::after{
  content:'';position:absolute;width:140px;height:140px;top:-60px;right:-60px;
  background:radial-gradient(circle,rgba(55,200,240,.10) 0%,transparent 70%);
  pointer-events:none;
}
.glass-card--rim{ border-color:transparent; }
.glass-card--rim::before{
  content:'';position:absolute;inset:-1px;border-radius:inherit;
  background:linear-gradient(135deg,rgba(55,200,240,.22),rgba(77,141,255,.12),rgba(200,164,93,.18));
  padding:1px;
  -webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
}

/* squircle helper universal */
.squircle{ border-radius:var(--r-lg); }

/* ══ GLASS EDGE LENSING real — borde de luz refractiva 135deg (más luminoso arriba-izq, casi invisible abajo-der) ══ */
/* Agregar junto a .glass-card (no la reemplaza): '<div class="glass-card glass-edge">' */
.glass-edge{ border-color:transparent; }
.glass-edge::before{
  content:'';position:absolute;inset:0;border-radius:inherit;padding:1px;
  background:var(--glass-edge-light);
  -webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
  pointer-events:none;
}
html[data-theme="light"] .glass-edge::before{
  background:linear-gradient(135deg,rgba(10,20,40,.28) 0%,rgba(10,20,40,.08) 22%,rgba(10,20,40,.02) 45%,transparent 62%,rgba(10,20,40,.05) 100%);
}

/* ══ SPECULAR SWEEP — brillo diagonal estático + barrido al tocar ══ */
.glass-sweep{ position:relative; overflow:hidden; }
.glass-sweep::after{
  content:'';position:absolute;inset:0;pointer-events:none;
  background:var(--glass-sweep);
  transform:translateX(-120%);
  transition:transform .7s var(--ease-out);
}
.glass-sweep:active::after,
.glass-sweep.sweep-play::after{
  transform:translateX(120%);
}
@media(prefers-reduced-motion:reduce){
  .glass-sweep::after{ transition:none; }
}

/* ══════════ INSTRUMENTOS (anillos de precisión, DESIGN-DIRECTION §2) ══════════ */
/* .instrument envuelve un ring-gauge; agrega bisel con tick marks (conic-gradient enmascarado) */
.instrument{
  position:relative; display:inline-flex; align-items:center; justify-content:center;
  --instrument-accent:var(--score-readiness);
}
/* Bisel fino: 60 ticks de 1px estilo cronógrafo suizo */
.instrument::before{
  content:'';position:absolute;inset:-9%;border-radius:50%;pointer-events:none;
  background:
    repeating-conic-gradient(from 0deg,rgba(255,255,255,.5) 0deg 0.55deg,transparent 0.55deg 6deg);
  -webkit-mask:radial-gradient(circle,transparent 0 84%,#fff 86% 89%,transparent 91% 100%);
  mask:radial-gradient(circle,transparent 0 84%,#fff 86% 89%,transparent 91% 100%);
  opacity:.5;
}
/* Ticks mayores cada 5 (12 marcas), como los índices de hora de un cronógrafo real, más el punto de origen a las 12 */
.instrument::after{
  content:'';position:absolute;inset:-9%;border-radius:50%;pointer-events:none;
  background:
    repeating-conic-gradient(from 0deg,rgba(255,255,255,.9) 0deg 0.9deg,transparent 0.9deg 30deg),
    conic-gradient(from -1.4deg,var(--instrument-accent) 0deg 2.8deg,transparent 2.8deg 360deg);
  -webkit-mask:radial-gradient(circle,transparent 0 83%,#fff 85% 89.5%,transparent 91.5% 100%);
  mask:radial-gradient(circle,transparent 0 83%,#fff 85% 89.5%,transparent 91.5% 100%);
  opacity:.65;
  filter:drop-shadow(0 0 2px color-mix(in srgb,var(--instrument-accent) 40%,transparent));
}
html[data-theme="light"] .instrument::before{ opacity:.22; }
html[data-theme="light"] .instrument::after{ opacity:.4; }
.instrument .ring-gauge{ filter:drop-shadow(0 6px 14px rgba(0,0,0,.32)); }
.instrument .ring-gauge .track{ stroke:var(--border-strong); opacity:.9; }
.instrument .ring-gauge .fill{ stroke:var(--instrument-accent); filter:drop-shadow(0 0 6px color-mix(in srgb,var(--instrument-accent) 55%,transparent)); }

/* Variantes de acento por score, aplicar como clase adicional en .instrument */
.instrument--readiness{ --instrument-accent:var(--score-readiness); }
.instrument--strain{ --instrument-accent:var(--score-strain); }
.instrument--sleep{ --instrument-accent:var(--score-sleep); }
.instrument--momentum{ --instrument-accent:var(--score-momentum); }
.instrument--fuel{ --instrument-accent:var(--score-fuel); }

/* Variante hero (Núcleo, splash): bisel más presente y halo del acento propio */
.instrument--lg::before{ opacity:.62; }
.instrument--lg::after{ opacity:.8; }

/* Profundidad base del ring-gauge SIN envoltura .instrument (fallback para módulos que aún no la usan) */
.ring-gauge{ filter:drop-shadow(0 4px 10px rgba(0,0,0,.24)); }

/* ══════════ TIPOGRAFÍA DE INSTRUMENTO ══════════ */
.sys-label{
  font-family:var(--font-heading); font-weight:600; text-transform:uppercase;
  font-size:clamp(10px,2.6vw,11px); letter-spacing:.14em; color:var(--muted);
}
.mega-num{
  font-family:var(--font-heading); font-weight:800; letter-spacing:-.03em;
  font-variant-numeric:tabular-nums; font-feature-settings:'tnum' 1;
  /* AUDITORIA-MOVIL Ola 4: 13vw en 390px = 50px+; bajado a 9vw (techo 3.4rem) para que el número
     hero no domine la pantalla. En 390px queda ~35px (<=36px, dentro del criterio de la ola). */
  font-size:clamp(2rem,9vw,3.4rem); line-height:1;
}
/* Utilidad: el número "late" una vez al mejorar (DESIGN-DIRECTION §motion) — agregar/quitar clase desde JS al detectar delta positivo */
.mega-num-pulse{ animation:megaNumPulse .5s var(--ease-out) both; }
@keyframes megaNumPulse{ 0%{ transform:scale(1); } 40%{ transform:scale(1.08); } 100%{ transform:scale(1); } }
@media(prefers-reduced-motion:reduce){
  .mega-num-pulse{ animation:none; }
}

/* ══════════ ESTADO "DÍA ÉPICO" — orbe/acentos champagne (DESIGN-DIRECTION §6, game.js) ══════════ */
.dia-epico .orb-wrap .orb{
  background:radial-gradient(circle at 38% 36%,var(--champagne-soft) 0%,rgba(4,16,31,.95) 65%);
  border-color:rgba(200,164,93,.4);
  box-shadow:var(--champagne-glow);
}
.dia-epico .instrument{ --instrument-accent:var(--champagne); }
.dia-epico.halo::before{
  background:radial-gradient(circle at 50% 42%,rgba(200,164,93,.28) 0%,rgba(200,164,93,.1) 32%,transparent 68%);
}
.dia-epico-flare{
  position:fixed; inset:0; z-index:9998; pointer-events:none;
  background:radial-gradient(circle at 50% 40%,rgba(200,164,93,.5),transparent 60%);
  opacity:0; animation:flareOnce 1.1s var(--ease-out) both;
}
@keyframes flareOnce{
  0%{ opacity:0; }
  18%{ opacity:1; }
  100%{ opacity:0; }
}
@media(prefers-reduced-motion:reduce){
  .dia-epico-flare{ animation-duration:.4s; }
}

/* ══════════ TRANSICIONES SHARED-AXIS del router ══════════ */
/* Blur leve en el enter (emil-design-eng: enmascara el crossfade, funde la pantalla nueva sobre la anterior en vez de "cortar") */
/* P0-3: los ENTER usan 'backwards', no 'both'. El estado final del keyframe (transform:translateX(0);
   filter:blur(0)) YA es el estado natural del elemento montado; 'both' persistía transform:matrix()
   y filter computados para siempre, creando stacking context/containing block permanentes (misma
   trampa del menú drawer) que degradan el backdrop-filter del header. 'backwards' cubre el primer
   frame y suelta el estilo al terminar: cero residuo. Los EXIT quedan en 'both' porque su elemento
   se desmonta enseguida (no persiste nada). */
.screen-enter{ animation:screenEnterX .32s var(--ease) backwards; }
.screen-enter-back{ animation:screenEnterXBack .32s var(--ease) backwards; }
.screen-exit{ animation:screenExitX .2s var(--ease-exit) both; }
.screen-exit-back{ animation:screenExitXBack .2s var(--ease-exit) both; }
@keyframes screenEnterX{ from{ opacity:0; transform:translateX(14px); filter:blur(3px); } to{ opacity:1; transform:translateX(0); filter:blur(0); } }
@keyframes screenEnterXBack{ from{ opacity:0; transform:translateX(-14px); filter:blur(3px); } to{ opacity:1; transform:translateX(0); filter:blur(0); } }
@keyframes screenExitX{ from{ opacity:1; transform:translateX(0); } to{ opacity:0; transform:translateX(-14px); } }
@keyframes screenExitXBack{ from{ opacity:1; transform:translateX(0); } to{ opacity:0; transform:translateX(14px); } }
@media(prefers-reduced-motion:reduce){
  /* Ola 1B: la transición de pantalla es movimiento ESENCIAL. Fade real de 200ms (no 0.01ms):
     !important + selector de clase (mayor especificidad que el nuke *:not(...)) garantiza que la
     duración sobreviva. La app se siente viva y calmada, nunca muerta. */
  .screen-enter,.screen-enter-back,.screen-exit,.screen-exit-back{ animation:fadeIn .2s var(--ease) both!important; }
}

/* ══ Variantes --left/--right, 240ms (DIRECCION-ELITE §6) ══
   Mismo shared-axis que .screen-enter/-back arriba, pero con nombre explícito de dirección
   para que Ola 2 (shell/router) elija el sentido por orden de tabs sin adivinar "back" vs
   "forward": tab a la derecha del actual -> entra desde la derecha (--right calls in from
   right = contenido llega deslizando desde la derecha); tab a la izquierda -> --left.
   240ms exacto (spec), ease estándar del sistema (--ease), con el mismo blur-mask del enter
   y salida más rápida que la entrada (asimetría deliberada: entrar se nota, salir es rápido). */
.screen-enter--left{ animation:screenEnterLeft .24s var(--ease) backwards; }
.screen-enter--right{ animation:screenEnterRight .24s var(--ease) backwards; }
.screen-exit--left{ animation:screenExitLeft .18s var(--ease-exit) both; }
.screen-exit--right{ animation:screenExitRight .18s var(--ease-exit) both; }
@keyframes screenEnterLeft{ from{ opacity:0; transform:translateX(-18px); filter:blur(3px); } to{ opacity:1; transform:translateX(0); filter:blur(0); } }
@keyframes screenEnterRight{ from{ opacity:0; transform:translateX(18px); filter:blur(3px); } to{ opacity:1; transform:translateX(0); filter:blur(0); } }
@keyframes screenExitLeft{ from{ opacity:1; transform:translateX(0); } to{ opacity:0; transform:translateX(18px); } }
@keyframes screenExitRight{ from{ opacity:1; transform:translateX(0); } to{ opacity:0; transform:translateX(-18px); } }
@media(prefers-reduced-motion:reduce){
  .screen-enter--left,.screen-enter--right,.screen-exit--left,.screen-exit--right{ animation:fadeIn .2s var(--ease) both!important; }
}

/* ══ ENTRADA CON PROFUNDIDAD (dock vivo) ══
   La pantalla nueva EMERGE desde el fondo: desliza según dirección (izq/der), escala desde 0.965 y
   un blur leve que se resuelve. Como .screen-enter--depth va JUNTO a --left/--right sobre el mismo
   elemento y ambas son igual de específicas, se define la animación en el selector COMPUESTO para
   que el translateX direccional y el scale+blur vivan en UN solo keyframe (no compiten por la
   propiedad 'animation'). fill-mode 'backwards' => cero residuo de transform/filter (P0-3); app.js
   quita las clases en animationend como defensa extra. Sus capas (header vs contenido) llegan a
   velocidades ligeramente distintas: parallax sutil. */
.screen-enter--depth.screen-enter--right{ animation:screenDepthRight .34s var(--ease) backwards; }
.screen-enter--depth.screen-enter--left{ animation:screenDepthLeft .34s var(--ease) backwards; }
@keyframes screenDepthRight{
  from{ opacity:0; transform:translateX(18px) scale(.965); filter:blur(4px); }
  60%{ opacity:1; filter:blur(0); }
  to{ opacity:1; transform:translateX(0) scale(1); filter:blur(0); }
}
@keyframes screenDepthLeft{
  from{ opacity:0; transform:translateX(-18px) scale(.965); filter:blur(4px); }
  60%{ opacity:1; filter:blur(0); }
  to{ opacity:1; transform:translateX(0) scale(1); filter:blur(0); }
}
/* Parallax de capas: header entra un pelín antes y desde un poco más arriba; contenido un poco
   después y desde más abajo (plano fijo vs plano de datos). */
.screen-layer-hd{ animation:screenLayerHd .38s var(--ease) backwards; }
.screen-layer-body{ animation:screenLayerBody .42s var(--ease) 40ms backwards; }
@keyframes screenLayerHd{ from{ opacity:0; transform:translateY(-6px); } to{ opacity:1; transform:none; } }
@keyframes screenLayerBody{ from{ opacity:0; transform:translateY(12px); } to{ opacity:1; transform:none; } }
@media(prefers-reduced-motion:reduce){
  .screen-enter--depth.screen-enter--right,.screen-enter--depth.screen-enter--left{ animation:fadeIn .2s var(--ease) both!important; }
  .screen-layer-hd,.screen-layer-body{ animation:none; }
}

/* ══ .pressable — press-scale global (DIRECCION-ELITE §6, emil-design-eng: feedback instantáneo) ══
   Agregar junto a cualquier botón/card accionable que aún no tenga su propio :active (ej.
   .glass-card usado como fila clicable, .smart-card, .list-row, .mas-item ya tiene el suyo).
   scale(0.97) es sutil (rango recomendado 0.95-0.98) y compuesto sobre transform existente vía
   transform-origin:center default. 80ms: más rápido que el estándar de botones (100-160ms)
   porque es SOLO el feedback de presión, no una transición de entrada/salida. */
.pressable{ transition:transform 80ms var(--ease-out); }
.pressable:active{ transform:scale(.97); }
@media(prefers-reduced-motion:reduce){
  .pressable{ transition:none; }
  .pressable:active{ transform:none; }
}

/* ══════════════════════════════════════════════════════════════
   ESCRITORIO (Ola 3, BLUEPRINT-REDISENO §3.2) — cierra el gap de
   --max-w:560px. Móvil sigue siendo el ancho de lectura de 560px
   (iPhone primero); aquí solo AMPLIAMOS el techo para pantallas
   anchas, nunca angostamos algo que ya funciona en móvil.
   ══════════════════════════════════════════════════════════════ */
@media(min-width:1024px){
  :root{
    --h-pad:clamp(32px,4vw,64px);
    --max-w:var(--max-w-desktop);
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   LANDING-A-APP · Fundación L0 (docs/LANDING-A-APP-DESIGN.md §1)
   El lenguaje de /unete/ (la landing que Roberto ama) tokenizado para la app.
   ADITIVO: cero cambio visual hasta que un módulo consuma estas variables.
   ═══════════════════════════════════════════════════════════════════════════ */
:root{
  /* Aire Whoop en tres escalas (proporción ~3:1.5:1), la única fuente de separación */
  --gap-zone:clamp(28px,7vw,40px);   /* entre zonas de un root; UNA idea por zona */
  --gap-cards:14px;                  /* entre cards hermanas dentro de una zona */
  --gap-intra:12px;                  /* entre bloques dentro de una card */
  --gap-micro:6px;                   /* label a valor, micro */
  /* Cuerpo navy del material deep (la card tiene MASA, no es humo). Flipa en claro. */
  --glass-deep-tint:rgba(11,20,44,.5);
}
html[data-theme="light"]{ --glass-deep-tint:rgba(255,255,255,.6); }
@media(prefers-color-scheme:light){ html[data-theme="system"]{ --glass-deep-tint:rgba(255,255,255,.6); } }

