/* ============================================================
   FX — warstwa animacji v6 (komiks + AI). Całość jest opcjonalna:
   działa tylko z klasą "fx" na <html>, którą skrypt w <head> dodaje
   WYŁĄCZNIE, gdy użytkownik nie prosi o ograniczenie ruchu. Bez tej
   klasy (albo bez fx.js) strona wygląda i działa jak v5.
   ============================================================ */

/* ---------- 1. WIZJA MASZYNOWA: ramki wykrytych obiektów na tle ---------- */
/* Nakładka siedzi w .bg-parallax obok obrazka, więc jedzie razem z
   najazdem kamery i paralaksą. fx.js ustawia jej wymiary na obszar,
   który obrazek faktycznie zajmuje (object-fit: cover + object-position). */
.hud {
  position: absolute;
  pointer-events: none;
  display: none;
}
.fx .hud { display: block; }

.hud-scan {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 2px;
  background: #ff4136;
  box-shadow: 0 0 14px 3px rgba(255, 65, 54, 0.55);
  opacity: 0;
}
.hud-scan::before {                 /* smuga za linią skanu */
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 2px;
  height: 90px;
  background: linear-gradient(to bottom, rgba(255, 65, 54, 0), rgba(255, 65, 54, 0.13));
}
.hud.is-run .hud-scan { animation: hud-scan 1.7s cubic-bezier(0.45, 0, 0.25, 1) 0.15s both; }

@keyframes hud-scan {
  0%   { top: 0;    opacity: 0; }
  8%   {            opacity: 1; }
  88%  {            opacity: 1; }
  100% { top: 100%; opacity: 0; }
}

.hud-box {
  position: absolute;
  opacity: 0;
  transform: scale(1.35);
  transition: opacity 0.2s ease-out, transform 0.5s cubic-bezier(0.2, 0.9, 0.3, 1.25);
}
.hud.is-run .hud-box {
  opacity: 1;
  transform: none;
  transition-delay: var(--d, 0s);
}

/* Narożniki ramki — osiem odcinków z gradientów, bez dodatkowego DOM-u */
.hud-frame {
  position: absolute;
  inset: 0;
  --c: #ff4136;
  --l: 14px;
  --w: 2px;
  background:
    linear-gradient(var(--c), var(--c)) left top    / var(--l) var(--w) no-repeat,
    linear-gradient(var(--c), var(--c)) left top    / var(--w) var(--l) no-repeat,
    linear-gradient(var(--c), var(--c)) right top   / var(--l) var(--w) no-repeat,
    linear-gradient(var(--c), var(--c)) right top   / var(--w) var(--l) no-repeat,
    linear-gradient(var(--c), var(--c)) left bottom / var(--l) var(--w) no-repeat,
    linear-gradient(var(--c), var(--c)) left bottom / var(--w) var(--l) no-repeat,
    linear-gradient(var(--c), var(--c)) right bottom/ var(--l) var(--w) no-repeat,
    linear-gradient(var(--c), var(--c)) right bottom/ var(--w) var(--l) no-repeat,
    rgba(255, 65, 54, 0.05);
  outline: 1px dashed rgba(255, 65, 54, 0.28);
  outline-offset: -1px;
}
/* Po namierzeniu ramka lekko "śledzi" obiekt */
.hud.is-run .hud-frame {
  animation: hud-track 7s ease-in-out infinite;
  animation-delay: calc(var(--d, 0s) + 0.8s);
}
@keyframes hud-track {
  0%, 100% { transform: translate(0, 0) scale(1); }
  30%      { transform: translate(1.5px, -1px) scale(1.012); }
  60%      { transform: translate(-1px, 1.5px) scale(0.992); }
}

.hud-label {
  position: absolute;
  left: -2px;
  bottom: 100%;
  margin-bottom: 5px;
  padding: 3px 6px 3px 5px;
  white-space: nowrap;
  font: 700 10px/1.1 ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  letter-spacing: 0.08em;
  color: #f5f1e4;
  background: #141210;
  border: 1.5px solid #ff4136;
  box-shadow: 3px 3px 0 rgba(20, 18, 16, 0.85);
}
.hud-box.lbl-below .hud-label { bottom: auto; top: 6px; left: 6px; margin: 0; }
.hud-label::before {                /* czerwony znacznik jak w dymku komiksu */
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 5px;
  vertical-align: 1px;
  background: #ff4136;
}
.hud-conf { color: #ff4136; margin-left: 6px; }

/* ---------- 2. RASTER BEN-DAY POD KURSOREM (tylko desktop) ---------- */
#fx-halftone {
  position: fixed;
  inset: 0;
  z-index: 5;                       /* nad tłami (1–2), pod ziarnem (15) i treścią (20) */
  pointer-events: none;
}

/* ---------- 3. LINIE PĘDU przy przejściu do sceny ---------- */
#fx-speed {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
}

/* ---------- 4. KADRY WCHODZĄ JAK NA PLANSZĘ (ukośne zdarcie tuszu + opad) ---------- */
/* Panel NIE jest przycinany (clip-path na obserwowanym elemencie sprawia,
   że IntersectionObserver w main.js nigdy go nie "widzi"). Zamiast tego
   nad panelem leży warstwa tuszu (::after), którą ukośne cięcie zdziera. */
.fx .reveal {
  position: relative;
  opacity: 0;
  transform: translate(-6px, 14px) rotate(-0.8deg);
  transition:
    opacity 0.15s linear,
    transform 0.8s cubic-bezier(0.2, 0.9, 0.3, 1.2);
}
.fx .reveal::after {
  content: "";
  position: absolute;
  inset: -3px;
  z-index: 2;
  pointer-events: none;
  background: #141210;
  clip-path: polygon(0% 0%, 120% 0%, 100% 100%, -20% 100%);
  transition: clip-path 0.7s cubic-bezier(0.77, 0, 0.18, 1) 0.12s;
}
.fx .reveal.is-visible { opacity: 1; transform: none; }
.fx .reveal.is-visible::after { clip-path: polygon(120% 0%, 120% 0%, 100% 100%, 100% 100%); }

.fx .panel-grid > .reveal:nth-child(2),
.fx .panel-grid > .reveal:nth-child(2)::after { transition-delay: 0.08s; }
.fx .panel-grid > .reveal:nth-child(3),
.fx .panel-grid > .reveal:nth-child(3)::after { transition-delay: 0.16s; }
.fx .panel-grid > .reveal:nth-child(4),
.fx .panel-grid > .reveal:nth-child(4)::after { transition-delay: 0.24s; }
.fx .panel-grid > .reveal:nth-child(5),
.fx .panel-grid > .reveal:nth-child(5)::after { transition-delay: 0.32s; }
.fx .panel-grid > .reveal:nth-child(6),
.fx .panel-grid > .reveal:nth-child(6)::after { transition-delay: 0.40s; }

/* ---------- 5. NEON ZAPALA SIĘ + TYTUŁ "DEKODOWANY" ---------- */
.fx.fx-ready .hero-neon { animation: neon-on 1.3s steps(1, end) both; }
@keyframes neon-on {
  0%   { opacity: 0.15; text-shadow: none; }
  12%  { opacity: 1; }
  18%  { opacity: 0.2;  text-shadow: none; }
  30%  { opacity: 1; }
  36%  { opacity: 0.35; text-shadow: none; }
  52%  { opacity: 1; }
  100% { opacity: 1; }
}

/* Każdy znak tytułu stoi w swoim <span>; prawdziwa litera trzyma układ
   (przezroczysta), a nad nią ::after pokazuje losowy znak, dopóki litera
   nie zostanie "rozpoznana". Dzięki temu tekst nie skacze. */
.dc-ch { position: relative; }
.dc-ch.is-noise { color: transparent; }
.dc-ch.is-noise::after {
  content: attr(data-g);
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  text-align: center;
  color: #e53935;
}

/* ---------- 6. CYTAT "STRUMIENIOWANY" jak odpowiedź modelu ---------- */
.quote-panel.is-streaming .tok { opacity: 0; }
.quote-panel.is-streaming .tok.on {
  opacity: 1;
  animation: tok-in 0.7s ease-out;
}
@keyframes tok-in {
  from { background: rgba(255, 65, 54, 0.38); }
  to   { background: rgba(255, 65, 54, 0); }
}
.tok-cursor {
  display: inline-block;
  width: 0.55em;
  height: 1em;
  margin-left: 3px;
  vertical-align: -0.12em;
  background: #e53935;
  animation: tok-blink 0.9s steps(1, end) infinite;
}
@keyframes tok-blink { 50% { opacity: 0; } }
.quote-panel.is-streaming .quote-source {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.5s ease-out, transform 0.5s ease-out;
}
.quote-panel.is-streaming.is-done .quote-source { opacity: 1; transform: none; }

@media (max-width: 899px) {
  .hud-label { font-size: 9px; padding: 2px 5px 2px 4px; }
  .hud-frame { --l: 10px; }
}
