/* Paleta de Fitorex — generada desde web/site.config.mjs. No editar a mano. */
:root{--primary:#498506; --primary-ink:#3d6f04; --accent:#12a594; --on-primary:#ffffff;}
@media (prefers-color-scheme:dark){:root{--primary:#a5ed45; --primary-ink:#bdf571; --accent:#2dd4bf; --on-primary:#0b1400;}}

/* Fuentes de la marca — generadas desde web/site.config.mjs. No editar a mano. */
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/inter-400-latin.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/inter-400-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;src:url('fonts/inter-500-latin.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;src:url('fonts/inter-500-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url('fonts/inter-600-latin.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url('fonts/inter-600-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Inter';font-style:normal;font-weight:700;font-display:swap;src:url('fonts/inter-700-latin.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Inter';font-style:normal;font-weight:700;font-display:swap;src:url('fonts/inter-700-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Inter';font-style:normal;font-weight:800;font-display:swap;src:url('fonts/inter-800-latin.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Inter';font-style:normal;font-weight:800;font-display:swap;src:url('fonts/inter-800-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Oswald';font-style:normal;font-weight:500 700;font-display:swap;src:url('fonts/oswald-latin.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Oswald';font-style:normal;font-weight:500 700;font-display:swap;src:url('fonts/oswald-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Chivo Mono';font-style:normal;font-weight:400 700;font-display:swap;src:url('fonts/chivomono-latin.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
:root{--sans:'Inter',system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;--display:'Oswald','Inter',system-ui,-apple-system,'Segoe UI',sans-serif;--mono:'Chivo Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}

/* ====================================================================
   Sistema de diseño del sitio público — v2
   --------------------------------------------------------------------
   Un solo archivo para los tres sitios del grupo (Fitorex, Medorax y
   Somatryx) y los dos idiomas. El generador inyecta DELANTE de este
   fichero la paleta y las fuentes de cada marca, y DETRÁS sus neutros y
   sus tokens propios. El resultado: tres sitios que se reconocen como
   del mismo estudio sin parecer el mismo sitio.

   Dos restricciones mandan sobre todo lo que hay aquí, y conviene
   entenderlas antes de tocar una línea:

     1. La CSP lleva `style-src 'self'` SIN `'unsafe-inline'`. Eso no
        bloquea solo los `<style>`: en CSP 3 `style-src-attr` hereda de
        `style-src`, así que un `style="…"` suelto en una página se
        descarta en producción y en local no se nota. Por eso NO hay ni
        un atributo `style` en las páginas y por eso existen las
        utilidades del final del archivo.

     2. `script-src 'none'` en casi todas las rutas. No hay JavaScript
        que anime nada. Todo el movimiento de este archivo —revelados al
        entrar en pantalla, cabecera que se encoge, barra de progreso,
        marquesina, carruseles con su indicador— es CSS puro, con
        animaciones ligadas al scroll (`animation-timeline`). Donde el
        navegador no las soporta no hay animación y el contenido se ve,
        que es lo único que no se negocia.

   Compatibilidad: este archivo lo consumen ~4.600 páginas ya generadas
   (780 de Fitorex, 3.780 de Medorax, 20 de Somatryx). Ninguna clase que
   existiera antes se ha eliminado; todas siguen funcionando, reskinadas.
   ==================================================================== */

/* ==================================================================
   1 · TOKENS
   ================================================================== */
:root{
  color-scheme:light;

  /* --- Tipografía ---
     --sans, --display y --mono los inyecta el generador delante de este
     archivo junto con sus @font-face, porque la familia cambia con la
     marca (ver web/fonts.mjs). Aquí solo se usan. */

  /* --- Neutros y superficies ---
     La marca (--primary, --accent, --on-primary) va inyectada justo
     encima; los neutros de abajo son los de Fitorex y cada marca puede
     sobreescribirlos con `palette.light.neutrals`. */
  --bg:#f6f8f4; --surface:#ffffff; --surface-2:#eef2ea; --surface-3:#e3ebdb;
  /* `--muted` se oscureció de #6b7a63 a #64725d: el original daba 4,28:1 sobre el
     fondo y 4,04:1 sobre la superficie alterna, por debajo del 4,5:1 que pide la AA
     para texto normal. Es el color de los pies de foto, las etiquetas de las cifras y
     los enlaces del pie: texto pequeño y, encima, el más difícil de leer. */
  --ink:#0d1508; --text:#414d3a; --muted:#64725d; --border:#dde4d6;

  /* Tintes derivados del primario. Todo lo que «lleva color de marca»
     sin ser color plano sale de aquí, así que cambiar --primary cambia
     el sitio entero de forma coherente. */
  --tint:color-mix(in srgb, var(--primary) 12%, transparent);
  --tint-2:color-mix(in srgb, var(--primary) 6%, transparent);
  --tint-3:color-mix(in srgb, var(--primary) 22%, transparent);
  --edge:color-mix(in srgb, var(--primary) 32%, var(--border));

  /* Línea de luz superior de las superficies. Es el truco que separa una
     tarjeta «plana con borde» de una tarjeta con material: un pelo de luz
     en el canto de arriba, como el bisel de un objeto real. En claro es
     blanco puro; en oscuro, un blanco al 8 %. */
  --hairline:color-mix(in srgb, #ffffff 92%, transparent);

  /* Banda invertida: la sección que se pone siempre oscura, llueva o
     truene, para partir el ritmo de la página. Es el recurso de Apple y
     de Nike y funciona igual de bien en los tres sitios. */
  --invert-bg:#0b0f09;
  --invert-surface:#151b12;
  --invert-ink:#ffffff;
  --invert-text:#b9c4b2;
  --invert-border:#26301f;
  /* El primario DENTRO de la banda invertida. Tiene que declararse aparte porque el
     primario de marca está elegido para contrastar con el fondo normal, y la banda
     invertida es justo el fondo contrario:

       · en Somatryx el primario claro es #111 — negro sobre la banda negra: invisible;
       · en Fitorex el verde oscuro #4f8f06 sobre negro se queda en 2,4:1.

     La regla práctica es que cada marca ponga aquí el primario de SU OTRO tema. */
  --invert-primary:var(--primary);
  --invert-primary-ink:var(--primary-ink);

  /* Degradado del texto destacado del titular. Cada marca puede
     redefinirlo (Somatryx lo pone monocromo). */
  --grad:linear-gradient(102deg, var(--primary-ink), var(--accent));

  /* --- Forma --- */
  --radius-xl:30px; --radius:20px; --radius-sm:13px; --radius-xs:9px; --radius-pill:999px;

  /* --- Elevación ---
     Cuatro niveles y no más. Cada uno combina un contacto corto (la
     sombra que pega el objeto al fondo) con una difusa larga y muy
     abierta (la que le da altura). Una sola sombra siempre parece
     pegatina. */
  --shadow-sm:0 1px 2px rgba(13,21,8,.05);
  --shadow:0 1px 2px rgba(13,21,8,.05), 0 14px 34px -16px rgba(13,21,8,.20);
  --shadow-lg:0 2px 5px rgba(13,21,8,.06), 0 32px 66px -26px rgba(13,21,8,.30);
  --shadow-xl:0 4px 10px rgba(13,21,8,.07), 0 50px 100px -40px rgba(13,21,8,.38);

  /* --- Retícula --- */
  --wrap:1140px; --wrap-wide:1320px; --wrap-text:720px;
  --gut:22px;
  --head-h:66px;

  /* --- Espaciado ---
     Escala de 8 con dos medios pasos abajo, donde se nota. */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px;
  --s6:32px; --s7:44px; --s8:60px; --s9:80px; --s10:112px;

  /* --- Movimiento ---
     Tres curvas y nada más:
       --ease-out    salida exponencial: arranca rápido y frena mucho.
                     Es la de iOS y la que hace que algo «aterrice».
       --ease-spring rebota un pelo al final. Solo para lo que aparece.
       --ease-inout  simétrica, para lo que va y vuelve (menús). */
  --ease-out:cubic-bezier(.22,1,.36,1);
  --ease-spring:cubic-bezier(.34,1.42,.64,1);
  --ease-inout:cubic-bezier(.65,0,.35,1);
  --dur-1:.14s; --dur-2:.22s; --dur-3:.4s; --dur-4:.7s; --dur-5:1s;

  /* --- Capas --- */
  --z-bar:30; --z-head:50; --z-sheet:60; --z-skip:100;

  /* --- Personalidad de marca ---
     Estos cuatro los sobreescribe cada marca desde `site.tokens`
     (web/site.config.mjs). Son los que hacen que el mismo CSS suene
     atlético en Fitorex, clínico en Medorax y de casa matriz en
     Somatryx sin duplicar una sola regla.

       --case-display  MAYÚSCULAS en los antetítulos (Fitorex, Somatryx)
                       o caja normal (Medorax, que es una marca académica
                       y en versalitas serias parece un pie de foto)
       --track-display espaciado de las letras del titular grande
       --glow          cuánta luz de color hay detrás de la portada
       --grain         cuánto grano tienen las bandas destacadas */
  --case-display:uppercase;
  --track-display:.14em;
  --glow:1;
  --grain:.055;
  /* Familia y espaciado de los TITULARES. Por defecto la de cuerpo, que es lo que
     quieren Fitorex y Somatryx: una grotesca apretada y muy pesada, que es el registro
     de Apple, Nike o Linear.

     Medorax pone aquí `var(--display)` y sus titulares pasan a la serif. No es un
     capricho: es una marca académica, y una serif en titular la coloca junto a un
     manual en vez de junto a una app de consumo. Una serif necesita además menos
     espaciado negativo que una grotesca — de ahí el segundo mando. */
  --h-font:var(--sans);
  --h-track:-.035em;
  /* Y el peso. No es cosmético: si la marca sirve una serif que solo trae 500 y 600 y
     el titular pide 800, el navegador engorda la 600 por software y el resultado es una
     letra sucia y con las gracias empastadas. El peso tiene que caber en lo que se ha
     descargado de verdad. */
  --h-weight:800;

  /* Textura de grano. Es un SVG con ruido fractal en un data-URI: lo
     permite `img-src 'self' data:` (los `background-image` cuelgan de
     img-src, no de style-src) y pesa 300 bytes contra los 40 KB de un
     PNG de ruido. Nunca va fijo a la ventana: solo dentro de las bandas
     que lo piden, porque una capa a pantalla completa cuesta compositor
     en cada scroll. */
  --grain-url: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='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");

  /* --- Escala tipográfica ---
     Fluida: un solo juego que crece con la ventana, en vez de tres
     saltos bruscos en tres media queries. --t-display es la nueva y solo
     la usan las portadas; --t-hero es la de siempre, subida de tope
     porque 4,2 rem en un monitor de 27" se queda pequeño. */
  --t-display:clamp(2.75rem,1.15rem + 6.6vw,6.6rem);
  --t-hero:clamp(2.3rem,1.35rem + 4.2vw,4.9rem);
  --t-h2:clamp(1.75rem,1.28rem + 1.95vw,2.85rem);
  --t-h3:clamp(1.14rem,1.05rem + .42vw,1.4rem);
  --t-lede:clamp(1.08rem,1rem + .55vw,1.35rem);
  --t-body:1.0325rem;
  --t-sm:.925rem;
  --t-xs:.83rem;
}

@media (prefers-color-scheme:dark){
  :root{
    color-scheme:dark;
    --bg:#080c06; --surface:#111a0e; --surface-2:#16210f; --surface-3:#1d2a15;
    --ink:#ecf5e4; --text:#adbba4; --muted:#82907a; --border:#26331d;
    --hairline:color-mix(in srgb, #ffffff 9%, transparent);
    --shadow-sm:0 1px 2px rgba(0,0,0,.5);
    --shadow:0 1px 2px rgba(0,0,0,.45), 0 18px 44px -20px rgba(0,0,0,.85);
    --shadow-lg:0 2px 6px rgba(0,0,0,.55), 0 36px 76px -30px rgba(0,0,0,.95);
    --shadow-xl:0 4px 12px rgba(0,0,0,.6), 0 56px 110px -44px rgba(0,0,0,1);
    /* En oscuro la banda invertida no puede ser «más oscura»: se
       invierte al revés y se pone clara, que es lo que la sigue
       separando del resto de la página. */
    --invert-bg:#f4f6f2;
    --invert-surface:#ffffff;
    --invert-ink:#0b0f09;
    --invert-text:#4b5646;
    --invert-border:#dbe2d6;
    --grain:.03;
  }
}

/* ==================================================================
   2 · BASE
   ================================================================== */
*,*::before,*::after{box-sizing:border-box}
html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  scroll-padding-top:calc(var(--head-h) + 18px);
  /* `clip` y no `hidden`. La diferencia importa aquí por dos motivos concretos:
       · la hoja del menú móvil se aparca fuera de pantalla con
         `transform:translateX(100%)`, y con `hidden` eso ensancha el documento
         360 px — en un teléfono la página se arrastraba de lado sin motivo;
       · `hidden` convierte al elemento en contenedor de scroll, y eso rompe
         `position:sticky` en sus descendientes (la cabecera, la barra de filtros
         de la biblioteca y la columna lateral de las fichas). `clip` recorta sin
         crear scroll.
     El `hidden` de `body` se queda debajo como respaldo para Safari 15, que no
     conoce `clip` y descarta la línea. */
  overflow-x:clip;
}
body{
  margin:0; background:var(--bg); color:var(--text);
  font:400 var(--t-body)/1.68 var(--sans);
  -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;
  text-rendering:optimizeLegibility;
  overflow-x:hidden; overflow-x:clip;
  /* Las cifras nunca bailan de ancho al cambiar: en una página llena de
     números un «1» estrecho descoloca la columna entera. */
  font-variant-numeric:tabular-nums lining-nums;
}
img,svg,video{max-width:100%; height:auto; display:block}
a{color:var(--primary-ink); text-underline-offset:3px; text-decoration-thickness:1.5px}
a:hover{text-decoration:underline}

h1,h2,h3,h4{color:var(--ink); font-family:var(--h-font); line-height:1.14; letter-spacing:-.022em; margin:0; text-wrap:balance}
h1{font-size:var(--t-hero); font-weight:var(--h-weight); letter-spacing:var(--h-track); line-height:1.04}
h2{font-size:var(--t-h2); font-weight:var(--h-weight); letter-spacing:calc(var(--h-track) + .005em); line-height:1.08}
h3{font-size:var(--t-h3); font-weight:700}
h4{font-size:1.0325rem; font-weight:700}
p{margin:0 0 1em; text-wrap:pretty}
p:last-child{margin-bottom:0}
strong,b{color:var(--ink); font-weight:640}
em{font-style:italic}
small{font-size:var(--t-xs)}
code{font:500 .88em/1 var(--mono); background:var(--surface-2); border:1px solid var(--border); border-radius:6px; padding:.15em .42em}
hr{border:none; border-top:1px solid var(--border); margin:var(--s6) 0}
::selection{background:var(--tint-3); color:var(--ink)}

.wrap{max-width:var(--wrap); margin:0 auto; padding:0 var(--gut)}
.wrap-wide{max-width:var(--wrap-wide); margin:0 auto; padding:0 var(--gut)}
.wrap-text{max-width:var(--wrap-text); margin:0 auto}
.lede{font-size:var(--t-lede); line-height:1.58; color:var(--text)}
.muted{color:var(--muted)}
.center{text-align:center}
.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}

.skip{
  position:absolute; left:-9999px; top:0; z-index:var(--z-skip);
  background:var(--primary); color:var(--on-primary); padding:12px 18px;
  border-radius:0 0 10px 0; font-weight:650; text-decoration:none;
}
.skip:focus{left:0}
:focus-visible{outline:2.5px solid var(--primary); outline-offset:3px; border-radius:5px}

/* ==================================================================
   3 · MATERIAL
   ------------------------------------------------------------------
   Tres mezcladores que se aplican por composición y no por herencia.
   Están arriba del todo porque los usan casi todos los bloques de
   abajo, y así se lee una vez qué significa «superficie» en este sitio.
   ================================================================== */

/* Superficie base: fondo, borde de un pelo y la línea de luz del canto.
   El `::before` en vez de un `box-shadow: inset` para que no se lo coma
   un `overflow:hidden` ni pinte por encima del contenido. */
.surface,
.card,.plat,.plan,.tile,.steps li,.stats li,.pcard,.kpi,.lib-card,
.log article,.exanim,.facts,.calc,.login-card,.gloss article,.prevnext a,
.faq details,.callout,.table-wrap,.bento>*,.spec div,.pull,.timeline li{
  position:relative;
  background:var(--surface);
  border:1px solid var(--border);
  box-shadow:var(--shadow-sm);
}
/* La línea de luz va en ::after y no en ::before para no pelearse con
   los ::before que ya tienen contenido propio: el contador de los pasos
   numerados y el punto de la línea de tiempo. */
:where(.card,.plat,.plan,.tile,.stats li,.pcard,.kpi,.log article,.calc,
       .login-card,.gloss article,.bento>*,.spec div,.pull,.lib-card)::after{
  content:""; position:absolute; inset:0; border-radius:inherit;
  pointer-events:none; z-index:0;
  box-shadow:inset 0 1px 0 var(--hairline);
}
/* Los que llevan contenido propio en ::after se quedan fuera del truco. */
.phone::after,.crumbs li+li::before{box-shadow:none}

/* Cristal: la cabecera y la barra de filtros. `saturate` antes de `blur`
   porque el desenfoque a secas lava el color de lo que hay debajo. */
.glass{
  background:color-mix(in srgb, var(--bg) 78%, transparent);
  backdrop-filter:saturate(180%) blur(16px);
  -webkit-backdrop-filter:saturate(180%) blur(16px);
}

/* Grano. Solo dentro de bandas concretas. */
.grainy{position:relative; isolation:isolate}
.grainy::before{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
  background-image:var(--grain-url); background-size:160px 160px;
  opacity:var(--grain); mix-blend-mode:overlay;
}

/* Malla de color: dos o tres manchas muy diluidas del primario y del
   acento. Pesa cero, escala a cualquier pantalla y en modo oscuro se
   apaga sola porque sale de las mismas variables. */
.mesh{position:relative; isolation:isolate}
.mesh::after{
  content:""; position:absolute; inset:-40% -10% auto; height:150%; z-index:-2; pointer-events:none;
  background:
    radial-gradient(52% 44% at 18% 6%,  color-mix(in srgb, var(--primary) calc(20% * var(--glow)), transparent), transparent 68%),
    radial-gradient(46% 40% at 84% 0%,  color-mix(in srgb, var(--accent)  calc(17% * var(--glow)), transparent), transparent 66%),
    radial-gradient(40% 36% at 52% 30%, color-mix(in srgb, var(--primary) calc(8%  * var(--glow)), transparent), transparent 70%);
}

/* ==================================================================
   4 · ICONOS
   ================================================================== */
.ic{width:24px; height:24px; flex:none}
.ic-sm{width:18px; height:18px}
.ic-lg{width:30px; height:30px}
/* Cuadro tintado del icono: da peso visual sin recurrir al color plano. */
.ic-box{
  width:46px; height:46px; border-radius:14px; display:grid; place-items:center;
  margin-bottom:var(--s4); position:relative; z-index:1;
  background:var(--tint); color:var(--primary-ink);
  border:1px solid var(--tint-3);
  transition:transform var(--dur-2) var(--ease-spring), background var(--dur-2) ease;
}
.card:hover .ic-box,.tile:hover .ic-box{transform:translateY(-2px) rotate(-3deg)}

/* ==================================================================
   5 · CABECERA
   ================================================================== */
.site-head{
  position:sticky; top:0; z-index:var(--z-head);
  background:color-mix(in srgb, var(--bg) 78%, transparent);
  backdrop-filter:saturate(180%) blur(16px); -webkit-backdrop-filter:saturate(180%) blur(16px);
  border-bottom:1px solid transparent;
  transition:border-color var(--dur-2) ease;
}
/* La línea inferior y la sombra solo aparecen cuando la página está
   desplazada: con la página arriba del todo, una raya bajo la cabecera
   parte el diseño sin motivo. Ligado al scroll, sin JavaScript.

   Solo de 941 px para arriba, y esa condición NO es estética: ver el
   bloque de móvil de más abajo. */
@media (min-width:941px){
  @supports (animation-timeline:scroll()){
    .site-head{
      animation:head-settle linear both;
      animation-timeline:scroll();
      animation-range:0 130px;
    }
    @keyframes head-settle{
      to{
        border-bottom-color:var(--border);
        box-shadow:0 10px 30px -22px rgba(0,0,0,.5);
        background:color-mix(in srgb, var(--bg) 88%, transparent);
      }
    }
  }
  @supports not (animation-timeline:scroll()){ .site-head{border-bottom-color:var(--border)} }
}

/* ---------- por qué la cabecera pierde el cristal en móvil ----------
   `backdrop-filter` convierte al elemento en BLOQUE CONTENEDOR de sus
   descendientes `position:fixed`. La hoja del menú móvil es uno de
   ellos, así que con el cristal puesto dejaba de posicionarse respecto a
   la ventana y pasaba a hacerlo respecto a la cabecera: el menú medía
   84 px de alto —la altura de la barra— en vez de la pantalla entera, y
   sus nueve entradas se aplastaban dentro hasta 30 px cada una.

   Es un fallo que no se ve en el HTML, no da error en consola y solo
   aparece en un teléfono. La cabecera de móvil se queda opaca, que
   además cuesta menos compositor en el dispositivo que peor lo lleva. */
@media (max-width:940px){
  .site-head{
    background:var(--bg);
    backdrop-filter:none; -webkit-backdrop-filter:none;
    border-bottom-color:var(--border);
  }
}

/* Barra de progreso de lectura. Un pelo de color que crece con el
   scroll: en las guías largas y en las páginas legales es la única
   pista de cuánto queda. Puramente decorativa, así que va oculta a los
   lectores de pantalla desde el HTML. */
.head-progress{
  position:absolute; left:0; bottom:-1px; height:2px; width:100%;
  transform-origin:0 50%; transform:scaleX(0);
  background:linear-gradient(90deg, var(--primary), var(--accent));
}
@supports (animation-timeline:scroll()){
  @media (prefers-reduced-motion:no-preference){
    .head-progress{animation:progress linear both; animation-timeline:scroll(); animation-range:0 100%}
    @keyframes progress{to{transform:scaleX(1)}}
  }
}

.head-inner{display:flex; align-items:center; gap:var(--s4); min-height:var(--head-h)}
.brand{
  display:flex; align-items:center; gap:10px; font-weight:800; font-size:1.075rem;
  color:var(--ink); text-decoration:none; flex:none; letter-spacing:-.025em;
}
.brand img{border-radius:10px; transition:transform var(--dur-2) var(--ease-spring)}
.brand:hover{text-decoration:none}
.brand:hover img{transform:rotate(-6deg) scale(1.06)}

/* ---------- marca dibujada con máscara ----------
   Para las marcas con wordmark propio (una tipografía que el sitio no
   lleva), el logo se pinta con `mask-image` + `currentColor` en vez de
   con un <img>.

   El motivo es el tema: el original es tinta negra sobre papel blanco.
   Como <img> harían falta dos archivos y acertar con el
   `prefers-color-scheme` en los dos. Con máscara el PNG solo aporta la
   FORMA y el color lo pone el texto de al lado, así que la marca sigue
   al tema sola y siempre contrasta. */
.brand-mark,.brand-word{
  display:block; background:currentColor; flex:none;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-size:contain; mask-size:contain;
  -webkit-mask-position:center; mask-position:center;
}
/* Proporciones tomadas del original: monograma 247×376, wordmark 1044×61. */
.brand-mark{
  width:19px; height:29px;
  -webkit-mask-image:url('/assets/logo-mark.png'); mask-image:url('/assets/logo-mark.png');
}
.brand-word{
  width:188px; height:11px; margin-top:2px;
  -webkit-mask-image:url('/assets/logo-word.png'); mask-image:url('/assets/logo-word.png');
}
.brand-lock{gap:13px}
@media (max-width:420px){
  .brand-mark{width:16px; height:24px}
  .brand-word{width:145px; height:8.5px}
}
.foot-brand .brand-mark{width:23px; height:35px}
.foot-brand .brand-word{width:210px; height:12.3px}

/* ---------- navegación ---------- */
.site-nav{margin-left:auto; display:flex; align-items:center; gap:2px}
.site-nav a{
  position:relative; color:var(--text); text-decoration:none; font-size:.9rem; font-weight:530;
  padding:8px 13px; border-radius:10px; white-space:nowrap;
  transition:color var(--dur-1) ease, background var(--dur-1) ease;
}
.site-nav a:hover{color:var(--ink); background:var(--surface-2); text-decoration:none}
.site-nav a[aria-current="page"]{color:var(--primary-ink); background:var(--tint)}
/* Subrayado de precisión bajo el enlace activo: 2 px que arrancan desde
   el centro. Es el detalle que separa una barra de enlaces de una
   navegación. */
.site-nav a[aria-current="page"]::after{
  content:""; position:absolute; left:13px; right:13px; bottom:3px; height:2px;
  border-radius:2px; background:var(--primary);
  animation:underline var(--dur-3) var(--ease-out) both;
}
@keyframes underline{from{transform:scaleX(0)}to{transform:scaleX(1)}}

.nav-lang{
  margin-left:var(--s2); font-weight:700!important; font-size:.78rem!important; letter-spacing:.05em;
  border:1px solid var(--border); color:var(--muted)!important; padding:6px 10px!important;
}
.nav-lang:hover{color:var(--ink)!important; border-color:var(--edge)}
.nav-login{color:var(--ink)!important; font-weight:620!important}
/* Botón principal de la cabecera, con barrido de luz al pasar por
   encima. El barrido es un pseudoelemento inclinado que cruza el botón:
   no hay imagen ni script, y en reduced-motion se queda quieto. */
.nav-cta{
  position:relative; overflow:hidden;
  background:var(--primary)!important; color:var(--on-primary)!important;
  margin-left:6px; font-weight:660!important; padding:9px 17px!important;
  box-shadow:0 8px 20px -10px var(--primary);
  transition:box-shadow var(--dur-2) ease, transform var(--dur-2) var(--ease-out);
}
.nav-cta:hover{transform:translateY(-1px); box-shadow:0 12px 26px -10px var(--primary)}
.nav-cta::before{
  content:""; position:absolute; top:0; bottom:0; left:-140%; width:60%;
  background:linear-gradient(100deg, transparent, color-mix(in srgb, #fff 45%, transparent), transparent);
  transform:skewX(-18deg); pointer-events:none;
}
@media (prefers-reduced-motion:no-preference){
  .nav-cta:hover::before{animation:sheen .85s var(--ease-out)}
  @keyframes sheen{to{left:150%}}
}

/* ---------- menú móvil ----------
   Hoja a pantalla completa, no un desplegable. Con seis entradas más
   idioma, acceso y descarga, un acordeón bajo la cabecera obliga a
   apuntar a objetivos de 30 px; una hoja da un objetivo de 56 px por
   fila y sitio para separar la navegación de las acciones.

   Todo con un checkbox: la etiqueta del hamburguesa lo marca, el velo
   de fondo lo desmarca. Cero JavaScript, y el foco del teclado sigue el
   orden natural del documento. */
/* El checkbox va invisible pero NO `display:none` ni `hidden`: así sigue en el
   árbol de accesibilidad y se puede abrir y cerrar el menú con Tab + Espacio.
   Con `hidden` —que es como estaba— el menú solo se abría con el ratón. */
.navtoggle{position:absolute; opacity:0; width:1px; height:1px; margin:0; pointer-events:none}
.burger{
  display:none; margin-left:auto; padding:11px; cursor:pointer; border-radius:11px;
  transition:background var(--dur-1) ease;
}
.burger:hover{background:var(--surface-2)}
/* El foco del teclado vive en el checkbox, que es invisible: hay que pintarlo en el
   hamburguesa o quien navega con Tab no sabe dónde está. */
.navtoggle:focus-visible ~ .burger{outline:2.5px solid var(--primary); outline-offset:2px}
.burger span{
  display:block; width:21px; height:2px; background:var(--ink); border-radius:2px;
  transition:transform var(--dur-3) var(--ease-out), opacity var(--dur-2) ease;
}
.burger span+span{margin-top:5px}
/* El hamburguesa se convierte en aspa cuando el menú está abierto. */
.navtoggle:checked ~ .burger span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.navtoggle:checked ~ .burger span:nth-child(2){opacity:0; transform:scaleX(.4)}
.navtoggle:checked ~ .burger span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

.nav-scrim{display:none}

@media (max-width:940px){
  .burger{display:block; order:3}
  .site-nav{
    position:fixed; inset:var(--head-h) 0 0 auto; width:min(360px,86vw);
    z-index:var(--z-sheet);
    margin:0; flex-direction:column; align-items:stretch; justify-content:flex-start;
    gap:2px; padding:var(--s5) var(--s5) var(--s8);
    background:var(--bg); border-left:1px solid var(--border);
    box-shadow:var(--shadow-xl);
    overflow-y:auto; overscroll-behavior:contain;
    transform:translateX(100%); visibility:hidden;
    transition:transform var(--dur-3) var(--ease-out), visibility var(--dur-3);
  }
  .navtoggle:checked ~ .site-nav{transform:none; visibility:visible}
  .site-nav a{
    padding:15px 14px; font-size:1.06rem; font-weight:600; border-radius:12px;
    border-bottom:1px solid var(--border);
    /* Un menú largo se desplaza, no se comprime. Sin esto, en cuanto las entradas no
       caben, el reparto flexible les quita altura hasta dejarlas por debajo del
       objetivo táctil de 44 px — y las últimas, que son «Entrar» y «Descargar», son
       justo las que hay que poder pulsar. */
    flex:none;
  }
  .site-nav a[aria-current="page"]::after{display:none}
  /* 13 px de relleno y no 6: en la hoja móvil el selector de idioma se quedaba en 35 px
     de alto, por debajo del objetivo táctil de 44 px que piden tanto Apple como las
     pautas WCAG. Es el único control del menú que no era un enlace de ancho completo, y
     por eso se le había escapado. */
  .nav-lang{align-self:flex-start; margin:var(--s4) 0 0; padding:13px 16px!important; font-size:.85rem!important; border-bottom:1px solid var(--border)!important}
  .nav-cta,.nav-login{margin:var(--s3) 0 0; text-align:center; justify-content:center; border-bottom:none!important}
  .nav-cta{padding:15px 18px!important; border-radius:12px; font-size:1.02rem}
  /* Velo. Nace en display:none, así que no hay ninguna capa a pantalla
     completa compositando mientras el menú está cerrado. */
  .navtoggle:checked ~ .nav-scrim{
    display:block; position:fixed; inset:0; z-index:calc(var(--z-sheet) - 1);
    background:color-mix(in srgb, var(--ink) 42%, transparent);
    backdrop-filter:blur(3px); -webkit-backdrop-filter:blur(3px);
    animation:fade var(--dur-3) ease both; cursor:pointer;
  }
  @keyframes fade{from{opacity:0}to{opacity:1}}
}

/* ==================================================================
   6 · SECCIONES
   ================================================================== */
section{padding:clamp(64px,8.5vw,132px) 0; position:relative}
section.tight{padding:clamp(34px,4.5vw,62px) 0}
section.flush{padding-top:0}
.alt{background:var(--surface-2); border-block:1px solid var(--border)}

.section-head{max-width:720px; margin:0 auto clamp(36px,4.6vw,62px); text-align:center}
.section-head h2{margin-bottom:var(--s4)}
.section-head p{color:var(--muted); font-size:1.09rem; margin:0}
/* Encabezado alineado a la izquierda, para las secciones editoriales
   donde el centrado hace que todo parezca una landing de plantilla. */
.section-head.left{text-align:left; margin-inline:0; max-width:760px}

.eyebrow{
  display:inline-block; font-family:var(--display); font-size:.86rem; font-weight:600;
  letter-spacing:var(--track-display); text-transform:var(--case-display);
  color:var(--primary-ink); margin-bottom:var(--s3);
}
/* Antetítulo con guía: una raya corta delante, como en una portada de
   revista. Se usa donde el antetítulo va solo, sin icono. */
.kicker{
  display:inline-flex; align-items:center; gap:10px;
  font-family:var(--display); font-size:.82rem; font-weight:600;
  letter-spacing:var(--track-display); text-transform:var(--case-display);
  color:var(--muted); margin-bottom:var(--s4);
}
.kicker::before{content:""; width:26px; height:1px; background:var(--primary); flex:none}

/* Regla con etiqueta: separa dos bloques largos sin gritar. */
.rule{display:flex; align-items:center; gap:var(--s4); margin:var(--s7) 0; color:var(--muted); font-size:var(--t-xs); text-transform:var(--case-display); letter-spacing:var(--track-display)}
.rule::before,.rule::after{content:""; height:1px; background:var(--border); flex:1}

/* ---------- banda invertida ----------
   La sección que se pone al revés que el resto de la página. Sirve para
   partir el ritmo cada tres o cuatro secciones; usada dos veces en una
   portada funciona, usada seis parece un tablero de ajedrez. */
section.invert{
  background:var(--invert-bg); border-block:none;
  /* Se reasigna la paleta ENTERA para el subárbol. Todo lo de dentro —tarjetas,
     iconos, tintes, bordes— sale de estas mismas variables, así que no hace falta ni
     una regla `.invert .card{…}`: los componentes se recolorean solos. */
  --primary:var(--invert-primary);
  --primary-ink:var(--invert-primary-ink);
  --surface:var(--invert-surface);
  --surface-2:color-mix(in srgb, var(--invert-surface) 70%, var(--invert-bg));
  --ink:var(--invert-ink);
  --text:var(--invert-text);
  --muted:color-mix(in srgb, var(--invert-text) 78%, transparent);
  --border:var(--invert-border);
  --hairline:color-mix(in srgb, var(--invert-ink) 8%, transparent);
  color:var(--invert-text);
}
section.invert h1,section.invert h2,section.invert h3,section.invert h4{color:var(--invert-ink)}
section.invert .eyebrow{color:var(--primary)}

/* ==================================================================
   7 · PORTADAS
   ================================================================== */
.hero{
  padding:clamp(64px,8vw,124px) 0 clamp(34px,4.4vw,58px);
  text-align:center; position:relative; isolation:isolate;
}
.hero::before{
  content:""; position:absolute; inset:-34% -10% 0; z-index:-1; pointer-events:none;
  background:
    radial-gradient(58% 46% at 22% 8%,  color-mix(in srgb, var(--primary) calc(20% * var(--glow)), transparent), transparent 70%),
    radial-gradient(50% 42% at 82% 0%,  color-mix(in srgb, var(--accent)  calc(17% * var(--glow)), transparent), transparent 68%);
}
/* Grano sobre la malla: sin él, dos degradados grandes en una pantalla
   OLED enseñan bandas de color escalonadas. */
.hero::after{
  content:""; position:absolute; inset:-34% -10% 0; z-index:-1; pointer-events:none;
  background-image:var(--grain-url); background-size:160px 160px;
  opacity:var(--grain); mix-blend-mode:overlay;
}
/* Monograma grande de la portada. Mismo mecanismo de máscara que la
   cabecera, así que sigue al tema. */
.hero-mark{
  display:block; margin:0 auto var(--s5); width:clamp(48px,5vw,66px); height:clamp(73px,7.6vw,100px);
  background:currentColor; color:var(--primary-ink); opacity:.92;
  -webkit-mask-image:url('/assets/logo-mark.png'); mask-image:url('/assets/logo-mark.png');
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-size:contain; mask-size:contain;
  -webkit-mask-position:center; mask-position:center;
}
.hero h1{margin-bottom:var(--s5); max-width:17ch; margin-inline:auto}
.hero .grad{
  background:var(--grad); -webkit-background-clip:text; background-clip:text; color:transparent;
  /* Una descendente de la «g» o la «p» se corta con background-clip si
     la caja va justa: un pelo de relleno abajo lo evita. */
  padding-bottom:.06em;
}
.hero .lede{max-width:680px; margin:0 auto var(--s6)}
.hero-note{font-size:var(--t-sm); color:var(--muted); margin:var(--s4) 0 0}

/* Portada extragrande: la de la home. El titular a --t-display y sin
   límite de 17ch, porque aquí el titular ES el diseño. */
.hero-xl{padding:clamp(78px,10vw,168px) 0 clamp(40px,5vw,72px)}
.hero-xl h1{font-size:var(--t-display); letter-spacing:-.04em; line-height:.98; max-width:19ch}
.hero-xl .lede{max-width:600px; font-size:clamp(1.1rem,1rem + .7vw,1.42rem)}

/* Portada alineada a la izquierda con media al lado. Es la disposición
   editorial: el texto manda y la imagen acompaña, en vez del bloque
   centrado que usa todo el mundo. */
.hero-split{text-align:left}
.hero-split .wrap{
  display:grid; grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);
  gap:clamp(32px,5vw,76px); align-items:center;
}
/* En la portada partida el titular vive en media retícula, así que no puede usar la
   escala de la portada centrada: 6,6 rem en una columna de 540 px deja cinco letras
   por línea y ocho líneas de titular. Esta escala está calculada para esa columna. */
.hero-split h1{margin-inline:0; max-width:15ch; font-size:clamp(2.3rem,1.2rem + 3.4vw,4.15rem)}
.hero-split .lede{margin-inline:0; max-width:52ch}
.hero-split .cta,.hero-split .trustbar{justify-content:flex-start}
.hero-split .trustbar{gap:10px 22px}
.hero-media{display:flex; justify-content:center; align-items:center; min-width:0}
.hero-media .phone{max-width:290px}
.hero-media .frame{width:100%}
@media (max-width:900px){
  .hero-split{text-align:center}
  .hero-split .wrap{grid-template-columns:1fr}
  .hero-split h1,.hero-split .lede{max-width:none; margin-inline:auto}
  .hero-split .cta,.hero-split .trustbar{justify-content:center}
  /* La media baja debajo del texto y no encima: en un teléfono, empujar el titular
     por debajo del pliegue con una imagen es perder la única frase que se lee seguro. */
  .hero-split .hero-media{order:2; margin-top:var(--s6)}
}

.hero-page{padding:clamp(54px,6.4vw,96px) 0 clamp(24px,3.2vw,42px); text-align:center; position:relative; isolation:isolate}
.hero-page::before{
  content:""; position:absolute; inset:-40% 0 40%; z-index:-1; pointer-events:none;
  background:radial-gradient(48% 60% at 50% 0%, var(--tint), transparent 72%);
}
/* Mismo grano que la portada. Sin él, un degradado radial grande en una pantalla OLED
   enseña anillos escalonados justo detrás del titular. */
.hero-page::after{
  content:""; position:absolute; inset:-40% 0 40%; z-index:-1; pointer-events:none;
  background-image:var(--grain-url); background-size:160px 160px;
  opacity:var(--grain); mix-blend-mode:overlay;
}
.hero-page h1{margin-bottom:var(--s4)}
.hero-page .lede{max-width:720px; margin:0 auto}
.hero-page .cta{margin-top:var(--s6)}
/* Cifras bajo la entradilla de una página de colección. Sin tarjeta y separadas por
   líneas: en una portada interior no compiten con el titular, lo respaldan. */
.hero-stats{
  display:flex; flex-wrap:wrap; justify-content:center; align-items:stretch;
  gap:0; list-style:none; margin:var(--s6) 0 0; padding:0;
}
.hero-stats li{padding:0 clamp(18px,3vw,34px); border-left:1px solid var(--border)}
.hero-stats li:first-child{border-left:none}
.hero-stats b{
  display:block; font-family:var(--display); font-weight:600; line-height:1;
  font-size:clamp(1.5rem,1.2rem + 1.1vw,2.2rem); color:var(--ink);
  letter-spacing:-.01em; font-variant-numeric:tabular-nums;
}
.hero-stats span{display:block; margin-top:7px; font-size:var(--t-xs); color:var(--muted); line-height:1.4}
@media (max-width:600px){
  .hero-stats{gap:var(--s4) 0}
  .hero-stats li{flex:1 0 45%; padding:0 var(--s3)}
  .hero-stats li:nth-child(odd){border-left:none}
}
.hero-page-media{margin-top:clamp(30px,4vw,52px)}

/* Sello de confianza bajo los botones de la portada. */
.trustbar{
  display:flex; flex-wrap:wrap; justify-content:center; gap:10px 28px;
  list-style:none; margin:var(--s6) 0 0; padding:0;
}
.trustbar li{display:flex; align-items:center; gap:8px; font-size:var(--t-sm); color:var(--muted)}
.trustbar .ic{width:19px; height:19px; color:var(--primary-ink)}

/* ---------- entrada de la portada ----------
   Los hijos directos de la portada aparecen escalonados al cargar. Es
   la única animación del sitio que no depende del scroll, y existe
   porque la primera pantalla es la única que nadie desplaza para ver.

   `both` deja el estado inicial aplicado antes de arrancar; si el
   usuario pide menos movimiento, el bloque global del final las reduce
   a 1 ms y el contenido aparece de golpe, que es lo correcto. */
@media (prefers-reduced-motion:no-preference){
  .hero > .wrap > *,
  .hero-copy > *,
  .hero-split .hero-media{animation:enter var(--dur-4) var(--ease-out) both}
  /* En la portada partida el escalonado lo llevan los hijos del texto, no las dos
     columnas: si animas la columna entera, el titular y los botones aparecen a la vez
     y se pierde justo el efecto que se buscaba. */
  .hero-split > .wrap > *{animation:none}
  :where(.hero > .wrap, .hero-copy) > *:nth-child(1){animation-delay:.04s}
  :where(.hero > .wrap, .hero-copy) > *:nth-child(2){animation-delay:.11s}
  :where(.hero > .wrap, .hero-copy) > *:nth-child(3){animation-delay:.18s}
  :where(.hero > .wrap, .hero-copy) > *:nth-child(4){animation-delay:.25s}
  :where(.hero > .wrap, .hero-copy) > *:nth-child(5){animation-delay:.32s}
  .hero-split .hero-media{animation-delay:.22s; animation-duration:var(--dur-5)}
  @keyframes enter{from{opacity:0; transform:translateY(18px)} to{opacity:1; transform:none}}
}

/* ==================================================================
   8 · BOTONES
   ================================================================== */
.cta{display:flex; gap:12px; justify-content:center; flex-wrap:wrap}
.btn{
  position:relative; overflow:hidden;
  display:inline-flex; align-items:center; justify-content:center; gap:9px; text-decoration:none;
  font-weight:650; font-size:.96rem; padding:15px 26px; border-radius:14px; line-height:1.2;
  border:1.5px solid transparent; cursor:pointer;
  transition:transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) ease,
             filter var(--dur-2) ease, border-color var(--dur-2) ease;
}
.btn .ic{width:19px; height:19px; transition:transform var(--dur-2) var(--ease-out)}
.btn:hover{text-decoration:none; transform:translateY(-2px)}
.btn:active{transform:translateY(0) scale(.985)}
.btn-primary{background:var(--primary); color:var(--on-primary); box-shadow:0 12px 28px -12px var(--primary)}
.btn-primary:hover{filter:brightness(1.06); box-shadow:0 18px 38px -14px var(--primary)}
.btn-ghost{background:var(--surface); color:var(--ink); border-color:var(--border); box-shadow:var(--shadow-sm)}
.btn-ghost:hover{box-shadow:var(--shadow); border-color:var(--edge)}
/* Botón de texto: la tercera acción, la que no compite con las otras
   dos. Solo una flecha que se desplaza. */
.btn-text{
  background:none; border:none; padding:14px 4px; color:var(--primary-ink);
  box-shadow:none; text-decoration:none;
}
.btn-text:hover{transform:none; text-decoration:underline}
.btn-text:hover .ic{transform:translateX(4px)}
.btn-sm{padding:11px 19px; font-size:.9rem; border-radius:11px}
.btn-lg{padding:18px 32px; font-size:1.04rem; border-radius:16px}
.btn-block{width:100%}
/* Barrido de luz, igual que el de la cabecera. */
.btn-primary::before{
  content:""; position:absolute; top:0; bottom:0; left:-140%; width:55%;
  background:linear-gradient(100deg, transparent, color-mix(in srgb, #fff 40%, transparent), transparent);
  transform:skewX(-18deg); pointer-events:none;
}
@media (prefers-reduced-motion:no-preference){
  .btn-primary:hover::before{animation:sheen .85s var(--ease-out)}
}

/* ==================================================================
   9 · CIFRAS
   ================================================================== */
.stats{display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:14px; margin:0; padding:0; list-style:none}
.stats li{
  border-radius:var(--radius); padding:var(--s5) var(--s4); text-align:center;
  transition:transform var(--dur-2) var(--ease-out), border-color var(--dur-2) ease;
}
.stats li:hover{transform:translateY(-2px); border-color:var(--edge)}
.stats b{
  display:block; color:var(--ink); font-size:clamp(1.95rem,1.35rem + 1.6vw,2.75rem);
  font-family:var(--display); font-weight:600; letter-spacing:.005em; line-height:1.02;
  font-variant-numeric:tabular-nums; position:relative; z-index:1;
}
.stats span{display:block; font-size:var(--t-xs); color:var(--muted); margin-top:6px; line-height:1.45; position:relative; z-index:1}

/* ---------- banda de cifras grandes ----------
   Las mismas cifras sin tarjeta: números enormes separados por líneas.
   Es lo que hace Stripe con sus métricas y lo que hace que una cifra
   parezca un hecho y no un adorno. */
.numbers{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  list-style:none; margin:0; padding:0; gap:0;
}
.numbers li{padding:var(--s5) var(--s5); border-left:1px solid var(--border)}
.numbers li:first-child{border-left:none; padding-left:0}
@media (max-width:760px){
  .numbers{grid-template-columns:repeat(2,minmax(0,1fr))}
  .numbers li{padding:var(--s4) var(--s4)}
  .numbers li:nth-child(odd){border-left:none; padding-left:0}
  .numbers li:nth-child(n+3){border-top:1px solid var(--border)}
}
.numbers b{
  display:block; font-family:var(--display); font-weight:600;
  font-size:clamp(2.6rem,1.6rem + 3.4vw,4.6rem); line-height:.96;
  letter-spacing:-.02em; color:var(--ink); font-variant-numeric:tabular-nums;
}
.numbers span{display:block; margin-top:10px; font-size:var(--t-sm); color:var(--muted); line-height:1.5; max-width:24ch}
/* Las cifras entran barridas desde abajo, recortadas por su propia
   caja. Sin contador animado a propósito: un contador en JavaScript no
   cabe en esta CSP, y uno en CSS con `counter()` imprimiría «2160» sin
   el separador de millares, que en español es un error de ortografía. */
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    .numbers li{animation:reveal linear both; animation-timeline:view(); animation-range:entry 0% cover 26%}
    .numbers li:nth-child(2){animation-range:entry 0% cover 32%}
    .numbers li:nth-child(3){animation-range:entry 0% cover 38%}
    .numbers li:nth-child(4){animation-range:entry 0% cover 44%}
  }
}

/* ==================================================================
   10 · CAPTURAS Y MEDIA
   ================================================================== */
.shots{
  display:flex; gap:24px; overflow-x:auto; padding:10px 4px 20px;
  scroll-snap-type:x mandatory; scrollbar-width:thin; scroll-padding-inline:var(--gut);
}
.shots figure{margin:0; flex:0 0 auto; width:244px; scroll-snap-align:center}
.shots figcaption{font-size:var(--t-xs); color:var(--muted); text-align:center; margin-top:var(--s4); line-height:1.5}

/* Marco de teléfono en CSS: un borde grueso muy redondeado. Sin imagen
   de móvil que pesar ni que se vea borrosa en pantallas densas. */
.phone{
  border:7px solid color-mix(in srgb, var(--ink) 88%, transparent);
  border-radius:34px; padding:0; overflow:hidden; background:var(--ink);
  box-shadow:var(--shadow-lg); position:relative;
  transition:transform var(--dur-3) var(--ease-out), box-shadow var(--dur-3) ease;
}
.phone img{border-radius:27px; display:block}
/* Muesca del altavoz. */
.phone::after{
  content:""; position:absolute; top:6px; left:50%; transform:translateX(-50%);
  width:34%; height:4px; border-radius:99px; background:color-mix(in srgb, var(--bg) 34%, transparent);
  z-index:2;
}
/* Reflejo de la pantalla: una diagonal muy tenue que cruza el cristal.
   Es lo que hace que el marco parezca un objeto y no un rectángulo. */
.phone::before{
  content:""; position:absolute; inset:0; z-index:1; pointer-events:none; border-radius:27px;
  background:linear-gradient(122deg, color-mix(in srgb,#fff 13%,transparent) 0 26%, transparent 44%);
}
.shots figure:hover .phone,.split .media:hover .phone{transform:translateY(-6px); box-shadow:var(--shadow-xl)}

/* ---------- marco de imagen editorial ----------
   Para la fotografía, no para las capturas. Redondeado, con la misma
   línea de luz que las tarjetas y un zoom lento al pasar por encima. */
.frame{
  position:relative; overflow:hidden; border-radius:var(--radius-xl); margin:0;
  background:var(--surface-2); border:1px solid var(--border); box-shadow:var(--shadow-lg);
}
.frame img{width:100%; height:100%; object-fit:cover; transition:transform var(--dur-5) var(--ease-out)}
.frame:hover img{transform:scale(1.04)}
.frame figcaption{
  position:absolute; left:0; right:0; bottom:0; padding:var(--s6) var(--s5) var(--s4);
  font-size:var(--t-sm); color:#fff; line-height:1.5;
  background:linear-gradient(transparent, rgba(0,0,0,.72));
}
.frame.ratio-wide{aspect-ratio:16/9}
.frame.ratio-tall{aspect-ratio:3/4}
.frame.ratio-square{aspect-ratio:1/1}

/* ---------- banda de media a sangre ----------
   Fotografía a todo lo ancho con el texto encima. Es el recurso de
   portada de Nike y de Adidas: una imagen que ocupa la pantalla y tres
   palabras. Se usa una vez por página como mucho. */
.band{
  position:relative; isolation:isolate; overflow:hidden;
  min-height:min(78vh,660px); display:grid; align-items:center;
  /* Fondo oscuro FIJO detrás de la foto, y no `var(--invert-bg)` ni transparente.
     La imagen va en diferido —está muy por debajo del pliegue—, así que durante un
     instante no hay nada debajo del velo: sin este color, el titular blanco aparece
     sobre el fondo claro de la página y no se lee. El color no sigue al tema porque el
     texto de la banda es blanco en los dos. */
  background:#0a0d0b;
}
.band > img{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:-2;
}
/* Velo de contraste. Sin él, un titular blanco sobre una foto clara es
   ilegible justo en la mitad de los casos, y no se sabe en cuál. */
.band::before{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
  background:linear-gradient(180deg, rgba(0,0,0,.62), rgba(0,0,0,.34) 42%, rgba(0,0,0,.74));
}
.band .wrap{padding-block:clamp(60px,9vw,120px); position:relative}
.band h2,.band h1{color:#fff; max-width:15ch}
.band p{color:rgba(255,255,255,.82); max-width:52ch}
.band .eyebrow,.band .kicker{color:#fff}
.band .kicker::before{background:#fff}
.band .btn-ghost{background:rgba(255,255,255,.1); color:#fff; border-color:rgba(255,255,255,.34); backdrop-filter:blur(6px)}
.band .btn-ghost:hover{background:rgba(255,255,255,.18)}
/* Paralaje muy contenido: la imagen se desplaza un 8 % mientras la
   banda cruza la pantalla. Ligado al scroll, así que no hay ni un
   listener ni un `requestAnimationFrame`. */
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    .band > img{
      animation:parallax linear both; animation-timeline:view(); animation-range:cover 0% cover 100%;
      height:116%; top:-8%;
    }
    @keyframes parallax{from{transform:translateY(-4%)} to{transform:translateY(4%)}}
  }
}

/* ==================================================================
   11 · REJILLAS DE TARJETAS
   ================================================================== */
/* `.grid` es para conjuntos de 3 o 6: `auto-fit` los reparte en 3
   columnas y salen filas llenas. Para conjuntos de 4 usa `.grid-2`, que
   fuerza 2×2: con `auto-fit` saldrían 3+1 y la tarjeta huérfana canta. */
.grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(282px,1fr)); gap:18px}
.grid-2{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px}
.grid-4{display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:14px}
@media (max-width:900px){ .grid-4{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media (max-width:760px){ .grid-2{grid-template-columns:1fr} }

.card{
  border-radius:var(--radius); padding:var(--s6) 28px;
  transition:transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) ease, border-color var(--dur-2) ease;
}
.card > *{position:relative; z-index:1}
.card:hover{transform:translateY(-4px); box-shadow:var(--shadow); border-color:var(--edge)}
.card h3{margin-bottom:9px}
.card p{font-size:var(--t-sm); margin-bottom:.8em}
.card ul{margin:var(--s3) 0 0; padding-left:19px; font-size:var(--t-sm)}
.card li{margin-bottom:7px}
.card li::marker{color:var(--primary)}
.card-note{font-size:var(--t-xs)!important; color:var(--muted); margin-top:var(--s3)!important; font-style:italic}
.card-link{margin-top:var(--s4)!important; font-size:var(--t-sm)!important}
.card-link a{display:inline-flex; align-items:center; gap:6px; font-weight:620; text-decoration:none}
.card-link a:hover{text-decoration:underline}
.card-link .ic{width:16px; height:16px; transition:transform var(--dur-2) var(--ease-out)}
.card-link a:hover .ic{transform:translateX(4px)}

/* ---------- bento ----------
   La rejilla de celdas de distinto tamaño que Apple usa desde 2022. No
   es decoración: es jerarquía. La celda ancha lleva la idea principal y
   las pequeñas los detalles, y se lee en ese orden sin necesidad de
   numerarlas.

   Doce columnas para poder decir «esta ocupa 7 y esta 5», que es lo que
   rompe la monotonía del 6+6. */
.bento{display:grid; grid-template-columns:repeat(12,minmax(0,1fr)); gap:16px; grid-auto-rows:minmax(0,auto)}
.bento > *{
  border-radius:var(--radius-xl); padding:clamp(24px,2.4vw,36px); grid-column:span 4;
  display:flex; flex-direction:column; overflow:hidden;
  transition:transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) ease, border-color var(--dur-2) ease;
}
.bento > *:hover{transform:translateY(-4px); box-shadow:var(--shadow); border-color:var(--edge)}
.bento > * > *{position:relative; z-index:1}
.bento h3{font-size:clamp(1.18rem,1.05rem + .6vw,1.55rem); margin-bottom:10px; letter-spacing:-.025em}
.bento p{font-size:var(--t-sm); color:var(--text)}
.bento .b-num{
  font-family:var(--display); font-weight:600; line-height:1;
  font-size:clamp(2.4rem,1.6rem + 2.6vw,3.6rem); color:var(--ink);
  letter-spacing:-.02em; margin-bottom:10px;
}
.bento .b-media{margin:auto -8px -14px; border-radius:var(--radius-sm); overflow:hidden}
.bento .b-media img{width:100%; display:block}
/* Anchos. Se combinan libremente mientras sumen 12 por fila. */
.b-3{grid-column:span 3} .b-4{grid-column:span 4} .b-5{grid-column:span 5}
.b-6{grid-column:span 6} .b-7{grid-column:span 7} .b-8{grid-column:span 8}
.b-9{grid-column:span 9} .b-12{grid-column:span 12}
.b-tall{grid-row:span 2}
/* Celda destacada: fondo tintado en vez de superficie plana. */
.bento .b-hi{
  background:linear-gradient(160deg, var(--tint), var(--tint-2) 60%, transparent), var(--surface);
  border-color:var(--tint-3);
}
@media (max-width:1000px){
  .bento{grid-template-columns:repeat(6,minmax(0,1fr))}
  .b-3,.b-4,.b-5{grid-column:span 3}
  .b-6,.b-7,.b-8,.b-9,.b-12{grid-column:span 6}
  .b-tall{grid-row:auto}
}
@media (max-width:640px){
  .bento{grid-template-columns:1fr}
  .bento > *,.b-3,.b-4,.b-5,.b-6,.b-7,.b-8,.b-9,.b-12{grid-column:1/-1}
}

/* ---------- rejilla de especificaciones ----------
   Etiqueta arriba, dato grande abajo, sin tarjeta. Para las fichas
   técnicas: qué plataformas, qué idiomas, qué versión. */
.spec{display:grid; grid-template-columns:repeat(auto-fit,minmax(184px,1fr)); gap:1px; background:var(--border); border:1px solid var(--border); border-radius:var(--radius); overflow:hidden}
.spec div{border:none; border-radius:0; box-shadow:none; padding:var(--s5)}
.spec dt,.spec .k{display:block; font-size:var(--t-xs); color:var(--muted); font-weight:600; letter-spacing:.03em; text-transform:var(--case-display); margin-bottom:8px}
.spec dd,.spec .v{margin:0; font-size:1.06rem; color:var(--ink); font-weight:650; line-height:1.35}

/* ---------- lista de verificación ---------- */
.checks{list-style:none; margin:0; padding:0; display:grid; gap:11px}
.checks li{display:flex; gap:11px; align-items:flex-start; font-size:var(--t-sm)}
.checks .ic{color:var(--primary-ink); margin-top:3px}

/* ==================================================================
   12 · EDITORIAL
   ================================================================== */

/* ---------- texto + captura alternos ---------- */
.split{display:grid; grid-template-columns:1.05fr .95fr; gap:clamp(32px,5vw,76px); align-items:center}
.split + .split{margin-top:clamp(60px,8vw,116px)}
.split .media{display:flex; justify-content:center}
.split .phone{max-width:268px}
.split .txt h3{font-size:clamp(1.34rem,1.08rem + 1.2vw,2rem); margin-bottom:var(--s4); letter-spacing:-.028em}
.split .txt ul{margin:var(--s5) 0 0; padding-left:20px}
.split .txt li{margin-bottom:10px}
.split .txt li::marker{color:var(--primary)}
@media (max-width:820px){
  .split{grid-template-columns:1fr; gap:30px}
  .split.rev .media{order:-1}
}

/* ---------- relato con media fija ----------
   La columna de la imagen se queda pegada mientras la de texto pasa por
   delante. Es lo que hace Apple en las páginas de producto y lo que
   convierte tres párrafos sueltos en una secuencia.

   Sin JavaScript: `position:sticky` y ya. En móvil se deshace y vuelve
   a ser una columna, porque una imagen fija ocupando media pantalla en
   un teléfono deja al texto sin sitio. */
.story{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:clamp(32px,5vw,84px); align-items:start}
.story.rev .story-media{order:2}
.story-media{position:sticky; top:calc(var(--head-h) + 40px)}
.story-steps{display:grid; gap:clamp(48px,9vw,120px); padding-block:clamp(20px,4vw,60px)}
.story-steps > li{list-style:none}
.story-steps h3{font-size:clamp(1.3rem,1.1rem + 1vw,1.8rem); margin-bottom:var(--s3); letter-spacing:-.026em}
.story-steps p{font-size:var(--t-sm)}
.story-n{
  display:inline-grid; place-items:center; width:34px; height:34px; border-radius:11px;
  background:var(--tint); color:var(--primary-ink); font-family:var(--display);
  font-weight:700; font-size:.95rem; margin-bottom:var(--s3);
}
@media (max-width:900px){
  .story{grid-template-columns:1fr; gap:32px}
  .story.rev .story-media{order:-1}
  .story-media{position:static}
  .story-steps{gap:44px; padding-block:0}
}

/* ---------- marquesina ----------
   Una tira que se desplaza sin fin. Sirve para enseñar una lista larga
   sin gastar altura: las plataformas soportadas, los grupos musculares,
   las especialidades.

   El truco es duplicar el contenido en el HTML y desplazar el carril
   exactamente la mitad: al llegar al 50 % la copia está donde estaba el
   original y el salto no se ve. La copia va con `aria-hidden`, así que
   un lector de pantalla lee la lista una sola vez. */
.marquee{
  overflow:hidden; position:relative;
  /* Se desvanece por los dos lados en vez de cortarse a hachazo. */
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
}
.marquee-track{display:flex; width:max-content; gap:0}
.marquee-track > *{
  display:flex; align-items:center; gap:14px; padding:0;
  list-style:none; margin:0;
}
.marquee li,.marquee-item{
  display:inline-flex; align-items:center; gap:10px; white-space:nowrap;
  padding:0 clamp(20px,3vw,44px);
  font-family:var(--display); font-weight:600;
  font-size:clamp(1.1rem,.9rem + .9vw,1.7rem);
  letter-spacing:var(--track-display); text-transform:var(--case-display);
  color:var(--muted);
}
.marquee li::after,.marquee-item::after{
  content:""; width:6px; height:6px; border-radius:50%; background:var(--primary); flex:none; opacity:.55;
}
.marquee .ic{color:var(--primary-ink)}
@media (prefers-reduced-motion:no-preference){
  .marquee-track{animation:marquee 42s linear infinite}
  .marquee:hover .marquee-track{animation-play-state:paused}
  @keyframes marquee{to{transform:translateX(-50%)}}
}

/* ---------- carrusel con indicador ----------
   Desplazamiento horizontal con anclaje, más una barra que marca por
   dónde va. La barra está ligada al scroll DEL PROPIO carril
   (`scroll(self inline)`), así que refleja la posición real y no una
   estimación. */
.rail{position:relative}
.rail-track{
  display:flex; gap:18px; overflow-x:auto; padding:6px 4px 22px;
  scroll-snap-type:x mandatory; scroll-padding-inline:var(--gut);
  scrollbar-width:none;
}
.rail-track::-webkit-scrollbar{display:none}
.rail-track > *{flex:0 0 auto; scroll-snap-align:start; width:min(340px,78vw)}
.rail-bar{height:3px; border-radius:99px; background:var(--border); overflow:hidden; margin-top:var(--s2)}
.rail-bar::after{content:""; display:block; height:100%; width:34%; border-radius:99px; background:var(--primary); transform-origin:0 50%}
@supports (animation-timeline:scroll()){
  .rail-bar::after{
    width:100%; transform:scaleX(.2);
    animation:rail-progress linear both;
    animation-timeline:scroll(nearest inline);
  }
  /* El carril es el antecesor con scroll horizontal más cercano al
     indicador, así que hay que meterlo dentro para que `nearest` lo
     encuentre. Cuando el indicador va fuera, se usa la versión de
     respaldo de arriba. */
  @keyframes rail-progress{from{transform:scaleX(.2)} to{transform:scaleX(1)}}
}

/* ---------- cita destacada ----------
   El bloque editorial que da voz. En Somatryx va en serif y es lo que
   hace que la casa matriz suene distinta de sus dos productos. */
.pull{
  border-radius:var(--radius-xl); padding:clamp(30px,4vw,56px);
  border-left:3px solid var(--primary);
}
.pull p{
  /* `--serif` solo lo declara la marca que separa los dos roles (Somatryx: grotesca
     para titulares, serif para citas). Las demás caen en su propia display. */
  font-family:var(--serif, var(--display)); font-size:clamp(1.3rem,1.05rem + 1.3vw,2.1rem);
  line-height:1.32; letter-spacing:-.02em; color:var(--ink); font-weight:500;
  margin:0; text-wrap:balance; position:relative; z-index:1;
}
.pull footer,.pull .who{
  margin-top:var(--s5); font-size:var(--t-sm); color:var(--muted);
  font-family:var(--sans); position:relative; z-index:1;
}

/* ---------- línea de tiempo ---------- */
.timeline{list-style:none; margin:0; padding:0; display:grid; gap:14px}
.timeline li{
  border-radius:var(--radius); padding:var(--s5) var(--s5) var(--s5) 56px;
}
.timeline li::before{
  content:""; position:absolute; left:24px; top:30px; width:11px; height:11px;
  border-radius:50%; background:var(--primary); box-shadow:0 0 0 4px var(--tint); z-index:1;
}
.timeline h3{font-size:1.05rem; margin-bottom:6px}
.timeline p{font-size:var(--t-sm); margin:0}
.timeline time{display:block; font-size:var(--t-xs); color:var(--muted); margin-bottom:5px; font-variant-numeric:tabular-nums}

/* ---------- pasos numerados ----------
   El número lo pone el CSS con un contador: si mañana se añade un paso
   en medio, la numeración se recoloca sola. */
.steps{list-style:none; counter-reset:s; margin:0; padding:0; display:grid; gap:18px; grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
.steps li{counter-increment:s; border-radius:var(--radius); padding:var(--s6)}
.steps li::before{
  content:counter(s); display:grid; place-items:center; width:34px; height:34px; border-radius:11px;
  background:var(--tint); color:var(--primary-ink); font-family:var(--display);
  font-weight:700; font-size:.95rem; margin-bottom:15px; position:relative; z-index:1;
}
.steps h3{margin-bottom:7px; position:relative; z-index:1}
.steps p{font-size:var(--t-sm); margin:0; position:relative; z-index:1}

/* ---------- cierre de página ---------- */
.closer .lede{max-width:620px; margin:var(--s4) auto var(--s6)}
/* Llamada final con fondo propio: cierra la página en vez de dejarla
   deshilachada contra el pie. */
.ctaband{
  border-radius:var(--radius-xl); padding:clamp(40px,6vw,88px) clamp(24px,4vw,60px);
  text-align:center; position:relative; overflow:hidden; isolation:isolate;
  background:
    radial-gradient(70% 130% at 50% 0%, var(--tint), transparent 70%),
    var(--surface);
  border:1px solid var(--border); box-shadow:var(--shadow);
}
.ctaband::before{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
  background-image:var(--grain-url); background-size:160px 160px;
  opacity:var(--grain); mix-blend-mode:overlay;
}
.ctaband h2{margin-bottom:var(--s4)}
.ctaband .lede{max-width:600px; margin:0 auto var(--s6); color:var(--muted)}

/* ==================================================================
   13 · TABLAS
   ================================================================== */
.table-wrap{overflow-x:auto; border-radius:var(--radius); background:var(--surface)}
table{border-collapse:collapse; width:100%; min-width:540px; font-size:var(--t-sm)}
caption{text-align:left; padding:16px 20px 0; color:var(--muted); font-size:var(--t-xs)}
th,td{text-align:left; padding:15px 20px; border-bottom:1px solid var(--border); vertical-align:top}
thead th{
  background:var(--surface-2); color:var(--ink); font-weight:700; font-size:var(--t-xs);
  text-transform:uppercase; letter-spacing:.05em; white-space:nowrap;
  position:sticky; top:0; z-index:1;
}
tbody th{color:var(--ink); font-weight:650}
tbody tr{transition:background var(--dur-1) ease}
tbody tr:hover{background:var(--tint-2)}
tr:last-child th,tr:last-child td{border-bottom:none}
td .yes{color:var(--primary-ink); font-weight:700}
td .no{color:var(--muted)}

/* ==================================================================
   14 · AVISOS
   ================================================================== */
.callout{
  display:flex; gap:15px; align-items:flex-start;
  border-left:3px solid var(--primary);
  border-radius:0 var(--radius-sm) var(--radius-sm) 0;
  padding:var(--s5) var(--s5); font-size:var(--t-sm);
}
.callout .ic{color:var(--primary-ink); margin-top:2px}
.callout.warn{border-left-color:#d98324}
.callout.warn .ic{color:#d98324}
.callout h3{font-size:1rem; margin-bottom:7px}
.callout p:last-child{margin-bottom:0}

/* ==================================================================
   15 · PLATAFORMAS
   ================================================================== */
.plats{display:grid; grid-template-columns:repeat(auto-fit,minmax(232px,1fr)); gap:16px}
.plat{
  border-radius:var(--radius); padding:var(--s6); text-decoration:none; color:inherit; display:block;
  transition:transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) ease, border-color var(--dur-2) ease;
}
.plat > *{position:relative; z-index:1}
a.plat:hover{transform:translateY(-4px); box-shadow:var(--shadow); text-decoration:none; border-color:var(--edge)}
.plat .ic{color:var(--primary-ink); margin-bottom:var(--s4); width:26px; height:26px; position:relative; z-index:1; transition:transform var(--dur-2) var(--ease-spring)}
a.plat:hover .ic{transform:scale(1.12) rotate(-4deg)}
.plat b{display:block; color:var(--ink); font-size:1.03rem; margin-bottom:5px}
.plat span{font-size:var(--t-sm); color:var(--muted); display:block; line-height:1.5}
.plat[aria-disabled="true"]{opacity:.62}
.badge{
  display:inline-block; font-size:.7rem; font-weight:720; letter-spacing:.05em; text-transform:uppercase;
  background:var(--surface-3); color:var(--primary-ink); border-radius:99px; padding:4px 10px; margin-top:11px;
}

/* ==================================================================
   16 · PLANES DE PRECIO
   ================================================================== */
.plans{display:grid; grid-template-columns:repeat(auto-fit,minmax(268px,1fr)); gap:18px; align-items:start}
.plan{border-radius:var(--radius); padding:32px 28px}
.plan > *{position:relative; z-index:1}
.plan.featured{border-color:var(--primary); box-shadow:var(--shadow); border-width:1.5px}
/* El plan destacado lleva un halo de color muy suave para que se
   distinga del de al lado sin cambiarle el tamaño. */
.plan.featured::after{box-shadow:inset 0 1px 0 var(--hairline), 0 0 0 4px var(--tint-2)}
.plan-tag{
  position:absolute; top:-12px; left:28px; background:var(--primary); color:var(--on-primary);
  font-size:.72rem; font-weight:740; letter-spacing:.05em; text-transform:uppercase;
  padding:5px 12px; border-radius:99px; z-index:2;
}
.plan h3{margin-bottom:12px}
.plan-price{display:flex; align-items:baseline; gap:7px; margin-bottom:10px!important}
.plan-price b{font-size:2.3rem; font-weight:800; letter-spacing:-.038em; color:var(--ink); line-height:1}
.plan-price span{font-size:var(--t-sm); color:var(--muted)}
.plan-blurb{font-size:var(--t-sm); color:var(--muted); margin-bottom:var(--s5)!important}
.plan .checks{margin-bottom:var(--s5)}
.plan-cta{margin:0!important}

/* ==================================================================
   17 · PREGUNTAS FRECUENTES
   ------------------------------------------------------------------
   `<details>` nativo: sin JavaScript, accesible por teclado sin
   programar nada, y el Ctrl+F del navegador encuentra dentro de los
   cerrados en Chrome.
   ================================================================== */
.faq{max-width:840px; margin:0 auto}
.faq details{border-radius:var(--radius-sm); margin-bottom:11px; overflow:hidden}
.faq details[open]{border-color:var(--edge)}
.faq summary{
  cursor:pointer; padding:20px 22px; font-weight:640; color:var(--ink); font-size:1.03rem;
  list-style:none; display:flex; align-items:flex-start; gap:14px;
  transition:background var(--dur-1) ease;
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::before{
  content:""; flex:none; width:11px; height:11px; margin-top:8px;
  background:currentColor; color:var(--primary-ink);
  clip-path:polygon(46% 0,54% 0,54% 46%,100% 46%,100% 54%,54% 54%,54% 100%,46% 100%,46% 54%,0 54%,0 46%,46% 46%);
  transition:transform var(--dur-2) var(--ease-out);
}
.faq details[open] summary::before{transform:rotate(135deg)}
.faq summary:hover{background:var(--surface-2)}
.faq .answer{padding:2px 22px 24px 47px; font-size:var(--t-sm)}
.faq .answer ul{padding-left:19px; margin:10px 0 0}
.faq .answer li{margin-bottom:7px}
@media (prefers-reduced-motion:no-preference){
  .faq details[open] .answer{animation:answer var(--dur-3) var(--ease-out) both}
  @keyframes answer{from{opacity:0; transform:translateY(-6px)} to{opacity:1; transform:none}}
}
@media (max-width:540px){ .faq .answer{padding-left:22px} }

/* ==================================================================
   18 · NOVEDADES
   ================================================================== */
.log{max-width:820px; margin:0 auto}
.log article{border-radius:var(--radius); padding:var(--s6) 28px; margin-bottom:16px}
.log article > *{position:relative; z-index:1}
.log h3{display:flex; align-items:baseline; gap:14px; flex-wrap:wrap; margin-bottom:var(--s4)}
.log time{font-size:var(--t-xs); color:var(--muted); font-weight:500}
.log ul{margin:0; padding-left:19px; font-size:var(--t-sm)}
.log li{margin-bottom:8px}
.log li::marker{color:var(--primary)}

/* ==================================================================
   19 · PIE
   ================================================================== */
/* Va por CLASE y no por etiqueta. `<footer>` es un elemento legal dentro de
   `<article>`, `<section>` y `<blockquote>` —la atribución de una cita destacada usa uno,
   que es lo semánticamente correcto—, y un selector `footer{…}` a secas le encasquetaba
   a esa atribución el fondo, el borde superior y los 52 px de relleno del pie del sitio.
   El fallo era invisible en el HTML y evidente en pantalla. */

.site-foot{border-top:1px solid var(--border); background:var(--surface-2); padding:clamp(52px,6vw,80px) 0 40px; position:relative; overflow:hidden}
/* Marca + cinco columnas de enlaces. `minmax(0,1fr)` y no `1fr` a
   secas: sin el mínimo en cero, una etiqueta larga («Recuperación y
   wearables») ensancha su columna y descuadra las otras cuatro. */
.foot-grid{display:grid; grid-template-columns:1.3fr repeat(5,minmax(0,1fr)); gap:32px}
@media (max-width:1080px){ .foot-grid{grid-template-columns:repeat(3,minmax(0,1fr)); gap:30px} .foot-brand{grid-column:1/-1} }
@media (max-width:700px){ .foot-grid{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media (max-width:460px){ .foot-grid{grid-template-columns:1fr} }
.foot-brand p{font-size:var(--t-sm); color:var(--muted); margin:var(--s4) 0 0; max-width:280px}

.site-foot h2{font-size:.79rem; text-transform:uppercase; letter-spacing:.08em; color:var(--muted); margin-bottom:var(--s4); font-weight:740}
.site-foot ul{list-style:none; margin:0; padding:0}
.site-foot li{margin-bottom:9px}
.site-foot li a{color:var(--text); text-decoration:none; font-size:var(--t-sm); transition:color var(--dur-1) ease}
.site-foot li a:hover{color:var(--primary-ink); text-decoration:underline}
.foot-legal{
  margin:clamp(34px,4.4vw,52px) 0 0; padding-top:28px; border-top:1px solid var(--border);
  font-size:var(--t-xs); color:var(--muted); line-height:1.65; max-width:900px;
}
.foot-copy{margin:var(--s4) 0 0!important; font-size:var(--t-xs); color:var(--muted)}
/* Nombre de la marca gigante al fondo del pie, recortado por el borde
   inferior. Es la firma de la casa: ocupa el espacio muerto del final y
   no compite con nada porque va detrás de todo y muy apagado. */
.foot-word{
  position:absolute; left:0; right:0; bottom:-.28em; z-index:0; pointer-events:none;
  margin:0; text-align:center; user-select:none;
  font-family:var(--display); font-weight:700; line-height:.8;
  font-size:clamp(4rem,17vw,15rem); letter-spacing:-.045em;
  color:var(--ink); opacity:.045; text-transform:var(--case-display);
}
.site-foot .wrap{position:relative; z-index:1}

/* ==================================================================
   20 · PÁGINAS LEGALES
   ------------------------------------------------------------------
   Contenido largo de una sola columna: privacidad, términos y borrado
   de cuenta.
   ================================================================== */
.legal{max-width:var(--wrap-text); margin:0 auto; padding:clamp(32px,4vw,52px) 0 clamp(56px,6.5vw,88px)}
.legal h2{font-size:1.38rem; margin:48px 0 12px; scroll-margin-top:calc(var(--head-h) + 24px)}
.legal h3{font-size:1.08rem; margin:30px 0 10px}
.legal p,.legal li{font-size:var(--t-sm)}
.legal ul,.legal ol{padding-left:22px; margin:0 0 1em}
.legal li{margin-bottom:7px}
.legal table{min-width:0}
.legal .updated{color:var(--muted); font-size:var(--t-xs); margin-bottom:8px}
.legal .toc{
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius);
  padding:24px 26px; margin:30px 0 44px; box-shadow:var(--shadow-sm);
}
.legal .toc h2{font-size:.79rem; text-transform:uppercase; letter-spacing:.08em; color:var(--muted); margin:0 0 12px}
.legal .toc ol{margin:0; padding-left:20px; font-size:var(--t-sm); columns:2; column-gap:30px}
@media (max-width:640px){ .legal .toc ol{columns:1} }
.legal .toc li{margin-bottom:6px; break-inside:avoid}
/* Resumen destacado en cabeza del documento: lo que dice el texto legal
   en cuatro frases, para quien no va a leer las cuarenta. */
.legal .tldr{
  background:var(--tint-2); border:1px solid var(--tint-3); border-left:3px solid var(--primary);
  border-radius:0 var(--radius-sm) var(--radius-sm) 0;
  padding:var(--s5) var(--s5); margin:0 0 var(--s6); font-size:var(--t-sm);
}
.legal .tldr strong{color:var(--ink)}

/* ==================================================================
   21 · PANEL WEB (solo /panel — /en/dashboard)
   ================================================================== */
.panel-loading{display:grid; place-items:center; gap:16px; padding:120px 20px; color:var(--muted)}
.spinner{
  width:34px; height:34px; border-radius:50%; border:3px solid var(--border);
  border-top-color:var(--primary); animation:spin .8s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}

.panel-app{padding:clamp(30px,4vw,48px) var(--gut) clamp(56px,6.5vw,88px)}
.panel-head{display:flex; flex-wrap:wrap; gap:18px; align-items:flex-end; justify-content:space-between; margin-bottom:32px}
.panel-head h1{font-size:clamp(1.7rem,1.3rem + 1.6vw,2.4rem); margin-bottom:6px}
.panel-head .muted{font-size:var(--t-sm); margin:0}
.panel-actions{display:flex; gap:10px; flex-wrap:wrap}
.panel-empty{max-width:620px; margin:0 auto; padding:80px var(--gut); text-align:center}
.panel-empty h1{margin-bottom:16px}
.panel-empty .lede{margin-bottom:var(--s5)}

/* Fila de indicadores. `auto-fit` con mínimo pequeño para que en móvil
   salgan de dos en dos en vez de una columna de ocho tarjetas. */
.kpis{display:grid; grid-template-columns:repeat(auto-fit,minmax(178px,1fr)); gap:14px; margin-bottom:var(--s5)}
.kpi{border-radius:var(--radius-sm); padding:18px 20px}
.kpi > *{position:relative; z-index:1}
.kpi-l{display:block; font-size:var(--t-xs); color:var(--muted); font-weight:600; letter-spacing:.02em}
.kpi-v{display:block; font-size:clamp(1.5rem,1.2rem + .9vw,1.9rem); font-weight:800; color:var(--ink); letter-spacing:-.03em; line-height:1.15; margin:6px 0 3px; font-variant-numeric:tabular-nums}
.kpi-s{display:block; font-size:var(--t-xs); color:var(--muted); line-height:1.4}

.pgrid{display:grid; grid-template-columns:repeat(auto-fit,minmax(340px,1fr)); gap:18px; margin-bottom:18px}
.pcard{border-radius:var(--radius); padding:var(--s5) var(--s6); margin-bottom:18px}
.pcard > *{position:relative; z-index:1}
.pcard h2{font-size:1.05rem; margin-bottom:18px}
.pcard-note{font-size:var(--t-xs)!important; color:var(--muted); margin:16px 0 0!important; line-height:1.55}
.pcard .table-wrap{box-shadow:none}

/* Gráficas SVG. Los colores salen de variables para que el tema oscuro
   no requiera volver a generarlas. */
.chart{width:100%; height:auto; overflow:visible}
.ch-grid{stroke:var(--border); stroke-width:1}
.ch-lab{fill:var(--muted); font-size:11px; font-family:inherit}
.ch-line{fill:none; stroke:var(--primary); stroke-width:2.4; stroke-linejoin:round; stroke-linecap:round}
.ch-area{fill:var(--tint); stroke:none}
.ch-dot{fill:var(--primary); stroke:var(--surface); stroke-width:1.5}
.ch-bar{fill:var(--primary)}
.ch-bar.zero{fill:var(--border)}
.ch-goal{stroke:var(--muted); stroke-width:1.5; stroke-dasharray:5 4}

/* Veredicto de volumen frente a los rangos de referencia. */
.vtag{
  display:inline-block; font-size:var(--t-xs); font-weight:660; border-radius:99px;
  padding:3px 10px; border:1px solid; white-space:nowrap;
}
.vtag.ok{background:var(--tint); color:var(--primary-ink); border-color:color-mix(in srgb,var(--primary) 34%,transparent)}
.vtag.high{background:color-mix(in srgb,#d98324 12%,transparent); color:#a4611a; border-color:color-mix(in srgb,#d98324 30%,transparent)}
.vtag.low,.vtag.over{background:color-mix(in srgb,#d94a3d 12%,transparent); color:#b3372c; border-color:color-mix(in srgb,#d94a3d 30%,transparent)}
@media (prefers-color-scheme:dark){
  .vtag.high{color:#f0b46a} .vtag.low,.vtag.over{color:#ff9d92}
}

/* Ranking de barras horizontales (volumen por músculo). */
.rank{list-style:none; margin:0; padding:0; display:grid; gap:11px}
.rank li{display:grid; grid-template-columns:minmax(96px,1.1fr) 3fr auto; align-items:center; gap:12px; font-size:var(--t-sm)}
.rank-l{color:var(--ink); font-weight:560}
.rank-t{background:var(--surface-2); border-radius:99px; height:11px; overflow:hidden}
.rank-f{display:block; height:100%; background:var(--primary); border-radius:99px}
.rank-v{color:var(--muted); font-variant-numeric:tabular-nums; min-width:38px; text-align:right}
@media (max-width:520px){ .rank li{grid-template-columns:minmax(78px,1fr) 2fr auto; gap:8px} }

/* ---------- acceso ---------- */
.login-wrap{display:grid; grid-template-columns:minmax(0,420px) minmax(0,1fr); gap:clamp(30px,5vw,64px); align-items:start; max-width:940px; margin:0 auto}
@media (max-width:800px){ .login-wrap{grid-template-columns:1fr} .login-side{order:-1} }
.login-card{border-radius:var(--radius); padding:32px 28px; box-shadow:var(--shadow)}
.login-card > *{position:relative; z-index:1}
.login-card h2{font-size:1.25rem; margin-bottom:6px}
.login-card #pGoogle{margin-top:20px}
.login-card label{display:block; font-size:var(--t-xs); font-weight:660; color:var(--ink); margin:16px 0 6px}
.login-card input{
  width:100%; font:inherit; font-size:.95rem; padding:12px 14px; border-radius:var(--radius-xs);
  border:1.5px solid var(--border); background:var(--bg); color:var(--ink);
}
.login-card input:focus-visible{border-color:var(--primary); outline:none; box-shadow:0 0 0 3px var(--tint)}
.login-card #pSubmit{margin-top:22px}
.login-sep{display:flex; align-items:center; gap:14px; margin:22px 0 4px; color:var(--muted); font-size:var(--t-xs)}
.login-sep::before,.login-sep::after{content:""; flex:1; height:1px; background:var(--border)}
.login-forgot{margin:16px 0 0!important; font-size:var(--t-xs); text-align:center}
.login-foot{margin:20px 0 0!important; padding-top:18px; border-top:1px solid var(--border); font-size:var(--t-xs); color:var(--muted)}
.login-side h2{font-size:1.15rem; margin-bottom:18px}

.panel-msg{margin:14px 0 0!important; font-size:var(--t-sm); padding:11px 14px; border-radius:var(--radius-xs); border:1px solid}
.panel-msg.err{background:color-mix(in srgb,#d94a3d 10%,transparent); border-color:color-mix(in srgb,#d94a3d 34%,transparent); color:#b3372c}
.panel-msg.ok{background:var(--tint); border-color:color-mix(in srgb,var(--primary) 34%,transparent); color:var(--primary-ink)}
@media (prefers-color-scheme:dark){ .panel-msg.err{color:#ff9d92} }

/* ====================================================================
   22 · BIBLIOTECA PÚBLICA
   --------------------------------------------------------------------
   Ejercicios, suplementos, mitos, guías, glosario, síntomas, atlas.
   Estas páginas no son marketing: son el contenido de la app publicado
   tal cual. Por eso priorizan la lectura y el escaneo por encima del
   efecto — sin degradados de portada, con más densidad y con el dato
   siempre delante.
   ==================================================================== */

/* ---------- migas de pan ---------- */
.crumbs{border-bottom:1px solid var(--border); background:var(--surface-2)}
.crumbs ol{
  display:flex; flex-wrap:wrap; align-items:center; gap:6px;
  list-style:none; margin:0; padding:11px 0; font-size:var(--t-xs);
}
.crumbs li{display:flex; align-items:center; gap:6px; color:var(--muted)}
/* El separador lo pone el CSS y no el HTML: así no lo lee un lector de pantalla. */
.crumbs li+li::before{content:"›"; color:var(--border); font-size:1.05rem; line-height:1}
.crumbs a{color:var(--muted); text-decoration:none}
.crumbs a:hover{color:var(--primary-ink); text-decoration:underline}
.crumbs [aria-current]{color:var(--ink); font-weight:600}

/* ---------- barra de filtros ----------
   Pegajosa bajo la cabecera: con 306 tarjetas, perder el buscador al
   desplazarse obliga a subir del todo para cambiar un filtro. */
.lib-bar{
  position:sticky; top:var(--head-h); z-index:var(--z-bar);
  background:color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter:saturate(170%) blur(14px); -webkit-backdrop-filter:saturate(170%) blur(14px);
  border-bottom:1px solid var(--border); padding:14px 0;
}
.lib-bar .wrap{display:flex; flex-wrap:wrap; gap:10px; align-items:center}
.lib-search{
  flex:1 1 260px; min-width:0; font:inherit; font-size:.95rem; padding:12px 14px 12px 40px;
  border-radius:var(--radius-xs); border:1.5px solid var(--border); background:var(--surface); color:var(--ink);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b7a63' stroke-width='1.9' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='6.6'/%3E%3Cpath d='M16 16l4.4 4.4'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:12px center; background-size:18px;
  transition:border-color var(--dur-1) ease, box-shadow var(--dur-1) ease;
}
.lib-search:focus-visible{border-color:var(--primary); outline:none; box-shadow:0 0 0 3px var(--tint)}
.lib-sel{
  font:inherit; font-size:.9rem; padding:12px 32px 12px 13px; border-radius:var(--radius-xs);
  border:1.5px solid var(--border); background:var(--surface); color:var(--ink); cursor:pointer;
  appearance:none; -webkit-appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b7a63' stroke-width='2' stroke-linecap='round'%3E%3Cpolyline points='6 9.5 12 15.5 18 9.5'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 9px center; background-size:16px;
}
.lib-count{font-size:var(--t-xs); color:var(--muted); margin-left:auto; font-variant-numeric:tabular-nums}
/* La barra nace OCULTA y solo la enseña `.js`, que añade el propio
   script al arrancar. Invertido a propósito: si el script no carga, no
   aparece un buscador que no busca — la lista completa sigue ahí abajo,
   enlazada y legible, que es lo que importa. */
.lib-bar{display:none}
.js .lib-bar{display:block}
@media (max-width:640px){ .lib-count{margin-left:0; width:100%} }

/* ---------- rejilla de fichas ---------- */
.lib-grid{display:grid; grid-template-columns:repeat(auto-fill,minmax(238px,1fr)); gap:16px}
.lib-card{
  display:flex; flex-direction:column; border-radius:var(--radius-sm);
  overflow:hidden; text-decoration:none; color:inherit;
  transition:transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) ease, border-color var(--dur-2) ease;
}
.lib-card:hover{transform:translateY(-4px); text-decoration:none; box-shadow:var(--shadow); border-color:var(--edge)}
.lib-card .thumb{background:var(--surface-2); aspect-ratio:1/1; display:grid; place-items:center; overflow:hidden}
.lib-card .thumb img{width:100%; height:100%; object-fit:cover; transition:transform var(--dur-4) var(--ease-out)}
.lib-card:hover .thumb img{transform:scale(1.05)}
.lib-card .thumb.none{color:var(--border)}
.lib-card .thumb.none .ic{width:44px; height:44px}
.lib-card .body{padding:15px 17px 17px; display:flex; flex-direction:column; gap:7px; flex:1; position:relative; z-index:1}
.lib-card b{color:var(--ink); font-size:.97rem; font-weight:650; line-height:1.32; letter-spacing:-.012em}
.lib-card .meta{font-size:var(--t-xs); color:var(--muted); line-height:1.45; margin-top:auto}
.lib-hidden{display:none!important}
.lib-empty{text-align:center; padding:60px 20px; color:var(--muted)}

/* ---------- lista densa ----------
   Variante para las colecciones SIN miniatura: síntomas, fármacos,
   términos del glosario, guías. Con 1.082 fichas, una rejilla de
   tarjetas cuadradas obliga a recorrer tres pantallas de hueco para ver
   lo que en una lista cabe de un vistazo. */
.lib-grid.rows{grid-template-columns:repeat(auto-fill,minmax(min(100%,330px),1fr)); gap:10px}
.lib-grid.rows .lib-card{flex-direction:row; align-items:center}
.lib-grid.rows .lib-card .body{padding:13px 16px; gap:3px}
.lib-grid.rows .lib-card .meta{margin-top:0}
.lib-grid.rows .lib-card:hover{transform:translateX(3px)}

/* Secciones dentro de un índice. El grupo entero es el que se oculta
   cuando el filtro deja su lista a cero: un encabezado «Cardiología»
   encima de ningún resultado es peor que no tener encabezado. */
.lib-sections{display:flex; flex-direction:column; gap:clamp(28px,3.2vw,42px)}
.lib-section > h2{font-size:var(--t-h3); margin:0 0 3px; scroll-margin-top:calc(var(--head-h) + 60px)}
.lib-section > p{font-size:var(--t-xs); color:var(--muted); margin:0 0 13px}

/* ---------- etiquetas ---------- */
.tags{display:flex; flex-wrap:wrap; gap:7px; list-style:none; margin:0; padding:0}
.tag{
  display:inline-flex; align-items:center; gap:5px; font-size:var(--t-xs); font-weight:600;
  background:var(--surface-2); color:var(--text); border:1px solid var(--border);
  border-radius:99px; padding:4px 11px; text-decoration:none; line-height:1.5;
  transition:border-color var(--dur-1) ease, color var(--dur-1) ease, background var(--dur-1) ease;
}
a.tag:hover{border-color:var(--primary); color:var(--primary-ink); background:var(--tint-2); text-decoration:none}
.tag.on{background:var(--tint); color:var(--primary-ink); border-color:var(--tint-3)}
.tag.warn{background:color-mix(in srgb,#d98324 12%,transparent); color:#a4611a; border-color:color-mix(in srgb,#d98324 30%,transparent)}
.tag.bad{background:color-mix(in srgb,#d94a3d 12%,transparent); color:#b3372c; border-color:color-mix(in srgb,#d94a3d 30%,transparent)}
@media (prefers-color-scheme:dark){
  .tag.warn{color:#f0b46a} .tag.bad{color:#ff9d92}
}

/* ---------- ficha de detalle (dos columnas) ---------- */
.detail{
  display:grid; grid-template-columns:minmax(0,1fr) minmax(0,320px);
  gap:clamp(30px,4.4vw,60px); align-items:start;
  padding:clamp(32px,4vw,52px) 0 clamp(56px,6.5vw,88px);
}
@media (max-width:900px){ .detail{grid-template-columns:1fr} .detail .aside{order:-1} }
.detail h1{font-size:clamp(1.8rem,1.35rem + 1.9vw,2.85rem); margin-bottom:12px}
.detail .lede{margin-bottom:var(--s5)}
.detail h2{font-size:1.3rem; margin:40px 0 14px}
.detail h2:first-child{margin-top:0}
.detail h3{font-size:1.05rem; margin:26px 0 9px}
.detail p,.detail li{font-size:var(--t-sm)}
.detail ol,.detail ul{padding-left:21px; margin:0 0 1em}
.detail li{margin-bottom:9px}
.detail li::marker{color:var(--primary)}

/* Columna lateral pegajosa: la animación y los datos rápidos acompañan
   mientras se lee la técnica. Se despega en móvil. */
.detail .aside{position:sticky; top:calc(var(--head-h) + 22px); display:grid; gap:16px}
@media (max-width:900px){ .detail .aside{position:static} }

/* Animación del ejercicio. Cuadrada porque así vienen las de la app. */
.exanim{border-radius:var(--radius); overflow:hidden; margin:0}
.exanim img{width:100%; aspect-ratio:1/1; object-fit:cover; background:var(--surface-2)}
.exanim figcaption{font-size:var(--t-xs); color:var(--muted); padding:11px 15px; border-top:1px solid var(--border)}
/* Sin recortar: una animación de ejercicio es cuadrada y se puede
   encajar, pero un ECG de 12 derivaciones o una radiografía de tórax
   son apaisados y `object-fit:cover` les corta justo el borde donde
   está el hallazgo. Aquí la imagen manda sobre la caja. */
.exanim.fit img{aspect-ratio:auto; object-fit:contain; height:auto}

/* Lista de datos rápidos: etiqueta a la izquierda, valor a la derecha. */
.facts{border-radius:var(--radius); padding:8px 20px; margin:0}
.facts div{display:flex; gap:14px; justify-content:space-between; align-items:baseline; padding:12px 0; border-bottom:1px solid var(--border)}
.facts div:last-child{border-bottom:none}
.facts dt{font-size:var(--t-xs); color:var(--muted); font-weight:600; flex:none}
.facts dd{margin:0; font-size:var(--t-sm); color:var(--ink); font-weight:560; text-align:right}

/* Cues y errores: dos listas con el mismo peso visual y signo opuesto. */
.cues,.errs{list-style:none; padding:0; margin:0; display:grid; gap:11px}
.cues li,.errs li{display:flex; gap:11px; align-items:flex-start; font-size:var(--t-sm)}
.cues li::before,.errs li::before{
  content:""; flex:none; width:19px; height:19px; margin-top:2px; border-radius:50%;
  background-repeat:no-repeat; background-position:center; background-size:13px;
}
.cues li::before{
  background-color:var(--tint);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234f8f06' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='5 12.5 10 17.5 19 6.5'/%3E%3C/svg%3E");
}
.errs li::before{
  background-color:color-mix(in srgb,#d94a3d 13%,transparent);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c0392b' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M7 7l10 10M17 7L7 17'/%3E%3C/svg%3E");
}
@media (prefers-color-scheme:dark){
  .cues li::before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a5ed45' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='5 12.5 10 17.5 19 6.5'/%3E%3C/svg%3E")}
  .errs li::before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ff9d92' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M7 7l10 10M17 7L7 17'/%3E%3C/svg%3E")}
}

/* ---------- veredicto de un mito ---------- */
.verdict{
  display:flex; align-items:center; gap:14px; border-radius:var(--radius);
  padding:19px 23px; margin-bottom:var(--s5); border:1px solid; font-weight:650;
  background:color-mix(in srgb,#d94a3d 9%,transparent); border-color:color-mix(in srgb,#d94a3d 28%,transparent); color:#b3372c;
}
.verdict b{font-family:var(--display); font-size:1.4rem; font-weight:600; letter-spacing:.03em; text-transform:uppercase; color:inherit}
.verdict.ok{background:var(--tint); border-color:var(--tint-3); color:var(--primary-ink)}
.verdict.mid{background:color-mix(in srgb,#d98324 11%,transparent); border-color:color-mix(in srgb,#d98324 30%,transparent); color:#a4611a}
@media (prefers-color-scheme:dark){ .verdict{color:#ff9d92} .verdict.mid{color:#f0b46a} }

/* Barra de nivel de evidencia: cinco tramos, los llenos en color de marca. */
.eviscale{display:flex; gap:4px; align-items:center}
.eviscale i{width:20px; height:7px; border-radius:99px; background:var(--border)}
.eviscale i.on{background:var(--primary)}

/* ---------- glosario ----------
   187 términos en una sola página con anclas, y no 187 páginas de dos
   líneas: una definición suelta no sostiene una página propia, y Google
   trata un montón de páginas casi vacías como contenido de relleno. */
.gloss{display:grid; gap:12px}
.gloss article{border-radius:var(--radius-sm); padding:20px 22px; scroll-margin-top:calc(var(--head-h) + 84px)}
.gloss article > *{position:relative; z-index:1}
.gloss h3{font-size:1.05rem; margin-bottom:7px; display:flex; align-items:baseline; gap:10px; flex-wrap:wrap}
.gloss h3 .tag{font-weight:600}
.gloss p{font-size:var(--t-sm); margin:0}
.gloss .syn{font-size:var(--t-xs); color:var(--muted); margin-top:9px!important}
/* Índice alfabético que salta a cada letra. */
.alpha{display:flex; flex-wrap:wrap; gap:5px; margin-bottom:var(--s5); justify-content:center}
.alpha a{
  display:grid; place-items:center; min-width:32px; height:32px; padding:0 7px;
  border-radius:9px; border:1px solid var(--border); background:var(--surface);
  font-size:var(--t-sm); font-weight:650; color:var(--text); text-decoration:none;
  transition:border-color var(--dur-1) ease, color var(--dur-1) ease, transform var(--dur-1) var(--ease-out);
}
.alpha a:hover{border-color:var(--primary); color:var(--primary-ink); text-decoration:none; transform:translateY(-2px)}
.gloss-letter{
  font-family:var(--display); font-size:1.55rem; font-weight:600; color:var(--primary-ink);
  margin:34px 0 12px; scroll-margin-top:calc(var(--head-h) + 84px); letter-spacing:.04em;
}
.gloss-letter:first-child{margin-top:0}

/* ---------- calculadoras ---------- */
.calc{border-radius:var(--radius); padding:clamp(24px,3vw,36px); box-shadow:var(--shadow)}
.calc > *{position:relative; z-index:1}
.calc-fields{display:grid; grid-template-columns:repeat(auto-fit,minmax(158px,1fr)); gap:16px}
.calc label{display:block; font-size:var(--t-xs); font-weight:660; color:var(--ink); margin-bottom:6px}
.calc input,.calc select{
  width:100%; font:inherit; font-size:.95rem; padding:12px 13px; border-radius:var(--radius-xs);
  border:1.5px solid var(--border); background:var(--bg); color:var(--ink);
  transition:border-color var(--dur-1) ease, box-shadow var(--dur-1) ease;
}
.calc input:focus-visible,.calc select:focus-visible{border-color:var(--primary); outline:none; box-shadow:0 0 0 3px var(--tint)}
.calc .hint{font-size:var(--t-xs); color:var(--muted); margin:6px 0 0}
/* Grupo de botones tipo radio (sexo, objetivo, actividad). */
.seg{display:flex; flex-wrap:wrap; gap:6px}
.seg input{position:absolute; opacity:0; width:0; height:0}
.seg label{
  margin:0; cursor:pointer; font-size:var(--t-sm); font-weight:600; padding:10px 16px;
  border-radius:99px; border:1.5px solid var(--border); background:var(--bg); color:var(--text);
  transition:background var(--dur-1) ease, border-color var(--dur-1) ease, color var(--dur-1) ease;
}
.seg label:hover{border-color:var(--edge)}
.seg input:checked + label{background:var(--tint); border-color:var(--primary); color:var(--primary-ink)}
.seg input:focus-visible + label{outline:2.5px solid var(--primary); outline-offset:2px}

.calc-out{margin-top:var(--s5); padding-top:var(--s5); border-top:1px solid var(--border)}
.calc-res{display:grid; grid-template-columns:repeat(auto-fit,minmax(132px,1fr)); gap:13px}
.calc-res div{background:var(--surface-2); border:1px solid var(--border); border-radius:var(--radius-sm); padding:18px; text-align:center}
.calc-res b{
  display:block; font-family:var(--mono); font-size:clamp(1.4rem,1.15rem + .85vw,1.9rem);
  font-weight:700; color:var(--ink); letter-spacing:-.02em; line-height:1.1; font-variant-numeric:tabular-nums;
}
.calc-res span{display:block; font-size:var(--t-xs); color:var(--muted); margin-top:6px; line-height:1.4}
.calc-res .hi{background:var(--tint); border-color:var(--tint-3)}
.calc-res .hi b{color:var(--primary-ink)}
/* Sin JavaScript una calculadora no calcula. Así que el formulario nace
   oculto y en su lugar se ve un aviso; `.js` invierte las dos cosas.
   Nunca se enseña un formulario muerto que parece roto. */
.calc-live{display:none}
.js .calc-live{display:block}
.js .calc-nojs{display:none}

/* ---------- rejilla de índice de secciones ---------- */
.tiles{display:grid; grid-template-columns:repeat(auto-fit,minmax(252px,1fr)); gap:16px}
.tile{
  display:block; border-radius:var(--radius); padding:var(--s5) var(--s6);
  text-decoration:none; color:inherit;
  transition:transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) ease, border-color var(--dur-2) ease;
}
.tile > *{position:relative; z-index:1}
.tile:hover{transform:translateY(-4px); box-shadow:var(--shadow); text-decoration:none; border-color:var(--edge)}
.tile .ic{color:var(--primary-ink); margin-bottom:13px; position:relative; z-index:1}
.tile b{display:block; color:var(--ink); font-size:1.06rem; margin-bottom:6px}
.tile span{display:block; font-size:var(--t-sm); color:var(--muted); line-height:1.5}
.tile .n{font-family:var(--display); font-weight:600; color:var(--primary-ink); font-size:.9rem; letter-spacing:.04em}

/* ---------- índice interno de una guía ---------- */
.guide-toc{padding:20px 22px}
.guide-toc h2{font-size:.79rem; text-transform:uppercase; letter-spacing:.08em; color:var(--muted); margin:0 0 12px; font-weight:740}
.guide-toc ol{margin:0; padding-left:19px; font-size:var(--t-sm)}
.guide-toc li{margin-bottom:8px}
.guide-toc li::marker{color:var(--primary); font-variant-numeric:tabular-nums}
.guide-toc a{color:var(--text); text-decoration:none}
.guide-toc a:hover{color:var(--primary-ink); text-decoration:underline}
/* Cada sección de una guía va separada por una línea fina: son bloques
   largos y sin respiro visual se leen como un muro. */
.guide-sec + .guide-sec{margin-top:36px; padding-top:34px; border-top:1px solid var(--border)}

/* ---------- navegación entre fichas ---------- */
.prevnext{display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-top:48px; padding-top:30px; border-top:1px solid var(--border)}
@media (max-width:600px){ .prevnext{grid-template-columns:1fr} }
.prevnext a{
  display:block; padding:17px 20px; border-radius:var(--radius-sm);
  text-decoration:none; color:inherit;
  transition:border-color var(--dur-2) ease, transform var(--dur-2) var(--ease-out);
}
.prevnext a:hover{border-color:var(--primary); text-decoration:none}
.prevnext a:first-child:hover{transform:translateX(-3px)}
.prevnext .next:hover{transform:translateX(3px)}
.prevnext span{display:block; font-size:var(--t-xs); color:var(--muted); margin-bottom:4px}
.prevnext b{color:var(--ink); font-size:var(--t-sm); font-weight:640}
.prevnext .next{text-align:right}

/* ====================================================================
   23 · MOVIMIENTO AL ENTRAR EN PANTALLA
   --------------------------------------------------------------------
   Solo donde el navegador lo soporta de forma nativa
   (`animation-timeline: view()`). Sin JavaScript, sin
   IntersectionObserver y sin el riesgo clásico de dejar contenido
   invisible para siempre si el script falla: si no hay soporte, no hay
   animación y el contenido se ve, que es lo único que importa.

   El escalonado dentro de una fila se consigue variando el RANGO por
   posición, no con un `animation-delay`: en una animación ligada al
   scroll el retardo no existe (no hay tiempo, hay recorrido), así que
   lo que se retrasa es el tramo en el que cada elemento completa su
   entrada.
   ==================================================================== */
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    :where(.stats li,.card,.plat,.steps li,.plan,.split,.log article,.tile,
           .bento > *,.timeline li,.spec div,.pull,.frame,.story-steps > li,
           .ctaband,.numbers li,.table-wrap,.faq details){
      animation:reveal linear both;
      animation-timeline:view();
      animation-range:entry 0% cover 28%;
    }
    :where(.grid,.grid-2,.grid-4,.tiles,.plats,.plans,.stats,.steps,.bento,.spec,.lib-grid) > *:nth-child(2){animation-range:entry 0% cover 34%}
    :where(.grid,.grid-2,.grid-4,.tiles,.plats,.plans,.stats,.steps,.bento,.spec,.lib-grid) > *:nth-child(3){animation-range:entry 0% cover 40%}
    :where(.grid,.grid-2,.grid-4,.tiles,.plats,.plans,.stats,.steps,.bento,.spec,.lib-grid) > *:nth-child(4){animation-range:entry 0% cover 46%}
    @keyframes reveal{from{opacity:0; transform:translateY(18px)} to{opacity:1; transform:none}}

    /* Los encabezados de sección entran igual, pero sin desplazamiento
       lateral y un poco antes: si el titular aparece a la vez que las
       tarjetas, la sección entera parpadea. */
    .section-head{animation:reveal-soft linear both; animation-timeline:view(); animation-range:entry 0% cover 22%}
    @keyframes reveal-soft{from{opacity:0; transform:translateY(10px)} to{opacity:1; transform:none}}
  }
}

/* ====================================================================
   24 · PREFERENCIAS Y MEDIOS
   ==================================================================== */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:.001ms!important; animation-iteration-count:1!important;
    transition-duration:.001ms!important; scroll-behavior:auto!important;
  }
  /* La marquesina no se puede «acelerar»: se para y se deja como una
     lista normal que se puede desplazar a mano. */
  .marquee-track{animation:none!important; transform:none!important}
  .marquee{overflow-x:auto}
}

/* Modo de contraste forzado de Windows. El sistema sustituye los
   colores, así que lo único que hay que hacer es devolver los bordes
   que se pierden y asegurar que lo dibujado con `currentColor`
   (iconos, máscaras) sigue el color del sistema. */
@media (forced-colors:active){
  .card,.plat,.plan,.tile,.stats li,.bento > *,.lib-card,.faq details,.table-wrap{border:1px solid CanvasText}
  .btn{border:1px solid ButtonText}
  .brand-mark,.brand-word,.hero-mark{background:CanvasText}
  .head-progress,.rail-bar::after,.rank-f{background:Highlight}
  .hero::before,.hero::after,.mesh::after,.grainy::before,.ctaband::before{display:none}
}

/* ---------- impresión ---------- */
@media print{
  .site-head,.site-foot,.cta,.skip,.trustbar,.lib-bar,.marquee,.ctaband,.head-progress,.foot-word{display:none!important}
  body{background:#fff; color:#000}
  .card,.plan,.plat,.table-wrap,.bento > *{box-shadow:none; border-color:#ccc}
  .band > img{position:static; height:auto}
  .band::before{display:none}
  .band h2,.band p{color:#000}
  a[href^="http"]::after{content:" (" attr(href) ")"; font-size:.75em; color:#555}
}

/* ====================================================================
   25 · UTILIDADES DE ESPACIADO Y TIPOGRAFÍA
   --------------------------------------------------------------------
   Existen por una razón de seguridad, no de estilo. La CSP de los tres
   sitios lleva `style-src 'self'` SIN `'unsafe-inline'`, y esa
   directiva no solo bloquea `<style>`: también bloquea los atributos
   `style="…"` sueltos (en CSP 3, `style-src-attr` hereda de
   `style-src`).

   O sea que cada `style="margin-top:30px"` que quedaba en las páginas
   se descartaba en producción: el sitio se veía con el espaciado roto y
   en local, sin cabeceras, no se notaba.

   La alternativa era añadir `'unsafe-inline'` y perder la protección
   entera. Estas clases son la otra: el espaciado vuelve a aplicarse y
   la política se queda igual de cerrada.

   No es un sistema de utilidades al estilo Tailwind ni pretende serlo:
   son exactamente los valores que las páginas ya usaban.
   ==================================================================== */

.mt-18 { margin-top: 18px }
.mt-20 { margin-top: 20px }
.mt-22 { margin-top: 22px }
.mt-24 { margin-top: 24px }
.mt-26 { margin-top: 26px }
.mt-28 { margin-top: 28px }
.mt-30 { margin-top: 30px }
.mt-32 { margin-top: 32px }
.mt-34 { margin-top: 34px }
.mt-36 { margin-top: 36px }
.mt-44 { margin-top: 44px }
.mt-56 { margin-top: 56px }
.mb-24 { margin-bottom: 24px }
.mb-44 { margin-bottom: 44px }
.my-22 { margin-top: 22px; margin-bottom: 22px }
/* El resumen destacado de los documentos legales: párrafos muy juntos. */
.my-tight { margin: .2em 0 }

/* Bloques centrados con ancho de lectura. El `margin:Npx auto 0`
   original se parte en dos: la clase pone el centrado y el margen
   superior lo elige la utilidad `.mt-*` correspondiente. */
.block-600 { max-width: 600px; margin-left: auto; margin-right: auto }
.block-820 { max-width: 820px; margin-left: auto; margin-right: auto }
.block-840 { max-width: 840px; margin-left: auto; margin-right: auto }
/* Entradilla suelta bajo un titular: centrada, con aire arriba y abajo. */
.lede-block { max-width: 600px; margin: 16px auto 28px }
.lede-block-narrow { margin: 18px auto 26px }

.fs-xs { font-size: var(--t-xs) }
.fs-sm { font-size: var(--t-sm) }
.fs-105 { font-size: 1.05rem }
.fs-135 { font-size: 1.35em }
/* `.card-note` va en cursiva por defecto; esta lo devuelve a redonda
   cuando el contenido es una cita bibliográfica y la cursiva estorba. */
.fst-normal { font-style: normal }

/* Tokens de la marca — generados desde web/site.config.mjs. No editar a mano. */
:root{--case-display:uppercase; --track-display:.16em; --glow:1; --grain:.06;}
:root{--invert-bg:#07090a; --invert-surface:#12160f; --invert-ink:#ffffff; --invert-text:#a9b5a2; --invert-border:#232a1e; --invert-primary:#a5ed45; --invert-primary-ink:#bdf571;}
@media (prefers-color-scheme:dark){:root{--invert-bg:#f4f7f1; --invert-surface:#ffffff; --invert-ink:#0b1006; --invert-text:#4a5644; --invert-border:#dde4d6; --invert-primary:#4f8f06; --invert-primary-ink:#3d6f04;}}
