/* ==========================================================================
   ASTRO — TUBO DE RAYOS CATÓDICOS (crt.css)
   --------------------------------------------------------------------------
   Una PANTALLA CIRCULAR (rueda natal, bicircular, efemérides, comparador,
   reloj) no aparece: es un tubo de los 90 que recibe corriente.

     APAGADA  ->  cristal muerto, negro, sin imagen            (is-off)
     GOLPE    ->  el haz barre y queda una línea blanca        (is-strike)
     ENCENDIDO->  la línea se abre, parpadea y se deforma      (is-open)
     VIVA     ->  se asienta y queda a plena luz               (is-live)

   Regla de la casa: todo lo que se mueve son `transform`, `opacity` y
   `clip-path` (compositor). La ÚNICA excepción es la deformación real del
   tubo, que va por filtro SVG y la gobierna `ui_crt.js`: es un puñado de
   fotogramas al encender, no un bucle.

   Este fichero se carga DESPUÉS de theme_motion.css, así que manda él.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. EL CRISTAL: capas que viven DENTRO de la pantalla
   --------------------------------------------------------------------------
   Todas son `position:absolute`, así que no entran en el flujo del flex/grid
   que ya usan los visores: no mueven ni un píxel de la rueda.
   -------------------------------------------------------------------------- */

.crt {
  position: relative;
  overflow: hidden;

  /* Cada encendido sortea sus tiempos (los escribe `ui_crt.js` en línea, así
     que dos gráficas que enciendan a la vez NO van a la vez). Éstos son sólo
     los valores de respaldo. */
  --crt-strike-dur: 110ms;
  --crt-line-dur: 110ms;
  --crt-open-dur: 900ms;
  --crt-flicker-dur: 430ms;
  --crt-roll-dur: 560ms;
  --crt-glitch-dur: 480ms;
  --crt-bar-delay-1: 0ms;
  --crt-bar-delay-2: 40ms;
  --crt-bar-delay-3: 90ms;
}

.crt-veil,
.crt-bloom,
.crt-dot,
.crt-emit,
.crt-roll,
.crt-glitch {
  position: absolute;
  pointer-events: none;
  display: block;
  opacity: 0;
}

/* Negro de tubo apagado: cristal muerto, sin imagen que se adivine. */
.crt-veil {
  inset: 0;
  z-index: 9;
  background: radial-gradient(ellipse 90% 85% at 50% 45%, #080f14 0%, #03060a 65%, #010304 100%);
  will-change: opacity;
}

/* Fogonazo del haz cuando golpea el fósforo. Pequeño y contenido: es un
   destello de filamento, no un flash de cámara. */
.crt-bloom {
  inset: -12%;
  z-index: 10;
  background: radial-gradient(
    ellipse 44% 9% at 50% 50%,
    rgba(245, 255, 244, 0.55) 0%,
    rgba(150, 255, 160, 0.20) 42%,
    rgba(74, 246, 38, 0.05) 66%,
    rgba(74, 246, 38, 0) 82%
  );
  will-change: opacity;
}

/* EL PUNTO: el filamento golpeado en el centro del tubo. Es el primer
   fotograma de verdad de un CRT encendiéndose y el que lo delata. */
.crt-dot {
  left: 50%;
  top: 50%;
  width: 7px;
  height: 7px;
  margin: -3.5px 0 0 -3.5px;
  z-index: 12;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    #ffffff 0%,
    #ecffe6 30%,
    rgba(150, 255, 150, 0.5) 58%,
    rgba(74, 246, 38, 0) 100%
  );
  box-shadow:
    0 0 9px 3px rgba(215, 255, 205, 0.6),
    0 0 26px 8px rgba(74, 246, 38, 0.32);
  transform: scale(0.15);
}

/* LA LÍNEA: el punto estirado a lo ancho del tubo. Crece DESDE el centro,
   así que se escala en X, no se le cambia el `width`. */
.crt-emit {
  left: 0;
  right: 0;
  top: 50%;
  height: 2px;
  margin-top: -1px;
  z-index: 11;
  background: #f4fff2;
  box-shadow:
    0 0 7px 2px rgba(205, 255, 195, 0.66),
    0 0 20px 5px rgba(74, 246, 38, 0.34);
  transform: scaleX(0);
  transform-origin: 50% 50%;
}

/* Barra de rodillo: la banda clara que sube por la pantalla al sincronizar. */
.crt-roll {
  top: 0;
  left: 0;
  right: 0;
  height: 42%;
  z-index: 8;
  background: linear-gradient(
    180deg,
    rgba(200, 255, 210, 0) 0%,
    rgba(200, 255, 210, 0.03) 38%,
    rgba(210, 255, 218, 0.14) 50%,
    rgba(200, 255, 210, 0.03) 62%,
    rgba(200, 255, 210, 0) 100%
  );
  will-change: transform, opacity;
}

/* Rotura de sincronía: bandas que saltan de sitio. */
.crt-glitch {
  inset: 0;
  z-index: 7;
  overflow: hidden;
}

.crt-glitch i {
  position: absolute;
  left: -6%;
  right: -6%;
  height: 11%;
  display: block;
  transform: translateY(-200%);
  background:
    linear-gradient(90deg, rgba(255, 70, 70, 0.32) 0, rgba(255, 70, 70, 0) 16px),
    linear-gradient(270deg, rgba(70, 220, 255, 0.30) 0, rgba(70, 220, 255, 0) 16px),
    linear-gradient(180deg, rgba(190, 255, 200, 0.08), rgba(190, 255, 200, 0.02));
  border-top: 1px solid rgba(230, 255, 230, 0.28);
  border-bottom: 1px solid rgba(0, 0, 0, 0.35);
  will-change: transform;
}

/* --------------------------------------------------------------------------
   2. APAGADA — el tubo no recibe señal
   -------------------------------------------------------------------------- */

.crt.is-off {
  clip-path: inset(0);
}

.crt.is-off .crt-veil {
  opacity: 1;
  animation: none;
}

.crt.is-off .crt-bloom,
.crt.is-off .crt-dot,
.crt.is-off .crt-emit,
.crt.is-off .crt-roll,
.crt.is-off .crt-glitch {
  opacity: 0;
  animation: none;
}

/* Un rescoldo de fósforo que se apaga al cortar la corriente. */
.crt.is-off::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 13;
  pointer-events: none;
  background: radial-gradient(ellipse 70% 60% at 50% 50%, rgba(120, 255, 140, 0.16), transparent 70%);
  animation: crt-afterglow 220ms steps(4, end) both;
}

@keyframes crt-afterglow {
  0% { opacity: 1; }
  100% { opacity: 0; }
}

/* --------------------------------------------------------------------------
   3. GOLPE — el PUNTO: el filamento golpeado en el centro del tubo
   --------------------------------------------------------------------------
   Todavía no hay imagen: el cristal sigue negro y lo único encendido es el
   punto. Es el fotograma que delata a un CRT y el que faltaba.
   -------------------------------------------------------------------------- */

.crt.is-strike {
  clip-path: inset(0);
}

.crt.is-strike .crt-veil { opacity: 0.97; animation: none; }
.crt.is-strike .crt-dot { animation: crt-dot-strike var(--crt-strike-dur) cubic-bezier(0.2, 0.9, 0.3, 1) both; }
.crt.is-strike .crt-bloom { animation: crt-bloom 220ms var(--ease-ignite) both; }

@keyframes crt-dot-strike {
  0% { opacity: 0; transform: scale(0.15); }
  35% { opacity: 1; transform: scale(1); }
  55% { opacity: 0.55; }
  72% { opacity: 1; transform: scale(0.86); }
  100% { opacity: 1; transform: scale(1); }
}

@keyframes crt-bloom {
  0% { opacity: 0.95; }
  100% { opacity: 0; }
}

/* --------------------------------------------------------------------------
   4. LÍNEA — el punto se estira a lo ancho (la etapa que faltaba)
   -------------------------------------------------------------------------- */

.crt.is-line .crt-veil { opacity: 0.93; animation: none; }
.crt.is-line .crt-dot { opacity: 1; transform: scale(1); }
.crt.is-line .crt-emit { opacity: 1; animation: crt-line-out var(--crt-line-dur) cubic-bezier(0.15, 0.85, 0.25, 1) both; }

@keyframes crt-line-out {
  0% { transform: scaleX(0); }
  68% { transform: scaleX(1.015); }
  100% { transform: scaleX(1); }
}

/* --------------------------------------------------------------------------
   5. ENCENDIDO — la línea se abre, el tubo parpadea y se deforma
   --------------------------------------------------------------------------
   El recorte hace de "apertura vertical"; el `transform` añade el tirón
   horizontal del tubo que todavía no ha enganchado la sincronía.
   -------------------------------------------------------------------------- */

.crt.is-open {
  animation: crt-open var(--crt-open-dur) var(--ease-mech) both;
}

/* El punto ya ha hecho su trabajo: se apaga estirándose. */
.crt.is-open .crt-dot { animation: crt-dot-out calc(var(--crt-open-dur) * 0.22) var(--ease-ignite) both; }
.crt.is-open .crt-emit { opacity: 1; transform: scaleX(1); animation: crt-emit-out calc(var(--crt-open-dur) * 0.42) var(--ease-ignite) both; }

@keyframes crt-dot-out {
  0% { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(3.2); }
}

@keyframes crt-emit-out {
  0% { opacity: 1; }
  55% { opacity: 0.65; }
  100% { opacity: 0; }
}

@keyframes crt-open {
  0% {
    clip-path: inset(calc(50% - 2px) 0 calc(50% - 2px) 0);
    transform: translateX(0) skewX(0deg) scaleX(1.05);
  }
  10% { clip-path: inset(44% 0 44% 0); }
  20% {
    clip-path: inset(26% 0 26% 0);
    transform: translateX(-4px) skewX(0.7deg) scaleX(1.03);
  }
  30% {
    clip-path: inset(0 0 0 0);
    transform: translateX(3px) skewX(-0.5deg) scaleX(0.985);
  }
  42% {
    clip-path: inset(7% 0 7% 0);
    transform: translateX(-2px) skewX(0.35deg) scaleX(1.012);
  }
  54% {
    clip-path: inset(0 0 0 0);
    transform: translateX(1px) skewX(-0.18deg) scaleX(0.996);
  }
  70% { transform: translateX(-1px) skewX(0.08deg) scaleX(1.004); }
  86% { transform: translateX(0) skewX(0deg) scaleX(0.999); }
  100% {
    clip-path: inset(0 0 0 0);
    transform: none;
  }
}

/* Parpadeo rápido: negro/ imagen a saltos, sin suavizado. */
.crt.is-open .crt-veil {
  animation: crt-veil-flicker var(--crt-flicker-dur) steps(1, end) both;
}

@keyframes crt-veil-flicker {
  0% { opacity: 0.88; }
  7% { opacity: 0.14; }
  15% { opacity: 0.72; }
  23% { opacity: 0.04; }
  31% { opacity: 0.58; }
  43% { opacity: 0.11; }
  55% { opacity: 0.42; }
  67% { opacity: 0.06; }
  79% { opacity: 0.24; }
  91% { opacity: 0.05; }
  100% { opacity: 0; }
}

.crt.is-open .crt-roll {
  opacity: 1;
  animation: crt-roll var(--crt-roll-dur) cubic-bezier(0.25, 0.5, 0.3, 1) both;
}

@keyframes crt-roll {
  0% { transform: translateY(-130%); opacity: 0.9; }
  80% { opacity: 0.75; }
  100% { transform: translateY(250%); opacity: 0; }
}

.crt.is-open .crt-bloom {
  animation: crt-bloom 220ms var(--ease-ignite) both;
}

.crt.is-open .crt-glitch { animation: crt-glitch var(--crt-glitch-dur) linear both; }
.crt.is-open .crt-glitch i:nth-child(1) { animation: crt-bar-1 calc(var(--crt-glitch-dur) * 0.9) steps(11, end) var(--crt-bar-delay-1) both; }
.crt.is-open .crt-glitch i:nth-child(2) { animation: crt-bar-2 var(--crt-glitch-dur) steps(9, end) var(--crt-bar-delay-2) both; }
.crt.is-open .crt-glitch i:nth-child(3) { animation: crt-bar-3 calc(var(--crt-glitch-dur) * 0.8) steps(13, end) var(--crt-bar-delay-3) both; }

@keyframes crt-glitch {
  0% { opacity: 1; }
  70% { opacity: 0.7; }
  100% { opacity: 0; }
}
@keyframes crt-bar-1 {
  0% { transform: translateY(-160%); }
  100% { transform: translateY(780%); }
}
@keyframes crt-bar-2 {
  0% { transform: translateY(520%); }
  100% { transform: translateY(-240%); }
}
@keyframes crt-bar-3 {
  0% { transform: translateY(140%); }
  100% { transform: translateY(620%); }
}

/* --------------------------------------------------------------------------
   6. VIVA — el tubo ya está enganchado
   -------------------------------------------------------------------------- */

.crt.is-live {
  clip-path: none;
  transform: none;
  animation: none;
}

.crt.is-live .crt-veil,
.crt.is-live .crt-bloom,
.crt.is-live .crt-dot,
.crt.is-live .crt-emit,
.crt.is-live .crt-roll,
.crt.is-live .crt-glitch,
.crt.is-live .crt-glitch i {
  opacity: 0;
  animation: none;
}

/* --------------------------------------------------------------------------
   7. NOTA SOBRE `prefers-reduced-motion`
   --------------------------------------------------------------------------
   Aquí NO hay bloque de movimiento reducido, y es a propósito.

   Brave (y algún otro navegador) pone `prefers-reduced-motion: reduce` POR
   DEFECTO, como defensa antifingerprinting, aunque el usuario no haya pedido
   nada. Comprobado: Brave 155 devuelve `reduce` con un perfil recién creado.
   Si esta hoja obedeciera esa señal, en Brave no se vería ni el punto ni la
   línea: la animación entera desaparecería en silencio.

   El interruptor de verdad es explícito y del usuario:

       CRT.setEnabled(false)   // y se acuerda entre sesiones
   -------------------------------------------------------------------------- */
