/* ═══════════════════════════════════════════════════════════════
   „Akcja kanalizacja” — gra labiryntowa e-lekcji SELEKT (klasy 4–5)
   Klocek K04, Trop 3. Zastępuje moduł Genially „Rurociąg”.

   Paleta projektu: #02468d  #1b9dd8  #3669ac  #afdaea
   Strzałki:        #1f7fc4 naprzód / #8fcdf3 wróć / #4b6b86 rura zajęta
   Rury na grafice: #4a6b4a — stąd zieleń w tłach paneli.

   ZASADA WARSTW w kadrze (od spodu):
     img.maze       — oryginał labiryntu 1800×1800 (ZERO doładowań w grze)
     svg.water      — kopia labiryntu z NIEBIESKIMI rurami, odsłaniana maską
                      wzdłuż przebytej trasy (viewBox 0 0 100 100 = procenty)
     svg.debug      — graf + trasa wzorcowa, tylko ?debug=1
     .arrows        — strzałki kierunków (HTML: fokus, 48 px, aria)

   Kadr jest kwadratowy, więc procent w viewBox = procent obrazu na każdym
   ekranie — żadnego przeliczania w JS przy zmianie rozmiaru okna.
   ═══════════════════════════════════════════════════════════════ */

:root {
  --c-navy:   #02468d;
  --c-blue:   #1b9dd8;
  --c-steel:  #3669ac;
  --c-ice:    #afdaea;
  --c-text:   #0d2340;
  --c-white:  #ffffff;
  --c-amber:  #e8a020;
  --c-amber-d:#a86a06;
  --c-pipe:   #4a6b4a;

  --water-dark: #1f7fc4;
  --water:      #35a7ee;
  --water-lite: #a9dcff;

  --hud-h: 58px;
  --radius: 18px;
  --shadow: 0 10px 30px rgba(2, 70, 141, 0.28);

  /* Bok kadru w px — ustawia k04.js po zmierzeniu sceny.
     Od niego zależy rozmiar strzałek na małych ekranach. */
  --scene: 640px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body { height: 100%; overflow: hidden; }

body {
  font-family: "Segoe UI", system-ui, -apple-system, Roboto, Arial, sans-serif;
  color: var(--c-text);
  background: #2a1d12;          /* kolor ziemi z grafiki — kadr wtapia się w tło */
  -webkit-tap-highlight-color: transparent;
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}

.game { position: fixed; inset: 0; overflow: hidden; }

/* ══════════════ HUD ══════════════ */

.hud {
  position: absolute;
  top: 0; left: 0; right: 0;
  min-height: var(--hud-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px max(12px, env(safe-area-inset-right)) 0 max(12px, env(safe-area-inset-left));
  z-index: 20;
  pointer-events: none;
}

.hud > * { pointer-events: auto; }

.hud-stat {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: #f2e4cf;
  background: rgba(20, 14, 8, 0.62);
  border-radius: 999px;
  padding: 8px 14px;
}

.hud-stat strong { color: var(--c-white); font-size: 0.94rem; }
.hud-sep { opacity: 0.5; margin: 0 4px; }

.btn-sound {
  font: inherit;
  font-size: 0.76rem;
  font-weight: 700;
  min-height: 40px;
  padding: 8px 16px;
  color: #f2e4cf;
  background: rgba(20, 14, 8, 0.62);
  border: 2px solid rgba(242, 228, 207, 0.35);
  border-radius: 999px;
  cursor: pointer;
}

.btn-sound[aria-pressed="true"] { border-color: var(--c-blue); color: #d9f0ff; }
.btn-sound:hover { border-color: var(--c-ice); }
.btn-sound:focus-visible { outline: 3px solid var(--c-blue); outline-offset: 3px; }

/* ══════════════ KADR ══════════════ */

/* Kadr i podpowiedź stoją w jednej kolumnie i razem są wyśrodkowane —
   dzięki temu podpowiedź jest zawsze tuż pod rurami, a nie przyklejona
   do dolnej krawędzi ekranu (co na wysokim telefonie wyglądało na błąd). */
.stage {
  position: absolute;
  inset: var(--hud-h) 0 0 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 6px 6px 10px;
}

/* Kadr 1:1: bierze mniejszy z wymiarów, więc nigdy nie wychodzi poza ekran
   ani nie wymusza przewijania w poziomie. */
.scene {
  position: relative;
  width: min(100%, calc(100vh - var(--hud-h) - 92px));
  max-width: 900px;
  aspect-ratio: 1 / 1;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.45);
}

.maze {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
  -webkit-user-drag: none;
}

.water, .debug-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.debug-layer[hidden] { display: none; }

/* Obrysy w masce wstęgi. Białe = odsłonięte, czarne tło maski = ukryte.
   Szerokość 2,25 % kadru: sama rura ma 2,07 %, pierścienie łączeń do 2,3 %,
   a poza rurę wychodzi to o ~1,2 px (przy 1400 px) — dzięki temu błękit nie
   przecieka na rurę sąsiednią. Kopia „niebieska” ma dodatkowo alfę obciętą
   do maski rur, więc na piasku i tak nic nie widać. */
.ribbon {
  fill: none;
  stroke: #fff;
  stroke-width: 2.25;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ══════════════ STRZAŁKI ══════════════ */

.arrows { position: absolute; inset: 0; }

/* Wspólna baza: przycisk jest kołem o boku min. 48 px, wyśrodkowanym
   na swojej pozycji procentowej. Na dużym kadrze rośnie razem z nim. */
.act {
  position: absolute;
  transform: translate(-50%, -50%);
  width: max(48px, calc(var(--scene) * 0.08));
  height: max(48px, calc(var(--scene) * 0.08));
  display: grid;
  place-items: center;
  border: 0;
  padding: 0;
  border-radius: 50%;
  cursor: pointer;
  background: transparent;
}

.act svg { width: 74%; height: 74%; display: block; }
.act:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }

/* WSZYSTKIE strzałki są niebieskie — różnią się odcieniem, nie kolorem.

   naprzód  — pełny błękit wody, biały grot
   wróć     — jaśniejszy błękit, ciemny grot (rura, którą woda przypłynęła)
   zajęta   — przygaszona i przekreślona (rura już wypełniona; blokada pętli) */
.act--fwd .act-bg { fill: var(--water-dark); stroke: #ffffff; stroke-width: 3; }
.act--fwd .act-fg { fill: #ffffff; }
.act--fwd:hover .act-bg { fill: var(--water); }

.act--back .act-bg { fill: #8fcdf3; stroke: #ffffff; stroke-width: 3; }
.act--back .act-fg { fill: #10527f; }
.act--back:hover .act-bg { fill: #a9dcff; }

.act--off { opacity: 0.62; cursor: not-allowed; }
.act--off .act-bg { fill: #4b6b86; stroke: rgba(255, 255, 255, 0.75); stroke-width: 3; }
.act--off .act-fg { fill: rgba(255, 255, 255, 0.7); }
.act--off .act-bar { stroke: #ffffff; stroke-width: 8; stroke-linecap: round; }

/* Delikatne pulsowanie: pulsują tylko rury, w które można wpłynąć dalej. */
@keyframes k04-pulse {
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  50%      { transform: translate(-50%, -50%) scale(1.09); }
}
.act--fwd { animation: k04-pulse 1.9s ease-in-out infinite; }
.act--fwd:hover, .act--fwd:focus-visible { animation-play-state: paused; }

.arrows.is-busy .act { pointer-events: none; opacity: 0.35; }

/* ══════════════ BŁYSK ALARMU ══════════════ */

.alarm-flash {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 92%, rgba(255, 140, 0, 0.85), rgba(255, 60, 0, 0) 55%);
  opacity: 0;
  pointer-events: none;
}

.alarm-flash.is-on { animation: k04-alarm 1.5s ease-out 2; }

@keyframes k04-alarm {
  0%   { opacity: 0; }
  25%  { opacity: 0.9; }
  100% { opacity: 0; }
}

/* ══════════════ PODPOWIEDŹ POD KADREM ══════════════ */

.hint {
  flex: 0 0 auto;
  z-index: 18;
  max-width: 94vw;
  text-align: center;
  font-size: 0.8rem;
  font-weight: 600;
  color: #f2e4cf;
  background: rgba(20, 14, 8, 0.62);
  border-radius: 999px;
  padding: 6px 16px;
  pointer-events: none;
}

/* ══════════════ KARTA HYDRAULIKA ══════════════ */

.card {
  position: absolute;
  right: max(12px, env(safe-area-inset-right));
  bottom: 46px;
  z-index: 30;
  width: min(300px, 78vw);
  padding: 10px 14px 14px;
  background: var(--c-white);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  text-align: center;
  transform: translateY(0);
  transition: opacity 0.22s ease, transform 0.22s ease;
}

.card[hidden] { display: none; }
.card.is-enter { opacity: 0; transform: translateY(14px); }

.card-imgbox { position: relative; display: block; }

.card-img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  border-radius: 12px;
  background: #fff;
}

/* ETAP T (A06): łatka na dymek ze starym tekstem. Obraz jest kwadratowy
   i wypełnia kwadratowe pudełko (`object-fit: contain` na 1/1), więc
   procenty łatki to procenty samej grafiki. Zdejmujemy ją jedną zmianą —
   usunięciem `zaslonDymek` w k04.js — gdy dojdą nowe plansze. */
.card[data-dymek="ukryty"] .card-imgbox::after {
  content: "";
  position: absolute;
  top: 0; right: 0; left: 54%; height: 40%;
  background: #fff;
  border-radius: 12px;
}

.card-text {
  margin: 4px 0 10px;
  font-size: 0.88rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--c-navy);
}

.card-close {
  font: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  min-height: 44px;
  width: 100%;
  padding: 10px 18px;
  color: var(--c-white);
  background: var(--c-steel);
  border: 0;
  border-radius: 999px;
  cursor: pointer;
}

.card-close:hover { background: var(--c-navy); }
.card-close:focus-visible { outline: 3px solid var(--c-amber); outline-offset: 3px; }

/* ══════════════ EKRANY: START I FINAŁ ══════════════ */

.overlay {
  position: absolute;
  inset: 0;
  z-index: 40;
  display: grid;
  place-items: center;
  padding: 14px;
  background: rgba(10, 22, 36, 0.86);
  overflow-y: auto;
}

.overlay.is-hidden { display: none; }

.panel {
  width: min(520px, 100%);
  max-height: 100%;
  padding: 18px 22px 22px;
  background: var(--c-white);
  border-radius: 22px;
  box-shadow: var(--shadow);
  text-align: center;
}

.panel-cover {
  display: block;
  width: min(230px, 62%);
  height: auto;
  margin: 0 auto 10px;
  border-radius: 16px;
}

.panel-cover--plate { width: min(180px, 50%); }

.panel-title {
  font-size: clamp(1.25rem, 3.6vw, 1.7rem);
  line-height: 1.15;
  color: var(--c-navy);
  margin-bottom: 8px;
}

.panel-text {
  font-size: 0.94rem;
  line-height: 1.45;
  margin-bottom: 10px;
}

.panel-text--verdict { font-weight: 700; color: var(--c-navy); }
.panel-text--label { font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.06em; opacity: 0.75; margin-bottom: 4px; }

.panel-info {
  display: flex;
  gap: 10px;
  text-align: left;
  align-items: flex-start;
  padding: 10px 12px;
  margin-bottom: 14px;
  background: #eef6fb;
  border-radius: 14px;
  font-size: 0.86rem;
  line-height: 1.4;
}

.panel-info-icon { flex: 0 0 20px; width: 20px; height: 20px; color: var(--c-steel); margin-top: 1px; }

.reward-letter {
  width: 74px; height: 74px;
  margin: 0 auto 10px;
  display: grid; place-items: center;
  font-size: 2.4rem; font-weight: 800;
  color: var(--c-white);
  background: var(--c-blue);
  border-radius: 20px;
  box-shadow: var(--shadow);
}

.panel-score {
  font-size: 0.8rem;
  opacity: 0.75;
  margin-bottom: 12px;
}

.btn {
  font: inherit;
  font-weight: 800;
  letter-spacing: 0.04em;
  min-height: 50px;
  padding: 12px 26px;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
}

.btn--primary { color: var(--c-white); background: var(--c-navy); }
.btn--primary:hover { background: var(--c-steel); }
.btn:focus-visible { outline: 3px solid var(--c-amber); outline-offset: 3px; }

.panel-hint { margin-top: 10px; font-size: 0.78rem; opacity: 0.7; }

/* ══════════════ DEBUG ══════════════ */

.d-edge  { fill: none; stroke: #ff5a3c; stroke-width: 0.5; opacity: 0.85; }
.d-path  { fill: none; stroke: #0d7bd6; stroke-width: 1.5; opacity: 0.95; }
.d-node  { fill: #101820; stroke: #fff; stroke-width: 0.28; }
.d-dead  { fill: #a3009b; stroke: #fff; stroke-width: 0.28; }
.d-entry { fill: #ffd200; stroke: #fff; stroke-width: 0.34; }
.d-goal  { fill: #00c85a; stroke: #fff; stroke-width: 0.34; }
.d-label { fill: #fff; font-size: 1.15px; font-weight: 700; text-anchor: middle; paint-order: stroke; stroke: #000; stroke-width: 0.35; }

.debug-readout {
  position: absolute;
  left: max(10px, env(safe-area-inset-left));
  bottom: max(8px, env(safe-area-inset-bottom));
  z-index: 25;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.7rem;
  color: #d9f0ff;
  background: rgba(0, 0, 0, 0.62);
  padding: 5px 9px;
  border-radius: 8px;
  pointer-events: none;
  white-space: pre;
}

.debug-readout[hidden] { display: none; }

/* ══════════════ EKRANY MAŁE ══════════════ */

@media (max-width: 560px) {
  :root { --hud-h: 52px; }
  .hud-stat { font-size: 0.68rem; padding: 6px 11px; }
  .btn-sound { font-size: 0.68rem; min-height: 36px; padding: 6px 12px; }
  .hint { font-size: 0.72rem; padding: 5px 12px; }
  .panel { padding: 14px 16px 18px; }
  .card { right: 50%; transform: translateX(50%); width: min(280px, 86vw); }
  .card.is-enter { transform: translateX(50%) translateY(14px); }
}

/* Telefon w pionie. Kadr jest kwadratowy, więc — inaczej niż przy kadrach
   16:9 — pion jest dla niego LEPSZY niż poziom (w poziomie ogranicza go
   niska wysokość ekranu). Dlatego nie ma tu podpowiedzi „obróć telefon”.
   Kadr siada tuż pod HUD, a podpowiedź i karta hydraulika lądują pod nim —
   pozycję liczymy ze zmiennej --scene, którą k04.js ustawia po pomiarze. */
@media (orientation: portrait) and (max-width: 560px) {
  .scene { width: min(100%, calc(100vh - var(--hud-h) - 150px)); }
  /* karta ląduje w wolnym pasie pod kadrem, na środku ekranu */
  .card { bottom: max(10px, env(safe-area-inset-bottom)); }
}

/* ══════════════ OSADZENIE W TABLICY LEKCJI ══════════════ */

.k04-embed body { background: transparent; }
.k04-embed .scene { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.32); }

/* ══════════════ OGRANICZONY RUCH ══════════════
   Woda skacze zamiast płynąć (JS pomija animację dash-offset),
   strzałki przestają pulsować, karta nie wjeżdża. */
@media (prefers-reduced-motion: reduce) {
  .act--fwd { animation: none; }
  .alarm-flash.is-on { animation: none; opacity: 0.55; }
  .card { transition: none; }
  .card.is-enter { opacity: 1; transform: none; }
}

/* ══════════════ TABLICA KOŃCOWA ══════════════
   Grafika z wpalonymi napisami. Żywe są tylko trzy liczby (SVG w układzie
   współrzędnych grafiki) i przycisk (przezroczysty, dokładnie na wpalonej
   zielonej płytce). Pola po wypalonych liczbach są wyczyszczone w samym
   pliku WebP — sklonowanym paskiem pigułki, bez łat w DOM: płaska łata
   zostawiała widoczny ślad, bo tło pigułki ma delikatną fakturę. */

.board { position: relative; flex: 0 0 auto; }

/* Szerokość ustawia k04.js — patrz updateBoards(). Wartości domyślne są
   tylko na wypadek, gdyby skrypt nie zdążył policzyć. */
.board--start { width: var(--board-start, 640px); aspect-ratio: 2016 / 2120; }
.board--final { width: var(--board-final, 640px); aspect-ratio: 2114 / 2016; }

.board img { display: block; width: 100%; height: 100%; }

.vals { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

/* Kalibrację stopnia pisma i szerokości robi k04.js — celem jest wysokość
   36 i szerokość 24,5 na cyfrę w układzie grafiki, czyli dokładnie tyle,
   ile miały cyfry wypalone. Systemowy grotesk jest szerszy od użytego
   w grafice, dlatego szerokość wymuszamy przez textLength. */
.vals text {
  font-family: system-ui, "Segoe UI", Arial, sans-serif;
  font-weight: 700;
  fill: #fffef9;
  stroke: #4a3325;
  stroke-width: 4;
  paint-order: stroke fill;
  stroke-linejoin: round;
}

/* Przycisk na wpalonej płytce: przezroczysty, więc grafika zostaje widoczna,
   ale to prawdziwy <button> — ma fokus, Enter i etykietę. Na telefonie
   min-height podnosi go do 44 px, rosnąc symetrycznie względem płytki.

   POŁOŻENIE JEST OSOBNE DLA KAŻDEJ TABLICY (S1.A.1). Jedna wspólna reguła
   ustawiała pole klikalne w obu, a przycisk leży na nich w innych miejscach:
   pomiar pikseli grafik dał środek na 80,8% wysokości w tablicy początkowej
   i na 90,5% w końcowej. Wspólne wartości były skalibrowane pod końcową,
   więc na początkowej pole klikalne siedziało ok. 10% wysokości NIŻEJ niż
   zielona pigułka. Wartości niżej opisują pole dotykowe, więc są nieco
   większe od samej pigułki — obejmują obwódkę i cień. */
.board-go {
  position: absolute;
  transform: translate(-50%, -50%);
  min-height: 44px;
  border: 0; padding: 0;
  font: inherit;
  color: transparent;
  background: transparent;
  border-radius: 999px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* tablica początkowa „Zaczynamy akcję Kanalizacja" (1200 × 1262) —
   zielona pigułka „SCHODZIMY POD ZIEMIĘ" */
.board--start .board-go {
  left: 52.3%; top: 80.7%;
  width: 42%; height: 8.1%;
}
/* tablica końcowa (1200 × 1144) — pigułka „ZAPISZ LITERĘ I KONTYNUUJ";
   te wartości były w arkuszu od początku i pomiar je potwierdził */
.board--final .board-go {
  left: 50.71%; top: 90.55%;
  width: 39.45%; height: 10.47%;
}

/* ══════════════ LITERA NAGRODY NA TABLICY (etap H) ══════════════
   Hasło lekcji to OBIEG, więc ten klocek daje literę O — ale na grafice
   `tablica-koncowa.webp` wpalona jest jeszcze stara litera P. Zasłaniamy ją
   plakietką HTML w tym samym miejscu i w tym samym stylu (złota ramka,
   granatowe wnętrze, złoty znak).

   ZMIERZONE POŁOŻENIE STAREJ PLAKIETKI w pliku 1200 × 1144:
     lewy górny róg 536 × 463, prawy dolny 681 × 615,
     rozmiar 146 × 153 px, środek 609 × 540.
   Stąd procenty: left 50,75 %, top 47,16 %, szerokość 12,17 %,
   wysokość 13,37 %. Nakładka jest o ok. 12 % większa od oryginału, żeby
   przykryć także obwódkę i cień — inaczej spod spodu wystawałby rant.

   Gdy dojdzie nowa grafika z literą O, wystarczy usunąć ten blok razem
   ze znacznikiem `.board-litera` w index.html. */
.board--final .board-litera {
  position: absolute;
  left: 50.75%; top: 47.16%;
  width: 13.6%; height: 14.9%;
  transform: translate(-50%, -50%);
  display: grid; place-items: center;
  border-radius: 22%;
  background:
    linear-gradient(180deg, #2f5fa8 0%, #14356b 55%, #0e2650 100%);
  /* Ramka i poświata w `em`, nie w procentach: `em` idzie za stopniem pisma,
     a ten liczy się z szerokości tablicy — więc plakietka zachowuje
     proporcje na każdym kadrze. W procentach ramka schodziła poniżej
     piksela i znikała (zmierzone: 0,8 px przy tablicy 640). */
  border: 0.085em solid #d8a63c;
  box-shadow:
    inset 0 0 0 0.045em #f3d489,
    inset 0 0.05em 0.14em rgba(255, 255, 255, 0.28),
    0 0.05em 0.14em rgba(0, 0, 0, 0.45),
    0 0 0.5em 0.12em rgba(255, 205, 90, 0.35);
  color: #f6d98a;
  font-family: 'Segoe UI', system-ui, -apple-system, Roboto, Arial, sans-serif;
  font-weight: 800;
  line-height: 1;
  /* stopień pisma z szerokości TABLICY, nie okna: litera ma rosnąć razem
     z grafiką, a nie z ekranem */
  font-size: calc(var(--board-final, 640px) * 0.085);
  text-shadow: 0 0.06em 0 rgba(0, 0, 0, 0.35);
  pointer-events: none;
  user-select: none;
}
.board-go:hover  { background: rgba(255, 255, 255, 0.12); }
.board-go:active { background: rgba(0, 0, 0, 0.14); }
.board-go:focus-visible { outline: 3px solid #ffd899; outline-offset: 3px; }
.board-go[aria-disabled="true"] { cursor: default; background: rgba(0, 0, 0, 0.22); }

/* Puenta lekcji — na tablicy nie ma na nią miejsca, a klocek nie może się
   skończyć samą gratulacją. */
.board-note {
  width: var(--board-final, 640px);
  margin-top: 10px;
  font-size: 0.82rem;
  line-height: 1.45;
  text-align: center;
  color: #f2e4cf;
}

/* PRZEŁĄCZNIK POSTACI. Decyduje nie rozmiar okna, tylko szerokość, do jakiej
   tablica REALNIE się skaluje w dostępnym kadrze — w lekcji gra siedzi
   w ramce o własnej wysokości i media query na oknie kłamałaby.
   Wartość liczy updateBoards() w k04.js przy każdej zmianie rozmiaru.

   Domyślnie (zanim skrypt policzy) widać kartę HTML — bezpieczniejszy wybór
   niż nieczytelna grafika. */
.board, .board-note, .board-replay, .sr-board { display: none; }

.overlay[data-form="graf"] .board,
.overlay[data-form="graf"] .board-note,
.overlay[data-form="graf"] .board-replay,
.overlay[data-form="graf"] .sr-board { display: block; }

.overlay[data-form="graf"] .panel--small { display: none; }

/* Przycisk finału po kliknięciu: zostaje na miejscu, ale już nie reaguje —
   `k04:continue` leci dokładnie raz, a tablica ma zostać na ekranie. */
.btn[aria-disabled="true"] { opacity: 0.55; cursor: default; }
.board-go.is-done:hover, .btn[aria-disabled="true"]:hover { background: rgba(0, 0, 0, 0.22); }
.btn[aria-disabled="true"]:hover { background: var(--c-navy); }

/* Na ekranie finału podpowiedź spod kadru jest już niepotrzebna — tablica
   mówi wszystko, a dwa komunikaty naraz to szum. */
.game[data-state="final"] .hint,
.game[data-state="intro"] .hint { display: none; }

/* ══════════════ KARTA HTML W SZACIE TABLICY (etap S2, pkt 12) ══════════════
   Poniżej ~640 px grafiki tablic są nieczytelne (wpalone napisy schodzą do
   x-height 4,5 px), więc zostaje karta HTML — ale dotąd wyglądała jak obcy
   element: biały prostokąt w środku świata rur i mosiądzu.

   Odbudowujemy tu wygląd tablicy z desktopu SAMYM CSS-em, bez dotykania
   mechaniki i kontraktu zdarzeń: ciemnozielona płyta z nitami, złota
   tabliczka z tytułem, okrągły portret hydraulika w bulaju i zielony
   przycisk w złotej obwódce. Napisy zostają prawdziwym tekstem, więc
   skalują się i czyta je czytnik ekranu — to jedyna przewaga karty nad
   grafiką i nie oddajemy jej dla samego wyglądu.

   Kolory zdjęte pipetą z `tablica-koncowa.webp` i `tablica-poczatkowa.webp`:
   rura #3f4c39 / #5a6b4e, nit #a9743f, wnętrze #3b3f42, złoto #f0d08a →
   #a97c31, zieleń przycisku #236330. */
.panel--small {
  --tb-plyta:    #4a5b40;
  --tb-plyta-c:  #35422e;
  --tb-nit:      #b07a41;
  --tb-wnetrze:  #3b3f42;
  --tb-zloto-1:  #f6e2a8;
  --tb-zloto-2:  #c99a3c;
  --tb-zloto-c:  #7d5a16;
  --tb-zielen:   #2b6f36;
  --tb-zielen-c: #17491f;

  /* Wypełnienie musi być SZERSZE niż pas nitów (inset 8 px + promień 2,6 px),
     inaczej długie wiersze wchodzą na nity — na 390 px tekst przykrywał je
     po obu stronach, a podpowiedź na dole biegła przez trzy z nich. */
  padding: 20px 28px 30px;
  background: linear-gradient(180deg, var(--tb-plyta) 0%, var(--tb-plyta-c) 100%);
  border: 3px solid var(--tb-plyta-c);
  border-radius: 20px;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.45),
              inset 0 1px 0 rgba(255, 255, 255, 0.14);
  color: #f3ede0;
  overflow: hidden;
}

/* Nity: powtarzalny gradient promienisty wzdłuż wewnętrznej krawędzi płyty.
   Warstwa jest dekoracją, więc leży w ::before i nie łapie zdarzeń. */
.panel--small::before {
  content: "";
  position: absolute;
  inset: 8px;
  border-radius: 14px;
  border: 2px solid rgba(0, 0, 0, 0.22);
  /* Pasy pionowe zaczynają się 22 px niżej, więc w narożnikach nie siadają
     dwa nity obok siebie (widoczne na pierwszym zrzucie w prawym górnym rogu). */
  background:
    radial-gradient(circle, var(--tb-nit) 0 2.6px, transparent 2.9px) 0 0 / 30px 30px repeat-x,
    radial-gradient(circle, var(--tb-nit) 0 2.6px, transparent 2.9px) 0 100% / 30px 30px repeat-x,
    radial-gradient(circle, var(--tb-nit) 0 2.6px, transparent 2.9px) 0 22px / 30px 30px repeat-y,
    radial-gradient(circle, var(--tb-nit) 0 2.6px, transparent 2.9px) 100% 22px / 30px 30px repeat-y;
  pointer-events: none;
}
.panel--small { position: relative; }

/* treść leży NAD warstwą nitów */
.panel--small > * { position: relative; z-index: 1; }
.panel--small > .btn { width: 100%; }
.panel--small > *:last-child { margin-bottom: 0; }

/* PORTRET W BULAJU — okrągła ramka jak właz w tablicy z desktopu */
.panel--small .panel-cover,
.panel--small .panel-cover--plate {
  width: 108px; height: 108px;
  margin: 0 auto 12px;
  border-radius: 50%;
  object-fit: cover;
  border: 5px solid var(--tb-plyta-c);
  box-shadow: 0 0 0 3px rgba(176, 122, 65, 0.75),
              0 8px 18px rgba(0, 0, 0, 0.4);
  background: #cfd6c6;
}

/* ZŁOTA TABLICZKA Z TYTUŁEM */
.panel--small .panel-title {
  display: block;
  padding: 9px 16px;
  background: linear-gradient(180deg, var(--tb-zloto-1) 0%, var(--tb-zloto-2) 100%);
  border: 2px solid var(--tb-zloto-c);
  border-radius: 12px;
  color: #4a2c12;
  font-size: clamp(1.05rem, 4.6vw, 1.35rem);
  line-height: 1.16;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.34),
              inset 0 1px 0 rgba(255, 255, 255, 0.6);
}

/* WNĘTRZE TABLICY — ciemna płyta pod treścią */
.panel--small .panel-text,
.panel--small .panel-score {
  color: #ece5d6;
}
.panel--small .panel-text--verdict {
  color: #ffe9b8;
  padding: 10px 12px;
  background: var(--tb-wnetrze);
  border: 2px solid rgba(0, 0, 0, 0.3);
  border-radius: 12px;
}
.panel--small .panel-text--label {
  color: #f0c469;
  opacity: 1;
}
.panel--small .panel-info {
  background: rgba(59, 63, 66, 0.92);
  border: 2px solid rgba(0, 0, 0, 0.3);
  color: #e6e0d2;
}
.panel--small .panel-info-icon { color: #f0c469; }
.panel--small .panel-hint { color: #d8cfbb; opacity: 0.9; }

/* litera nagrody — złota ramka zamiast niebieskiego kwadratu */
.panel--small .reward-letter {
  background: linear-gradient(180deg, #2e5fa8 0%, #14356b 100%);
  border: 3px solid var(--tb-zloto-2);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.45);
}

/* ZIELONY PRZYCISK W ZŁOTEJ OBWÓDCE — jak pigułka na tablicy */
.panel--small .btn--primary {
  background: linear-gradient(180deg, #3a8a45 0%, var(--tb-zielen-c) 100%);
  border: 3px solid var(--tb-zloto-2);
  color: #fff6dd;
  text-transform: uppercase;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.42),
              inset 0 1px 0 rgba(255, 255, 255, 0.22);
}
.panel--small .btn--primary:hover {
  background: linear-gradient(180deg, #45a052 0%, var(--tb-zielen) 100%);
}
.panel--small .btn--primary:focus-visible {
  outline: 3px solid var(--tb-zloto-1);
  outline-offset: 3px;
}

/* Ograniczony ruch nic tu nie zmienia — karta jest statyczna, ale gdyby
   ktoś dołożył animację, ma jej nie dostać. */
@media (prefers-reduced-motion: reduce) {
  .panel--small { transition: none; }
}

/* ══════════ NAKŁADKI ZAWSZE PRZEWIJALNE (etap S2.1) ══════════
   Zabezpieczenie ostatniej szansy. Karta jest wyższa od tablicy graficznej,
   a wysokość ramki ustala LEKCJA — gdyby kiedykolwiek wypadła niższa, niż
   karta potrzebuje, przycisk „Schodzimy pod ziemię" / „Zapisz literę"
   zniknąłby pod krawędzią i gry NIE DAŁOBY SIĘ zacząć ani skończyć.
   Tak było na wydaniu-04 przy ramce obniżonej do 410 px.

   Nakładka dostaje więc własne przewijanie i dolny zapas. To nie zastępuje
   poprawnej wysokości ramki — to gwarancja, że przycisk zawsze da się
   dosięgnąć, niezależnie od tego, jaki kadr dostaniemy z zewnątrz.

   Dwie rzeczy, bez których samo `overflow-y:auto` (było tu od początku) nic
   nie dawało:
     • `place-items: center` przy treści wyższej od kadru wypycha ją w OBIE
       strony — góra karty ląduje nad krawędzią i przewijanie do niej nie
       sięga. `safe center` w takiej sytuacji wyrównuje do góry;
     • `.panel{max-height:100%}` przycinał kartę do wysokości nakładki, więc
       nadmiaru nie było czym przewinąć — po prostu znikał. */
.overlay {
  place-items: safe center;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding-bottom: max(16px, env(safe-area-inset-bottom));
}
.overlay .panel { max-height: none; }

/* ══════════ KARTA KOMPAKTOWA (etap S2.1) ══════════
   Cel: obie karty — startowa i finałowa — mieszczą się w kadrze 360 × 560 px
   w całości, bez przewijania. Wersja pełna (desktop) zostaje bez zmian.

   Próg to WYSOKOŚĆ kadru, nie szerokość okna: gra siedzi w ramce lekcji,
   więc `@media` w jej dokumencie mierzy właśnie ten kadr. */
@media (max-height: 700px), (max-width: 560px) {
  .panel--small {
    /* dolne 24 px to miejsce na rząd nitów pod podpowiedzią — przy 18 px
       ostatni wiersz „Hydraulik mówi na głos…" wchodził na nie (zmierzone
       na 390 px) */
    padding: 12px 16px 24px;
    border-radius: 16px;
  }
  .panel--small::before { inset: 5px; border-radius: 11px; }

  /* portret: limit 120 px z zlecenia, w praktyce mniejszy, bo to on
     najtaniej oddaje wysokość (108 → 82 px to 26 px dla treści) */
  .panel--small .panel-cover,
  .panel--small .panel-cover--plate {
    width: 82px; height: 82px;
    max-height: 120px;
    margin-bottom: 8px;
    border-width: 4px;
  }

  .panel--small .panel-title {
    padding: 6px 12px;
    font-size: clamp(0.98rem, 4.2vw, 1.15rem);
    line-height: 1.1;
    margin-bottom: 8px;
    border-radius: 10px;
  }

  .panel--small .panel-text {
    font-size: 0.86rem;
    line-height: 1.34;
    margin-bottom: 8px;
  }
  .panel--small .panel-text--verdict { padding: 8px 10px; }
  .panel--small .panel-text--label { margin-bottom: 2px; }

  /* Kolumna tekstu notki jest tu najwęższym miejscem karty, a notka niesie
     instrukcję gry — więc zamiast zmniejszać pismo, oddajemy jej marginesy:
     ciaśniejsze wypełnienie, mniejsza ikona i mniejszy odstęp. Stopień pisma
     zostaje czytelny (12,5 px), bo czyta to dziesięciolatek na telefonie. */
  .panel--small .panel-info {
    gap: 6px;
    padding: 7px 8px;
    margin-bottom: 10px;
    font-size: 0.78rem;
    line-height: 1.32;
    margin-inline: -6px;
  }
  .panel--small .panel-info-icon { flex-basis: 15px; width: 15px; height: 15px; }
  /* Notka zostaje w PEŁNEJ treści — decyzja użytkownika po zrzutach S2.1.
     Trzy wiersze zamiast dwóch, bo zdanie o cofaniu wody jest instrukcją gry,
     a nie ozdobą: uczeń bez niego nie wie, że da się wrócić. Karta ma na to
     zapas — pomiar na 360 × 640 w raporcie 85. */

  .panel--small .reward-letter {
    width: 56px; height: 56px;
    font-size: 1.8rem;
    margin-bottom: 8px;
    border-radius: 15px;
  }
  .panel--small .panel-score { font-size: 0.74rem; margin-bottom: 8px; }

  .panel--small .btn {
    min-height: 46px;
    padding: 10px 18px;
    font-size: 0.92rem;
  }
  .panel--small .panel-hint {
    margin-top: 7px;
    font-size: 0.72rem;
    line-height: 1.3;
  }
}

/* ══════════ START: PULS I STRZAŁKA (etap K, uwaga 4) ══════════
   Klient nie wiedział, gdzie kliknąć na ekranie startowym. Przycisk
   „Schodzimy pod ziemię" oddycha łagodną poświatą co 1,5 s, a obok stoi
   mała strzałka. Oba znikają po pierwszym kliknięciu (klasa `is-puls`
   zdejmowana w startGame) i nie wracają przy kolejnym wejściu na ekran
   startowy w tej sesji. Tablica graficzna: strzałka z lewej, poziomo —
   po lewej stronie pigułki są tylko rury. Karta HTML: strzałka WEWNĄTRZ
   przycisku, przy lewej krawędzi — na wąskim ekranie przycisk zajmuje
   prawie całą szerokość karty, a strzałka nad nim wchodziła w tekst
   ramki z instrukcją (zrzut 390 px). */
@keyframes k04-puls {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 214, 102, 0); }
  50%      { box-shadow: 0 0 0.9em 0.35em rgba(255, 214, 102, 0.85); }
}
@keyframes k04-strzalka-bok {
  0%, 100% { transform: translate(0, -50%); }
  50%      { transform: translate(0.35em, -50%); }
}
.js-start.is-puls { animation: k04-puls 1.5s ease-in-out infinite; }
.js-start.is-puls::after {
  content: "";
  position: absolute;
  pointer-events: none;
  background: no-repeat center / contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 24'%3E%3Cpath d='M2 12h20M15 4l9 8-9 8' fill='none' stroke='%23231a10' stroke-width='7' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M2 12h20M15 4l9 8-9 8' fill='none' stroke='%23ffd666' stroke-width='3.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.board--start .js-start.is-puls::after {
  right: 100%; top: 50%;
  width: 34px; height: 26px;
  margin-right: 8px;
  animation: k04-strzalka-bok 1.5s ease-in-out infinite;
}
.panel--small .js-start.is-puls { position: relative; }
.panel--small .js-start.is-puls::after {
  left: 14px; top: 50%;
  width: 28px; height: 22px;
  animation: k04-strzalka-bok 1.5s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .js-start.is-puls { animation: none; box-shadow: 0 0 0.6em 0.2em rgba(255, 214, 102, 0.7); }
  .js-start.is-puls::after { animation: none; }
  .board--start .js-start.is-puls::after { transform: translate(0, -50%); }
  .panel--small .js-start.is-puls::after { transform: translate(0, -50%); }
}

/* ══════════ POWTÓRKA (etap K, uwaga 9) ══════════ */
.panel-akcje { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
.btn--wtorny {
  color: #f2e4cf;
  background: rgba(0, 0, 0, 0.28);
  border: 2px solid rgba(242, 228, 207, 0.7);
}
.btn--wtorny:hover { background: rgba(0, 0, 0, 0.45); border-color: #f2e4cf; }
.panel--small .btn--wtorny { color: var(--tb-zloto-1, #f6d98a); }
.board-replay { width: var(--board-final, 640px); margin-top: 10px; text-align: center; }
