/* ==========================================================================
   LIFE OS — BASE
   --------------------------------------------------------------------------
   Cimientos adaptados de kit/base.css al lenguaje de una app iOS.
   Cambia respecto al kit del estudio en tres cosas, a propósito:

     1. Tema doble real (claro por defecto, oscuro por atributo o por
        preferencia del sistema). Una app no es un sitio: el usuario elige.
     2. Escala tipográfica de UI fija en rem equivalentes a px (15/17 px
        como iOS) en vez de fluida — dentro de un móvil no hay ancho que
        interpolar. Lo fluido se reserva a los titulares editoriales.
     3. Easings de muelle (`linear()`) calculados a partir de la física de
        SwiftUI, no cubic-bezier. Es lo que hace que el movimiento se
        sienta nativo y no «web».

   Índice:
     0. @property
     1. Reset
     2. Tokens — color (claro / oscuro), tipografía, espacio, muelles
     3. Estilos base
     4. Utilidades
     5. Movimiento reducido
   ========================================================================== */


/* ==========================================================================
   0. PROPIEDADES TIPADAS
   --------------------------------------------------------------------------
   Registrar un porcentaje y un ángulo los vuelve interpolables: así el
   anillo de progreso anima su relleno y el sol su halo sin JS por frame.
   ========================================================================== */

@property --progreso {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 0%;
}

@property --angulo {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

/* Y las dos de nutrición. Sin registrar, «transition: width» sobre un
   «width: calc(var(--comido) * 100%)» NO anima nada: el valor queda pendiente
   de sustitución y el navegador no tiene dos números entre los que interpolar.
   El carril daba un salto al añadir comida —justo lo que la tarjeta quería
   enseñar— y la viga de la balanza pegaba un tirón. Las dos HEREDAN, porque
   se ponen en el padre (el carril, la viga) y las leen los hijos. */
@property --comido {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

@property --inclina {
  syntax: "<angle>";
  inherits: true;
  initial-value: 0deg;
}


/* ==========================================================================
   1. RESET
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  /* Sin scroll de documento: la app vive dentro de su propio marco */
  height: 100%;
  overflow: hidden;
}

body {
  height: 100%;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow: hidden;
  /* El resalte azul de iOS al tocar lo gestionamos nosotros */
  -webkit-tap-highlight-color: transparent;
}

img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
}

img,
video {
  height: auto;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
}

button {
  padding: 0;
  cursor: pointer;
  /* Mata el retardo de 300 ms y el doble-tap-zoom sobre controles */
  touch-action: manipulation;
}

h1, h2, h3, h4 {
  font-size: inherit;
  font-weight: inherit;
  text-wrap: balance;
  overflow-wrap: break-word;
}

p, li {
  text-wrap: pretty;
  overflow-wrap: break-word;
}

ul, ol {
  padding: 0;
  list-style: none;
}

a {
  color: inherit;
  text-decoration: none;
}


/* ==========================================================================
   2. TOKENS
   ========================================================================== */

:root {

  /* ----- Color: fallback HEX (tema claro) -------------------------------
     «Amanecer en calma»: papel hueso cálido, tinta parda casi negra,
     salvia para lo vivo e índigo para lo que se pulsa. */

  --papel:        #f4f1eb;   /* fondo de la app */
  --lienzo:       #fdfcfa;   /* tarjeta */
  --lienzo-2:     #f7f4ee;   /* relieve dentro de una tarjeta */
  --lienzo-3:     #eeeae1;   /* pista de barras, chips apagados */

  --tinta:        #23201b;   /* texto principal */
  --tinta-fuerte: #171511;   /* titulares */
  --tinta-2:      #6f685d;   /* secundario */
  --tinta-3:      #726c64;   /* metadatos */

  --linea:        #e4dfd4;   /* separadores */
  --linea-suave:  #edE9e0;

  --salvia:       #3f7a55;   /* LA marca: progreso, vida, hecho */
  --salvia-suave: #e7efe8;
  --indigo:       #1b3a6b;   /* LA acción: botón primario, pestaña activa */
  --indigo-vivo:  #2f5da8;   /* enlaces y acentos de acción */
  --indigo-suave: #e6ecf6;

  --ambar:        #8e601c;   /* aviso */
  --ambar-suave:  #f7edda;
  --rojo:         #b53f2c;   /* alerta */
  --rojo-suave:   #fae8e3;
  /* EL ROSA DE LA CASA no es un color nuevo: es el rojo tirando al ámbar, que
     es lo que ya escribía .eti--rosa a mano. Se define aquí porque lo piden
     tres sitios, y dos de ellos lo pedían como var(--rosa), que no existía:
     una propiedad personalizada inexistente invalida la declaración entera y
     el punto se quedaba transparente, sin un solo aviso en ninguna parte.
     Sale de --rojo y de --ambar, así que en oscuro cambia solo. */
  --rosa:         color-mix(in oklab, var(--rojo) 62%, var(--ambar));
  --sol:          #f4cdb2;   /* el sol de la acuarela: SOLO rellenos */
  --sol-tinta:    #a4592b;   /* el sol bajo de la tarde: trazos e iconos */
  --marca-grafito:#1f2126;   /* el grafito de marca de Startify */
  --bruma:        #a9bdb0;   /* las montañas */

  --sobre-color:  #ffffff;   /* texto sobre salvia / índigo / rojo */
  --foco:         #2f5da8;   /* anillo de foco */

  /* Sombras: luz difusa, nunca negro puro. Dos capas = profundidad real */
  --sombra-1: 0 1px 2px rgb(35 32 27 / 0.04), 0 2px 8px rgb(35 32 27 / 0.04);
  --sombra-2: 0 2px 6px rgb(35 32 27 / 0.05), 0 8px 24px rgb(35 32 27 / 0.06);
  --sombra-3: 0 6px 16px rgb(35 32 27 / 0.07), 0 20px 48px rgb(35 32 27 / 0.10);
  --sombra-pulsada: 0 1px 2px rgb(35 32 27 / 0.05);

  /* ----- CRISTAL (iOS 26 «liquid glass») -------------------------------
     Un desenfoque no es un cristal. Lo que hace que una superficie parezca
     vidrio de verdad son cuatro capas, y hay que poner las cuatro:

       1. fondo translúcido        → deja pasar el color de debajo
       2. backdrop-filter con      → el desenfoque SATURA, no agrisa: sin
          saturate() alto            saturate el vidrio parece plástico sucio
       3. filo especular superior  → un `inset 0 .5px 0` casi blanco: es el
                                     canto del cristal recogiendo la luz
       4. sombra de dos capas      → separa la lámina del fondo

     El borde va a 0.5 px a propósito: en pantallas @2x/@3x es medio píxel
     real, que es exactamente como lo dibuja iOS. */

  --cristal:         rgb(253 252 250 / 0.62);   /* lámina normal */
  --cristal-fuerte:  rgb(253 252 250 / 0.78);   /* cuando debajo hay texto */
  --cristal-borde:   rgb(255 255 255 / 0.72);
  --cristal-filo:    rgb(255 255 255 / 0.85);   /* el canto que brilla */
  --cristal-brillo:  rgb(255 255 255 / 0.38);   /* velo diagonal de reflejo */
  --cristal-filtro:  blur(24px) saturate(190%);

  /* Grano: se hornea la opacidad DENTRO del SVG para poder usarlo como
     background-image. Así no hace falta un velo a pantalla completa por
     encima de las barras, que obligaba a recomponer sus desenfoques. */
  --grano: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.038'/%3E%3C/svg%3E");
  --cristal-filtro-corto: blur(14px) saturate(170%);

  /* Tinte de las esferas del botón +. Hacen falta dos juegos porque en claro
     el tono tiñe un vidrio blanco (acerca la bola al icono oscuro: tiñe a
     favor) y en oscuro tiñe un vidrio oscuro (la acerca al icono claro: tiñe
     en contra). Con la misma mezcla, en oscuro los iconos caían a 1,1:1. */
  --esfera-lamina:   var(--cristal);
  --esfera-mezcla-a: 22%;
  --esfera-mezcla-b: 34%;

  /* ----- Tipografía -----------------------------------------------------
     Fraunces (serif variable con eje óptico) para lo editorial; Inter
     para la UI. -apple-system va en --font-ui como respaldo inmediato:
     en un iPhone real eso es SF Pro y la app pasa a ser indistinguible. */

  --font-display: "Fraunces", "Iowan Old Style", Georgia, serif;
  --font-ui: "Inter", -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;

  /* Fraunces: terminales suaves, sin swashes. La voz cálida del proyecto */
  --fraunces: "SOFT" 30, "WONK" 0;

  /* Tipografía de UI: tamaños de iOS, fijos. No se interpolan: dentro de
     un teléfono no hay viewport que crezca. */
  --ui-caption2: 0.6875rem;  /* 11px — pestañas, sellos */
  --ui-caption:  0.75rem;    /* 12px — pies, metadatos */
  --ui-footnote: 0.8125rem;  /* 13px — texto de apoyo */
  --ui-sub:      0.9375rem;  /* 15px — cuerpo secundario, filas */
  --ui-body:     1.0625rem;  /* 17px — cuerpo iOS */
  --ui-title3:   1.25rem;    /* 20px */
  --ui-title2:   1.375rem;   /* 22px */
  --ui-title1:   1.75rem;    /* 28px */

  /* Titulares editoriales: aquí sí, fluido — pero contra el ancho de la
     APP (cqi), nunca contra el viewport. Ver la nota de `.app` en app.css.
     Referencia: a 393 px de ancho, 1cqi = 3,93 px. */
  --fs-hero:  clamp(2.2rem,  1.60rem + 4.2cqi, 2.9rem);   /* ~41 px */
  --fs-large: clamp(1.75rem, 1.30rem + 3.4cqi, 2.4rem);   /* ~34 px */
  --fs-dato:  clamp(1.4rem,  1.10rem + 2.2cqi, 1.9rem);   /* ~26 px */

  --lh-hero: 1.04;
  --tracking-hero: -0.028em;
  --tracking-ui: -0.011em;   /* Inter pide tracking negativo para leerse como SF */
  --tracking-etiqueta: 0.06em;

  /* ----- Espaciado ------------------------------------------------------- */

  --e-1: 0.25rem;
  --e-2: 0.5rem;
  --e-3: 0.75rem;
  --e-4: 1rem;
  --e-5: 1.25rem;
  --e-6: 1.5rem;
  --e-8: 2rem;
  --e-10: 2.5rem;
  --e-12: 3rem;

  --margen: 1.25rem;          /* margen lateral de la app (20px, como iOS) */

  /* ----- Radios: concéntricos ---------------------------------------------
     Regla de Apple: el radio interior = exterior − separación. Si no, las
     esquinas anidadas «pellizcan» y la pieza se ve barata. */

  --r-xs: 8px;
  --r-sm: 12px;
  --r-md: 16px;
  --r-lg: 22px;
  --r-xl: 28px;
  --r-2xl: 34px;
  --r-full: 999px;

  /* ----- Alturas del chrome ----------------------------------------------- */

  --alto-estado: 54px;        /* barra de estado + isla dinámica */
  --isla-top: 11px;           /* la isla marca el eje óptico de la barra */
  --isla-alto: 36px;
  --alto-nav: 44px;           /* barra de navegación compacta (iOS: 44) */
  --alto-barra: 64px;         /* barra inferior de ámbitos */
  --alto-indicador: 22px;
  --orbe: 56px;               /* diámetro del botón + */
  --hueco-orbe: 34px;         /* radio del recorte de la barra a su alrededor */

  /* ----- Z-index ----------------------------------------------------------- */

  --z-fondo: 0;
  --z-cajon: 1;               /* el cajón vive DETRÁS del lienzo */
  --z-contenido: 2;           /* el lienzo, que se desplaza para revelarlo */
  --z-nav: 30;                /* barra de navegación con cristal */
  --z-radial: 47;             /* telón y esferas: tapan también la barra */
  --z-barra: 46;              /* barra inferior de ámbitos */
  --z-tapa: 52;               /* toque para cerrar el cajón: por encima del orbe */
  --z-orbe: 50;               /* el botón +, siempre por encima de sus esferas */
  --z-estado: 60;             /* barra de estado e isla */
  --z-telon: 78;              /* telón de la hoja modal */
  --z-hoja: 82;               /* la hoja: por encima incluso de la isla */
  --z-aviso: 90;

  /* ----- MUELLES ----------------------------------------------------------
     Curvas `linear()` calculadas resolviendo la ecuación del oscilador
     amortiguado de SwiftUI —spring(response:dampingFraction:)—, no
     cubic-bezier aproximados. Un cubic-bezier no puede pasar de 1 y
     volver: el rebote de iOS es literalmente imposible sin esto.

       smooth  (0.44 / 1.00) — crítico, sin rebote: lo que se usa por defecto
       snappy  (0.36 / 0.86) — vivo, con un guiño de overshoot: controles
       bouncy  (0.50 / 0.70) — rebote franco: hojas, FAB, celebraciones
       gentle  (0.62 / 1.00) — sedoso y largo: títulos grandes, telones     */

  --muelle-smooth: linear(0 0%, 0.0525 3.85%, 0.1665 7.69%, 0.2994 11.54%, 0.429 15.38%, 0.5449 19.23%, 0.6433 23.08%, 0.7241 26.92%, 0.7889 30.77%, 0.8398 34.62%, 0.8794 38.46%, 0.9097 42.31%, 0.9328 46.15%, 0.9502 50%, 0.9632 53.85%, 0.9729 57.69%, 0.9802 61.54%, 0.9855 65.38%, 0.9894 69.23%, 0.9923 73.08%, 0.9944 76.92%, 0.996 80.77%, 0.9971 84.62%, 0.9979 88.46%, 0.9985 92.31%, 0.9989 96.15%, 1 100%);
  --muelle-snappy: linear(0 0%, 0.0387 3.33%, 0.1301 6.67%, 0.2463 10%, 0.3689 13.33%, 0.4866 16.67%, 0.593 20%, 0.6851 23.33%, 0.7622 26.67%, 0.8248 30%, 0.8745 33.33%, 0.9129 36.67%, 0.9419 40%, 0.9632 43.33%, 0.9785 46.67%, 0.9891 50%, 0.9962 53.33%, 1.0006 56.67%, 1.0032 60%, 1.0045 63.33%, 1.005 66.67%, 1.0049 70%, 1.0045 73.33%, 1.004 76.67%, 1.0033 80%, 1.0027 83.33%, 1.0022 86.67%, 1.0017 90%, 1.0013 93.33%, 1.001 96.67%, 1 100%);
  --muelle-bouncy: linear(0 0%, 0.0306 2.5%, 0.1077 5%, 0.2125 7.5%, 0.3304 10%, 0.4505 12.5%, 0.5653 15%, 0.6698 17.5%, 0.7611 20%, 0.838 22.5%, 0.9006 25%, 0.9496 27.5%, 0.9863 30%, 1.0126 32.5%, 1.03 35%, 1.0403 37.5%, 1.0451 40%, 1.0459 42.5%, 1.0437 45%, 1.0397 47.5%, 1.0346 50%, 1.0291 52.5%, 1.0237 55%, 1.0185 57.5%, 1.0139 60%, 1.0099 62.5%, 1.0065 65%, 1.0038 67.5%, 1.0018 70%, 1.0002 72.5%, 0.9991 75%, 0.9984 77.5%, 0.9981 80%, 0.9979 82.5%, 0.9979 85%, 0.998 87.5%, 0.9982 90%, 0.9985 92.5%, 0.9987 95%, 0.999 97.5%, 1 100%);
  --muelle-gentle: linear(0 0%, 0.0518 3.85%, 0.1645 7.69%, 0.2964 11.54%, 0.4253 15.38%, 0.5409 19.23%, 0.6393 23.08%, 0.7203 26.92%, 0.7854 30.77%, 0.8368 34.62%, 0.8767 38.46%, 0.9075 42.31%, 0.9309 46.15%, 0.9487 50%, 0.962 53.85%, 0.972 57.69%, 0.9794 61.54%, 0.9849 65.38%, 0.989 69.23%, 0.9919 73.08%, 0.9941 76.92%, 0.9957 80.77%, 0.9969 84.62%, 0.9978 88.46%, 0.9984 92.31%, 0.9988 96.15%, 1 100%);

  --d-smooth: 0.66s;
  --d-snappy: 0.52s;
  --d-bouncy: 0.84s;
  --d-gentle: 0.93s;

  /* Curvas sin muelle, para lo que no debe rebotar nunca: opacidad,
     color, desenfoques. Un fundido con overshoot parpadea. */
  --ease-salida: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-entrada: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-pagina: cubic-bezier(0.32, 0.72, 0, 1);   /* la curva de push/pop de UIKit */

  --d-micro: 0.14s;   /* pulsación */
  --d-rapido: 0.22s;  /* color, opacidad */
  --d-medio: 0.36s;
  --d-pagina: 0.46s;  /* push / pop entre pantallas */

  accent-color: var(--salvia);
  color-scheme: light;
}

/* `hidden` lo pone el navegador con `display: none` y una especificidad de
   cero: cualquier `display` del autor lo tumba. Sin esto, esconder un botón
   con `el.hidden = true` no hace nada, y el fallo es mudo. */
[hidden] { display: none !important; }


/* ----- Refinado OKLCH -------------------------------------------------------
   Mismos tokens en espacio perceptual. Todos los neutros comparten el
   matiz cálido del papel (--h-papel) con croma mínimo: la app entera
   respira una sola temperatura. */

@supports (color: oklch(50% 0.1 200)) {
  :root {
    --h-papel: 75;   /* el matiz que tiñe TODO el neutro */

    --papel:        oklch(0.956 0.010 var(--h-papel));
    --lienzo:       oklch(0.991 0.004 var(--h-papel));
    --lienzo-2:     oklch(0.969 0.009 var(--h-papel));
    --lienzo-3:     oklch(0.929 0.013 var(--h-papel));

    --tinta:        oklch(0.245 0.013 var(--h-papel));
    --tinta-fuerte: oklch(0.180 0.014 var(--h-papel));
    --tinta-2:      oklch(0.492 0.014 var(--h-papel));
    --tinta-3:      oklch(0.535 0.015 var(--h-papel));

    --linea:        oklch(0.895 0.013 var(--h-papel));
    --linea-suave:  oklch(0.928 0.010 var(--h-papel));

    --salvia:       oklch(0.508 0.083 155);
    --salvia-suave: oklch(0.945 0.021 155);
    --indigo:       oklch(0.348 0.087 263);
    --indigo-vivo:  oklch(0.487 0.135 263);
    --indigo-suave: oklch(0.945 0.020 263);

    --ambar:        oklch(0.525 0.100 72);
    --ambar-suave:  oklch(0.955 0.030 82);
    --rojo:         oklch(0.520 0.150 31);
    --rojo-suave:   oklch(0.948 0.026 31);
    --sol:          oklch(0.876 0.055 56);
    --sol-tinta:    oklch(0.545 0.115 50);
    --bruma:        oklch(0.775 0.031 158);

    --foco:         oklch(0.487 0.135 263);
  }

  /* En P3 el acento gana croma real sin perder el contraste */
  @media (color-gamut: p3) {
    :root {
      --salvia: oklch(0.508 0.098 155);
      --indigo-vivo: oklch(0.487 0.158 263);
    }
  }
}


/* ----- Tema oscuro ----------------------------------------------------------
   No es el claro invertido. El papel se vuelve tinta azulada profunda
   (jamás #000: sobre OLED el degradado se corta y las sombras desaparecen),
   las superficies SUBEN de luminosidad en vez de bajar, y los acentos
   ganan luz para mantener el contraste.

   Se activa por atributo desde Ajustes. El valor «auto» delega en el
   sistema mediante la media query de más abajo. */

:root[data-tema="oscuro"] {
  color-scheme: dark;

  --papel:        #14161b;
  --lienzo:       #1c1f26;
  --lienzo-2:     #232730;
  --lienzo-3:     #2c313b;

  --tinta:        #eceef2;
  --tinta-fuerte: #fafbfc;
  --tinta-2:      #a2a9b5;
  --tinta-3:      #9095a1;

  --linea:        #2b303a;
  --linea-suave:  #242932;

  --salvia:       #6cc08a;
  --salvia-suave: #1d2c24;
  --indigo:       #638ad8;
  --indigo-vivo:  #7aa4ef;
  --indigo-suave: #1b2536;

  --ambar:        #e0a44e;
  --ambar-suave:  #2d2517;
  --rojo:         #f0705a;
  --rojo-suave:   #2e1c19;
  --sol:          #d99a6c;
  --sol-tinta:    #e99c70;
  --marca-grafito:#c9ced8;
  --bruma:        #527060;

  --sobre-color:  #0d0f13;
  --foco:         #85acf2;

  --sombra-1: 0 1px 2px rgb(0 0 0 / 0.30), 0 2px 8px rgb(0 0 0 / 0.24);
  --sombra-2: 0 2px 6px rgb(0 0 0 / 0.34), 0 8px 24px rgb(0 0 0 / 0.30);
  --sombra-3: 0 6px 16px rgb(0 0 0 / 0.40), 0 20px 48px rgb(0 0 0 / 0.44);
  --sombra-pulsada: 0 1px 2px rgb(0 0 0 / 0.36);

  /* En oscuro el cristal se apoya en el brillo del borde, no en el fondo:
     un vidrio oscuro sin filo es un rectángulo gris. */
  --cristal:        rgb(30 34 42 / 0.62);
  --cristal-fuerte: rgb(30 34 42 / 0.80);
  --cristal-borde:  rgb(255 255 255 / 0.14);
  --cristal-filo:   rgb(255 255 255 / 0.20);
  --cristal-brillo: rgb(255 255 255 / 0.07);

  --esfera-lamina:   var(--cristal-fuerte);
  --esfera-mezcla-a: 13%;
  --esfera-mezcla-b: 22%;

  --grano: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.07'/%3E%3C/svg%3E");
}

@supports (color: oklch(50% 0.1 200)) {
  :root[data-tema="oscuro"] {
    --h-noche: 265;

    --papel:        oklch(0.178 0.014 var(--h-noche));
    --lienzo:       oklch(0.232 0.016 var(--h-noche));
    --lienzo-2:     oklch(0.278 0.018 var(--h-noche));
    --lienzo-3:     oklch(0.330 0.020 var(--h-noche));

    --tinta:        oklch(0.945 0.006 var(--h-noche));
    --tinta-fuerte: oklch(0.985 0.003 var(--h-noche));
    --tinta-2:      oklch(0.728 0.016 var(--h-noche));
    --tinta-3:      oklch(0.670 0.018 var(--h-noche));

    --linea:        oklch(0.318 0.018 var(--h-noche));
    --linea-suave:  oklch(0.268 0.016 var(--h-noche));

    --salvia:       oklch(0.760 0.120 155);
    --salvia-suave: oklch(0.268 0.040 155);
    --indigo:       oklch(0.640 0.125 263);
    --indigo-vivo:  oklch(0.715 0.115 263);
    --indigo-suave: oklch(0.268 0.045 263);

    --ambar:        oklch(0.775 0.115 72);
    --ambar-suave:  oklch(0.272 0.045 72);
    --rojo:         oklch(0.680 0.155 31);
    --rojo-suave:   oklch(0.272 0.050 31);
    --sol:          oklch(0.720 0.085 56);
    --sol-tinta:    oklch(0.760 0.110 50);
    --bruma:        oklch(0.480 0.042 158);

    --foco:         oklch(0.760 0.110 263);
  }
}


/* ==========================================================================
   3. ESTILOS BASE
   ========================================================================== */

body {
  background-color: var(--papel);
  color: var(--tinta);
  font-family: var(--font-ui);
  font-size: var(--ui-body);
  letter-spacing: var(--tracking-ui);
  font-variant-numeric: tabular-nums;   /* ningún dato baila al actualizarse */
}

::selection {
  background-color: var(--salvia);
  color: var(--sobre-color);
}

/* ----- Foco accesible --------------------------------------------------------
   Solo :focus-visible. El anillo va con offset para no fundirse con el
   borde del componente, y sube a 3 px en oscuro (un anillo fino sobre
   fondo oscuro no llega a 3:1). */

:focus-visible {
  outline: 2px solid var(--foco);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

:root[data-tema="oscuro"] :focus-visible {
  outline-width: 3px;
}

:focus:not(:focus-visible) {
  outline: none;
}

/* Los titulares reciben el foco al cambiar de pantalla (para el teclado y
   los lectores de pantalla), pero no son controles: no dibujan anillo. */
.titular__texto:focus,
.ficha-cabeza__titulo:focus,
.hero__titulo:focus,
.navbar__titulo:focus { outline: none; }


/* ==========================================================================
   4. UTILIDADES
   ========================================================================== */

/* Titular editorial: la voz serif del proyecto */
.display {
  font-family: var(--font-display);
  font-variation-settings: var(--fraunces);
  font-weight: 500;
  line-height: var(--lh-hero);
  letter-spacing: var(--tracking-hero);
  color: var(--tinta-fuerte);
}

/* Etiqueta: versalita abierta sobre un titular o un grupo */
.etiqueta {
  font-size: var(--ui-caption);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-etiqueta);
  color: var(--tinta-3);
}

.suave  { color: var(--tinta-2); }
.tenue  { color: var(--tinta-3); }

/* Dato numérico: tamaño grande, tracking cerrado, cifras tabulares */
.dato {
  font-size: var(--fs-dato);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.1;
  color: var(--tinta-fuerte);
  font-variant-numeric: tabular-nums;
}

.oculto-visual {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


/* ==========================================================================
   5. MOVIMIENTO REDUCIDO
   --------------------------------------------------------------------------
   Con reduced-motion TODO el movimiento decorativo muere. Se conservan
   0.01 ms (no 0) para que los `transitionend` y `animationend` de los
   que depende el router sigan disparándose y la app no se quede a medias.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    /* Negativo, no 0: con 0 la animación aún nace en su fotograma inicial
       (el área del gráfico entraba a opacidad 0 y parpadeaba). Con -1ms
       nace ya resuelta. */
    animation-delay: -1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  /* Los reveals nacen resueltos: el contenido nunca depende del movimiento */
  [data-aparece] {
    opacity: 1 !important;
    transform: none !important;
  }
}
