/* starfield-background.css
   Fondo del tema "Cielo estrellado" para PomoFlow.
   #starfield-bg pinta el degradé de cielo + la Vía Láctea + las nebulosas
   de polvo cósmico; las estrellas parpadeantes viven en el canvas
   #app-particles y las constelaciones, la luna, los meteoros ocasionales
   y la aurora boreal/austral (evento raro) en #scene-fx (ver java.js).

   Dos MODOS para el degradé de cielo, elegidos vía [data-sky-mode] en
   #starfield-bg (lo decide java.js en updatePomodoroSky()):
   - "clock" (por defecto, sin temporizador corriendo): paleta fija según
     la hora real del usuario, con transición lenta entre franjas — el
     comportamiento original ([data-sky-phase]).
   - "cycle" (Pomodoro corriendo con este tema activo): el cielo deja de
     mirar el reloj real y en cambio sigue el avance del ciclo de enfoque,
     de noche cerrada al arrancar hacia un amanecer pleno al completarlo.
     Los colores de este modo son enteramente variables CSS (--sky-c1..c4
     y --sky-glow-*), recalculadas en JS en cada tick del timer
     (updatePomodoroSky) e interpoladas ahí mismo con lerp de RGB — no acá
     con transition, porque una transición CSS de "background" no anima
     bien gradientes con múltiples paradas que cambian de color a la vez.
     Por eso #starfield-bg[data-sky-mode="cycle"] no lleva transition en
     "background": el suavizado ya viene resuelto en los valores mismos
     que llegan tick a tick (1 vez por segundo, más que suficiente para
     que el ojo lo perciba como un fundido continuo). */

#starfield-bg {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(ellipse at 50% 0%, #0d1224 0%, #05070f 60%, #020308 100%);
  transition: opacity 1s ease-in-out, background 3s ease;
}

/* Se activa/desactiva desde java.js junto con el resto de los temas */
#starfield-bg.sf-active {
  opacity: 1;
}

/* Paletas según franja horaria local del usuario (modo "clock", el
   comportamiento por defecto cuando no hay Pomodoro corriendo). Cada una
   suma una capa radial extra para simular resplandor de horizonte
   (amanecer/atardecer) o profundidad de cielo despejado (noche/día), sin
   agregar más nodos DOM. */
#starfield-bg[data-sky-phase="night"] {
  background:
    radial-gradient(ellipse 60% 40% at 50% 0%, rgba(120, 140, 220, 0.12) 0%, transparent 70%),
    radial-gradient(ellipse at 50% 0%, #0d1224 0%, #05070f 60%, #020308 100%);
}

#starfield-bg[data-sky-phase="dawn"] {
  background:
    radial-gradient(ellipse 70% 35% at 50% 100%, rgba(255, 200, 140, 0.25) 0%, transparent 65%),
    radial-gradient(ellipse at 50% 100%, #ff8a5c 0%, #b3567a 35%, #2c2350 65%, #0a0e1f 100%);
}

#starfield-bg[data-sky-phase="day"] {
  background:
    radial-gradient(ellipse 65% 40% at 50% 15%, rgba(255, 255, 255, 0.18) 0%, transparent 70%),
    radial-gradient(ellipse at 50% 20%, #7fb8e8 0%, #4a86c9 45%, #1d3f6e 80%, #0e2140 100%);
}

#starfield-bg[data-sky-phase="dusk"] {
  background:
    radial-gradient(ellipse 70% 35% at 50% 90%, rgba(255, 150, 120, 0.22) 0%, transparent 65%),
    radial-gradient(ellipse at 50% 90%, #ff6b4a 0%, #c1416f 30%, #3d2760 60%, #0a0e1f 100%);
}

/* ------------------------------------------------------------------ */
/* MODO "cycle": el cielo del Pomodoro. Mientras está activo, el
   [data-sky-phase] de arriba queda anulado por orden de cascada (misma
   especificidad — un solo atributo cada selector — pero esta regla está
   declarada después, así que gana) y en su lugar se usan las variables
   que updatePomodoroSky() en java.js recalcula cada segundo. Con
   progress=0 (arranque del pomodoro) esto se ve ~idéntico a la paleta
   "night" de arriba; con progress=1 (pomodoro completo), un amanecer
   pleno. Los valores por defecto de las variables (el fallback tras la
   coma) son justamente los stops de "night", así que si por algún
   motivo JS todavía no corrió, el modo cycle no se ve roto.

   Resplandor de horizonte extra (--sky-glow-*), independiente del
   degradé de base, para que el amanecer se sienta "húmedo"/brillante en
   la franja baja y no sea solo un cambio de tono del cielo entero —
   mismo recurso visual que ya usan dawn/dusk arriba. */
#starfield-bg[data-sky-mode="cycle"] {
  background:
    radial-gradient(ellipse 68% var(--sky-glow-h, 40%) at 50% var(--sky-glow-y, 0%), var(--sky-glow-color, rgba(120, 140, 220, 0.12)) 0%, transparent 70%),
    radial-gradient(ellipse at 50% var(--sky-origin-y, 0%), var(--sky-c1, #0d1224) 0%, var(--sky-c2, #05070f) 60%, var(--sky-c3, #020308) 100%);
  transition: none;
}

/* Resplandor de amanecer al completar el Pomodoro: un segundo velo,
   independiente del degradé de base, que sube en opacity hasta un pico
   dorado y vuelve a bajar — la "recompensa visual" breve al terminar la
   sesión. Vive en su propio pseudo-elemento para no pelear con los dos
   radial-gradient del background principal ni depender de que JS anime
   "background" (que no transiciona bien con multi-stops). JS solo
   agrega/quita la clase .sf-sunrise-flash; toda la curva de intensidad
   la resuelve esta animación en CSS.  */
#starfield-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(ellipse 75% 55% at 50% 0%, rgba(255, 214, 150, 0.55) 0%, rgba(255, 170, 140, 0.28) 38%, transparent 72%);
  mix-blend-mode: screen;
}

#starfield-bg.sf-sunrise-flash::after {
  animation: sf-sunrise-flash 3.2s ease-out;
}

@keyframes sf-sunrise-flash {
  0% { opacity: 0; }
  18% { opacity: 1; }
  55% { opacity: 0.85; }
  100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  #starfield-bg.sf-sunrise-flash::after {
    animation-duration: 1.4s;
  }
}

/* ------------------------------------------------------------------ */
/* Vía Láctea + nebulosas de polvo cósmico: todo dentro de #starfield-bg,
   por debajo del canvas de estrellas y de #scene-fx. Tres capas:
   1) .sf-milkyway: la banda diagonal blanquecina de siempre.
   2) .sf-nebula (x3): manchas de color (rosa/violeta/cian) bien difusas,
      cada una con su propio drift lentísimo e independiente, para que la
      escena tenga profundidad y nunca se vea exactamente igual dos veces.
   3) .sf-star-dust: una capa de granulado (ruido) muy sutil por encima de
      todo, para romper la lisura de los gradientes — el detalle que hace
      que se sienta "foto de larga exposición" en vez de "degradé de CSS".
   Todo es opacidad baja + mix-blend-mode: screen, a propósito: son
   insinuaciones de color, nunca deben competir con constelaciones/luna. */
.sf-milkyway {
  position: absolute;
  inset: -20% -30%;
  background:
    linear-gradient(115deg,
      transparent 30%,
      rgba(180, 190, 230, 0.05) 42%,
      rgba(200, 205, 235, 0.09) 48%,
      rgba(210, 210, 240, 0.1) 50%,
      rgba(200, 205, 235, 0.09) 52%,
      rgba(180, 190, 230, 0.05) 58%,
      transparent 70%);
  transform: rotate(-18deg);
  opacity: 0.85;
  mix-blend-mode: screen;
  transition: opacity 1.5s ease;
}

#starfield-bg[data-sky-phase="day"] .sf-milkyway {
  opacity: 0;
}

/* Nebulosas: cada una es un div con un solo radial-gradient grande y muy
   difuso. El "punto" del gradiente se anima con background-position sobre
   un fondo sobredimensionado (200% del contenedor), así el movimiento es
   translación pura sin recalcular el gradiente en cada frame — barato
   para el navegador y perfectamente suave incluso en celulares gama baja.
   Las duraciones (110-160s) son deliberadamente largas y no sincronizadas
   entre sí, para que el drift nunca se sienta mecánico ni en bucle obvio. */
.sf-nebula {
  position: absolute;
  inset: -40%;
  background-repeat: no-repeat;
  background-size: 200% 200%;
  mix-blend-mode: screen;
  opacity: 0;
  filter: blur(2px);
  transition: opacity 2.5s ease;
}

#starfield-bg.sf-active .sf-nebula {
  opacity: 1;
}

#starfield-bg[data-sky-phase="day"] .sf-nebula {
  opacity: 0;
}

.sf-nebula-rose {
  background-image: radial-gradient(circle, rgba(255, 130, 170, 0.055) 0%, rgba(255, 130, 170, 0.022) 35%, transparent 65%);
  background-position: 22% 30%;
  animation: sf-nebula-drift-a 140s ease-in-out infinite alternate;
}

.sf-nebula-violet {
  background-image: radial-gradient(circle, rgba(150, 120, 255, 0.05) 0%, rgba(150, 120, 255, 0.02) 38%, transparent 68%);
  background-position: 68% 55%;
  animation: sf-nebula-drift-b 165s ease-in-out infinite alternate;
}

.sf-nebula-cyan {
  background-image: radial-gradient(circle, rgba(110, 210, 230, 0.045) 0%, rgba(110, 210, 230, 0.018) 36%, transparent 66%);
  background-position: 45% 78%;
  animation: sf-nebula-drift-c 190s ease-in-out infinite alternate;
}

@keyframes sf-nebula-drift-a {
  0% { background-position: 20% 28%; }
  100% { background-position: 27% 34%; }
}

@keyframes sf-nebula-drift-b {
  0% { background-position: 66% 53%; }
  100% { background-position: 72% 60%; }
}

@keyframes sf-nebula-drift-c {
  0% { background-position: 43% 76%; }
  100% { background-position: 49% 81%; }
}

/* Granulado sutil: SVG de ruido embebido como data-URI, repetido en
   mosaico. opacity muy baja — se nota más como "textura" que como imagen.
   Rompe la lisura de los radial-gradient de arriba sin costar un canvas
   extra ni JS. */
.sf-star-dust {
  position: absolute;
  inset: 0;
  opacity: 0.05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-repeat: repeat;
}

@media (max-width: 600px) {
  /* Los blur grandes son costosos en GPUs móviles de gama baja; se reduce
     el radio en vez de sacarlo del todo. */
  .sf-nebula {
    filter: blur(1px);
  }
}

/* ------------------------------------------------------------------ */
/* Constelaciones (dibujadas dentro de #scene-fx por buildStarrySky en
   java.js). Las líneas tienen un leve pulso para que no queden estáticas
   del todo; las estrellas de cada constelación titilan un poco más lento
   y más "grande" que el polvo de fondo del canvas, para que se lean como
   puntos de referencia reales del cielo. */
.sf-constellations {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  animation: sf-constellations-in 2.5s ease-out 0.3s forwards;
}

@keyframes sf-constellations-in {
  to { opacity: 1; }
}

.sf-constellation-line {
  stroke: rgba(180, 200, 255, 0.32);
  stroke-width: 0.09;
  vector-effect: non-scaling-stroke;
  animation: sf-line-pulse 6s ease-in-out infinite;
}

.sf-constellation-star {
  fill: #eef1ff;
  opacity: 0.95;
  transform-box: fill-box;
  transform-origin: center;
  animation: sf-star-twinkle 4s ease-in-out infinite;
}

.sf-constellation-star.sf-star-bright {
  fill: #fff9ec;
  filter: drop-shadow(0 0 1.1px rgba(255, 249, 236, 0.9));
}

@keyframes sf-line-pulse {
  0%, 100% { stroke-opacity: 0.7; }
  50% { stroke-opacity: 1; }
}

@keyframes sf-star-twinkle {
  0%, 100% { opacity: 0.55; transform: scale(0.85); }
  50% { opacity: 1; transform: scale(1.15); }
}

/* ------------------------------------------------------------------ */
/* Luna con fase real (dibujada dentro de #scene-fx por buildStarrySky).
   Halo de dos capas (resplandor amplio + brillo cercano) en vez de un
   único drop-shadow, y textura de cráteres sobre la base para que no
   se lea como un círculo plano. Sutil respiración en el halo. */
.sf-moon-layer {
  position: absolute;
  top: 10%;
  right: 9%;
  width: 64px;
  height: 64px;
  filter: drop-shadow(0 0 12px rgba(255, 250, 230, 0.5)) drop-shadow(0 0 28px rgba(255, 245, 210, 0.22));
  animation: sf-moon-glow 6s ease-in-out infinite;
}

@keyframes sf-moon-glow {
  0%, 100% { filter: drop-shadow(0 0 10px rgba(255, 250, 230, 0.45)) drop-shadow(0 0 24px rgba(255, 245, 210, 0.18)); }
  50% { filter: drop-shadow(0 0 15px rgba(255, 250, 230, 0.6)) drop-shadow(0 0 34px rgba(255, 245, 210, 0.28)); }
}

.sf-moon {
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
}

.sf-moon-base {
  fill: #f4f0e6;
}

.sf-moon-crater {
  fill: #d9d2bf;
  opacity: 0.55;
}

.sf-moon-crater.sf-crater-soft {
  opacity: 0.32;
}

.sf-moon-shadow {
  fill: #060810;
  opacity: 0.94;
}

@media (max-width: 600px) {
  .sf-moon-layer {
    width: 44px;
    height: 44px;
    top: 7%;
    right: 7%;
  }
}

/* ------------------------------------------------------------------ */
/* Estrellas fugaces: trazo corto que cruza en diagonal y se desvanece.
   Ahora frecuentes (varias tandas de 1-3 por segundo aprox, ver
   spawnMeteor en java.js) en vez del evento raro que eran antes; cada
   una sigue siendo una instancia independiente de este mismo div, así
   que pueden superponerse sin problema. */
.sf-meteor {
  position: absolute;
  width: 110px;
  height: 2px;
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.95) 78%, #ffffff 100%);
  filter: drop-shadow(0 0 3px rgba(255, 255, 255, 0.8));
  opacity: 0;
  animation: sf-meteor-streak 1.4s cubic-bezier(0.2, 0.6, 0.3, 1) forwards;
}

@keyframes sf-meteor-streak {
  0% { opacity: 0; transform: translate(0, 0) scaleX(0.3); }
  8% { opacity: 1; }
  75% { opacity: 0.9; }
  100% { opacity: 0; transform: translate(var(--sf-meteor-dx, 260px), var(--sf-meteor-dy, 160px)) scaleX(1); }
}

/* ------------------------------------------------------------------ */
/* Aurora boreal/austral: evento RARO, no un loop más. Misma filosofía
   que el meteoro (algo que "pasa" de vez en cuando y no se repite en
   patrón obvio) pero mucho más protagonista: una cortina de gradiente
   verde-violeta que cubre la franja superior de la pantalla, ondulando
   lentamente, durante 30-40s completos, con baja probabilidad de
   aparecer y solo tras haber tenido el tema activo un buen rato — un
   "premio" por quedarse (ver scheduleAuroraLoop en java.js).
   Estructura en dos capas dentro de un mismo wrapper:
   1) .sf-aurora-band (x2): dos bandas de color superpuestas, cada una
      con su propio gradiente cónico/lineal y su propio drift de
      background-position, para que el conjunto ondule con textura en
      vez de moverse como un bloque sólido.
   2) .sf-aurora-glow: resplandor difuso extra por debajo de las bandas,
      para que la base se sienta más brillante, como cerca del
      horizonte.
   Todo con mix-blend-mode: screen (igual que la Vía Láctea/nebulosas)
   para que se superponga a estrellas y constelaciones sin taparlas del
   todo, y opacity animada en dos fases (entrada / permanencia / salida)
   controlada desde JS vía la clase .sf-aurora-active. */
.sf-aurora {
  position: absolute;
  top: 0;
  left: -15%;
  width: 130%;
  height: 46%;
  min-height: 260px;
  pointer-events: none;
  opacity: 0;
  filter: blur(0.5px);
  transition: opacity 4s ease-in-out;
}

.sf-aurora.sf-aurora-active {
  opacity: 1;
}

.sf-aurora.sf-aurora-leaving {
  opacity: 0;
  transition: opacity 6s ease-in-out;
}

.sf-aurora-glow {
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 70% 55% at 50% 0%, rgba(120, 255, 190, 0.1) 0%, rgba(120, 255, 190, 0.03) 45%, transparent 75%);
  mix-blend-mode: screen;
}

.sf-aurora-band {
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
  background-size: 180% 100%;
  mix-blend-mode: screen;
}

.sf-aurora-band-a {
  background-image: linear-gradient(200deg,
    transparent 0%,
    rgba(90, 240, 170, 0) 8%,
    rgba(90, 240, 170, 0.16) 22%,
    rgba(130, 250, 190, 0.22) 30%,
    rgba(150, 220, 200, 0.12) 40%,
    rgba(140, 160, 230, 0.1) 52%,
    rgba(150, 120, 230, 0.14) 64%,
    rgba(150, 120, 230, 0.05) 78%,
    transparent 92%);
  background-position: 0% 0%;
  animation: sf-aurora-drift-a 26s ease-in-out infinite alternate;
  clip-path: polygon(0% 0%, 100% 0%, 100% 62%, 82% 78%, 62% 58%, 44% 82%, 24% 55%, 8% 88%, 0% 60%);
}

.sf-aurora-band-b {
  background-image: linear-gradient(165deg,
    transparent 0%,
    rgba(110, 250, 200, 0) 10%,
    rgba(110, 250, 200, 0.1) 26%,
    rgba(160, 230, 210, 0.16) 38%,
    rgba(170, 150, 240, 0.14) 55%,
    rgba(190, 130, 240, 0.08) 70%,
    transparent 90%);
  background-position: 100% 0%;
  animation: sf-aurora-drift-b 33s ease-in-out infinite alternate;
  animation-delay: -6s;
  clip-path: polygon(0% 0%, 100% 0%, 100% 70%, 88% 50%, 70% 85%, 50% 60%, 32% 90%, 14% 65%, 0% 82%);
}

@keyframes sf-aurora-drift-a {
  0% { background-position: 0% 15%; }
  50% { background-position: 30% 0%; }
  100% { background-position: 10% 30%; }
}

@keyframes sf-aurora-drift-b {
  0% { background-position: 100% 25%; }
  50% { background-position: 70% 5%; }
  100% { background-position: 90% 35%; }
}

@media (max-width: 600px) {
  .sf-aurora {
    height: 38%;
    min-height: 200px;
  }
}

/* ------------------------------------------------------------------ */
/* Horizonte: silueta de skyline muy simple pegada al borde inferior de
   la escena (ver buildStarrySky en java.js). Le da anclaje espacial al
   cielo — sin esto, todo el tema es cielo "flotando" sin referencia de
   tierra. Vive dentro de #scene-fx, dibujada última a propósito para
   quedar por encima de constelaciones/luna/meteoros en el DOM: si la
   luna cae baja, el horizonte la tapa parcialmente, como en un paisaje
   real. Tono casi negro con un dejo de azul (no negro puro) para que
   se sienta parte de la misma escena nocturna y no un recorte pegado.

   Se apaga de día igual que la Vía Láctea y las nebulosas (mismo
   selector [data-sky-phase="day"]): de noche/amanecer/atardecer la
   silueta y sus luces tienen sentido, a pleno día una ciudad con
   ventanas iluminadas no lo tendría. */
.sf-horizon {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 14%;
  min-height: 56px;
  max-height: 130px;
  display: block;
  opacity: 0.92;
  transition: opacity 1.5s ease;
}

#starfield-bg[data-sky-phase="day"] ~ #scene-fx .sf-horizon {
  opacity: 0;
}

.sf-horizon-silhouette {
  fill: #060812;
}

/* Ventanas: puntito cálido tenue, no blanco puro (una ventana real de
   noche se ve más ámbar que la luz de las estrellas), con parpadeo
   lento e irregular vía animation-delay negativo distinto por ventana
   (ver buildStarrySky). El "apagado" ocasional dentro del keyframe
   imita mejor una luz doméstica que un simple fade continuo. */
.sf-horizon-window {
  fill: #ffcf8a;
  opacity: 0.55;
  filter: drop-shadow(0 0 1.4px rgba(255, 200, 130, 0.7));
  animation: sf-window-flicker 7s ease-in-out infinite;
}

@keyframes sf-window-flicker {
  0%, 100% { opacity: 0.5; }
  38% { opacity: 0.85; }
  46% { opacity: 0.3; }
  52% { opacity: 0.8; }
  75% { opacity: 0.55; }
}

@media (max-width: 600px) {
  .sf-horizon {
    height: 12%;
    min-height: 40px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sf-horizon-window {
    animation: none;
    opacity: 0.65;
  }
}

/* prefers-reduced-motion: las animaciones puramente decorativas se
   apagan (titileo, pulso, meteoros); la luna y las constelaciones
   quedan visibles pero estáticas. La aurora directamente no se
   programa desde java.js cuando esta media query está activa (ver
   checkAuroraChance), así que acá solo se cortan sus animaciones de
   drift por si el sistema la deja pasar igual. */
@media (prefers-reduced-motion: reduce) {
  .sf-constellations {
    animation: none;
    opacity: 1;
  }
  .sf-constellation-line,
  .sf-constellation-star,
  .sf-moon-layer {
    animation: none;
  }
  .sf-meteor {
    display: none;
  }
  .sf-nebula {
    animation: none;
  }
  .sf-aurora-band {
    animation: none;
  }
  .sf-aurora {
    transition: none;
  }
}