/* ═══════════════════════════════════════════════════════════════
   CONSOLA — lo que comparten las dos pantallas: la ventana del teseracto
   (agent-window.css) y la pantalla del texto del wallpaper. Mismo marco
   (borde, radio y sombra de base.css) y el mismo balanceo 3D, con sus
   variantes por calidad y dispositivo. agent-window.js recorta su canvas con
   el mismo radio (FRAME_RADIUS).
   Aquí vive también la pantalla del texto: su barra, su tamaño fijo y el
   hueco de su borde detrás del emblema. La resonancia la mueve consola.js.
   ═══════════════════════════════════════════════════════════════ */
/* El marco: borde, radio y sombra. La sombra va en dos partes, el anillo (una línea
   de 1 px por fuera del borde) y el halo, y cada calidad las cambia más abajo. La
   ventana del teseracto las pinta juntas; la pantalla del texto pinta sus dos líneas
   (borde y anillo) aparte, para abrirles el hueco del emblema. */
:is(.ai-window__frame, .pantalla__marco) {
  border-radius: var(--marco-radio);
  border: var(--marco-borde);
}

.ai-window__frame {
  box-shadow: var(--marco-anillo), var(--marco-halo);
}

/* El balanceo mueve la pieza entera: la ventana del teseracto con su canvas, y el
   cuerpo de la pantalla con su marco y su emblema. Cada una ajusta el ritmo con
   --balanceo-ritmo: el mismo movimiento, nunca a la vez, así la consola respira en
   vez de marcar el paso. */
:is(.ai-window__frame, .pantalla__cuerpo) {
  will-change: transform;
  animation: ai-tilt calc(7.4s * var(--balanceo-ritmo, 1)) ease-in-out infinite;
}

@keyframes ai-tilt {
  0%,
  100% {
    transform: perspective(900px) rotateX(-5deg) rotateY(7deg);
  }
  50% {
    transform: perspective(900px) rotateX(6deg) rotateY(-8deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  html:not(.svf-motion-override) :is(.ai-window__frame, .pantalla__cuerpo) {
    animation: none;
  }
}

.quality-ultra :is(.ai-window__frame, .pantalla__cuerpo) {
  animation: none !important;
}

.is-desktop.quality-high :is(.ai-window__frame, .pantalla__cuerpo) {
  animation: ai-tilt-high calc(6.5s * var(--balanceo-ritmo, 1)) ease-in-out infinite;
}

.is-desktop.quality-high :is(.ai-window__frame, .pantalla__cuerpo) {
  --marco-anillo: 0 0 0 1px rgba(0, 255, 156, 0.12);
  --marco-halo:
    0 25px 70px rgba(0, 0, 0, 0.6),
    0 0 50px rgba(0, 255, 156, 0.15),
    0 0 100px rgba(0, 212, 255, 0.08);
}

@keyframes ai-tilt-high {
  0%, 100% {
    transform: perspective(800px) rotateX(-8deg) rotateY(10deg) translateZ(0);
    box-shadow:
      0 0 0 1px rgba(0, 255, 156, 0.12),
      0 30px 80px rgba(0, 0, 0, 0.65),
      0 0 55px rgba(0, 255, 156, 0.18),
      0 0 110px rgba(0, 212, 255, 0.1);
  }
  25% {
    transform: perspective(800px) rotateX(2deg) rotateY(-4deg) translateZ(5px);
  }
  50% {
    transform: perspective(800px) rotateX(9deg) rotateY(-11deg) translateZ(0);
    box-shadow:
      0 0 0 1px rgba(0, 255, 156, 0.15),
      0 20px 60px rgba(0, 0, 0, 0.55),
      0 0 45px rgba(0, 255, 156, 0.14),
      0 0 90px rgba(0, 212, 255, 0.06);
  }
  75% {
    transform: perspective(800px) rotateX(-3deg) rotateY(5deg) translateZ(3px);
  }
}

/* Mobile: las pantallas, más sutiles pero presentes */
.is-mobile.quality-medium :is(.ai-window__frame, .pantalla__cuerpo),
.is-mobile.quality-high :is(.ai-window__frame, .pantalla__cuerpo) {
  --marco-anillo: 0 0 0 1px rgba(0, 255, 156, 0.1);
  --marco-halo:
    0 15px 45px rgba(0, 0, 0, 0.5),
    0 0 30px rgba(0, 255, 156, 0.1);
}

/* Mobile High: balanceo suave (no tan intenso como escritorio) */
.is-mobile.quality-high :is(.ai-window__frame, .pantalla__cuerpo) {
  animation: ai-tilt-mobile calc(8s * var(--balanceo-ritmo, 1)) ease-in-out infinite;
}

@keyframes ai-tilt-mobile {
  0%, 100% {
    transform: perspective(900px) rotateX(-3deg) rotateY(4deg);
  }
  50% {
    transform: perspective(900px) rotateX(4deg) rotateY(-5deg);
  }
}

/* ───────────────────────────────────────────────────────────────
   LA PANTALLA DEL TEXTO — una terminal: barra de título arriba y, debajo,
   el texto que se escribe, hace glitch, colapsa y renace. Tamaño fijo en
   unidades del propio texto (--columnas × --lineas, por defecto 40 × 6: ahí
   cabe la frase más larga de ES, EN y PT), así no cambia entre frases ni
   idiomas; una página con menos ancho pide menos columnas y las líneas que
   hagan falta (la home en móvil, index.css). Sin backdrop-filter,
   mix-blend-mode ni filter. Dos piezas, como el teseracto: .pantalla resuena
   (consola.js) y .pantalla__cuerpo se balancea. Va con el emblema del logo
   (el wallpaper) o sin él (.pantalla--sin-emblema, la home).
   ─────────────────────────────────────────────────────────────── */
.pantalla {
  /* El balanceo va desfasado del teseracto para que la consola no marque el paso. El
     director no la oscurece: el texto se lee entero en todo el ciclo. */
  --balanceo-ritmo: 1.17;
}

/* El cuerpo es la pieza que se balancea: dentro van el emblema y el marco, y los dos
   giran juntos, así el hueco del borde no se despega del emblema. */
.pantalla__cuerpo {
  position: relative;
}

.pantalla__marco {
  --barra-alto: 3.8em;
  position: relative;
  z-index: 1;
  /* La lluvia se insinúa detrás del texto, sin competir con él. Arriba, el tinte de la
     barra, que la separa del texto sin una línea (una línea de 1 px sobre una pieza que
     gira cae entre píxeles y se parte en dos filas tenues que bailan). Va en el fondo
     del marco y no en la barra para que llegue hasta el borde: en el hueco del emblema,
     esa fila sigue teñida en vez de quedar oscura. */
  background:
    linear-gradient(rgba(0, 255, 156, 0.05) calc(var(--barra-alto) + 1px), transparent 0) border-box,
    rgba(5, 10, 15, 0.9);
  /* Aquí solo el halo: el borde y el anillo los dibuja .pantalla__cuerpo::after. El
     borde sigue ocupando su píxel, transparente, para que nada se mueva. */
  border-color: transparent;
  box-shadow: var(--marco-halo);
}

/* Las dos líneas del marco (borde y anillo), encima de él y debajo del emblema. Su
   máscara abre en ellas el hueco del emblema, y solo en ellas: el halo y el fondo del
   marco siguen enteros detrás, así el borde pasa por debajo del emblema sin dejar una
   rendija oscura. El hueco va desde el centro, lo que ocupa el GIF a la altura del
   bisel en sus 8 cuadros (la prueba lo mide cuadro a cuadro y comprueba que el borde
   no se ve donde el GIF pinta), con los extremos difuminados. Son dos capas del mismo
   tamaño que se suman, una abierta arriba y otra abierta en esas columnas, así solo se
   abre su cruce y no queda ninguna costura; no-clip y el alcance dejan entero el
   anillo, que va 1 px por fuera. */
.pantalla__cuerpo::after {
  --hueco-izq: 1.09em;
  --hueco-der: 1.6em;
  --hueco-difuso: 0.35em;
  --hueco-alcance: 4px;
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  border: var(--marco-borde);
  border-radius: var(--marco-radio);
  box-shadow: var(--marco-anillo);
  mask-image:
    linear-gradient(to bottom, transparent calc(var(--hueco-alcance) + 4px), #000 0),
    linear-gradient(
      to right,
      #000 calc(50% - var(--hueco-izq) - var(--hueco-difuso)),
      transparent calc(50% - var(--hueco-izq)) calc(50% + var(--hueco-der)),
      #000 calc(50% + var(--hueco-der) + var(--hueco-difuso))
    );
  mask-size: calc(100% + 2 * var(--hueco-alcance)) calc(100% + 2 * var(--hueco-alcance));
  mask-position: calc(-1 * var(--hueco-alcance)) calc(-1 * var(--hueco-alcance));
  mask-repeat: no-repeat;
  mask-clip: no-clip;
}

/* El mismo gesto que la ventana del teseracto, pero con la mitad de ángulo y más
   perspectiva: aquí hay texto, y el balanceo del marco 4D se lo come. Medido con
   Chrome headless sobre la frase del hero, comparando la nitidez de los bordes con
   la de la pantalla quieta: con el balanceo del teseracto, 83 %; con este, 89 %. */
@keyframes consola-tilt {
  0%,
  100% {
    transform: perspective(1400px) rotateX(-2.4deg) rotateY(3.4deg) translateY(-0.35%);
  }
  50% {
    transform: perspective(1400px) rotateX(2.8deg) rotateY(-3.8deg) translateY(0.35%);
  }
}

.pantalla__cuerpo,
.is-desktop.quality-high .pantalla__cuerpo,
.is-mobile.quality-high .pantalla__cuerpo {
  animation-name: consola-tilt;
}

/* La barra lleva las luces a la izquierda y el selector de idioma a la derecha; el
   emblema asoma en medio, por encima del bisel. */
.pantalla__barra {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  height: var(--barra-alto);
  padding: 0 0.9em;
}

.pantalla__luces {
  display: flex;
  gap: 0.45em;
}

.pantalla__luz {
  width: 0.5em;
  height: 0.5em;
  border-radius: 50%;
  background: rgba(0, 255, 156, 0.32);
}

/* El selector de idioma vive en la barra, a la derecha: mismos botones que la home
   (i18n.css), a la escala de la pantalla. */
.pantalla__barra .lang-switch {
  grid-column: 3;
  justify-self: end;
  gap: 0.3em;
}

.pantalla__barra .lang-option {
  padding: 0.12em 0.5em;
  font-size: 0.62em;
  letter-spacing: 0.12em;
}

.pantalla .typing {
  width: calc(var(--columnas, 40) * 1ch);
  height: calc(var(--lineas, 6) * 1lh);
  margin: 1em 1.1em 1.2em;
}

/* Sin emblema (la home, que lleva el logo en su encabezado): el borde ya no se abre para
   él y la barra solo lleva sus luces, así que es más baja. */
.pantalla--sin-emblema .pantalla__marco {
  --barra-alto: 2.4em;
}

.pantalla--sin-emblema .pantalla__cuerpo::after {
  mask-image: none;
}

/* El emblema: el GIF del logo asoma por encima del bisel con la base dentro de la
   barra, delante del marco: el borde pasa por DETRÁS (el hueco lo abre la máscara de
   .pantalla__cuerpo::after). Va sin las sombras de la home (sus tres drop-shadow cuestan
   +3.5 ms medidos; la animación, +0.2, que es ruido). */
.pantalla__logo {
  position: absolute;
  left: 50%;
  bottom: 100%;
  margin-bottom: -4.3em;
  transform: translateX(-50%);
  z-index: 2;
  height: 6.4em;
  width: auto;
  opacity: 0.95;
}
