/*!
 * SPDX-FileCopyrightText: © 2026 Amitiel Angelisme <armitiel@gmail.com>
 * SPDX-License-Identifier: LicenseRef-EwolucJA-Proprietary
 *
 * EwolucJA — gra edukacyjna dla dzieci.
 * Produkt powstał w ramach projektu Stowarzyszenia na Rzecz Edukacji „Pomost”;
 * autorskie prawa majątkowe pozostają przy autorze. Licencja: LICENSE.
 */
/* Tokeny --hud-* mieszkaja w ../tokeny.css (jedno zrodlo dla calej gry),
   linkowanym PRZED tym plikiem w index.html i w scena-3d/index.html.
   Zasady: docs/SYSTEM_STYLOW.md. */

.scena3d-hint,
.scena3d-runmode,
.scena3d-stickhint,
.scena3d-controls { display: none !important; }

.game-hud {
  position: fixed;
  inset: 0;
  z-index: 20;
  pointer-events: none;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  box-sizing: border-box;
  padding: calc(10px + env(safe-area-inset-top, 0px)) 10px calc(12px + env(safe-area-inset-bottom, 0px));
  font-family: "Arial Rounded MT Bold", "Trebuchet MS", system-ui, sans-serif;
  color: var(--hud-ink);
}

.game-hud a,
.game-hud button { pointer-events: auto; -webkit-tap-highlight-color: transparent; }

.game-hud-top { display: flex; align-items: flex-start; gap: 7px; }

.game-hud-profile,
.game-hud-counter {
  display: inline-flex;
  align-items: center;
  box-sizing: border-box;
  min-height: 43px;
  border: 2px solid transparent;
  border-radius: 999px;
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--krem-50) 97%, transparent), color-mix(in srgb, var(--hud-cream-bottom) 97%, transparent)) padding-box,
    linear-gradient(180deg, var(--hud-gold-light), var(--hud-gold) 58%, var(--hud-gold-deep)) border-box;
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, .82), 0 3px 0 var(--cien-twardy), 0 7px 13px color-mix(in srgb, var(--braz-900) 24%, transparent);
  /* ROLA, nie prymityw: wewnatrz .game-hud --tekst to --hud-ink (motyw w tokeny.css).
     Ta sama regula w hubie dalaby --p-ink. Pierwszy konsument warstwy rol (9.09). */
  color: var(--tekst);
  text-decoration: none;
}

.game-hud-profile {
  min-height: 50px;
  max-width: 45vw;
  padding: 2px 15px 2px 2px;
  gap: 7px;
  font-size: 15px;
  font-weight: 900;
  letter-spacing: .1px;
  white-space: nowrap;
}

.game-hud-profile img {
  width: 58px;
  height: 58px;
  flex: none;
  object-fit: contain;
  margin: -6px 0 -6px -3px;
  filter: drop-shadow(0 2px 1px color-mix(in srgb, var(--braz-800) 27%, transparent));
}

.game-hud-profile span {
  overflow: hidden;
  text-overflow: ellipsis;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .9);
}

.game-hud-resources { margin-left: auto; display: flex; align-items: center; gap: 7px; }

.game-hud-counter {
  min-width: 56px;
  padding: 2px 9px 2px 2px;
  gap: 2px;
  font-size: 15px;
  font-weight: 900;
}

.game-hud-counter img {
  width: 34px;
  height: 34px;
  object-fit: contain;
  margin: -1px 0 -1px -2px;
  filter: drop-shadow(0 2px 1px color-mix(in srgb, var(--braz-800) 30%, transparent));
}

.game-hud-counter--spark {
  min-height: 43px;
  padding-left: 0;
}

.game-hud-counter--spark img {
  width: 43px;
  height: 43px;
  margin: -5px 0 -5px -4px;
}

.game-hud-counter strong { min-width: 13px; text-align: center; text-shadow: 0 1px 0 rgba(255, 255, 255, .92); }

.game-hud-map {
  width: 48px;
  height: 48px;
  flex: none;
  display: grid;
  place-items: center;
  box-sizing: border-box;
  padding: 7px;
  border: 2px solid transparent;
  border-radius: 50%;
  background:
    radial-gradient(circle at 42% 30%, #3e6b89 0%, #244d70 52%, #183653 100%) padding-box,
    linear-gradient(180deg, var(--hud-gold-light), var(--zloto-450) 58%, var(--braz-500)) border-box;
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, .16), 0 4px 0 var(--braz-600), 0 8px 15px rgba(36,39,25,.3);
  color: var(--krem-300);
}

.game-hud-map svg {
  width: 26px;
  height: 26px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 2px 0 color-mix(in srgb, var(--noc-900) 58%, transparent));
}

.game-hud-bottom { display: grid; justify-items: center; gap: 8px; }

.game-hud-place {
  padding: 4px 14px;
  border: 1.5px solid transparent;
  border-radius: 999px;
  background:
    linear-gradient(180deg, rgba(62,117,110,.95), rgba(36,77,76,.96)) padding-box,
    linear-gradient(180deg, #ffe87c, #d58b27) border-box;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18), 0 2px 0 var(--braz-600), 0 5px 10px rgba(31, 42, 27, .2);
  color: var(--krem-200);
  font-size: 11px;
  font-weight: 900;
  line-height: 1;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  text-shadow: 0 1.5px 0 #253f3d;
}

.game-hud-dock {
  width: min(100%, 430px);
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  align-items: end;
  gap: 2px;
}

.game-hud-dock button {
  position: relative;
  min-width: 0;
  height: 73px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  transition: transform .16s ease;
}

.game-hud-dock button::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 1px;
  width: 68px;
  height: 68px;
  transform: translateX(-50%);
  box-sizing: border-box;
  border: 3px solid transparent;
  border-radius: 50%;
  background:
    linear-gradient(180deg, var(--hud-cream-top), var(--hud-cream-bottom)) padding-box,
    linear-gradient(180deg, var(--hud-gold-light), var(--hud-gold) 56%, var(--hud-gold-deep)) border-box;
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, .92), inset 0 -3px 0 color-mix(in srgb, var(--braz-300) 17%, transparent), 0 5px 0 var(--hud-shadow), 0 9px 14px color-mix(in srgb, var(--braz-900) 26%, transparent);
}

.game-hud-dock img {
  position: relative;
  z-index: 1;
  width: 60px;
  height: 60px;
  display: block;
  object-fit: contain;
  user-select: none;
  -webkit-user-drag: none;
  filter: drop-shadow(0 3px 1px color-mix(in srgb, var(--braz-800) 26%, transparent));
  transition: transform .16s ease, filter .16s ease;
}

/* Ikona zostaje pierwszym znakiem, ale dziecko nie musi zapamietywac, czy
   dymki to rozmowy, a koperta to listy z zadaniami. Krotki podpis siedzi
   wewnatrz kola i nie zwieksza wysokosci doku ani nie zabiera miejsca panelom. */
.game-hud-label {
  position: absolute;
  z-index: 4;
  left: 50%;
  /* -4 px zamiast -1: podpis siedzi o 3 px nizej, blizej dolnej krawedzi
     kola - inaczej wchodzil optycznie na ikone. */
  bottom: -4px;
  transform: translateX(-50%);
  min-width: 58px;
  padding: 3px 7px 2px;
  /* Obrys jest z RODZINY samej plakietki, nie kremowy. Kremowa obwodka
     powtarzala kolor zlotego kola pod spodem i podpis odrywal sie od tla,
     jakby byl osobna naklejka doklejona do ikony. Fiolet o dwa tony jasniejszy
     od gorki gradientu wystarczy, zeby pigulka miala krawedz, a nie ramke. */
  border: 2px solid #a582cc;
  border-radius: 999px;
  background: linear-gradient(180deg, #76569c, #503867);
  box-shadow: 0 2px 0 #35243d, 0 4px 7px rgba(53,36,61,.24);
  color: var(--krem-200);
  font-family: "Nunito", system-ui, sans-serif;
  /* +15% wzgledem 10 px - podpis ma sie czytac w biegu, jednym rzutem oka. */
  font-size: 11.5px;
  font-weight: 900;
  line-height: 1;
  white-space: nowrap;
  text-shadow: 0 1px 0 #35243d;
  pointer-events: none;
  /* Ten sam czas, co ruch przycisku (.16s) - kompensacja musi isc
     dokladnie z nim, inaczej podpis szarpnalby sie w polowie animacji. */
  transition: transform .16s ease;
}

/* PODPIS STOI W MIEJSCU - podnosi sie sama ikonka.
   Przycisk na wybranej zakladce jedzie do gory (translateY), a pigulka z nazwa
   jest jego dzieckiem, wiec jechala razem z nim. Zeby zostala przyklejona do
   belki, dostaje przesuniecie ODWROTNE o dokladnie tyle samo. Wartosci sa dwie,
   bo dok ma dwa tryby: na mapie unosi sie o 5 px, pod wysunieta szuflada o 4.
   `translateX(-50%)` musi byc powtorzone w kazdej deklaracji - transform nie
   sklada sie z regula bazowa, tylko ja nadpisuje.
   Przy wcisnieciu dochodzi jeszcze skala przycisku (.96 / .97), wiec podpis
   dostaje jej odwrotnosc - inaczej na moment kurczylby sie razem z klockiem. */
.game-hud-dock button:hover .game-hud-label,
.game-hud-dock button.is-active .game-hud-label {
  transform: translateX(-50%) translateY(5px);
}

.game-hud-dock button:active .game-hud-label {
  transform: translateX(-50%) translateY(1px) scale(1.0417);
}

.game-hud.is-shelf .game-hud-dock button:hover .game-hud-label,
.game-hud.is-shelf .game-hud-dock button.is-active .game-hud-label {
  transform: translateX(-50%) translateY(4px);
}

.game-hud.is-shelf .game-hud-dock button:active .game-hud-label {
  transform: translateX(-50%) translateY(1px) scale(1.0309);
}

/* Plakietka z liczba. DWA RAZY WIEKSZA niz byla (20 px -> 40 px): przy 20 px
   cyferka na telefonie znikala w ikonie i dziecko po prostu jej nie zauwazalo,
   a to jedyny sygnal "cos na Ciebie czeka" w calym HUD-zie.
   Skalowane jest wszystko naraz - kolko, obrys, cien i pismo - zeby przy
   podwojnym rozmiarze nie wyszla plaska naklejka. */
.game-hud-badge {
  position: absolute;
  z-index: 3;
  /* Wsuniete w glab ikony, a nie na jej krawedzi: przy 40 px plakietka
     ostatniej sekcji wystawala poza zlota polke doku i wygladala na urwana. */
  top: -2px;
  right: 7px;
  min-width: 40px;
  height: 40px;
  box-sizing: border-box;
  display: grid;
  place-items: center;
  padding: 0 9px;
  border: 3px solid var(--krem-100);
  border-radius: 999px;
  background: linear-gradient(180deg, #ff6a5e, #d53537);
  box-shadow: 0 3px 0 var(--czerwien-700), 0 6px 11px rgba(72, 25, 21, .28);
  color: var(--hud-cream-top);
  font-size: 22px;
  font-weight: 900;
  line-height: 1;
  text-shadow: 0 2px 0 var(--czerwien-700);
}

/* Cyferka LEKKO DO GORY wewnatrz kolka. Pismo wyswietlane jest z odstepem pod
   linia bazowa, wiec optycznie siedzi nizej niz srodek kolka; przy 40 px roznica
   jest juz widoczna golym okiem. Dwa piksele w gore ustawiaja ja na srodku. */
.game-hud-badge > span {
  display: block;
  transform: translateY(-2px);
}

/* Wariant KROPKA - bez liczby. Uzywamy go tam, gdzie liczba nic nie wnosi:
   "pojawila sie nowa minigra" to jedna wiadomosc, nie ilosc do odhaczenia.
   Zielona, bo to nie jest zaleglosc do nadrobienia (czerwone plakietki), tylko
   cos nowego do obejrzenia. */
.game-hud-badge.is-kropka {
  min-width: 20px;
  width: 20px;
  height: 20px;
  padding: 0;
  top: 1px;
  right: 8px;
  background: linear-gradient(180deg, #7ede76, #37a84a);
  box-shadow: 0 2px 0 #28753b, 0 4px 8px rgba(20, 66, 30, .28);
}

.game-hud-dock button:hover,
.game-hud-dock button.is-active { transform: translateY(-5px); }

/* Mrugniecie przycisku doku - swiat zapala je na ~3,5 s, gdy postac wlasnie
   powiedziala, DOKAD isc ("czeka w twoich Listach" -> mruga koperta).
   Podskok + rozblysk, 5 powtorzen i koniec: to wskazowka, nie alarm. */
.game-hud-dock button.is-miga img {
  animation: dock-mig .62s ease-in-out 5;
}
@keyframes dock-mig {
  0%, 100% { transform: translateY(0) scale(1); filter: drop-shadow(0 3px 1px color-mix(in srgb, var(--braz-800) 26%, transparent)); }
  50% {
    transform: translateY(-7px) scale(1.12);
    filter: drop-shadow(0 3px 1px color-mix(in srgb, var(--braz-800) 26%, transparent)) drop-shadow(0 0 13px rgba(255, 221, 85, .95)) brightness(1.22);
  }
}
@media (prefers-reduced-motion: reduce) {
  .game-hud-dock button.is-miga img { animation: none; filter: drop-shadow(0 0 13px rgba(255, 221, 85, .95)); }
}

/* WEJSCIE NOWEJ IKONY (30.09) - Minigry wskakuja do doku po pierwszej partii.
   Caly przycisk (z kremowym kolem pod spodem) wyrasta z zera ze sprezystym
   przeskokiem, a ikonka rozblyskuje zlotem. Raz, na montowaniu przycisku -
   potem swiat gasnie i ikona zostaje w swietle reflektora. */
.game-hud-dock button.is-wchodzi {
  animation: dock-wejscie .72s cubic-bezier(.3, 1.55, .5, 1) both;
}
.game-hud-dock button.is-wchodzi img {
  animation: dock-wejscie-blysk 1.1s ease-out .35s both;
}
/* SEKCJA WYLACZONA (30.09) - Minigry po koncu dnia: ikona zostaje w belce,
   ale szara i przygaszona, bez plakietki. Dotkniecie daje cichy podpis
   („Polana spi"), nie otwiera szuflady. */
.game-hud-dock button.is-wylaczony img {
  filter: grayscale(1) brightness(.78);
  opacity: .55;
}
.game-hud-dock button.is-wylaczony .game-hud-label { opacity: .55; }
.game-hud-dock button.is-wylaczony:hover img { transform: none; }

@keyframes dock-wejscie {
  0% { transform: translateY(18px) scale(0); opacity: 0; }
  55% { transform: translateY(-8px) scale(1.18); opacity: 1; }
  100% { transform: none; opacity: 1; }
}
@keyframes dock-wejscie-blysk {
  0%, 100% { filter: drop-shadow(0 3px 1px color-mix(in srgb, var(--braz-800) 26%, transparent)); }
  35% { filter: drop-shadow(0 3px 1px color-mix(in srgb, var(--braz-800) 26%, transparent)) drop-shadow(0 0 16px rgba(255, 221, 85, 1)) brightness(1.25); }
}
@media (prefers-reduced-motion: reduce) {
  .game-hud-dock button.is-wchodzi,
  .game-hud-dock button.is-wchodzi img { animation: none; }
}

/* SAMA IKONA JEDZIE JESZCZE WYZEJ niz przycisk. Podpis zostaje przyklejony
   do belki (patrz kompensacja przy `.game-hud-label`), wiec caly sygnal
   „ta zakladka jest wybrana" musi uniesc ikona. Na mapie skok jest mniejszy,
   bo ikona siedzi w zlotym kole i przy wiekszym z niego wychodzi. */
.game-hud-dock button:hover img,
.game-hud-dock button.is-active img { transform: translateY(-3px); }

.game-hud-dock button:hover::before,
.game-hud-dock button.is-active::before {
  background:
    linear-gradient(180deg, var(--krem-50), #ffe797) padding-box,
    linear-gradient(180deg, var(--krem-300), var(--hud-gold) 56%, var(--hud-gold-deep)) border-box;
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, .96), 0 5px 0 var(--hud-shadow), 0 0 18px rgba(255, 221, 85, .58), 0 10px 15px color-mix(in srgb, var(--braz-900) 28%, transparent);
}

.game-hud-dock button:active { transform: translateY(-1px) scale(.96); }

.game-hud-dock button:focus-visible,
.game-hud-profile:focus-visible,
.game-hud-map:focus-visible { outline: 3px solid var(--hud-gold-light); outline-offset: 3px; }

.game-hud-toast {
  position: fixed;
  left: 50%;
  bottom: calc(104px + env(safe-area-inset-bottom, 0px));
  z-index: 25;
  transform: translate(-50%, 8px);
  opacity: 0;
  pointer-events: none;
  /* Zwykly blok, NIE flex. Flexem ikona monety ustawiala sie obok calego
     dwulinijkowego napisu jak odznaka przyklejona do prawej krawedzi.
     W przeplywie tekstu plynie razem z ostatnim slowem - czyli tak, jak
     czyta sie zdanie „ZBIERZ 10 [moneta]". */
  padding: 11px 22px;
  /* Szerokosc ograniczona, zeby zdanie lamalo sie na dwie WYSRODKOWANE linijki
     zamiast ciagnac sie przez caly ekran. Bez tego `text-align` nic nie robi,
     bo pojedyncza linijka wypelnia kafelek co do piksela. */
  /* `width: max-content` ZDEJMUJE UKRYTY LIMIT POLOWY EKRANU (21.09). Pasek
     stoi na `left: 50%` bez `right` i bez `width`, a taki element `fixed`
     dopasowuje szerokosc do miejsca od `left` do prawej krawedzi — czyli do
     50vw. Na telefonie 390 px pasek mial 195 px i lamal kazde zdanie na 4-6
     linijek; `max-width` ponizej w ogole nie dochodzil do glosu. */
  width: max-content;
  max-width: min(86vw, 420px);
  box-sizing: border-box;
  border: 2px solid var(--zloto-450);
  border-radius: 999px;
  background: linear-gradient(180deg, #466f68, #244d4c);
  box-shadow: 0 3px 0 #6f3a12, 0 7px 13px rgba(38, 31, 18, .28);
  color: var(--krem-200);
  /* WIEKSZY NIZ RESZTA HUD-u (decyzja wlasciciela 2026-09-16): to jest
     jedyne zdanie, ktore tlumaczy dziecku, co ma teraz robic — ma sie czytac
     z odleglosci reki, a nie konkurowac rozmiarem z licznikami. */
  font-size: 15px;
  font-weight: 900;
  letter-spacing: .5px;
  line-height: 1.25;
  text-align: center;
  text-wrap: balance;
  text-transform: uppercase;
  text-shadow: 0 1px 0 #253f3d;
  transition: opacity .18s ease, transform .18s ease;
}

/* Ikona wchodzi W MIEJSCE slowa („ZBIERZ 10 [gwiazdka]"), wiec plynie
   w przeplywie tekstu, a nie stoi jako osobny guzik obok napisu.

   34 px, nie 24 (decyzja wlasciciela 19.09). Wczesniej rownala sie mniej
   wiecej wersalikowi — i przy trzech kreskach na renderze 3D (sloje kloda,
   fasetki kamieni) z odleglosci reki nie bylo widac, CO to jest. Pasek ma
   jedna ikone, wiec moze byc wyrazna; sprawdzone na 390 px i 330 px, gdzie
   40 px zaczynalo juz dociskac napis do zlotej obreczy. Powyzej tej wartosci
   trzeba by ruszyc `padding` paska, a nie sama ikone. */
.game-hud-toast-ikona {
  display: inline-block;
  width: 34px;
  height: 34px;
  /* SRODEK IKONY NA WYSOKOSCI WERSALIKOW (21.09). Ramka obrazka biegnie od
     24 px nad linia pisma do 10 px pod nia, wiec jej srodek lezy ok. 1,5 px
     nad srodkiem wersalika (11 px). Wczesniej (-0.46em) wisiala 2,5 px wyzej,
     dotykala zlotej obreczy, a tytul obok wygladal na zjechany w dol —
     stad zgloszenie „teksty mialy pojsc wyzej".

     IKONA NIE ROZPYCHA WIERSZA. CSS liczy wysokosc obrazka w wierszu po jego
     pudelku z marginesami: -10 z gory i -6 z dolu zostawiaja w wierszu 18 px
     (od 14 px nad linia pisma do 4 px pod nia) — mniej niz sam wiersz tytulu,
     wiec o polozeniu tekstu decyduje tylko padding. Obrazek rysuje sie dalej
     w pelnych 34 px, zachodzac na padding i na odstep do opisu. Do 21.09
     dolny margines wynosil -2 i ikona spychala opis o 2,5 px w dol — to byla
     czesc „za duzego odstepu miedzy liniami". Liczby sa sprzezone
     z paddingiem paskow z ikona (nizej, `:has`) — ruszasz jedno, mierzysz
     drugie. */
  vertical-align: -4px;
  margin-block: -10px -6px;
  /* MARGINES PO OBU STRONACH, nie tylko z lewej. Przy jednowierszowym
     „ZBIERZ 10 [moneta]" lewy odstep wystarczal, bo ikona konczyla zdanie.
     Odkad tytul bywa wlasnym wierszem nad drugim („GRA NA PAMIEC CZEKA
     [karta]"), sam lewy odstep przesuwal optyczny srodek tego wiersza
     w prawo wzgledem wiersza nizej — oba wysrodkowane tak samo, a wygladajace
     na przesuniete wzgledem siebie (zgloszone 20.09). */
  margin-inline: 4px;
  filter: drop-shadow(0 1px 1px rgba(37,63,61,.45));
}

/* Drugi wiersz toastu: GDZIE i CO Z TYM ZROBIC. Mniejszy, bez wersalikow
   i bez pogrubienia tytulu — ma sie czytac jako dopowiedzenie, nie jako
   drugie polecenie. Do 18.09.2026 ten tekst istnial wylacznie w `aria-label`. */
.game-hud-toast-opis {
  display: block;
  margin-top: 3px;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .2px;
  line-height: 1.3;
  text-transform: none;
  opacity: .88;
}

/* DWA WIERSZE: TRESC WYZEJ NIZ SRODEK (21.09, „teksty mialy pojsc wyzej").
   Mniej paddingu z gory, wiecej z dolu. Pod opisem sa ogonki (ę, ą, p, j),
   wiec liczac od linii pisma dol dostaje o 3-4 px wiecej niz gora — dopiero
   wtedy blok czyta sie jako wysrodkowany albo odrobine uniesiony.
   Zmierzone przy 390 px: wersaliki 12 px od gornej krawedzi pola (bylo 14),
   pod ogonkami opisu 13 px, pasek nizszy o 3 px. */
.game-hud-toast:has(.game-hud-toast-opis) { padding-top: 9px; padding-bottom: 12px; }

/* PASEK Z IKONA: WYZSZY WIERSZ TYTULU, ZA TO MNIEJSZY PADDING. Gdy tytul
   lamie sie na dwie linijki (telefony 320-360 px, dlugie zdania), ikona na
   koncu drugiej linijki siega 24 px nad jej linie pisma — przy zwyklych
   18,75 px miedzy wierszami wchodzila na litery pierwszej linijki (karta
   na „W GRĘ", puzel na „SZUKASZ"). 24 px miedzy liniami pisma daje jej
   miejsce. W jednej linijce wiersz rosnie o 5,25 px rowno z gory i z dolu,
   a padding (8,5 zamiast 11; 6 zamiast 9) i margines opisu (0,75 zamiast 3)
   oddaja dokladnie tyle — tekst i ikona stoja co do piksela tam, gdzie
   w pasku bez tej reguly. Bez `:has` (stare przegladarki) zostaje zwykly
   pasek: w jednej linijce bez zmian, przy zlamanym tytule ikona zachodzi. */
.game-hud-toast:has(.game-hud-toast-ikona) { line-height: 1.6; padding-top: 8.5px; padding-bottom: 8.5px; }
.game-hud-toast:has(.game-hud-toast-ikona):has(.game-hud-toast-opis) { padding-top: 6px; padding-bottom: 12px; }
.game-hud-toast:has(.game-hud-toast-ikona) .game-hud-toast-opis { margin-top: .75px; }

.game-hud-toast.is-visible { opacity: 1; transform: translate(-50%, 0); }

/* PASEK, KTORY PROWADZI (23.09). Pasek mowiacy o miejscu w UI („dotknij
   licznika puzelkow", „zajrzyj do Zadan") jest klikalny CALY — dziecko nie
   musi trafiac w maly guzik — a zielony krazek ze znakiem startu mowi, ze
   jest co dotknac. Reszta paskow zostaje bez zmian: `pointer-events: none`
   w bloku glownym pilnuje, zeby zwykle potwierdzenie nie lapalo dotyku mapy.

   TRZY KOLUMNY: IKONA | ZDANIE | GUZIK (wybor autora 23.09). Ikona wychodzi
   z linii tekstu na wlasne miejsce po lewej, wiec zdanie zostaje zdaniem,
   a oko idzie: co -> o co chodzi -> co zrobic. Uklada to `grid-template-areas`,
   a nie kolejnosc w HTML: `img` stoi w kodzie po tytule (tam jest jego miejsce
   w paskach BEZ akcji) i tylko tutaj przeskakuje na lewo. */
.game-hud-toast.ma-akcje {
  pointer-events: auto;
  cursor: pointer;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "ikona tytul cta" "ikona opis cta";
  align-items: center;
  column-gap: 11px;
  text-align: left;
  padding: 8px 10px 8px 14px;
}
.game-hud-toast.ma-akcje .game-hud-toast-tekst { grid-area: tytul; }
.game-hud-toast.ma-akcje .game-hud-toast-opis { grid-area: opis; margin-top: 2px; }
.game-hud-toast.ma-akcje .game-hud-toast-ikona { grid-area: ikona; margin: 0; width: 38px; height: 38px; }
.game-hud-toast.ma-akcje .game-hud-toast-cta { grid-area: cta; }
/* Pasek bez drugiego wiersza: jeden rzad, zeby tytul nie wisial u gory. */
.game-hud-toast.ma-akcje:not(:has(.game-hud-toast-opis)) { grid-template-areas: "ikona tytul cta"; }
.game-hud-toast.ma-akcje:active { transform: translate(-50%, 1px) scale(.985); }

/* GUZIK: KRAZEK ZE ZNAKIEM STARTU, BEZ SLOWA (wybor autora 23.09). Slowo
   wraca do czytnika ekranu przez `aria-label` — na ekranie zostaje sam znak,
   czytelny dla dziecka, ktore jeszcze nie czyta. 46 px to rozmiar palca. */
.game-hud-toast-cta {
  width: 46px;
  height: 46px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--cta-lico, linear-gradient(180deg, #8EE13D 8.6%, #41AB0A 53.1%, #248F05 85.3%));
  box-shadow: 0 3px 0 var(--cta-rant-barwa, #3C761F), 0 4px 8px rgba(38, 31, 18, .3);
  color: var(--cta-tekst, #F3EFC3);
  cursor: pointer;
}
/* Trojkat jest optycznie ciezszy po lewej, wiec krazek centruje sie na oko
   dopiero z 2 px w prawo. Rogi zaokraglone obrysem w tej samej barwie, co
   wypelnienie (`stroke-linejoin: round` w SVG) — „lekko", prosba autora. */
.game-hud-toast-cta svg { width: 26px; height: 26px; margin-left: 2px; }
.game-hud-toast-cta:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--cta-rant-barwa, #3C761F); }
.game-hud-toast-cta:focus-visible { outline: 3px solid var(--hud-gold-light); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
  .game-hud-toast.ma-akcje:active, .game-hud-toast-cta:active { transform: none; }
}

/* TELEFONY DOSTAJA PRAWIE CALA SZEROKOSC, nie mniejsza ikone (21.09: „na
   mobilnych daj wiecej szerokosci — za duzo linii tekstu"). 10 px od kazdej
   krawedzi ekranu i wezszy padding boczny. Zmierzone na prawdziwych zdaniach
   paska: przy 390 i 360 px kazdy tytul poza „Widze, ze nadal szukasz
   gwiazdek" miesci sie w jednej linijce, opis w jednej albo dwoch; przy
   320 px lamia sie jeszcze trzy dlugie tytuly. Zwezanie ikony NIE pomaga —
   za szeroki jest tekst, nie obrazek. Na tabletach i komputerach zostaje
   gorne ograniczenie 420 px z bloku glownego. */
@media (max-width: 480px) {
  .game-hud-toast { max-width: calc(100vw - 20px); padding-left: 16px; padding-right: 16px; }
}

/* Wariant A: niska wspólna półka. Ikony pozostają duże i wystają ponad jej
   górną krawędź, więc belka nie zabiera tak dużo mapy jak klasyczny dock. */
.game-hud.is-shelf .game-hud-bottom {
  gap: 8px;
  margin-bottom: 0;
}

.game-hud.is-shelf .game-hud-dock {
  position: relative;
  width: min(100%, 458px);
  height: 72px;
  box-sizing: border-box;
  padding: 4px 9px 6px;
  border: 2.5px solid transparent;
  border-radius: 26px;
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--krem-50) 90%, transparent) 0%, color-mix(in srgb, var(--hud-cream-bottom) 86%, transparent) 100%) padding-box,
    linear-gradient(180deg, var(--hud-gold-light) 0%, var(--hud-gold) 56%, var(--hud-gold-deep) 100%) border-box;
  backdrop-filter: blur(5px) saturate(1.06);
  -webkit-backdrop-filter: blur(5px) saturate(1.06);
  box-shadow:
    inset 0 -2px 0 color-mix(in srgb, var(--braz-400) 12%, transparent),
    0 3px 0 color-mix(in srgb, var(--zloto-800) 88%, transparent),
    0 7px 12px color-mix(in srgb, var(--braz-900) 20%, transparent);
}

.game-hud.is-shelf .game-hud-dock button {
  height: 60px;
  align-self: center;
  transform: none;
}

.game-hud.is-shelf .game-hud-dock button::before { display: none; }

.game-hud.is-shelf .game-hud-dock img {
  width: 62px;
  height: 62px;
  filter:
    drop-shadow(0 3px 1px color-mix(in srgb, var(--braz-800) 30%, transparent))
    drop-shadow(0 0 1px color-mix(in srgb, var(--krem-300) 70%, transparent));
}

.game-hud.is-shelf .game-hud-dock button:hover,
.game-hud.is-shelf .game-hud-dock button.is-active {
  transform: translateY(-4px);
}

.game-hud.is-shelf .game-hud-dock button:hover img,
.game-hud.is-shelf .game-hud-dock button.is-active img {
  transform: translateY(-6px) scale(1.08);
  filter:
    drop-shadow(0 4px 1px color-mix(in srgb, var(--braz-800) 30%, transparent))
    drop-shadow(0 0 9px rgba(255,221,85,.9));
}

.game-hud.is-shelf .game-hud-dock button:active {
  transform: translateY(-1px) scale(.97);
}

.game-hud.is-shelf + .game-hud-toast {
  bottom: calc(142px + env(safe-area-inset-bottom, 0px));
}

/* Rozwijany zwój wiadomości. */
.message-scroll {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  place-items: center;
  box-sizing: border-box;
  padding: 18px 14px calc(96px + env(safe-area-inset-bottom, 0px));
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease, visibility 0s linear .3s;
  font-family: "Arial Rounded MT Bold", "Trebuchet MS", system-ui, sans-serif;
  color: #50351f;
}

.message-scroll.is-open {
  visibility: visible;
  opacity: 1;
  pointer-events: auto;
  transition: opacity .2s ease;
}

.message-scroll-backdrop {
  position: absolute;
  inset: 0;
  border: 0;
  background: rgba(24, 38, 30, .38);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  cursor: pointer;
}

.message-scroll-parchment {
  --message-scroll-height: 390px;
  position: relative;
  width: min(100%, 430px);
  height: 78px;
  transform: translateY(28px) scale(.96);
  transform-origin: center bottom;
  opacity: 0;
  transition:
    height 1.05s cubic-bezier(.33,0,.30,1),
    transform .34s cubic-bezier(.2,.84,.32,1.08),
    opacity .16s ease;
}

.message-scroll.is-open .message-scroll-parchment {
  /* Sufit 72dvh byl za niski: na telefonie 640 px zwoj konczyl sie na 460 px,
     a samo zadanie potrzebuje ponad 500 - CTA "OTWORZ" wchodzilo pod dolna
     rolke. 86dvh zostawia miejsce na dok i bezpieczna krawedz, a i tak nie
     pozwoli zwojowi wyjsc poza ekran. */
  height: min(var(--message-scroll-height), 86dvh, 640px);
  transform: translateY(0) scale(1);
  opacity: 1;
}

.message-scroll-parchment.is-resizing {
  transition:
    height .34s cubic-bezier(.22,.74,.24,1),
    transform .34s cubic-bezier(.2,.84,.32,1.08),
    opacity .16s ease;
}

.message-scroll-parchment::before {
  content: "";
  position: absolute;
  z-index: 0;
  inset: 8% -12%;
  border-radius: 50%;
  background: radial-gradient(ellipse, rgba(255,225,113,.36), color-mix(in srgb, var(--zloto-350) 12%, transparent) 48%, transparent 72%);
  filter: blur(14px);
  opacity: 0;
  transform: scale(.7);
  transition: opacity .7s ease .35s, transform .9s ease .25s;
}

.message-scroll.is-open .message-scroll-parchment::before {
  opacity: 1;
  transform: scale(1);
}

.message-scroll-paper {
  position: absolute;
  z-index: 1;
  left: 7.5%;
  right: 7.5%;
  top: clamp(29px, 8.4vw, 39px);
  bottom: clamp(29px, 8.4vw, 39px);
  overflow: hidden;
  background: url('/zwoj-papier.svg') center / 100% 100% no-repeat;
}

.message-scroll-content {
  position: absolute;
  /* Oddech gora/dol wiekszy niz na oko potrzeba: tresc konczy sie przy
     ZWINIETEJ krawedzi papieru, a rolka rzuca na nia cien - bez zapasu
     przycisk wyglada, jakby wchodzil pod rolke. Powiekszenie TYCH procentow
     wymaga powiekszenia zapasu w pomiarze zwoju (MessageScroll.jsx, +96)
     i sufitow wysokosci - inaczej tresc dostaje scroll zamiast miejsca. */
  inset: 11% 6% 10.5%;
  display: flex;
  flex-direction: column;
  justify-content: safe center;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
  opacity: 0;
  transform: translateY(-5px);
  pointer-events: none;
  transition: opacity .36s ease .68s, transform .36s ease .68s;
}

.message-scroll.is-open .message-scroll-content {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.message-scroll-content::-webkit-scrollbar { display: none; }

.message-scroll-rod {
  position: absolute;
  z-index: 3;
  left: 0;
  width: 100%;
  height: auto;
  display: block;
  pointer-events: none;
  user-select: none;
  filter: drop-shadow(0 5px 6px color-mix(in srgb, var(--ochra-800) 27%, transparent));
}

.message-scroll-rod--top { top: 0; }
.message-scroll-rod--bottom { bottom: 0; }

.message-scroll-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding-top: 8px;
  padding-bottom: 12px;
  border-bottom: 2px solid color-mix(in srgb, var(--braz-300) 20%, transparent);
}

.message-scroll-kicker {
  display: block;
  margin-bottom: 2px;
  color: var(--braz-400);
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 1.2px;
  text-transform: uppercase;
}

.message-scroll-header h2 {
  margin: 0;
  color: var(--krem-200);
  font-size: 30px;
  font-weight: 900;
  line-height: 1;
  letter-spacing: .3px;
  -webkit-text-stroke: 4px #4f3020;
  paint-order: stroke fill;
  text-shadow: 0 3px 0 var(--braz-400), 0 5px 8px rgba(73,42,20,.22);
}

.message-scroll-close {
  position: absolute;
  z-index: 5;
  top: -6px;
  right: -3px;
  width: 46px;
  height: 46px;
  flex: none;
  display: grid;
  place-items: center;
  padding: 0 0 4px;
  border: 2px solid var(--czerwien-700);
  border-radius: 50%;
  background: linear-gradient(180deg, #ff6a5e, #d53537);
  box-shadow: inset 0 2px 0 rgba(255,255,255,.35), 0 3px 0 var(--czerwien-700), 0 6px 9px color-mix(in srgb, var(--czerwien-900) 20%, transparent);
  color: var(--krem-100);
  font: 900 32px/1 system-ui, sans-serif;
  text-shadow: 0 2px 0 var(--czerwien-700);
  cursor: pointer;
  transform-origin: center;
  transition: transform .14s ease, box-shadow .14s ease, filter .14s ease;
}

.message-scroll-close:hover { filter: brightness(1.08); }

.message-scroll-close.is-pressed {
  animation: message-scroll-close-press .18s cubic-bezier(.2,.82,.3,1) both;
}

.message-scroll-note {
  margin: 13px 0;
  padding: 10px 12px;
  border: 1.5px solid rgba(190,126,39,.34);
  border-radius: 14px;
  background: color-mix(in srgb, var(--p-paper) 68%, transparent);
  color: #79553a;
  font-family: "Trebuchet MS", system-ui, sans-serif;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.4;
}

.message-scroll-list {
  display: grid;
  gap: 9px;
}

.scroll-message {
  overflow: hidden;
  border: 1.5px solid color-mix(in srgb, var(--braz-300) 28%, transparent);
  border-radius: 17px;
  background: color-mix(in srgb, var(--krem-50) 68%, transparent);
  box-shadow: 0 3px 8px rgba(83,51,20,.1);
}

.scroll-message.is-unread {
  border-color: rgba(213,139,39,.72);
  background: color-mix(in srgb, var(--krem-50) 94%, transparent);
}

.scroll-message-head {
  width: 100%;
  display: grid;
  grid-template-columns: 43px minmax(0,1fr) auto;
  align-items: center;
  gap: 9px;
  padding: 9px 10px;
  border: 0;
  background: transparent;
  color: #50351f;
  text-align: left;
  cursor: pointer;
}

.scroll-message-head:focus-visible {
  outline: 3px solid var(--zloto-500);
  outline-offset: -3px;
  border-radius: 15px;
}

.scroll-message-avatar {
  width: 43px;
  height: 43px;
  display: grid;
  place-items: center;
}

.scroll-message-avatar img {
  width: 48px;
  height: 48px;
  object-fit: contain;
  filter: drop-shadow(0 2px 1px color-mix(in srgb, var(--braz-700) 24%, transparent));
}

.scroll-message-copy { min-width: 0; }
.scroll-message-copy strong { display: block; font-size: 13px; line-height: 1.25; }
.scroll-message-copy small {
  display: -webkit-box;
  overflow: hidden;
  margin-top: 2px;
  color: #82644e;
  font-family: "Trebuchet MS", system-ui, sans-serif;
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1.32;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.scroll-message-meta {
  align-self: start;
  display: grid;
  justify-items: end;
  gap: 4px;
  color: #9a765b;
  font-size: 9px;
  font-weight: 800;
  white-space: nowrap;
}

.scroll-message-meta i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #e74343;
  box-shadow: 0 1px 0 #a6312d;
}

.scroll-message-body {
  padding: 0 14px 13px 62px;
  color: #694b35;
  font-family: "Trebuchet MS", system-ui, sans-serif;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.48;
  animation: scroll-message-open .22s ease both;
}

.scroll-message-body span {
  display: block;
  margin-bottom: 4px;
  color: var(--braz-400);
  font-size: 10px;
  font-weight: 900;
  letter-spacing: .7px;
  text-transform: uppercase;
}

.scroll-message-body p { margin: 0; }

@keyframes scroll-message-open {
  from { opacity: 0; transform: translateY(-5px); }
  to { opacity: 1; transform: translateY(0); }
}

/* --- Zadanie w realu: TRESC WPISANA W ZWOJ, a nie kartka na nim polozona --- */
/* Zwoj miesza dwie rzeczy: wiesci (przyszly, przeczytane, koniec) i ZADANIE,
   ktore trwa, dopoki go nie zrobisz. Wiesci zostaja kartami, bo jest ich wiele
   i lista ma sie dac przejrzec jednym rzutem oka.

   Zadanie jest JEDNO i po nie sie tu przychodzi, wiec przestalo byc kartka
   POLOZONA na pergaminie - jest tym, co na pergaminie NAPISANO: bez tla, bez
   ramki, bez cienia. Karta w karcie (papier zwoju + prostokat wpisu) czytala sie
   jak wydruk przypiety do zwoju, a nie jak wiadomosc od czarodzieja.

   Wyroznia je teraz sama tresc - wieksza ilustracja, wiekszy tytul, wieksze
   pismo - plus CIENKA KRESKA, ktora wsiaka w papier na obu koncach (fiolet
   Wizkora, ta sama barwa co plakietka). Kreska niczego nie zamyka, wiec oko
   bierze ja za podkreslenie w rekopisie, a nie za brzeg kartki. */
.scroll-message.is-quest {
  overflow: visible;
  margin: 2px 0 4px;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}

/* Nagłówek zadania odtwarza hierarchię mockupu: duży Wizkor po lewej, tytuł
   jako główny napis i status bezpośrednio pod nim. Cienki ornament oddziela
   nagłówek od polecenia, ale nie tworzy kolejnej „karty na zwoju". */
.scroll-message.is-quest .scroll-message-head {
  grid-template-columns: 104px minmax(0,1fr);
  grid-template-rows: auto auto;
  align-items: center;
  column-gap: 10px;
  row-gap: 8px;
  min-height: 112px;
  padding: 0 8px 15px 0;
  border-bottom: 0;
  box-shadow: none;
  background: linear-gradient(90deg,
      transparent,
      color-mix(in srgb, var(--braz-300) 48%, transparent) 14%,
      color-mix(in srgb, var(--braz-300) 48%, transparent) 45%,
      transparent 45%, transparent 55%,
      color-mix(in srgb, var(--braz-300) 48%, transparent) 55%,
      color-mix(in srgb, var(--braz-300) 48%, transparent) 86%,
      transparent) bottom left / 100% 1.5px no-repeat;
}
.scroll-message.is-quest .scroll-message-avatar {
  width: 104px;
  height: 104px;
  grid-column: 1;
  grid-row: 1 / span 2;
  align-self: center;
  overflow: hidden;
  border: 3px solid var(--braz-300);
  border-radius: 48% 48% 42% 42%;
  background: radial-gradient(circle at 50% 42%, #8f51c8 0 42%, #73349c 70%, #54286f 100%);
  box-shadow: inset 0 0 0 3px color-mix(in srgb, var(--krem-500) 58%, transparent), 0 4px 0 rgba(111,58,18,.34), 0 8px 14px color-mix(in srgb, var(--braz-800) 18%, transparent);
}
.scroll-message.is-quest .scroll-message-avatar img {
  width: 116px;
  height: 116px;
  object-fit: contain;
  transform: translate(-6px, 3px) scale(1.08);
}

/* Tytul zadania jest o klase wiekszy od tytulu wiesci i nie ma juz z czym
   dzielic wiersza - stad 18 px i pelna szerokosc drugiej kolumny. */
.scroll-message.is-quest .scroll-message-copy {
  grid-column: 2;
  grid-row: 1;
  align-self: end;
}
.scroll-message.is-quest .scroll-message-copy strong {
  color:var(--braz-800);
  font-size: 29px;
  line-height: 1.02;
  letter-spacing: .2px;
  text-shadow: 0 2px 0 color-mix(in srgb, var(--krem-100) 72%, transparent);
}

/* Plakietka w drugim wierszu, przy LEWEJ krawedzi tekstu (dziedziczone
   `justify-items: end` zepchneloby ja pod prawy brzeg, daleko od tytulu,
   ktory opisuje). */
.scroll-message.is-quest .scroll-message-meta {
  grid-column: 2;
  grid-row: 2;
  justify-items: start;
  align-self: start;
}

/* TRESC: JEDNO zdanie, duze. W zwoju stoi tylko cel zadania (patrz
   `MessageScroll`), wiec ten akapit nie konkuruje juz z niczym i moze wziac
   caly stopien, na jaki go stac.
   - 16 px zamiast pierwotnych 12.5: to czyta szesciolatek, a nie stopka
     regulaminu.
   - Wciecia boczne rowne zeru, tak jak w naglowku - tekst zaczyna sie w tej
     samej pionowej linii co ilustracja i lezy wprost na papierze. */
.scroll-message.is-quest .scroll-message-body {
  display:flex;
  flex-direction:column;
  align-items:center;
  padding: 18px 1px 0;
  font-size: 18px;
  line-height: 1.45;
  /* Ciemniej niz na karcie (#6b5233). Kartka miala tlo prawie biale, pergamin
     jest zloty (#f5cb7f-var(--p-sky-2)) - ten sam braz czytal sie na nim o polowe
     slabiej. Ta wartosc daje ~6:1 na najciemniejszym miejscu papieru. */
  color: #5e4123;
}

/* Uwaga Mentora ("prosze poprawic") tez schodzi ciemniej i zostawia sobie
   pionowa kreske - to jedyny fragment zadania, ktory jest CUDZYM glosem. */
.scroll-message.is-quest .scroll-message-note {
  margin-top: 10px;
  border-left-color: color-mix(in srgb, var(--p-magic-dk) 42%, transparent);
  color: #5e4123;
  font-size: 13px;
}
.scroll-message.is-quest .scroll-message-body p {
  margin: 0;
  color: inherit;
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
}

/* Główne polecenie jest jedyną jasną płytą wewnątrz pergaminu. Obramowanie
   jest lekkie i ozdobne jak w mockupie; nie wraca efekt „karty na karcie",
   bo blok nie ma ciężkiego cienia ani osobnej belki nagłówka. */
.scroll-message-task-copy{
  width:100%;
  box-sizing:border-box;
  padding:18px 20px 15px;
  border:1.5px solid color-mix(in srgb, var(--braz-300) 44%, transparent);
  border-radius:20px;
  background:color-mix(in srgb, var(--krem-50) 42%, transparent);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.58);
  text-align:center;
}
.scroll-message.is-quest .scroll-message-task-copy > p:first-child{
  color:var(--braz-800);
  font-size:21px;
  font-weight:900;
  line-height:1.28;
}
.scroll-message.is-quest .scroll-message-whisper{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:12px;
  margin-top:10px;
  color:#92704a;
  font-size:16px;
  font-weight:900;
}
.scroll-message-whisper i{
  width:26px;
  height:1.5px;
  background:linear-gradient(90deg,transparent,#c6954d);
}
.scroll-message-whisper i:last-child{ transform:scaleX(-1); }

.scroll-message-reward{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:8px;
  min-width:118px;
  min-height:43px;
  box-sizing:border-box;
  margin-top:-1px;
  padding:5px 16px 6px 10px;
  border:2px solid #b8842c;
  border-radius:999px;
  background:linear-gradient(180deg,var(--krem-200),#f1d28d);
  box-shadow:inset 0 2px 0 rgba(255,255,255,.7),0 3px 0 color-mix(in srgb, var(--braz-550) 35%, transparent);
  color:var(--braz-700);
}
.scroll-message-reward img{ width:34px; height:34px; object-fit:contain; filter:drop-shadow(0 2px 1px color-mix(in srgb, var(--braz-700) 25%, transparent)); }
.scroll-message-reward strong{ font-size:24px; line-height:1; }

/* Koniec zadania, poczatek wiesci. Bez ramki akapit na golym papierze zlewalby
   sie z pierwsza kartka listy. Ta sama kreska co pod naglowkiem, bledsza, i tez
   znikajaca na koncach. Gdy zadanie jest jedynym wpisem - nie ma czego dzielic,
   wiec kreski nie ma. */
.scroll-message.is-quest:not(:last-child) {
  padding-bottom: 14px;
  background: linear-gradient(90deg,
      transparent,
      color-mix(in srgb, var(--p-magic-dk) 20%, transparent) 14%,
      color-mix(in srgb, var(--p-magic-dk) 20%, transparent) 86%,
      transparent) bottom left / 100% 1.5px no-repeat;
}

/* CTA odbija sie od tresci. Bez tego przycisk kleil sie do ostatniego wiersza
   i wygladal jak jego dalszy ciag, a nie jak decyzja.
   Margines POD przyciskiem, bo to on jest ostatnim elementem karty zadania:
   bez niego zielen konczyla sie tuz przy krawedzi pergaminu i dolnej rolce.
   Pomiar zwoju liczy wysokosc z scrollHeight listy, wiec ten margines
   powieksza tez sam pergamin - przycisk dostaje oddech, a nie scisk. */
/* WZORZEC ROZMIARU CTA: 56 px wysokosci, ~21 px liter, na cala szerokosc.
   Ten przycisk ("OTWORZ") jest miara dla wszystkich pozostalych - liczby
   siedza w zmiennych `--cta-*` w `ewolucja.css`, tu tylko po nie siegamy,
   zeby zwoj i reszta gry nie rozjechaly sie przy nastepnej zmianie. */
.scroll-message.is-quest .scroll-message-body .hub-btn {
  width: 100%;
  min-height:var(--cta-h,56px);
  margin-top: 12px;
  margin-bottom: 18px;
  font-size:var(--cta-fs,21px);
  letter-spacing:.5px;
}

/* Plakietka stanu ("Do zrobienia", "Nagroda czeka") zamiast daty. Kropka
   "jest co zrobic" siedzi W SRODKU: osobno, obok plakietki, byly to dwa
   znaczki mowiace dokladnie to samo. Obwodka robi jej kontrast na fiolecie -
   sam czerwony na fiolecie robi sie brudny. */
.scroll-message-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px 8px;
  border-radius: 999px;
  background: linear-gradient(180deg, #9a75da, #6b3fb4);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.28), 0 2px 0 rgba(67,34,111,.75);
  color: var(--krem-100);
  font-size: 12px;
  font-weight: 900;
  letter-spacing: .5px;
  text-transform: uppercase;
  white-space: nowrap;
}

.scroll-message-tag i {
  order:-1;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: #ff5b5b;
  box-shadow: 0 0 0 1.6px color-mix(in srgb, var(--krem-100) 75%, transparent);
}

@keyframes message-scroll-close-press {
  0% { transform: translateY(0) scale(1); }
  48% {
    transform: translateY(4px) scale(.86);
    box-shadow: inset 0 3px 4px rgba(111,24,24,.3), 0 1px 0 var(--czerwien-700), 0 2px 4px color-mix(in srgb, var(--czerwien-900) 18%, transparent);
  }
  100% { transform: translateY(0) scale(1); }
}

@media (max-width: 390px) {
  .game-hud { padding-left: 7px; padding-right: 7px; }
  .game-hud-top, .game-hud-resources { gap: 4px; }
  .game-hud-profile { max-width: 40vw; padding-right: 9px; font-size: 13px; }
  .game-hud-profile img { width: 53px; height: 53px; }
  .game-hud-counter { min-width: 51px; padding-right: 7px; }
  .game-hud-counter img { width: 31px; height: 31px; }
  .game-hud-counter--spark img { width: 39px; height: 39px; }
  .game-hud-map { width: 45px; height: 45px; }
  .game-hud-dock { gap: 0; }
  .game-hud-dock button::before { width: 64px; height: 64px; }
  .game-hud-dock img { width: 56px; height: 56px; }
  .game-hud.is-shelf .game-hud-bottom { margin-bottom: 0; }
  .game-hud.is-shelf .game-hud-dock {
    height: 69px;
    padding: 4px 4px 6px;
  }
  .game-hud.is-shelf .game-hud-dock img { width: 58px; height: 58px; }
  /* Waski ekran: plakietka schodzi o wlos w glab ikony, zeby nie wystawala
     poza dok. Rozmiaru NIE zmniejszamy - po to zostala powiekszona. */
  .game-hud-badge { top: 0; right: 3px; min-width: 36px; height: 36px; font-size: 20px; }
  .game-hud-badge.is-kropka { min-width: 18px; width: 18px; height: 18px; top: 2px; right: 6px; }
  .message-scroll { padding: 14px 8px calc(91px + env(safe-area-inset-bottom, 0px)); }
  .message-scroll-parchment { width: min(100%, 390px); }
  .message-scroll.is-open .message-scroll-parchment { height: min(var(--message-scroll-height), 86dvh, 640px); }
  .message-scroll-content { inset: 8% 5% 7%; }
  .message-scroll-header h2 { font-size: 27px; }
  .scroll-message-head { grid-template-columns: 40px minmax(0,1fr) auto; gap: 7px; padding: 8px; }
  .scroll-message-avatar { width: 40px; height: 40px; }
  .scroll-message-avatar img { width: 45px; height: 45px; }
  .scroll-message-body { padding-left: 55px; }
}

@media (max-width: 340px) {
  .game-hud-profile span { display: none; }
  .game-hud-profile { width: 47px; padding-right: 1px; }
  .game-hud-dock button::before { width: 58px; height: 58px; }
  .game-hud-dock img { width: 51px; height: 51px; }
  .game-hud-label { min-width: 52px; padding-inline: 5px; font-size: 10.5px; }
}


/* --- Oddech wokol ikon HUD (profil, iskry, monety) --- */
/* Dopisane na koncu pliku celowo: te same selektory sa wczesniej ustawiane
   kilkukrotnie, takze w @media, a przy rownej specyficznosci decyduje kolejnosc. */
.game-hud-profile {
  padding-left: 4px;
  padding-right: 16px;
  gap: 10px;
}

.game-hud-counter {
  min-width: 0;
  padding-left: 8px;
  padding-right: 13px;
  gap: 7px;
}

.game-hud-counter--spark {
  padding-left: 8px;
}

@media (max-width: 340px) {
  .game-hud-profile { padding-right: 10px; }
  .game-hud-counter { padding-left: 6px; padding-right: 10px; }
  .game-hud-counter--spark { padding-left: 6px; }
}


/* --- Iskra wieksza od monety --- */
/* Iskra to zasob fabularny (zdobywa sie ja rzadko), moneta - bilansowy.
   Roznica rozmiaru robi te hierarchie szybciej niz jakikolwiek podpis.
   Dopisane na koncu, bo wczesniej te same selektory ustawiane sa kilkukrotnie. */
.game-hud-counter--spark {
  min-width: 64px;
  padding-left: 0;
  padding-right: 15px;
}

.game-hud-counter--spark img {
  width: 52px;
  height: 52px;
  margin: -8px 0 -8px -5px;
}

@media (max-width: 340px) {
  .game-hud-counter--spark { min-width: 58px; padding-right: 11px; }
  .game-hud-counter--spark img { width: 46px; height: 46px; margin: -6px 0 -6px -4px; }
}


/* --- Oddech w gornym HUD: kafelki nie moga sciskac ikon --- */
/* Ikony maja ujemne marginesy (wystaja poza kafelek), wiec padding musi byc
   liczony od krawedzi kafelka, nie od obrazka. Stad asymetria: z lewej malo,
   z prawej duzo - po prawej stoi liczba i to ona potrzebuje powietrza. */
.game-hud-resources { gap: 10px; }

.game-hud-profile {
  padding: 2px 20px 2px 4px;
  gap: 12px;
}

.game-hud-counter {
  min-width: 70px;
  padding: 3px 18px 3px 4px;
  gap: 9px;
}

.game-hud-counter--spark {
  min-width: 80px;
  padding-left: 2px;
  padding-right: 20px;
}

@media (max-width: 340px) {
  .game-hud-resources { gap: 7px; }
  .game-hud-profile { padding: 2px 13px 2px 3px; gap: 8px; }
  .game-hud-counter { min-width: 62px; padding: 3px 13px 3px 3px; gap: 7px; }
  .game-hud-counter--spark { min-width: 70px; padding-left: 1px; padding-right: 14px; }
}

/* --- Przycisk muzyki --- */
/* Siedzi w gornym pasku, nie w dolnej belce: dolna belka to MIEJSCA (dokad ide),
   a muzyka to USTAWIENIE (jak ma brzmiec) - mieszanie ich uczy dziecko, ze
   ikonki na dole robia rozne rodzaje rzeczy. Ksztaltem trzyma sie rodziny
   .game-hud-map, zeby oba okragle przyciski czytaly sie jako jedna grupa. */
.game-hud-music {
  width: 52px;
  height: 52px;
  flex: none;
  display: grid;
  place-items: center;
  box-sizing: border-box;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 50%;
  background:
    radial-gradient(circle at 42% 30%, var(--krem-50) 0%, var(--hud-cream-bottom) 58%, #e3c274 100%) padding-box,
    linear-gradient(180deg, var(--hud-gold-light), var(--hud-gold) 58%, var(--hud-gold-deep)) border-box;
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, .82), 0 3px 0 var(--hud-shadow), 0 7px 13px color-mix(in srgb, var(--braz-900) 24%, transparent);
  cursor: pointer;
  transition: transform .16s ease, filter .16s ease;
}

.game-hud-music img {
  width: 44px;
  height: 44px;
  object-fit: contain;
  user-select: none;
  -webkit-user-drag: none;
  filter: drop-shadow(0 2px 1px color-mix(in srgb, var(--braz-800) 27%, transparent));
  transition: filter .16s ease, opacity .16s ease;
}

.game-hud-music:active { transform: translateY(2px); }
.game-hud-music:focus-visible { outline: 3px solid var(--hud-gold-light); outline-offset: 3px; }

/* Wyciszone: ikona traci kolor i sile, ale przycisk zostaje tak samo duzy -
   dziecko ma trafic w to samo miejsce, zeby wlaczyc muzyke z powrotem. */
.game-hud-music.is-off img { filter: grayscale(1) opacity(.55); }

.game-hud-music.is-off::after {
  content: "";
  position: absolute;
  width: 40px;
  height: 3px;
  border-radius: 2px;
  background: var(--braz-500);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .6);
  transform: rotate(-38deg);
}

.game-hud-music { position: relative; }

@media (max-width: 340px) {
  .game-hud-music { width: 46px; height: 46px; }
  .game-hud-music img { width: 39px; height: 39px; }
  .game-hud-music.is-off::after { width: 35px; }
}


/* --- Awatar gracza bez kafelka --- */
/* Imie znika, zostaje sama postac. Powod: imie dziecko zna, a zloty kafelek
   robil z awatara kolejny "przycisk zasobu" - tego samego rodzaju co monety
   i iskry. Bez tla awatar czyta sie jako TY, a nie jako licznik.
   Nadpisujemy wspolna regule .game-hud-profile, .game-hud-counter z gory pliku. */
.game-hud-profile {
  min-height: 0;
  max-width: none;
  padding: 0;
  gap: 0;
  border: 0;
  background: none;
  box-shadow: none;
}

.game-hud-profile span { display: none; }

.game-hud-profile img {
  width: 66px;
  height: 66px;
  margin: -4px 0 -4px -2px;
  /* Mocniejszy cien niz w kafelku - bez zlotej obwodki awatar musi sam
     odkleic sie od sceny, ktora bywa jasna. */
  filter: drop-shadow(0 3px 2px color-mix(in srgb, var(--ochra-900) 42%, transparent)) drop-shadow(0 1px 0 rgba(255, 255, 255, .35));
}

@media (max-width: 340px) {
  .game-hud-profile { padding: 0; gap: 0; }
  .game-hud-profile img { width: 58px; height: 58px; }
}


/* --- Muzyka: ten sam format co ikony obok --- */
/* Nutka wypelniala kolko po brzegi, wiec przy monecie (34 px w kafelku 43 px)
   czytala sie jako inny, wiekszy element. Zrownujemy: sama ikona ma rozmiar
   monety, a kolko dostaje taki sam pierscien powietrza jak kafelki. */
.game-hud-music {
  width: 48px;
  height: 48px;
}

.game-hud-music img {
  width: 32px;
  height: 32px;
}

.game-hud-music.is-off::after { width: 27px; }

@media (max-width: 340px) {
  .game-hud-music { width: 43px; height: 43px; }
  .game-hud-music img { width: 29px; height: 29px; }
  .game-hud-music.is-off::after { width: 24px; }
}


/* --- Monety: sama liczba, bez paska celu --- */
/* Do 01.10 licznik mial pod spodem pasek do celu 100 monet. W fazie
   turniejowej cel przestal cokolwiek znaczyc: sam lancuch Wizkora daje
   w dzien ~165 monet, z powtorkami gier 300+, wiec pasek stal pelny przez
   wieksza czesc sesji i tylko powtarzal liczbe ksztaltem. Decyzja
   wlasciciela 01.10: zostaje moneta i liczba (bez sufitu).
   Iskra trzyma wysokosc, ktora miala obok dawnego kafelka z paskiem, zeby
   gorny pasek nie zmienil rytmu. */
.game-hud-counter--spark { min-height: 54px; }

@media (max-width: 340px) {
  .game-hud-counter--spark { min-height: 48px; }
}


/* --- Monety: moneta i liczba w jednej linii --- */
/* Kafelek trzyma wysokosc przycisku muzyki (48 px), padding i odstep bierze
   z reguly bazowej `.game-hud-counter` — tak samo jak gwiazdki czy baloniki.
   Szerokosc rosnie z liczba (min-width z bazy), wiec trzy cyfry mieszcza sie
   bez obcinania. */
.game-hud-counter--coins { min-height: 48px; }

@media (max-width: 340px) {
  .game-hud-counter--coins { min-height: 43px; }
}


/* --- Wpisy zwoju: reszta drobiazgow --- */
/* Stara oprawa zadania (zlota lewa krawedz + zolte tlo) zniknela stad razem
   z kartka: zadanie jest teraz WPISANE w pergamin, a caly jego wyglad stoi
   wyzej, przy .scroll-message.is-quest. Dwie definicje tego samego wpisu
   w jednym pliku znaczyly tylko tyle, ze wygrywala ta nizsza. */
.scroll-message-how {
  margin: 6px 0 0;
  color: #6f5540;
  font-size: 12px;
  line-height: 1.45;
}

.scroll-message-note {
  margin: 6px 0 0;
  padding-left: 9px;
  border-left: 2px solid rgba(184,132,44,.5);
  color: #79553a;
  font-size: 12px;
  font-style: italic;
  line-height: 1.45;
}


/* --- MONETA-ODSTEPY: moneta blizej liczby, dalej od krawedzi kafelka --- */
/* Ikona ma ujemny margines z lewej (celowo wystaje poza zloty kant), przez co
   dotykala krawedzi tla, a jednoczesnie wspolny `gap` odsuwal od niej liczbe.
   Wygladalo to, jakby moneta i "0" nalezaly do dwoch roznych kafelkow.
   Padding odsuwa ja od krawedzi, a ujemny margines z PRAWEJ przyciaga liczbe -
   `gap` zostaje nietkniety (wspolny z pozostalymi licznikami). */
.game-hud-counter--coins { padding-left: 10px; }
.game-hud-counter--coins img { margin-left: 0; margin-right: -6px; }

/* Nutka byla na 44 px w krazku 52 px - zlota obwodka schowala sie pod ikona.
   Odstep robi teraz PADDING przycisku, a nie wpisany rozmiar obrazka: ikona
   dostaje 100% tego, co zostanie w srodku, wiec zmiana wielkosci krazka nigdy
   nie zjedzie oddechu do zera. 11 px paddingu przy krazku 52 px i obwodce 2 px
   daje nutke ~26 px z rownym marginesem dookola. */
.game-hud-music { padding: 11px; }
.game-hud-music img {
  width: 100%;
  height: 100%;
  /* Geometrycznie nutka stoi w srodku, ale OPTYCZNIE ucieka w prawo i w dol:
     ciezar ksztaltu siedzi w dwoch dolnych glowkach, a choragiewka u gory jest
     lekka i cienka. Przesuniecie w procentach, nie w px, zeby trzymalo sie
     rowniez na wezszym ekranie, gdzie ikona jest mniejsza. */
  transform: translate(-4%, -4%);
}
.game-hud-music.is-off::after { width: 26px; }

@media (max-width: 340px) {
  .game-hud-counter--coins { padding-left: 8px; }
  .game-hud-counter--coins img { margin-right: -5px; }
  .game-hud-music { padding: 9px; }
  .game-hud-music.is-off::after { width: 22px; }
}


/* --- ROWNA-GORA: wszystkie ikony gornego paska zaczynaja sie na tej samej wysokosci --- */
/* Awatar mial `margin: -4px 0 -4px -2px` z czasow, gdy siedzial w zlotym kafelku
   i mial z niego celowo wystawac. Kafelka juz nie ma, a ujemny margines zostal -
   przez to awatar zaczynal sie 6 px od krawedzi ekranu, a moneta i nutka 10 px.
   Same pudelka flexa byly rowne, rozjezdzal sie dopiero obrazek w srodku, wiec
   w inspektorze wygladalo to na porzadek. Zerujemy margines: gora, dol i lewa
   krawedz awatara zgadzaja sie teraz z reszta paska i z dokiem na dole. */
.game-hud-profile img { margin: 0; }

/* --- Podklad pod dokiem (tylko pod wysunieta szuflada) --- */
/* Dok zostaje NAD panelem, gdy szuflada jest wysunieta (przejscie z minigier
   do czatu ma byc jednym dotknieciem, a nie "zamknij, otworz"). Kosztem jest
   to, ze ikony leza wtedy na tresci - na wpisach czatu, na polu tekstowym.
   Tam rozjasniacz jest potrzebny i zostaje: regula `.ma-szuflade` nizej.

   NA SAMEJ MAPIE GO NIE MA (decyzja wlasciciela 2026-09-15). Wczesniej byl
   staly, zeby dok mial jedna, przewidywalna podstawe niezaleznie od tego, co
   pod nim akurat jest. Tyle, ze nad zielona scena 3D czytalo sie to jako
   jasny pas przyklejony do dolu ekranu - bardziej bylo widac rozjasniacz niz
   problem, ktory mial rozwiazywac. Trawa i woda sa na tyle jednolite, ze
   ikony ze swoim wlasnym rantem i cieniem bronia sie na nich same.

   GDYBY MIAL WROCIC: sa dokladnie dwa miejsca - `display: none` ponizej
   i `display: block` w regule `.ma-szuflade`. Sam gradient zostaje nietkniety,
   wiec powrot to zmiana jednej wartosci, nie pisanie go od nowa.
   Bez z-index: ::before rysuje sie przed pozycjonowanymi dziecmi doka,
   wiec same ikony zostaja ostre na wierzchu. */
.game-hud-bottom { position: relative; }

.game-hud-bottom::before {
  content: "";
  /* Wylaczony na mapie - wlacza go dopiero `.ma-szuflade` (patrz komentarz
     nad ta sekcja). Reszta regul zostaje, zeby stan z szuflada mial z czego
     dziedziczyc geometrie. */
  display: none;
  position: absolute;
  left: -12vw; right: -12vw;
  /* Na samej mapie rozjasniacz jest niski i nie dochodzi do pelnego krycia:
     ma podlozyc sie pod ikony, a nie zabielac dolu sceny. Pod szuflada
     (nizej) siega wyzej i kryje mocniej, bo tam konkuruje z trescia. */
  top: -58px; bottom: -56px;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(251,241,214,0) 0%,
    color-mix(in srgb, var(--p-paper) 22%, transparent) 34%,
    color-mix(in srgb, var(--krem-50) 50%, transparent) 62%,
    color-mix(in srgb, var(--krem-100) 72%, transparent) 86%,
    color-mix(in srgb, var(--krem-100) 80%, transparent) 100%
  );
}

/* --- Mocniejszy podklad, gdy szuflada jest wysunieta --- */
/* Pod otwartym arkuszem ikony leza na gestej tresci: wpisy czatu, pole
   tekstowe, przyciski wyboru. Podklad musi tam dochodzic do pelnego krycia
   szybciej niz na samej mapie.
   Nie dotyczy zwoju wiadomosci - komponent nie dodaje wtedy tej klasy,
   bo pergamin sam przykrywa ekran i drugie tlo pod dokiem tylko by z nim
   konkurowalo. */
/* ILE MA SIEGAC W GORE - policzone, nie zgadniete (2026-08-20).
   Bylo `top: -118px`, czyli podklad zaczynal sie 118 px NAD dokiem i juz
   40 px wyzej mial ~0,5 krycia. Tyle, ze tresc otwartej szuflady i tak nigdy
   tam nie dochodzi: cialo arkusza ma na dole 110-156 px paddingu, wiec
   ostatni element konczy sie NAD gorna krawedzia doku. Jedyne, co te 118 px
   naprawde przykrywalo, to pasek pisania czatu (mierzone na 375x812: pole
   leżało pod 53-86% kremowej mgly i wygladalo na wylaczone) oraz zielony
   "Wyslij do Mentora" w panelu zadania - stad 88 px pustego pergaminu, ktorym
   oba te elementy obchodzilo sie w `hub.css`.
   Teraz podklad zaczyna sie 17 px nad dokiem i dochodzi do pelnego krycia
   w tych 17 px. Tresc przewijana POD dok dalej ma czym sie wygaszac: nizej
   dokłada sie `.hub-sheet::after` (74 px kremowego gradientu przy dolnej
   krawedzi arkusza). Zmieniajac te liczbe sprawdz, czy nie wchodzi na pasek
   pisania czatu - to jedyny element, ktory stoi tuz nad dokiem. */
.game-hud.ma-szuflade .game-hud-bottom::before {
  display: block;
  top: -22px;
  left: -16vw; right: -16vw;
  background: linear-gradient(
    180deg,
    rgba(251,241,214,0) 0%,
    color-mix(in srgb, var(--p-paper) 40%, transparent) 7%,
    color-mix(in srgb, var(--krem-50) 78%, transparent) 12%,
    color-mix(in srgb, var(--krem-100) 95%, transparent) 16%,
    var(--krem-100) 24%
  );
}

/* --- Szuflada, ktora sama trzyma tresc nad dokiem (czat) --- */
/* Rozjasniacz w gore chroni ikony przed trescia PRZEWIJANA pod dok. W czacie
   nic sie tam nie przewija: pasek pisania jest przyklejony do dolu arkusza
   i przycina strumien, a lista rozmow i ekran Mentora koncza sie na tej samej
   krawedzi. Za dokiem jest wtedy sam pergamin arkusza (plus `.hub-sheet::after`,
   74 px kremowego wygaszenia przy jego dolnej krawedzi) — czyli dokladnie to,
   po co rozjasniacz istnieje, tylko za darmo.
   Zdjecie go pozwala podciagnac pasek pisania blisko ikon; wczesniej musial
   konczyc sie nad mgla i zostawialo to 37 px pustego pergaminu. Klasa idzie
   ze `Swiat.jsx` (`szufladaPelna`) i jest sprzezona z `wypelnia` na arkuszu —
   jesli kiedys inny panel dostanie `wypelnia`, ma dostac takze ta klase. */
.game-hud.ma-szuflade-pelna .game-hud-bottom::before { display: none; }


/* --- JOYSTICK-SUBTELNIE: na dotyku joystick ma byc podpowiedzia, nie elementem sceny --- */
/* Style joysticka siedza w bundlu `scena3d.js` i wstrzykuja sie do <head> PO tym
   arkuszu, wiec zwykle nadpisanie by przegralo kolejnoscia. Stad podwojona klasa
   (`.scena3d-stick.scena3d-stick`) - ta sama regula, wyzsza specyficznosc, wiec
   wygrywa niezaleznie od kolejnosci i przezyje przebudowe bundla.
   Warunek to `pointer: coarse`, a nie szerokosc ekranu: joystick istnieje dla
   palca, a nie dla waskiego okna - na myszy sterowanie idzie strzalkami. */
@media (pointer: coarse) {
  .scena3d-stick.scena3d-stick.on { opacity: .5; }

  /* Bieg musi zostac czytelny - to jedyna informacja zwrotna, ze dziecko
     trzyma palec dluzej. Ciszej niz bylo, ale wyrazniej niz chod. */
  .scena3d-stick.scena3d-stick.run.on { opacity: .72; }

  .scena3d-stick.scena3d-stick {
    background: radial-gradient(circle, color-mix(in srgb, var(--krem-50) 10%, transparent), color-mix(in srgb, var(--krem-50) 3%, transparent) 60%, transparent 70%);
    box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--krem-50) 28%, transparent);
  }

  .scena3d-stick.scena3d-stick.run {
    box-shadow: inset 0 0 0 2.5px color-mix(in srgb, var(--zloto-250) 60%, transparent), 0 0 16px color-mix(in srgb, var(--zloto-250) 22%, transparent);
  }

  .scena3d-stick.scena3d-stick .scena3d-knob {
    box-shadow: 0 3px 9px rgba(0, 0, 0, .3), inset 0 0 0 1.5px rgba(255, 255, 255, .35);
  }
}


/* --- Licznik zadania: gwiazdki dla czarodzieja --- */
/* Ten sam kafelek co moneta (zlota obwodka, kremowe tlo), zeby czytal sie jako
   ta sama rodzina; przy dziesieciu sztukach "3/10" mowi wiecej niz kreska
   w jednej trzeciej (licznik monet tez jest dzis sama liczba — bez paska).
   Wchodzi na ekran dopiero po przyjeciu zadania - stad brak stanu "pustego". */
.game-hud-counter--gwiazdki,
.game-hud-counter--misja,
.game-hud-counter--baloniki {
  min-width: 0;
  padding: 3px 13px 3px 4px;
  /* ZERO, nie 3 px. `gap` we flexie siedzi MIEDZY KAZDA para dzieci, wiec ta
     sama liczba rozsuwala ikonke od liczby I liczbe od "/16". Para liczb ma
     byc jednym napisem ("2/16", "16/16"), a odstep nalezy sie tylko ikonce -
     i ten dajemy jej osobno, marginesem nizej.
     Baloniki dopisane 01.10: bez wlasnej reguly brały `gap` z sekcji
     responsywnych (7-9 px), czyli dwa razy wiecej niz gwiazdki. */
  gap: 0;
  /* 15 px, NIE 16: wzorcem cyfr jest licznik monet (`--coins`), ktory bierze
     rozmiar z reguly bazowej `.game-hud-counter`. Szesnastka robila gwiazdki
     o pol kroku wieksze od monet i w jednym pasku widac bylo dwa rozmiary
     tej samej liczby. Rodzina i grubosc byly te same - rozjezdzal sie sam
     stopien. */
  font-size: 15px;
  font-weight: 900;
}

.game-hud-counter--gwiazdki img,
.game-hud-counter--misja img {
  width: 31px;
  height: 31px;
  flex: none;
  object-fit: contain;
  /* 31 px, nie 34: gwiazdka z gry (`/star.png`) jest pelna i ciezka optycznie,
     wiec przy rozmiarze monety zaczynala nad nia dominowac. Wczesniej stala tu
     `iskra.png` - czteroramienny klejnot z cienkimi ramionami, ktory dla
     rownowagi potrzebowal wiecej miejsca. */
  filter: drop-shadow(0 1.5px 1px color-mix(in srgb, var(--braz-800) 28%, transparent));
}

.game-hud-counter--gwiazdki strong,
.game-hud-counter--misja strong,
.game-hud-counter--baloniki strong {
  text-shadow: 0 1px 0 rgba(255, 255, 255, .9);
  /* KONIEC REZERWACJI SZEROKOSCI. Regula bazowa daje `min-width: 13px` i
     wysrodkowanie, zeby kafelek nie drgal przy przejsciu 9 -> 10. Przy
     jednocyfrowej liczbie zostawialo to pustke PO PRAWEJ i czytalo sie
     "2  /16" zamiast "2/16" - a tu para liczb ma byc jednym napisem.
     Kafelek zmienia przez to szerokosc o kilka pikseli na dziesiatce; to
     mniejsza cena niz dziura w srodku napisu. */
  min-width: 0;
  text-align: right;
}

/* Odstep nalezy sie IKONCE, nie cyfrom — stad margines zamiast `gap`. */
.game-hud-counter--gwiazdki img,
.game-hud-counter--misja img,
.game-hud-counter--baloniki img { margin-right: 3px; }

/* MATERIAL NA SCHRONIENIE: dwie ikonki obok siebie, BEZ liczb. Do etapu trzeba
   dwoch konkretnych rzeczy, wiec ulamek "1/2" byl by o krok dalej od tego, co
   dziecko ma zrobic. Zgaszona ikonka = "jeszcze nie mam".
   Wyciszamy ja przezroczystoscia i odbarwieniem TEJ SAMEJ grafiki, a nie druga,
   szara wersja pliku - jeden asset na rzecz, zero rozjazdu miedzy stanami. */
.game-hud-counter--drewno {
  min-width: 0;
  padding: 3px 11px 3px 6px;
  gap: 5px;
}

.game-hud-counter--drewno img {
  width: 29px;
  height: 29px;
  flex: none;
  object-fit: contain;
  opacity: .32;
  filter: grayscale(.85);
  transition: opacity .28s ease, filter .28s ease;
}

.game-hud-counter--drewno img.jest {
  opacity: 1;
  filter: drop-shadow(0 1.5px 1px color-mix(in srgb, var(--braz-800) 28%, transparent));
}

/* DRZEWKO ZAMIAST ZGASZONEJ KLODY (decyzja wlasciciela 1.10). Pusty slot mowi
   teraz, CO jest do zrobienia — "to jeszcze stoi w lesie" — a nie tylko "tego
   nie masz". Skoro znaczenie niesie sam KSZTALT, wygaszenie moze byc lzejsze:
   przy opacity .32 i szarosci .85 drzewko czytalo sie jak cel ZABLOKOWANY,
   a ono jest dokladnie odwrotnoscia — jest zaproszeniem. Zostaje tyle
   przygaszenia, zeby zdobyty stos nadal wygrywal pierwszenstwo na pasku.
   Drzewko jest wyzsze niz szersze, wiec przy `object-fit: contain` w kwadracie
   29 px wychodzi optycznie mniejsze od stosu — stad 2 px wiecej. */
.game-hud-counter--drewno img[data-rzecz="drzewko"] {
  width: 31px;
  height: 31px;
  opacity: .66;
  filter: grayscale(.28) saturate(.9);
}

.game-hud-znak {
  position: relative;
  display: inline-flex;
  flex: none;
}

/* PTASZEK KOŃCA CZYNNOSCI. Siedzi w rogu ikonki, a nie obok niej: obok
   rozpychalby licznik i przy dwoch celach pasek urosl by o polowe. */
.game-hud-znak b {
  position: absolute;
  right: -4px;
  bottom: -3px;
  display: grid;
  place-items: center;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 1.5px solid var(--krem-50);
  /* SCIETE, CZYLI DO DONIESIENIA — fiolet z rampy magii (`--p-magic`).
     Do 1.10 stalo tu zielone, a pomaranczowe znaczylo "na placu" — czyli
     ZIELONY, kolor konca, siedzial na robocie jeszcze niedokonczonej.
     Teraz jest odwrotnie (patrz `.jest-na-placu` nizej), a stan posredni
     dostaje barwe, ktora z zielonym nie konkuruje: ani cieple "zrob to teraz"
     (to rola pomaranczu placu i pierscienia pracy), ani zielone "gotowe".
     Chlodna i spokojna — "czeka na kurs". */
  background: linear-gradient(180deg, #B886E8, #7A4DC2);
  box-shadow: 0 1px 0 #53308C;
  color: #fff;
  font-size: 9px;
  font-weight: 900;
  line-height: 1;
}

/* NA PLACU — ZIELONY, bo to koniec drogi tego stosu (wlasciciel, 1.10).
   Zielen w calej grze znaczy "zrobione" i nie ma powodu, zeby akurat tu
   znaczyla cos innego. Fioletowy ptaszek znaczy "sciete, czeka na kurs",
   zielony — "lezy na budowie". */
.game-hud-znak.jest-na-placu b {
  background: linear-gradient(180deg, #8EE13D, #41AB0A);
  box-shadow: 0 1px 0 #3C761F;
}
.game-hud-znak.jest-na-placu img {
  filter: drop-shadow(0 0 5px rgba(65, 171, 10, .7));
}

/* W DRODZE. Ptaszka nie ma — czynnosc trwa, wiec nie ma czego odhaczac.
   Zamiast niego pulsuje sama ikonka: "to jest teraz na plecach liska". */
.game-hud-znak.jest-w-drodze img {
  animation: hud-niesie 1.05s ease-in-out infinite;
}
@keyframes hud-niesie {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-3px); }
}

/* --- Krok postepu na liczniku drewna --- */
/* Do 1.10 stany wchodzily "plasko": kloda po prostu robila sie kolorowa,
   ptaszek po prostu byl. Dziecko widzialo WYNIK, nie moment — a moment jest
   cala nagroda za sciecie i za doniesienie.

   Klasy `krok-*` zaklada `hub/ZnakiDrewna.jsx` NA CHWILE, tylko temu slotowi,
   ktory wlasnie ruszyl dalej, i tylko wtedy, gdy ruszyl TERAZ. Po wejsciu do
   swiata komplet drewna NIE odgrywa swojej historii od nowa.

   PODZIAL PRACY MIEDZY ELEMENTAMI jest tu konieczny, nie estetyczny: `img` ma
   juz wieczna animacje `hud-niesie` (kurs z ladunkiem), a jedna wlasciwosc
   `animation` nie pomiesci obu. Skoki kroku ida wiec na OPAKOWANIE
   (`.game-hud-znak`), blysk obreczy na jego `::after`, a ptaszek — na `b`.
   Trzy elementy, trzy osobne animacje, zero kolizji. */

/* SCIETE: kloda wpada z gory i odbija sie. Z niewielka (9 px) — kafelek ma
   43 px wysokosci, wiec dluzszy lot zaczynalby sie poza nim. */
@keyframes hud-kloda-wpada {
  0%   { transform: translateY(-9px) scale(.68); }
  45%  { transform: translateY(2px) scale(1.16); }
  72%  { transform: translateY(-1.5px) scale(.96); }
  100% { transform: translateY(0) scale(1); }
}
.game-hud-znak.krok-sciete { animation: hud-kloda-wpada .5s cubic-bezier(.3, 1.35, .5, 1); }

/* W DRODZE: jedno poderwanie — "lisek bierze to na plecy". Dalsze kolysanie
   przejmuje `img` (`hud-niesie`), wiec tutaj wystarczy szarpniecie w gore. */
@keyframes hud-kloda-poderwanie {
  0%   { transform: translateY(0) scale(1); }
  40%  { transform: translateY(-5px) scale(1.12); }
  100% { transform: translateY(0) scale(1); }
}
.game-hud-znak.krok-droga { animation: hud-kloda-poderwanie .34s ease-out; }

/* NA PLACU: ciezsze ladowanie niz przy scieciu — stos ma USIASC na budowie,
   a nie wskoczyc. Stad ruch w dol i mocniejsze splaszczenie w dolku. */
@keyframes hud-kloda-laduje {
  0%   { transform: translateY(-6px) scale(1.14); }
  40%  { transform: translateY(2.5px) scale(.9); }
  70%  { transform: translateY(-1px) scale(1.05); }
  100% { transform: translateY(0) scale(1); }
}
.game-hud-znak.krok-plac { animation: hud-kloda-laduje .44s cubic-bezier(.25, 1.2, .45, 1); }

/* PTASZEK WSKAKUJE. Przekrecenie na starcie robi roznice miedzy "pojawil sie"
   a "zatrzasnal sie": sam `scale` czyta sie jak dymek, dopiero obrot daje
   pieczatke. Opoznienie 0,1 s dogania klode w jej dolnym odbiciu, zeby dwa
   ruchy nie wystartowaly rownoczesnie i nie zlaly sie w jeden. */
@keyframes hud-ptaszek-wskakuje {
  0%   { transform: scale(0) rotate(-130deg); opacity: 0; }
  55%  { transform: scale(1.34) rotate(10deg); opacity: 1; }
  78%  { transform: scale(.92) rotate(-4deg); }
  100% { transform: scale(1) rotate(0); opacity: 1; }
}
.game-hud-znak.krok-sciete b,
.game-hud-znak.krok-plac b {
  animation: hud-ptaszek-wskakuje .42s .1s backwards cubic-bezier(.3, 1.5, .5, 1);
}

/* OBRECZ DOSTAWY — jeden blysk W KOLORZE STANU, ktory wlasnie zapadl, czyli
   od 1.10 zielony (byl pomaranczowy, gdy pomarancz znaczyl "na placu"). Blysk
   ma potwierdzac ptaszka, ktory za chwile zostanie na ikonce; w innym kolorze
   niz on czytalby sie jak osobne zdarzenie. Nie zostaje po nim nic: obrecz gasnie i znika razem
   z klasa. `inset: -4px` trzyma ja w obrysie kafelka w chwili startu;
   rozejscie sie poza rant wypada juz przy znikajacym kryciu. */
.game-hud-znak.krok-plac::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 2.5px solid #41AB0A;
  pointer-events: none;
  animation: hud-obrecz-dostawy .5s ease-out forwards;
}
@keyframes hud-obrecz-dostawy {
  0%   { transform: scale(.6); opacity: .95; }
  100% { transform: scale(1.35); opacity: 0; }
}

/* KAFELEK podskakuje TYLKO przy dostawie i tym samym ruchem, co przy dolocie
   iskry (`hud-podbicie` nizej) — w obu wypadkach znaczy to samo: "cos wlasnie
   wpadlo do licznika". Sciecie dostaje sama kloda, zeby dwa rozne zdarzenia
   nie wygladaly identycznie. Ikon tu NIE ruszamy: maja juz wlasny krok. */
.game-hud-counter--drewno.ma-dostawe { animation: hud-podbicie .46s cubic-bezier(.3, 1.4, .5, 1); }

@media (prefers-reduced-motion: reduce) {
  .game-hud-counter--drewno img { transition: none; }
  .game-hud-znak.jest-w-drodze img { animation: none; opacity: .75; }
  /* Krok zostaje widoczny jako STAN — kolor ikony i ptaszek — tylko bez ruchu.
     Zadna z tych animacji nie niesie informacji, ktorej nie ma w stanie. */
  .game-hud-znak.krok-sciete,
  .game-hud-znak.krok-droga,
  .game-hud-znak.krok-plac,
  .game-hud-znak.krok-sciete b,
  .game-hud-znak.krok-plac b,
  .game-hud-counter--drewno.ma-dostawe { animation: none; }
  .game-hud-znak.krok-plac::after { display: none; }
}

/* Cel jest mniejszy i ciemniejszy: liczy sie to, ile dziecko MA, a nie ile
   zostalo. "3" ma byc pierwsza rzecza, ktora widac. */
.game-hud-counter--gwiazdki em,
.game-hud-counter--misja em,
.game-hud-counter--baloniki em {
  /* BALONIKI DOPISANE 01.10. Licznik balonikow powstal "jak przy gwiazdkach",
     ale nie wszedl do tej reguly - i jako jedyny zostawal przy domyslnym
     `<em>`, czyli KURSYWIE w pelnym rozmiarze. W pasku, obok prostych cyfr
     monet, "/16" jechalo w bok i czytalo sie jak inny font. */
  font-style: normal;
  font-size: 12.5px;
  font-weight: 800;
  opacity: .62;
  letter-spacing: -.2px;
}

/* Komplet: kafelek swieci tym samym zlotem co pelny pasek monet. */
.game-hud-counter--gwiazdki.jest-spelnione,
.game-hud-counter--misja.jest-spelnione {
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--krem-50) 98%, transparent), color-mix(in srgb, var(--krem-500) 98%, transparent)) padding-box,
    linear-gradient(180deg, var(--hud-gold-light), var(--hud-gold) 52%, var(--hud-gold-deep)) border-box;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, .9),
    0 3px 0 var(--hud-shadow),
    0 0 14px color-mix(in srgb, var(--zloto-250) 85%, transparent);
}

.game-hud-counter--gwiazdki.jest-spelnione em,
.game-hud-counter--misja.jest-spelnione em,
.game-hud-counter--baloniki.jest-spelnione em { opacity: .8; }

/* Dolot iskry: kafelek podskakuje razem ze zmiana liczby. Krotko i tylko raz
   — to ma byc potwierdzenie, ze cos wpadlo, a nie osobna atrakcja. Skala idzie
   z `transform`, wiec animacja siedzi na kompozytorze i nie rusza ukladu
   pozostalych kafelkow w pasku. */
@keyframes hud-podbicie {
  0%   { transform: scale(1); }
  30%  { transform: scale(1.16); }
  55%  { transform: scale(.98); }
  100% { transform: scale(1); }
}

.game-hud-counter.jest-podbite {
  animation: hud-podbicie .46s cubic-bezier(.3, 1.4, .5, 1);
}

.game-hud-counter.jest-podbite img {
  animation: hud-podbicie .46s .04s cubic-bezier(.3, 1.6, .5, 1);
}

@media (prefers-reduced-motion: reduce) {
  .game-hud-counter.jest-podbite,
  .game-hud-counter.jest-podbite img { animation: none; }
}

/* --- Licznik drugiego zadania: karta Medrca --- */
/* Ten sam kafelek co licznik gwiazdek (selektory wyzej sa wspolne) — rozni
   sie tylko KSZTALTEM ikony.

   ODDECH DO KRAWEDZI. Gwiazdka i moneta maja przezroczyste rogi, wiec przy
   34 px optycznie i tak nie dotykaly obwodki. Ikona misji jest PELNYM
   prostokatem - przy tej samej wysokosci siadala na zlotej ramce i kafelek
   wygladal, jakby zawartosc z niego wychodzila. Rachunek: kafelek ma 43 px
   wysokosci, minus 2x2 px obwodki i 2x3 px paddingu zostaje 33 px na tresc.
   30 px ikony daje ~4.5 px realnego marginesu do ramki z gory i z dolu.
   Zerujemy tez odziedziczony ujemny margines z `.game-hud-counter img` - on
   celowo WYPYCHA moneta poza kafelek, a tutaj chcemy dokladnie odwrotnie. */
.game-hud-counter--misja img {
  width: 30px;
  height: 30px;
  margin: 0;
  border-radius: 6px;
}

/* Rewers karty (`/assets/karty/rewers-3d.png`) ma 512x768, czyli rowno 2:3.
   Wczesniej lezal w pudelku 26x34: `object-fit:contain` wpisywal go wiec
   w 22.7x34 i zostawial po bokach puste pole, a `border-radius` zaokraglal
   PUDELKO, nie karte - rogi zostawaly ostre, mimo ze promien byl ustawiony.
   Pudelko 20x30 ma ten sam stosunek co plik, wiec nie ma juz czego wpisywac
   i promien tnie prawdziwa krawedz karty. */
/* IKONA Z RODZINY CHMURKI (karta, bucik — `assets/wskazowki/`). Nie jest
   pelnym prostokatem jak stary kafelek gry: ma przezroczyste rogi i wlasny
   ciemny rant (`scripts/ikony-obrys.py`), czyli zachowuje sie jak gwiazdka.
   Dostaje wiec jej traktowanie: pelny rozmiar, bez zaokraglania pudelka
   (nie ma czego zaokraglac) i ten sam lekko ujemny margines, co gwiazdka
   i moneta — rant i tak trzyma odstep od zlotej obwodki kafelka.
   Pomiar 20.09: przy starym ksztalcie „zeton" bucik zajmowal w kafelku
   okolo pietnastu pikseli wysokosci obok szesnastopikselowej cyfry. */
.game-hud-counter--misja img[data-ksztalt="ikona"] {
  width: 32px;
  height: 32px;
  margin: -1px 0 -1px -2px;
  border-radius: 0;
}

.game-hud-counter--misja img[data-ksztalt="karta"] {
  width: 20px;
  height: 30px;
  border-radius: 5px;
}

/* IKONA JEST OD RAZU W PELNYM KOLORZE. Stalo tu wygaszenie do szarosci na
   czas, gdy znak nie byl jeszcze znaleziony - mialo znaczyc "jeszcze nie wiesz,
   czego szukasz", a czytalo sie jak zepsuty albo zablokowany kafelek. Dziecko
   ma widziec NAGRODE, po ktora idzie; slad odkrycia niesie licznik (0/1)
   i zlota poswiata po wygranej. */

@media (max-width: 380px) {
  .game-hud-counter--gwiazdki,
  .game-hud-counter--misja { padding: 3px 10px 3px 3px; font-size: 15px; }
  .game-hud-counter--gwiazdki img { width: 28px; height: 28px; }
  /* Ikona misji zostaje 30 px - kafelek ma tu te sama wysokosc (43 px),
     wiec oddech do ramki jest ten sam. Zwezal sie tylko padding poziomy. */
}


/* --- Trzeci kafelek w gornym pasku na waskim ekranie --- */
/* Do 01.10 ponizej 400 px chowal sie tu pasek postepu monet (klasa
   `ma-zadanie` z huba). Pasek zniknal z kafelka w ogole, wiec kafelek
   monet jest juz tak waski, jak kiedys z ukrytym paskiem — i nic nie musi
   ustepowac. Klasa `ma-zadanie` zostaje w hubie bez reguly. */


/* --- Licznik kawalkow puzzli --- */
/* Ten sam kostium co kafelek misji (`--misja` w klasach), ale to PRZYCISK:
   z kompletem kawalkow dotkniecie otwiera ukladanke. Bez kompletu nie robi
   nic - kusic ma dopiero wtedy, gdy naprawde jest co otworzyc (swieci
   wtedy przez `jest-spelnione`, jak spelniona misja). */
button.game-hud-counter--puzzle {
  appearance: none;
  -webkit-appearance: none;
  font: inherit;
  cursor: pointer;
}
button.game-hud-counter--puzzle:active { transform: translateY(1px); }
.game-hud-counter--puzzle img {
  width: 27px;
  height: 27px;
  margin-left: 5px;
}


/* --- JEDNA WYSOKOSC GORNEGO PASKA (wlasciciel, 1.10) --- */
/* Trzy elementy w prawym gornym rogu mialy trzy wysokosci: licznik puzelkow
   (i gwiazdek, misji, balonikow) 43 px z reguly bazowej, moneta 48 px
   (`--coins { min-height: 48px }` ustawione pod dawny przycisk muzyki),
   nutka 48 px, a iskra 54 px — kazda z osobnej poprawki, kazda uzasadniona
   wtedy, gdy stala sama. Obok siebie czytaly sie jako nierowny rzad.
   Wzorcem jest licznik puzelkow: 43 px, czyli tyle, ile daje regula bazowa
   `.game-hud-counter`. Reszta schodzi do niego; na najwezszym ekranie
   (<= 340 px) nutka i moneta mialy juz 43 px, wiec tam nic sie nie zmienia.
   Iskra traci 6 px obrazka (52 -> 46), bo przy ujemnych marginesach -8 px
   52 px wypychalo kafelek na 46 px — dalej jest wyraznie wieksza od monety
   (34 px), wiec hierarchia zasobow zostaje. */
.game-hud-counter,
.game-hud-counter--coins,
.game-hud-counter--spark { min-height: 43px; }

.game-hud-counter--spark img {
  width: 46px;
  height: 46px;
  margin: -8px 0 -8px -4px;
}

.game-hud-music {
  width: 43px;
  height: 43px;
  padding: 9px;
}
.game-hud-music.is-off::after { width: 22px; }
