/* Drobne uzupełnienia do Tailwinda – czcionka i animacje dla widoku dziecka */

/* ==========================================================================
   DESIGN TOKENS
   Źródło: AI_SPEC/VISUAL_DIRECTION.md, sekcje 4 (kolorystyka) i 7.2 (czasy
   animacji). To jest FUNDAMENT — same tokeny nie zmieniają jeszcze wyglądu
   żadnego istniejącego elementu (nic w app dziś ich nie używa). Wartości
   kolorów muszą być zgodne z `tailwind.config` w templates/index.html
   (brak build stepu = brak jednego wspólnego źródła prawdy, trzeba
   pilnować obu miejsc ręcznie).
   ========================================================================== */
:root {
  /* Kolory (VISUAL_DIRECTION.md sekcja 4.1) */
  --navy: #1b2a4a;
  --navy-light: #2e4066;
  --turquoise: #22c1d6;
  --gold: #f59e0b; /* = Tailwind amber-500, już używany w app */
  --quiz-surface: #ffffff;
  --quiz-surface-soft: #f8fafc;
  --success: #059669; /* = Tailwind emerald-600, bez zmian względem v1 */
  --warning: #f97316; /* = Tailwind orange-500, bez zmian względem v1 */
  --text: #1e293b; /* = Tailwind slate-800, bez zmian względem v1 */

  /* Promienie – nazwane odpowiedniki skali już używanej przez Tailwind
     (rounded-lg/xl/2xl/3xl/full) w całej aplikacji */
  --radius-sm: 0.5rem;
  --radius-md: 0.75rem;
  --radius-lg: 1rem;
  --radius-xl: 1.5rem;
  --radius-full: 9999px;

  /* Cienie – miękkie, w tonacji granatu, nigdy czarne/ostre
     (VISUAL_DIRECTION.md sekcja 3) */
  --shadow-soft: 0 4px 14px rgba(27, 42, 74, 0.12);
  --shadow-soft-lg: 0 10px 30px rgba(27, 42, 74, 0.16);

  /* Warstwy (z-index) – jedna skala dla całej aplikacji, żeby kolejne
     elementy redesignu (Brama w tle, Strażnik przed nią, celebracja nad
     wszystkim) nie zaczęły licytować się przypadkowymi liczbami.
     --z-overlay = 50 celowo równa się Tailwindowemu `z-50`, którego już
     dziś używają oba modale w index.html – dzięki temu skala opisuje stan
     faktyczny, zamiast wchodzić z nim w konflikt. */
  --z-base: 0;
  --z-gate: 10; /* scena Bramy – tło */
  --z-guardian: 20; /* Strażnik – przed Bramą */
  --z-content: 30; /* karty, pytania, przyciski */
  --z-sticky: 40; /* elementy przyklejone do krawędzi ekranu */
  --z-overlay: 50; /* przyciemnienie tła pod modalem */
  --z-modal: 60; /* zawartość modala */
  --z-celebration: 70; /* nagroda/otwarcie bramy – ponad wszystkim */

  /* Czasy animacji (VISUAL_DIRECTION.md sekcja 7.2) */
  --duration-micro: 180ms;
  --duration-feedback: 350ms;
  --duration-transition: 500ms;
  --duration-celebration: 1100ms;
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
}

body {
  font-family: "Segoe UI", "Comic Sans MS", "Trebuchet MS", system-ui, sans-serif;
}

.view {
  animation: fade-in 0.25s ease-out;
}

@keyframes fade-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.option-btn {
  transition: transform 0.1s ease, background-color 0.15s ease, border-color 0.15s ease;
}

.option-btn:active {
  transform: scale(0.97);
}

.option-btn.selected {
  background-color: #4f46e5;
  color: #fff;
  border-color: #4338ca;
}

/* ==========================================================================
   FUNDAMENT SYSTEMU ANIMACJI
   Ogólne, wielokrotnego użytku klasy `.fx-*` — odpowiedniki punktów z
   katalogu animacji VISUAL_DIRECTION.md sekcja 7.3. Celowo NIE zależą od
   Strażnika ani Bramy (które jeszcze nie istnieją) — działają na dowolnym
   elemencie. Włączane/wyłączane przez triggerFeedback() ze static/js/
   feedback.js. Na razie nieużywane przez żaden widok w app.js.
   Wyłącznie transform/opacity — zgodnie z zasadą wydajności z sekcji 10.
   ========================================================================== */

/* Poprawna odpowiedź – krótki, przyjazny "podskok" */
@keyframes fx-pulse-success {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.04); }
  100% { transform: scale(1); }
}
.fx-pulse-success {
  animation: fx-pulse-success var(--duration-feedback) var(--ease-standard);
}

/* Błędna odpowiedź – delikatne przesunięcie ±4px, NIGDY całego ekranu */
@keyframes fx-shake-soft {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-4px); }
  75%      { transform: translateX(4px); }
}
.fx-shake-soft {
  animation: fx-shake-soft var(--duration-feedback) var(--ease-standard);
}

/* Nagroda/celebracja – wejście przez skalę + fade */
@keyframes fx-pop-in {
  0%   { opacity: 0; transform: scale(0.8); }
  60%  { opacity: 1; transform: scale(1.05); }
  100% { opacity: 1; transform: scale(1); }
}
.fx-pop-in {
  animation: fx-pop-in var(--duration-celebration) var(--ease-standard);
}

/* Pojawienie się – najspokojniejszy z efektów, do zmiany treści w miejscu */
@keyframes fx-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.fx-fade-in {
  animation: fx-fade-in var(--duration-transition) var(--ease-standard);
}

/* Wejście przez skalę – dla elementów, które mają „przyjść do przodu”
   (karta wyniku, odznaka). Delikatniejsze niż .fx-pop-in: bez przeskoku
   ponad 100%, więc nadaje się też do rzeczy pojawiających się często. */
@keyframes fx-scale-in {
  from { opacity: 0; transform: scale(0.94); }
  to   { opacity: 1; transform: scale(1); }
}
.fx-scale-in {
  animation: fx-scale-in var(--duration-transition) var(--ease-standard);
}

/* Wjazd od dołu – dla elementów dokładanych do listy (kolejne pytanie,
   rozwinięte wyjaśnienie błędu). 12px, nie więcej: przy dłuższej liście
   większy dystans czyta się jak szarpnięcie całej strony. */
@keyframes fx-slide-up {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}
.fx-slide-up {
  animation: fx-slide-up var(--duration-transition) var(--ease-standard);
}

/* Poświata – zwrócenie uwagi bez ruszania elementem (np. klucz w pasku
   nagród, aktywna Brama).

   Animowany jest wyłącznie `opacity` pseudo-elementu, a nie `box-shadow`
   samego elementu. Animacja `box-shadow` zmusza przeglądarkę do
   przemalowywania przy każdej klatce; `opacity` idzie przez kompozytor.
   Efekt wizualnie ten sam, koszt nieporównywalnie mniejszy – a aplikacja
   ma chodzić płynnie na szkolnym laptopie, nie na stacji roboczej. */
@keyframes fx-glow {
  0%, 100% { opacity: 0; }
  50%      { opacity: 1; }
}
.fx-glow {
  position: relative;
}
.fx-glow::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: inherit;
  box-shadow: 0 0 18px 4px rgba(34, 193, 214, 0.55); /* --turquoise */
  opacity: 0;
  pointer-events: none; /* poświata nie może przechwytywać kliknięć */
  animation: fx-glow var(--duration-celebration) var(--ease-standard);
}

/* ==========================================================================
   SCENA — wspólny kontener Bramy (tło) i Strażnika (na pierwszym planie)
   FAZA 4.

   Poprawka po kontroli wizualnej: pierwsza wersja liczyła wysokość .scene
   z naturalnego przepływu .guardian (120–200px), a Brama (`position:
   absolute; inset:0`) miała własne proporcje SVG (600×320 ≈ 1,875:1) —
   przy szerokości ~560px dawało to ~300px wysokości, więc Brama
   WYSTAWAŁA poza wąski box .scene i nachodziła na nagłówek strony nad
   nią. Naprawione ustaleniem wysokości .scene wprost z `aspect-ratio`
   Bramy (ona jest głównym banerem wizualnym — sekcja 2.6 — więc to jej
   proporcje mają rządzić rozmiarem sceny, nie odwrotnie) i przeniesieniem
   też .guardian na `position: absolute` w tym samym boxie, żeby obie
   warstwy dzieliły dokładnie ten sam, przewidywalny obszar. */
.scene {
  position: relative;
  width: min(94%, 560px);
  aspect-ratio: 600 / 320; /* = viewBox Bramy, sekcja 2.5 */
  margin: 0 auto 1rem;
}

/* ==========================================================================
   BRAMA WIEDZY (FAZA 4)
   Źródło: AI_SPEC/VISUAL_DIRECTION.md sekcja 2. Jeden plik SVG (inline w
   index.html) z grupami door-left/door-right/emblem/energy-lines/
   light-beams/scene-beyond (sekcja 2.5) — cztery stany to transformacje
   i przełączanie widoczności tych samych elementów, nie cztery różne
   rysunki jak w przypadku Strażnika.
   ========================================================================== */
.gate {
  position: absolute;
  inset: 0;
  z-index: var(--z-gate);
  pointer-events: none; /* czysto dekoracyjna scena, nie przechwytuje kliknięć */
}

/* Tryb "hidden" — test w trakcie (`view-quiz`): pełna scena Bramy znika,
   zostaje tylko statyczny znak w nagłówku testu (osobny, niezależny
   element w templates/index.html — sekcja 2.6/9: „mini-watermark w
   nagłówku, bez animacji”, ustalenie z v1 bez zmian). */
.gate[data-mode="hidden"] {
  display: none;
}

.gate__svg {
  width: 100%;
  height: 100%;
  display: block;
  filter: drop-shadow(0 10px 22px var(--shadow-soft-lg));
}

/* --- Skrzydła: zamknięte domyślnie (transform: none), rozsuwają się w
   stanach opening/open. Ta sama reguła `transition` obowiązuje niezależnie
   od stanu — dzięki temu gate.js łapie `transitionend`, żeby zsekwencjo-
   nować activation → opening → open bez zgadywania czasu w setTimeout
   (jedno źródło prawdy o czasie trwania: CSS, nie duplikowana stała w JS). */
.gate__door-left,
.gate__door-right {
  transition: transform var(--duration-transition) var(--ease-standard);
}
/* -204px = szerokość skrzydła (204 jednostki viewBox) — skrzydło chowa się
   CAŁKOWICIE za sąsiednią kolumną (i poza widoczny obszar viewBox), więc
   scena za bramą odsłania się w pełni, a nie wąskim paskiem pośrodku. */
.gate[data-state="opening"] .gate__door-left,
.gate[data-state="open"] .gate__door-left {
  transform: translateX(-204px);
}
.gate[data-state="opening"] .gate__door-right,
.gate[data-state="open"] .gate__door-right {
  transform: translateX(204px);
}

/* --- Emblemat: trzy odrębne zachowania blasku (VISUAL_DIRECTION.md
   sekcja 2.4):
   1) closed + NIE ready (blokada) — bardzo powolne, subtelne „oddychanie”
      (5s, niska amplituda 0.25↔0.5) — jedyny dopuszczony wyjątek od
      zasady „brak pętli ambientowych” (sekcja 7.1): komunikuje „czekam”,
      nie „patrz na mnie”.
   2) closed + ready (dashboard, brama gotowa) — cieplejszy, STATYCZNY
      blask, bez pętli (zasada 70/20/10).
   3) activation — intensywny, JEDNORAZOWY rozbłysk turkus→złoto (bez
      `infinite`); po jego zakończeniu gate.js przechodzi do "opening". */
.gate__emblem-glow {
  opacity: 0.35;
  transform-origin: center;
  transition: opacity var(--duration-transition) var(--ease-standard);
}
.gate[data-state="closed"][data-ready="false"] .gate__emblem-glow {
  animation: gate-breathe 5s var(--ease-standard) infinite;
}
.gate[data-state="closed"][data-ready="true"] .gate__emblem-glow {
  opacity: 0.85;
}
.gate[data-state="activation"] .gate__emblem-glow {
  animation: gate-flash var(--duration-celebration) var(--ease-standard) 1;
}
.gate[data-state="opening"] .gate__emblem-glow,
.gate[data-state="open"] .gate__emblem-glow {
  opacity: 1;
}

@keyframes gate-breathe {
  0%, 100% { opacity: 0.25; }
  50%      { opacity: 0.5; }
}
@keyframes gate-flash {
  0%   { opacity: 0.85; transform: scale(1); }
  35%  { opacity: 1; transform: scale(1.2); }
  100% { opacity: 1; transform: scale(1); }
}

/* --- Promienie światła: niewidoczne, dopóki skrzydła się nie zaczną
   rozsuwać. */
.gate__light-beams {
  opacity: 0;
  transition: opacity var(--duration-transition) var(--ease-standard);
}
.gate[data-state="opening"] .gate__light-beams,
.gate[data-state="open"] .gate__light-beams {
  opacity: 0.85;
}

/* --- Scena za bramą (droga/góry/zamek/niebo) leży w SVG POD skrzydłami
   w kolejności rysowania — same skrzydła ją zasłaniają, dopóki się nie
   rozsuną. Nie trzeba osobno przełączać jej widoczności. */

/* --- Mini-watermark w nagłówku testu (`view-quiz`) — statyczny,
   niezależny od maszyny stanów Bramy (sekcja 2.6: bez animacji). */
.gate-mini {
  flex: none;
  opacity: 0.55;
}

/* ==========================================================================
   STRAŻNIK WIEDZY – gniazdo na asset (FAZA 3 / 3b)
   ========================================================================== */

/* `position: absolute` (FAZA 4, doprecyzowanie): Strażnik dzieli teraz box
   .scene z Bramą zamiast wyznaczać jego wysokość samym sobą (patrz notka
   przy .scene wyżej). `align-items: flex-end` + `padding-bottom` stawia go
   na poziomie "progu" Bramy (dolna krawędź skrzydeł w SVG, ≈89% wysokości
   viewBox) zamiast dead-center, żeby wizualnie stał na ziemi, nie unosił
   się w powietrzu w połowie drzwi. */
.guardian {
  display: flex;
  justify-content: center;
  align-items: flex-end;
  position: absolute;
  inset: 0;
  padding-bottom: 6%;
  z-index: var(--z-guardian);
}

/* Dopóki nie ma czego pokazać, gniazdo nie zajmuje miejsca. Bez tego
   aplikacja miałaby dziś w środku pusty prostokąt — a Faza 3 z założenia
   nie zmienia wyglądu. Faza 3b przełączy atrybut na "true". */
.guardian[data-has-asset="false"] {
  display: none;
}

/* Proporcje zarezerwowane z góry: kiedy asset się wczyta, układ strony nie
   drgnie (bez tego dziecko widziałoby przeskok treści w trakcie ładowania).
   `object-fit: contain` + `display: block` (FAZA 3b): #guardian-asset jest
   teraz prawdziwym <img> — bez tego doszłoby do drobnej szczeliny pod
   obrazkiem (domyślne `inline` ustawia go na linii bazowej tekstu) i do
   ewentualnego przycięcia, gdyby proporcje SVG kiedyś przestały być 1:1. */
.guardian__asset {
  width: clamp(120px, 28vw, 200px);
  aspect-ratio: 1 / 1;
  display: block;
  object-fit: contain;
}

/* ==========================================================================
   PREFERS-REDUCED-MOTION
   Globalna, standardowa reguła — obejmuje automatycznie WSZYSTKIE animacje
   i przejścia na stronie: powyższe .fx-*, istniejący .view fade-in, oraz
   klasy Tailwindowe już używane w index.html (animate-spin przy ładowaniu,
   animate-ping przy pulsującej kropce w stopce). Zgodne z VISUAL_DIRECTION.md
   sekcja 7.4.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
