/* app-zadania.css, zawartosc widoku Zadania: petla zadania ze stawka.
 *
 * Wykonanie sekcji 4.3 i 4.4 z .planning/design/MAKIETA-APP-2026-08-31.md oraz
 * jej sekcji 6 pkt 2 (ekran bledu, ktorego makieta nie narysowala).
 *
 * ZASADY TEGO PLIKU
 * 1. Zaden kolor, promien ani odstep nie jest literalem. Wszystko z css/base.css.
 * 2. `--reward` (bursztyn) jest WYLACZNIE wypelnieniem. Tresc na nim bierze
 *    `--reward-ink`. Zaden napis nie stoi w kolorze `--reward`.
 * 3. Paleta klasyfikacji ruchow i kolory planszy sa nietykalne. Ten plik ich
 *    nie dotyka ani razu.
 * 4. Plansza jest kotwica ukladu (D-10). Ponizej 900 px ten plik przestawia
 *    kolejnosc elementow, powyzej 900 px nie rusza ani `.board-column`, ani
 *    `.board-stack`, ani wysokosci paska nad plansza. Pilnuje tego
 *    test/e2e/planszaKotwica.spec.js.
 */

/* Tekst istniejacy tylko dla czytnika ekranu. Repozytorium nie mialo
   wspolnej klasy tego rodzaju; `.board-status` w css/board.css jest tym
   samym wzorcem przypisanym do jednego elementu. */
.zadanie-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ================= PASEK GORNY SESJI (makieta 4.3 pkt 1) ================= */

/* Cztery slupki w JEDNYM wierszu: pasek nad plansza ma na desktopie stala
   wysokosc 46 px (kotwica z css/app-desktop.css), wiec drugi wiersz zostalby
   przyciety, a postep zniknalby z ekranu. Uklad dwuwierszowy wchodzi dopiero
   na telefonie, nizej w tym pliku. */
.zadanie-topbar {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--sp-2);
}

/* Kropki postepu w pasie zadania (makieta `zadanie-mobile-dark.png`).
   Drugi host tej samej listy, co kropki w bloku „Postep sesji" prawej szyny.
   Na komputerze pas ich nie pokazuje: tam mieszkaja w szynie. */
.zadanie-topbar__dots { display: none; }

.zadanie-topbar__icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: none;
  color: var(--text-dim);
  cursor: pointer;
  transition: color var(--dur-base) var(--ease), background var(--dur-base) var(--ease), border-color var(--dur-base) var(--ease);
}
.zadanie-topbar__icon svg { width: 21px; height: 21px; }
.zadanie-topbar__icon:hover { color: var(--text); border-color: var(--border); background: var(--bg-raised); }
.zadanie-topbar__icon:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }

.zadanie-topbar__title {
  min-width: 0;
  margin: 0;
  overflow: hidden;
  color: var(--text);
  font-size: var(--fs-screen-title);
  font-weight: 700;
  letter-spacing: -.02em;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.zadanie-topbar__title:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 3px; border-radius: var(--radius-sm); }

.zadanie-topbar__progress {
  grid-column: 3;
  margin-left: 0;
  color: var(--text-dim);
  font: 600 var(--fs-micro) var(--font-mono);
  text-align: right;
  white-space: nowrap;
}

/* ================= SERCA I STAWKA (makieta 4.3 pkt 2) ================= */

.zadanie-stakes {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
}

/* ⚠️ SERCA SA WLASNYM RZEDEM I SA DUZE (kontrakt sekcja 1, makieta
   `zadanie-mobile-dark.png`). Do 03.09.2026 mialy 19 px i stały w jednej
   linijce z napisem „3 z 3" oraz plakietka XP, wiec czytaly sie jak trzeci
   licznik, a nie jak stawka. Teraz maja 26 px, odstep 10 px i nic obok. */
.zadanie-hearts {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-size: 26px;
  line-height: 1;
}
/* Stan serca czytelny BEZ koloru: inny znak (pelne kontra puste) plus liczba
   obok. Kolor jest tu dodatkiem, nie nosnikiem informacji (WCAG 1.4.1). */
.zadanie-heart.is-full { color: var(--heart); }
.zadanie-heart.is-spent { color: var(--text-dim); opacity: .75; }
/* ⚠️ Napis „3 z 3" ZNIKA Z OKA, ale nie z dokumentu. Makieta rysuje rzad
   samych serc, a liczba i tak jest w nim dwa razy: w licznikach pelnych
   i pustych znakow oraz w `aria-label` pojemnika, ktory widok ustawia przy
   kazdym przerysowaniu. Dla czytnika ekranu nic nie ubywa. */
.zadanie-hearts__label {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Odznaka stawki. Bursztyn jest WYPELNIENIEM, napis bierze --reward-ink. */
.zadanie-stake {
  padding: 5px var(--sp-3);
  border-radius: var(--radius-pill);
  background: var(--reward);
  color: var(--reward-ink);
  font: 700 var(--fs-micro) var(--font-mono);
  white-space: nowrap;
}
.zadanie-stake[hidden] { display: none; }

/* Odznaka „+N XP" obok serc (ECON-02): zapowiedz nagrody przed rozstrzygnieciem.
   Ten sam pillbox co stawka, ale w kolorze nagrody, bo to jest liczba, ktora
   za chwile naprawde wpadnie na konto. */
.zadanie-xp-badge {
  padding: 5px var(--sp-3);
  border-radius: var(--radius-pill);
  background: var(--reward);
  color: var(--reward-ink);
  font: 700 var(--fs-micro) var(--font-mono);
  white-space: nowrap;
}
.zadanie-xp-badge[hidden] { display: none; }

.zadanie-hearts-note {
  margin: 0;
  color: var(--text-dim);
  font-size: var(--fs-micro);
  line-height: 1.45;
}
.zadanie-hearts-note[hidden] { display: none; }

/* ================= KARTA POLECENIA =================
 * Hierarchia jest wprost z makiety `zadanie-mobile-dark.png` i ma cztery
 * pietra, ani jednego wiecej:
 *
 *   1. TYTUL       tlusto, 19 px, kolor tekstu       (nazwa motywu)
 *   2. ZDANIE CELU szaro, 14,5 px, normalna waga     (co trzeba zrobic)
 *   3. LINIA       1 px --border, odstep 14 px       (koniec polecenia)
 *   4. CZYJ RUCH   ikona figury + „Twoj ruch (biale)"
 *
 * Bylo do 03.09.2026: zdanie celu tluste 15 px, pod nim „Masz 1 ruch."
 * w monospace na zieleni, pod tym „Ruch bialych." w monospace, a pod karta
 * kreskowane pudelko „TWOJ RUCH". Cztery gestosci pisma na cztery linijki.
 */

.zadanie-prompt {
  display: grid;
  gap: 6px;
  padding: var(--sp-5) var(--sp-4);
  border-radius: var(--radius-lg);
}

/* Siatka, nie zawijany rzad: odznaki maja zostac PRZY tytule, a nie spasc
   pod niego wlasnym wierszem. Tytul dostaje `minmax(0, 1fr)`, wiec lamie sie
   na dwie linie, zamiast wypychac odznaki z karty. */
.zadanie-prompt__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--sp-3);
}
/* Odznaki po prawej stronie tytulu: zapowiedz nagrody i trudnosc zadania.
   Obie sa MALE i stoja w jednym ciagu, zeby tytul zostal jedyna rzecza,
   ktora rzuca sie w oczy. */
.zadanie-prompt__head > [hidden] { display: none; }

.zadanie-prompt__title {
  min-width: 0;
  margin: 0;
  color: var(--text);
  font-size: 19px;
  font-weight: 750;
  letter-spacing: -.02em;
  line-height: 1.25;
}
.zadanie-prompt__title:empty { display: none; }

/* Zdanie celu jest SZARE i NIETLUSTE. Tytul nad nim niesie nacisk; dwie
   tluste linijki jedna pod druga nie maja hierarchii. */
.zadanie-prompt__task {
  margin: 0;
  color: var(--text-dim);
  font-size: var(--fs-body-sm);
  font-weight: 400;
  line-height: 1.5;
}
.zadanie-prompt__limit {
  margin: 2px 0 0;
  color: var(--text-dim);
  font: 600 var(--fs-micro) var(--font-mono);
}
.zadanie-prompt__limit[hidden] { display: none; }

/* Znak figury z tej samej strony, co ruch. Kolor jest DODATKIEM: napis obok
   mowi „(biale)" albo „(czarne)", wiec stan czyta sie bez barwy (WCAG 1.4.1).
   Obrys utrzymuje bialy pionek widocznym takze w motywie jasnym. */
.zadanie-prompt__piece {
  font-size: 20px;
  line-height: 1;
}
/* ⚠️ Obrys, nie cien. W motywie jasnym bialy pionek na tle karty mial
   kontrast 1,2:1 i po prostu znikal; cien 1 px tego nie ratowal. Obrys
   `-webkit-text-stroke` trzyma znak widocznym w obu motywach, a wypelnienie
   dalej mowi, ktora to strona. */
.zadanie-prompt__piece.is-white {
  color: var(--sq-light);
  -webkit-text-stroke: 1px var(--text-dim);
}
.zadanie-prompt__piece.is-black { color: var(--text); }

.zadanie-prompt .lesson-feedback:empty { display: none; }

/* ================= SLOTY RUCHU (makieta 4.3 pkt 5) ================= */

.zadanie-slots {
  display: grid;
  gap: var(--sp-2);
}
.zadanie-slots[hidden] { display: none; }
.zadanie-slots__label {
  margin: 0;
  color: var(--text-dim);
  font: 700 var(--fs-label) var(--font-mono);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}
.zadanie-slots__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.zadanie-slot {
  display: grid;
  place-items: center;
  min-width: 68px;
  min-height: 40px;
  padding: 0 var(--sp-3);
  border: 2px dashed color-mix(in srgb, var(--text-dim) 55%, var(--border));
  border-radius: var(--radius);
  background: var(--bg-sunken);
  color: var(--text-dim);
  font: 700 var(--fs-meta) var(--font-mono);
}
.zadanie-slot.is-filled {
  border-style: solid;
  border-color: color-mix(in srgb, var(--accent) 52%, var(--border));
  background: color-mix(in srgb, var(--accent) 12%, var(--bg-raised));
  color: var(--text);
}

/* ================= DWA PRZYCISKI (makieta 4.3 pkt 6) ================= */

.zadanie-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-3);
}

.zadanie-action {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 4px;
  /* 44 px to minimum dotyku wg WCAG 2.2 AA (2.5.8). 62 px daje zapas na
     dwuwierszowa etykiete przy powiekszonym kroju. */
  min-height: 62px;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-raised);
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-body-sm);
  font-weight: 650;
  cursor: pointer;
  transition: background var(--dur-base) var(--ease), border-color var(--dur-base) var(--ease), color var(--dur-base) var(--ease), transform var(--dur-fast) var(--ease);
}
.zadanie-action svg { width: 22px; height: 22px; }
.zadanie-action:hover:not(:disabled) { border-color: var(--accent); }
.zadanie-action:active:not(:disabled) { transform: scale(.985); }
.zadanie-action:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
.zadanie-action:disabled { opacity: .55; cursor: default; }

/* ⚠️ „Poddaj sie" NIE MA WLASNEJ BARWY (szlif 1, znalezisko 10 z audytu
   wizualnego 03.09.2026).
   W zadaniu poddanie sie nie konczy niczego przegrana, tylko ODSLANIA
   rozwiazanie i uczy, wiec czerwien z partii tu nie wchodzi — to zostaje.
   Zielen tez nie: `--accent` niesie w calym produkcie JEDNA akcje
   pierwszoplanowa w kadrze, a pod plansza stoja cztery rownorzedne kafle.
   Do 03.09.2026 telefon malowal ten przycisk na zielono, desktop na ciemno,
   a partia kariery na czerwono: trzy wyglady jednej akcji. Zostaje jeden,
   ten neutralny z `.zadanie-action`, i to on obowiazuje w obu ukladach. */

/* Kaskada podpowiedzi zostaje karta, ale bez przycisku: ten stoi wyzej,
   w rzedzie akcji z makiety. Skoro karta nie ma juz wlasnego przycisku, PUSTA
   nie ma czego pokazac, a pusta ramka pod slotami wygladala jak usterka.
   Zwija sie wiec sama, bez ruszania atrybutu `hidden`, ktorym widok steruje
   dostepnoscia podpowiedzi w treningu rankingowym. */
.zadanie-hint {
  display: grid;
  gap: var(--sp-2);
  padding: var(--sp-3);
  border-radius: var(--radius);
}
.zadanie-hint[hidden] { display: none; }
.zadanie-hint:not(:has(.hint-note:not(:empty))) { display: none; }

/* Ciche wyjscie awaryjne. Nie ma ramki ani tla: makieta rysuje pod plansza
   CZTERY kafle i tylko cztery, wiec piaty ksztalt przycisku czytalby sie jak
   piata akcja. To jest napis, ktory da sie nacisnac. */
.lessons-player .zadanie-quiet {
  display: flex;
  gap: var(--sp-2);
  justify-content: center;
  padding: 0;
  border: 0;
  background: none;
}
.zadanie-quiet__btn {
  min-height: 44px;
  padding-inline: var(--sp-2);
  border-color: transparent;
  background: none;
  color: var(--text-dim);
  font-size: var(--fs-micro);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--text-dim) 45%, transparent);
  text-underline-offset: 4px;
}
.zadanie-quiet__btn:hover:not(:disabled) { border-color: transparent; background: none; color: var(--text); }
.zadanie-quiet__btn[hidden] { display: none; }

/* ================= EKRAN WYNIKU (makieta 4.4) ================= */

.zadanie-result[hidden] { display: none; }
.zadanie-result {
  z-index: 2;
  overflow-y: auto;
  /* Ekran wyniku: odstepy nosi __inner, powierzchnia jest z .card. */
  padding: 0;
}
.zadanie-result__inner {
  position: relative;
  display: grid;
  gap: var(--sp-3);
  justify-items: center;
  padding: var(--sp-5) var(--sp-4);
  text-align: center;
}

.zadanie-result__mascot { width: 92px; }
.mascot { display: block; width: 100%; height: auto; }
.mascot__shadow { fill: var(--accent); opacity: .28; }
.mascot__head,
.mascot__collar,
.mascot__stem,
.mascot__base { fill: var(--bg); stroke: var(--text-dim); stroke-width: 2.4; stroke-linejoin: round; }
.mascot__eye { fill: var(--text); }
.mascot__eye-lid,
.mascot__mouth { fill: none; stroke: var(--text); stroke-width: 2.4; stroke-linecap: round; }
.mascot__thumb { fill: var(--accent); stroke: var(--accent-strong); stroke-width: 2; stroke-linejoin: round; }
/* Bursztyn wypelnia zarowke; zaden napis go nie uzywa. */
.mascot__bulb { fill: var(--reward); stroke: var(--reward-ink); stroke-width: 2; stroke-linejoin: round; }
.mascot__bulb-base { fill: none; stroke: var(--reward-ink); stroke-width: 2.4; stroke-linecap: round; }

.zadanie-result__title {
  margin: 0;
  font-size: var(--fs-h2);
  font-weight: 780;
  letter-spacing: -.03em;
}
.zadanie-result.is-correct .zadanie-result__title { color: var(--accent-strong); }
/* Ekran bledu NIE dostaje czerwieni. Nagloowek stoi w zwyklym kolorze tekstu,
   bo pomylka nie jest kara, tylko informacja (sekcja 6 pkt 2). */
.zadanie-result.is-miss .zadanie-result__title { color: var(--text); }
.zadanie-result__title:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 4px; border-radius: var(--radius-sm); }

.zadanie-result__lead {
  max-width: 42ch;
  margin: 0;
  color: var(--text-dim);
  font-size: var(--fs-body-sm);
  line-height: 1.5;
}

.zadanie-card {
  width: 100%;
  text-align: left;
}

/* ---- karta ruchu ---- */
.zadanie-move {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--sp-1) var(--sp-3);
  align-items: center;
}
.zadanie-move__mark {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-meta);
  font-weight: 700;
}
.zadanie-result.is-correct .zadanie-move__mark { background: var(--accent); color: var(--accent-contrast); }
.zadanie-result.is-miss .zadanie-move__mark { background: var(--reward); color: var(--reward-ink); }
/* Ruch jest BOHATEREM karty rozwiazania (makieta: „1. Gxc1+!" duzym pismem).
   Bylo `--fs-h3`, czyli 16 px na telefonie: napis czytal sie jak podpis
   pod ikona, a nie jak odpowiedz na zadanie. */
.zadanie-move__san {
  margin: 0;
  color: var(--text);
  font: 750 22px var(--font-mono);
  letter-spacing: -.01em;
}
.zadanie-move__why {
  grid-column: 2;
  margin: 0;
  color: var(--text-dim);
  font-size: var(--fs-body-sm);
  line-height: 1.5;
}
.zadanie-move__variant {
  grid-column: 2;
  justify-self: start;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent-strong);
  font-family: inherit;
  font-size: var(--fs-micro);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.zadanie-move__variant[hidden] { display: none; }
.zadanie-move__variant:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; border-radius: var(--radius-xs); }
.zadanie-move__line {
  grid-column: 2;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.zadanie-move__line[hidden] { display: none; }
.zadanie-move__line li {
  padding: 3px var(--sp-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-xs);
  color: var(--text-dim);
  font: 600 var(--fs-micro) var(--font-mono);
}
/* Co drugi ruch nalezy do przeciwnika: inny odcien tla mowi to bez legendy. */
.zadanie-move__line li:nth-child(even) { background: var(--bg); }

/* ---- karta nagrody ---- */
.zadanie-reward { display: grid; gap: var(--sp-2); }
.zadanie-reward__title {
  margin: 0;
  color: var(--text-dim);
  font: 700 var(--fs-label) var(--font-mono);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}
.zadanie-reward__rows { display: grid; gap: 5px; margin: 0; padding: 0; list-style: none; }
.zadanie-reward__rows li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
}
.zadanie-reward__label { color: var(--text-dim); font-size: var(--fs-body-sm); }
.zadanie-reward__value { color: var(--text); font: 700 var(--fs-meta) var(--font-mono); }
.zadanie-reward__value.is-gain { color: var(--accent-strong); }
.zadanie-reward__note {
  margin: 0;
  color: var(--text-dim);
  font-size: var(--fs-micro);
  line-height: 1.5;
}

.zadanie-result__actions {
  display: grid;
  gap: var(--sp-2);
  width: 100%;
}
.zadanie-result__go { min-height: 52px; width: 100%; font-size: var(--fs-body); }
.zadanie-result__retry { min-height: 48px; width: 100%; }
.zadanie-result__retry[hidden] { display: none; }
/* Przy bledzie wiodace jest drugie podejscie, wiec to ono stoi wyzej i to ono
   dostaje wyglad akcji glownej. „Dalej" schodzi do roli cichego wyjscia. */
.zadanie-result.is-miss .zadanie-result__retry {
  order: -1;
  min-height: 52px;
  border-color: var(--accent);
  background: var(--accent);
  color: var(--accent-contrast);
  font-size: var(--fs-body);
}
.zadanie-result.is-miss .zadanie-result__retry:hover:not(:disabled) {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
}
.zadanie-result.is-miss .zadanie-result__go { background: none; border-color: var(--border); color: var(--text-dim); }
.zadanie-result.is-miss .zadanie-result__go:hover:not(:disabled) { color: var(--text); border-color: var(--accent); background: none; }

/* Wejscie karty: skala od 0.96 z wyprzedzeniem, bez odbicia (makieta, sekcja 5). */
@keyframes zadanie-result-in {
  from { opacity: 0; transform: scale(.96); }
  to { opacity: 1; transform: scale(1); }
}
.zadanie-result:not([hidden]) { animation: zadanie-result-in 220ms var(--ease) both; }

/* ---- konfetti: POJEDYNCZY wystrzal, nigdy petla ---- */
.zadanie-confetti {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  border-radius: inherit;
}
.zadanie-confetti span {
  position: absolute;
  top: -14px;
  width: 7px;
  height: 11px;
  border-radius: 1px;
  opacity: 0;
  /* Wypelnienie, przesuniecie i obrot przychodza z CSSOM (js/ui/confetti.js).
     CSP `style-src 'self'` blokuje ATRYBUT `style`, nie CSSOM. */
  background: var(--confetti-fill, var(--accent));
  animation: zadanie-confetti 1100ms var(--ease) forwards;
}
@keyframes zadanie-confetti {
  0% { opacity: 1; transform: translate3d(0, 0, 0) rotate(0deg); }
  100% { opacity: 0; transform: translate3d(var(--dx, 0), var(--dy, 260px), 0) rotate(var(--rot, 320deg)); }
}

/* ⚠️ ZASLONA NAD PLANSZA JEST WYGASZONA NA STALE (szlif 1, 03.09.2026).
 *
 * Bylo: na desktopie (blok 900 px) `.zadanie-veil` kladl na plansze
 * `color-mix(in srgb, var(--bg-sunken) 72%, transparent)` plus `blur(2px)`.
 * Na telefonie tej warstwy nie bylo wcale, wiec JEDEN stan produktu miał dwa
 * rozne zachowania.
 *
 * DLACZEGO POSZLA. Pomiar kontrastu obrysu figury wzgledem pola (skrypt
 * `scripts/zrzuty-szlif1.mjs`, dowod w `test/szlif1Welon.test.js`):
 *
 *   stan            biala figura / pole jasne   czarna figura / pole ciemne
 *   bez zaslony              8.97 : 1                    7.09 : 1
 *   zaslona 72 % jasna       1.59 : 1                    1.51 : 1
 *   zaslona 72 % ciemna      1.85 : 1                    1.71 : 1
 *
 * Prog 3:1 z WCAG 1.4.11 (elementy nieteksowe) nie byl domkniety w ZADNYM
 * motywie, a karta wyniku mowi wprost „Tak wygladalo rozwiazanie. Obejrzyj
 * je". Fala 12 dodala odgrywanie rozwiazania na planszy
 * (`LessonRunner#revealSolution`), wiec pod zaslona lezal ruch, ktorego caly
 * ekran kazal obejrzec.
 *
 * DLACZEGO NIC W ZAMIAN. Makieta ekranu wyniku
 * (`.planning/design/makiety/zadanie-wynik-mobile-dark.png`) rysuje plansze
 * w pelnej jasnosci, z odegranym ruchem i podswietlonym polem docelowym.
 * Zamiana zaslony na ramke czy winiete byłaby nowym elementem wizualnym bez
 * makiety, a plansza i tak nie przyjmuje juz ruchow (`setInteractive(false)`
 * w `revealSolution`). Slot `data-role="task-veil"` zostaje w markupie, bo
 * pilnuje go kontrakt slotow (test ZAD-01) — po prostu nic nie maluje.
 */
.zadanie-veil { display: none; }

/* ================= ELEMENTY WYLACZNIE DESKTOPOWE =================
 * Fala 3 nowej powloki (kontrakt MAKIETA-DESKTOP-2026-09-02, sekcja 1) dodaje
 * do ekranu Zadanie pasek nad plansza z trudnoscia, pasek akcji POD plansza
 * i trzy karty w kolumnie kontekstowej. Ponizej 900 px nic z tego nie ma prawa
 * sie pokazac, bo uklad mobilny z 01.09 zostaje bez zmian. Domyslka jest wiec
 * „wylaczone", a wlacza dopiero blok desktopowy na dole pliku.
 * Pojemniki nowej struktury sa `display: contents`, wiec na telefonie ich
 * dzieci wracaja tam, gdzie stawia je `order` z bloku mobilnego.
 */
.zadanie-rail,
.zadanie-block,
.zadanie-session,
.zadanie-strip { display: contents; }

.zadanie-topbar__difficulty,
.zadanie-prompt__turn,
.zadanie-block__label,
.zadanie-run,
.zadanie-session__head,
.zadanie-session__bar,
.zadanie-session__dots,
.zadanie-theme { display: none; }

/* ================= UKLAD MOBILNY (ponizej 900 px) ================= */
/*
 * ⚠️ KOLEJNOSC ZMIENIONA 03.09.2026 (grupa E, kontrakt makiet sekcja 2.12,
 * kadr `zadanie-mobile-dark.png`).
 *
 * Bylo (makieta 4.3 z 31.08): pasek gorny, serca ze stawka, polecenie,
 * plansza, sloty, podpowiedz. Plansza stala na czwartym miejscu, wiec przy
 * kadrze 390x844 jej gorna krawedz wypadala na y = 307 i pierwsze, co
 * widzial gracz, byly trzy paski liczb.
 *
 * Jest: pasek gorny (nazwa kategorii, trudnosc, licznik), kropki postepu
 * sesji, PLANSZA, karta polecenia, sloty, podpowiedz, serca. Plansza wchodzi
 * nad karte polecenia, bo zadanie jest pytaniem O POZYCJE, a nie o zdanie
 * pod nia; serca schodza pod polecenie, bo sa licznikiem prob, a nie
 * warunkiem wejscia (H11: serca sa MIEKKIE i niczego nie blokuja).
 *
 * `display: contents` na kolumnie planszy i na panelu rozsypuje oba pojemniki
 * na pojedyncze elementy siatki, dzieki czemu `order` moze przeplatac tresc
 * panelu z plansza. Powyzej 900 px ten blok nie obowiazuje w ogole, wiec
 * geometria kotwicy planszy zostaje nietknieta.
 */
@media (max-width: 899px) {
  .lessons-player.zadanie {
    display: flex;
    flex-direction: column;
    /* ⚠️ `align-items: start` dziedziczone z `.play-layout` (css/layout.css) w
       kolumnie flex znaczy „nie rozciagaj w poziomie", wiec kazdy element
       kurczyl sie do szerokosci wlasnej tresci: pasek gorny mial 189 px na
       358 px kolumny. W siatce ta sama deklaracja dotyczy pionu i jest tam
       poprawna, dlatego nie ruszamy jej u zrodla, tylko tutaj. */
    align-items: stretch;
    gap: var(--sp-3);
    max-width: none;
  }
  .zadanie > .board-column,
  .zadanie > .board-column > .board-stack,
  .zadanie > .side-panel { display: contents; }

  /* ---- EKRAN ZADANIA JEST ZANURZENIEM, NIE PODSTRONA ----
   * Kontrakt sekcja 1, zdanie pierwsze. Na czas rozwiazywania znika pasek
   * aplikacji (znak SZACHMATY, hamburger, kolo zebate): jego miejsce zajmuje
   * pas zadania. Zmierzone na kadrze 390x844: pasek aplikacji zabieral 56 px
   * gory, czyli 6,6 procent kadru, i spychal plansze o tyle w dol.
   * Warunek czyta STAN WIDOKU, a nie klase dopisana z JavaScriptu, wiec
   * wyjscie na inny widok samo przywraca pasek i nie da sie zostawic
   * aplikacji bez nawigacji. Powyzej 900 px `.app-bar` jest lewa szyna
   * nawigacji i ta regula go nie dotyczy. */
  /* Ukrycie paska gornego: stan sesji w css/layout.css (D-F1-07). */

  /* ---- pas zadania: powrot, „Sekcja · Nazwa", kropki, licznik ----
   *
   * ⚠️ css/lessons.css ponizej 480 px przestawia `.lesson-header` na wlasna
   * siatke (tytul na cala szerokosc w 2. wierszu, postep w 1.). Pasek zadania
   * dzieli z lekcja klase, wiec te reguly musza tu zostac odwrocone jawnie,
   * inaczej tytul i postep siadaja jeden na drugim.
   *
   * ⚠️ JEDEN WIERSZ, jak na makiecie. Fala z 03.09 rano musiala lamac pas na
   * dwa wiersze, bo licznik brzmial „0 / 9 rozwiazanych" (okolo 137 px z 358
   * px pasa) i na nazwe kategorii zostawalo 55 px. Licznik brzmi teraz „0 z 9"
   * (okolo 42 px), a ikona ustawien zeszla do paska pod plansza, wiec na tytul
   * zostaje 358 - 44 (powrot) - 42 (licznik) - 69 (kropki) - 18 (odstepy),
   * czyli okolo 185 px. Drugi wiersz nie jest juz potrzebny.
   */
  .zadanie .zadanie-topbar {
    order: 1;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 6px;
    min-height: 44px;
  }
  /* ⚠️ `grid-row` i `grid-column` MUSZA byc jawne: css/lessons.css ponizej
     480 px przestawia `.lesson-header-title` na drugi wiersz, a pas zadania
     dzieli z lekcja te klase. Bez tego tytul spadal pod strzalke powrotu
     i pas rosl z 44 do 70 px (zmierzone na kadrze 390x844). */
  .zadanie .zadanie-topbar__title {
    grid-column: 2;
    grid-row: 1;
    font-size: 15px;
    font-weight: 650;
    letter-spacing: -.015em;
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
  }
  /* ⚠️ ODZNAKA TRUDNOSCI ZNIKA Z PASA NA TELEFONIE. Jej miejsce zajely kropki
     postepu sesji z makiety, a dwa rzedy kropek obok siebie czytaly sie jak
     jeden rzad o dziwnej kolejnosci. Pomiar z kadru 390x844: odznaka zajmowala
     86 px z 358 px pasa i wypychala tytul do „Maty · Mat w 1: pod…".
     Ta sama odznaka stoi na telefonie przy prawej krawedzi rzedu serc
     (slot `practice-difficulty`), wiec liczba nie znika z ekranu. */
  .zadanie .zadanie-topbar__difficulty { display: none; }
  .zadanie .zadanie-topbar__progress {
    grid-column: 4;
    grid-row: 1;
    justify-self: end;
    margin-left: 0;
    color: var(--text);
    font: 600 15px var(--font-ui);
    text-align: right;
  }
  .zadanie .zadanie-topbar > [data-action="exit-practice"] { grid-column: 1; grid-row: 1; }
  /* „Zakoncz sesje" wchodzi do pasa WYLACZNIE w treningu rankingowym i staje
     w nowym wierszu na calej szerokosci: w rzedzie z tytulem nie ma dla niego
     miejsca, a sciskanie tytulu bylo usterka U1 z audytu 02.09.2026. */
  .zadanie .zadanie-topbar [data-action="end-rated-session"] {
    grid-column: 1 / -1;
    justify-self: end;
    min-width: 0;
    min-height: 30px;
    padding-block: 2px;
    padding-inline: var(--sp-2);
    font-size: var(--fs-micro);
    white-space: nowrap;
  }

  /* ---- kropki postepu sesji W PASIE (makieta `zadanie-mobile-dark.png`) ----
     Na obrazie stoja miedzy nazwa zadania a licznikiem, w jednym rzedzie.
     Element jest DRUGIM hostem tej samej listy, co kropki w prawej szynie:
     jedno zrodlo prawdy (`renderSessionDots` w js/views/practice.js), dwa
     uklady. Kropka pusta to zadanie jeszcze przed nami. */
  .zadanie .zadanie-topbar__dots {
    grid-column: 3;
    grid-row: 1;
    display: flex;
    align-items: center;
    gap: 3px;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .zadanie .zadanie-topbar__dots[hidden] { display: none; }
  /* ⚠️ 5 px zamiast 9 px, odstep 3 px zamiast 7 px. Pomiar z kadru 390x844:
     dziewiec kropek po 9 px z odstepem 7 px zabieralo 137 px z 358 px pasa
     i tytul konczyl sie na „Maty · Ma…". Przy 5/3 rzad ma 69 px, a na tytul
     zostaje okolo 185 px, czyli pelne „Maty · Mat w 1: podstawy". */
  .zadanie .zadanie-topbar__dots .zadanie-session__dot {
    width: 5px;
    height: 5px;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background: var(--bg-sunken);
  }
  .zadanie .zadanie-topbar__dots .zadanie-session__dot.is-ok { border-color: var(--reward); background: var(--reward); }
  .zadanie .zadanie-topbar__dots .zadanie-session__dot.is-miss { border-radius: var(--radius-xs); border-color: var(--text-dim); background: var(--text-dim); }
  .zadanie .zadanie-topbar__dots .zadanie-session__dot.is-skip { border-color: var(--text-dim); background: transparent; }
  .zadanie .zadanie-topbar__dots .zadanie-session__dot.is-pending { border-color: var(--border); background: color-mix(in srgb, var(--text-dim) 42%, transparent); }

  /* ---- wspolrzedne planszy (kontrakt sekcja 1: „czytelne, nie wciśnięte
     w narozniki pol") ----
     Zmiana jest ZAWEZONA do ekranu zadania: `.coord` z css/board.css obsluguje
     takze Gre, Lekcje i Analize, a te ekrany maja wlasne makiety. Bylo 10 px
     przy 4/3 px odstepu od krawedzi, jest 12 px przy 6/5 px. */
  .zadanie .board .coord { font-size: 12px; opacity: 1; }
  .zadanie .board .coord-file { right: 6px; bottom: 5px; }
  .zadanie .board .coord-rank { left: 6px; top: 5px; }

  /* Margines przewijania od DOLU, a nie od gory: widok przewija plansze tak,
     zeby jej dolna krawedz stanela tuz nad arkuszem wyniku (usterka U3).
     Wartosc to wysokosc arkusza plus 8 px odstepu, wiec cala plansza
     miesci sie nad nim, a nie tylko jej gorne rzedy. */
  /* Kotwica planszy (paczka 4/szlif4, 03.09.2026): `96vw - 34px` bylo
     wlasna liczba tego ekranu (340 px przy 390 px szerokosci) — token
     `--board-mobile-w` (css/board.css) daje 358 px, tak samo jak na
     Lekcji/Debiutach.
     ⚠️ Zwezanie PLANSZY, zeby zmiescic arkusz wyniku, psuloby jedyna rzecz,
     ktorej ta paczka pilnuje — wspolna lewa krawedz (16 px): `margin-inline:
     auto` na wezszej planszy odsuwa ja od lewej krawedzi WIECEJ niz 16 px.
     Poprawka idzie wiec w budzet ARKUSZA (58dvh -> 55dvh -> 50dvh, nizej), nie
     w szerokosc planszy. */
  .zadanie .board-wrap { order: 2; width: min(100%, var(--board-mobile-w)); margin-inline: auto; scroll-margin-bottom: calc(50dvh + 8px); }
  .zadanie .zadanie-prompt { order: 3; }
  .zadanie .zadanie-slots { order: 4; }
  .zadanie .zadanie-hint { order: 5; }
  .zadanie .zadanie-stakes { order: 6; }
  .zadanie .zadanie-hearts-note { order: 7; }
  .lessons-player .zadanie-quiet { order: 8; }

  /* ⚠️ ODZNAKA STAWKI W WARIANCIE „POSTEP KATEGORII" ZNIKA Z RZEDU SERC.
     Niosla, co do cyfry, ten sam napis co licznik pasa („0 z 9"), i do tego
     na bursztynie, wiec byla najglosniejszym elementem kadru bez ani jednej
     nowej informacji. Warianty „termin powtorki" i plakietka ratingu ZOSTAJA:
     one mowia rzeczy, ktorych pas nie mowi. Odznaka TRUDNOSCI takze zostaje
     i stoi przy prawej krawedzi rzedu (uzasadnienie przy pasie wyzej).
     Tresc odznaki stawki zostaje w dokumencie dla czytnika ekranu. */
  .zadanie .zadanie-stakes .zadanie-stake[data-stake="progress"] { display: none; }

  /* ---- karta polecenia: cienka linia i czyj ruch (kadr makiety) ----
     Kreska oddziela POLECENIE od STANU. Nad nia jest to, co masz zrobic,
     pod nia to, kim w tej pozycji jestes. */
  .zadanie .zadanie-prompt__turn {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 10px 0 0;
    padding-top: var(--sp-4);
    border-top: 1px solid var(--border);
    color: var(--text);
    font-size: var(--fs-body-sm);
    font-weight: 500;
  }
  .zadanie .zadanie-prompt__turn[hidden] { display: none; }

  /* Polecenie i sloty ruchu to JEDNA karta, dokladnie jak na desktopie:
     sloty sa ciagiem dalszym tego samego zdania. Do 03.09.2026 „TWOJ RUCH"
     wisial na telefonie bez ramki miedzy karta polecenia a rzedem serc
     i czytal sie jak sierota po trzeciej karcie. */
  .zadanie .zadanie-prompt:has(+ .zadanie-slots:not([hidden])) {
    padding-bottom: var(--sp-3);
    border-bottom: 0;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
  }
  .zadanie .zadanie-slots {
    padding: 0 var(--sp-4) var(--sp-4);
    border: 1px solid var(--border);
    border-top: 0;
    border-bottom-left-radius: var(--radius-lg);
    border-bottom-right-radius: var(--radius-lg);
    background: var(--bg-raised);
  }
  .zadanie .zadanie-slots[hidden] { display: none; }

  /* D-07: w trakcie sesji pasek zakladek ustepuje miejsca akcjom sesji.
     Warunek czyta STAN WIDOKU, a nie klase dopisana z JavaScriptu: dzieki
     temu wyjscie na inny widok samo przywraca pasek i nie da sie zostawic
     aplikacji bez nawigacji. */
  /* Ukrycie zakladek i stopki: stan sesji w css/layout.css (D-F1-07). */

  /* ---- PRZYPIETY PASEK CZTERECH AKCJI (kontrakt makiet 2.12) ----
   *
   * Historia tego miejsca w dwoch zdaniach. Usterka U2 z audytu 02.09.2026
   * (`audyt-zadania-sesja-390.png`): „Wstecz" i „Pomin zadanie" stoja w toku
   * dokumentu POD plansza, a pasek akcji jest przypiety do dolu, wiec przy kadrze
   * 390x844 wypadaly dokladnie pod paskiem i byly przeciete w polowie. Fala 12
   * naprawila to, doklejajac ciche wyjscia do przypietego dolu jako CIENKI
   * rzad nad dwoma duzymi akcjami, czyli DWA pasma jedno na drugim.
   *
   * ⚠️ 03.09.2026 (grupa E) dwa pasma zlewaja sie w JEDEN rzad czterech
   * rownych kafli, tak jak kadr `zadanie-mobile-dark.png`. Powod jest
   * mierzalny: dwa pasma zabieraly 142 px dolu ekranu (86 + 56), czyli 17
   * procent kadru 844 px, na cztery przyciski, ktore mieszcza sie w 78 px.
   * Odzyskane 64 px idzie do planszy.
   *
   * ⚠️ Rzad jest ZAGNIEZDZONA siatka, a nie jedna siatka czterech kolumn,
   * i to jest decyzja, nie przypadek. `.zadanie-strip` dzieli szerokosc na
   * dwie polowy, a kazdy z dwoch pojemnikow dzieli swoja polowe na dwie
   * kolumny. Wynik jest CO DO PIKSELA taki sam jak `repeat(4, 1fr)`
   * (szerokosc kafla to (W - 24) / 4 w obu wariantach, bo odstep wewnetrzny
   * rowna sie zewnetrznemu), ale `.zadanie-actions` zachowuje wlasne
   * pudelko. Pierwsza wersja robila oba pojemniki `display: contents`
   * i wywracala `zadaniaUsterki.spec.js` (U2), ktory mierzy, czy ciche
   * wyjscia nie chowaja sie POD paskiem akcji: pudelko pojemnika bez ukladu
   * jest puste, wiec test nie mial czego porownac. Zamiar tamtej bramy jest
   * dalej sluszny i dalej dziala: ciche wyjscia stoja OBOK akcji, nie pod
   * nimi.
   *
   * Kolejnosc w dokumencie zostaje kolejnoscia na ekranie, wiec tabulacja
   * zgadza sie z obrazem: Podpowiedz, Poddaj sie, Wstecz, Pomin zadanie.
   */
  .zadanie {
    /* 10 + 62 + 10: padding paska i minimalna wysokosc kafla. */
    --zadanie-bar-h: 82px;
    /* Zostaje na zero: cichy rzad nie ma juz wlasnego pasma. Zmienna zyje,
       bo czyta ja odstep tresci ponizej. */
    --zadanie-quiet-h: 0px;
  }

  /* Pasek akcji stoi nad trescia, wiec ostatni element widoku musi miec pod
     soba tyle miejsca, ile pasek zajmuje. */
  body:has(#view-practice.is-active [data-role="practice-player"]:not([hidden])) .app-main {
    padding-bottom: calc(var(--zadanie-bar-h, 82px) + var(--sp-3) + env(safe-area-inset-bottom, 0px));
  }

  .zadanie .zadanie-strip {
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 30;
    order: 9;
    display: block;
    max-width: 520px;
    margin-inline: auto;
    padding: 10px var(--sp-3) calc(10px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--border);
    background: color-mix(in srgb, var(--bg-raised) 95%, transparent);
    backdrop-filter: blur(16px);
  }

  /* Cztery rowne kafle w JEDNEJ siatce. Do 03.09.2026 rzad byl siatka
     zagniezdzona (dwa pojemniki po dwie kolumny), bo ciche wyjscia mialy
     wlasne pudelko mierzone przez `zadaniaUsterki.spec.js`. „Poddaj sie"
     wyprowadzilo sie z paska, wiec pojemnik zostal jeden i zagniezdzenie
     stracilo powod. */
  .zadanie .zadanie-strip > .zadanie-actions {
    position: static;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--sp-2);
    padding: 0;
    border: 0;
    background: none;
  }

  /* Cztery kafle o jednym KSZTALCIE, ikona nad podpisem (kontrakt sekcja 1).
     Cel dotyku 62 px, czyli powyzej minimum 44 px z WCAG 2.2 AA (2.5.8),
     takze przy dwuwierszowej etykiecie („Podpowiedz" lamie sie przy 320 px).
     ⚠️ Ta regula ustawia wylacznie geometrie i krój. Barwy przychodza
     z `.zadanie-action` i sa dla wszystkich czterech kafli te same. */
  .zadanie .zadanie-strip .zadanie-action {
    min-width: 0;
    min-height: 62px;
    gap: 5px;
    padding: var(--sp-2) 4px;
    font-size: var(--fs-micro);
    font-weight: 550;
    line-height: 1.2;
  }
  .zadanie .zadanie-strip .zadanie-action svg { width: 21px; height: 21px; }
  /* Podpis kafla ZAWIJA sie, a nie jest przycinany wielokropkiem: przy 320 px
     rzad pokazywal „Podpowi…" i „Ustawie…". Dwie linijki mieszcza sie
     w 62 px razem z ikona 21 px. */
  .zadanie .zadanie-strip .zadanie-action__label { max-width: 100%; text-wrap: balance; }

  /* „Poddaj sie" jest cichym wyjsciem pod trescia, a nie piatym kaflem:
     to rezygnacja, nie rownorzedna akcja. Pelna szerokosc, bo ponizej 680 px
     tak wyglada kazdy przycisk tego widoku. */
  .lessons-player .zadanie-quiet { margin-top: -2px; }
  .lessons-player .zadanie-quiet__btn {
    width: 100%;
    min-height: 44px;
    color: var(--text-dim);
    font-size: var(--fs-micro);
  }

  /* ⚠️ USTERKA U3 z audytu 02.09.2026 (audyt-zadania-wynik-poprawny-390.png).
     Makieta 4.4 mowila „ekran wyniku na telefonie zajmuje caly kadr" i tak
     bylo zbudowane: regula inset 0. Cena okazala sie za wysoka. Ekran wyniku
     tlumaczy RUCH — „hetman na a7 szachuje krola a8" — a plansza, na ktorej
     ten ruch stoi, znikala pod nakladka. Od 03.09.2026 wynik jest arkuszem
     przypietym do dolu: zajmuje najwyzej 60% wysokosci okna, a nad nim
     zostaje plansza z odegranym rozwiazaniem (zadanie Z3). Tresci nie ubywa,
     arkusz przewija sie w srodku. Na desktopie nic sie nie zmienia. */
  .zadanie-result {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 210;
    /* Kotwica planszy: 58dvh -> 55dvh (paczka 4/szlif4) -> 50dvh (przebudowa
       z makiety, 03.09.2026 wieczorem).
       ⚠️ Ostatnie ciecie ma inna przyczyne niz poprzednie i warto ja zapisac.
       Wczesniej ekran zadania byl WYZSZY od kadru (pasek aplikacji 56 px plus
       stopka serwisu), wiec plansze dalo sie PRZEWINAC nad arkusz i robil to
       `scrollIntoView` w `showResult`. Po zanurzeniu dokument ma dokladnie
       844 px przy oknie 844 px: nie ma czego przewijac, wiec o tym, czy
       plansza zostaje widoczna, decyduje juz wylacznie wysokosc arkusza.
       Pomiar: plansza konczy sie na y = 414, arkusz 55dvh zaczynal sie na
       y = 385 i zakrywal jej 29 px. 50dvh daje poczatek na y = 422, czyli
       8 px zapasu. Tresci nie ubywa: przyciski sa lepkie, a reszta przewija
       sie w srodku arkusza. */
    max-height: min(520px, 50dvh);
    overflow-y: auto;
    border: 1px solid var(--border);
    border-bottom: 0;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    background: var(--bg);
    box-shadow: 0 -18px 44px color-mix(in srgb, var(--bg-sunken) 70%, transparent);
  }
  /* Uchwyt arkusza (kadr `zadanie-wynik-mobile-dark.png`): jedna kreska
     u gory, ktora mowi „to jest arkusz wysuwany od dolu", a nie „ekran".
     Jest LEPKI, wiec zostaje na gorze takze wtedy, gdy tresc arkusza
     przewija sie w srodku. Pigulke rysuje tlo, bo pseudoelement nie ma
     wlasnego dziecka do zaokraglenia, a przy 4 px wysokosci roznicy nie
     widac, a jedna warstwa mniej to jedna warstwa mniej. */
  .zadanie-result::before {
    content: "";
    position: sticky;
    top: 0;
    z-index: 2;
    display: block;
    height: 16px;
    background-color: var(--bg);
    background-image: linear-gradient(var(--border), var(--border));
    background-repeat: no-repeat;
    background-position: center 7px;
    background-size: 44px 4px;
  }

  /* ⚠️ MASKOTKA W WIERSZU TYTULU, nie nad nim (kadr makiety).
     Uklad kolumnowy kosztowal 84 px wysokosci arkusza, ktory ma najwyzej
     58 procent kadru: przy 390x844 zielony „Dalej" wypadal 120 px pod dolna
     krawedzia i trzeba bylo przewijac arkusz, zeby domknac zadanie.
     Maskotka jest tu WYLACZNIE ustawiona inaczej; jej wyglad zostaje nasz
     (kontrakt makiet, H2). */
  .zadanie-result__inner {
    grid-template-columns: auto minmax(0, 1fr);
    align-content: start;
    justify-items: start;
    gap: var(--sp-2) var(--sp-3);
    padding: var(--sp-3) var(--sp-4) calc(var(--sp-4) + env(safe-area-inset-bottom, 0px));
    text-align: left;
  }
  .zadanie-result__inner > * { grid-column: 1 / -1; }
  .zadanie-result__mascot { grid-column: 1; grid-row: 1 / span 2; align-self: center; width: 56px; }
  .zadanie-result__title { grid-column: 2; grid-row: 1; align-self: end; font-size: 22px; }
  .zadanie-result__lead { grid-column: 2; grid-row: 2; align-self: start; }
  .zadanie-card { width: 100%; max-width: 520px; padding: var(--sp-3); }
  /* ⚠️ AKCJA WIODACA JEST ZAWSZE W KADRZE (kontrakt sekcja 2: „na dole pelnej
     szerokosci zielony Dalej").
     Pomiar z kadru 390x844, ekran bledu: tresc arkusza ma 510 px, a arkusz
     najwyzej 55 dvh, czyli 464 px. Zielony przycisk wypadal 56 px pod dolna
     krawedzia i domkniecie zadania wymagalo przewiniecia arkusza. Podniesienie
     limitu do 60 dvh zabieraloby plansze, czego zabrania usterka U3, wiec
     przyciski sa LEPKIE u dolu arkusza: tekst przewija sie za nimi, a akcja
     stoi tam, gdzie rysuje ja makieta. Ekran trafienia jest krotszy i lepkosc
     nie robi tam nic. */
  .zadanie-result__actions {
    position: sticky;
    bottom: calc(-1 * env(safe-area-inset-bottom, 0px));
    z-index: 3;
    width: 100%;
    max-width: 520px;
    padding-top: var(--sp-2);
    background: linear-gradient(to bottom, transparent, var(--bg) 12px);
  }
}

/* ⚠️ Ciche wyjscia wyprowadzily sie z panelu bocznego do paska pod plansza,
   wiec przestala je obejmowac regula `.lessons-player .side-panel >
   .controls-row .btn { width: 100% }` z css/lessons.css (blok 680 px). Bez
   przepisania jej na nowe miejsce oba przyciski na telefonie kurczyly sie do
   szerokosci wlasnego napisu zamiast wypelniac wiersz. Pomierzone: roznica
   737 pikseli w kadrze 390x844 wzgledem stanu sprzed zmiany. */
@media (max-width: 680px) {
  .lessons-player .side-panel > .zadanie-quiet .btn { width: 100%; min-width: 0; }
}

/* Najwezszy telefon w zestawie kontrolnym (320x720): podpis kafla schodzi
   o pol punktu, a kafel dostaje zapas na druga linijke. */
@media (max-width: 359px) {
  .zadanie .zadanie-strip .zadanie-action { min-height: 68px; font-size: 11.5px; }
}

/* ================= UKLAD DESKTOPOWY (od 900 px) ================= */
/*
 * Sekcja 3.3: „na desktopie wynik pojawia sie w prawej kolumnie i jako
 * nakladka nad plansza, nie zabiera calego widoku". Wynik siada wiec w tej
 * samej komorce siatki co kolumna kontekstowa i przykrywa ja. Plansza NIE
 * dostaje juz wlasnej zaslony (szlif 1, uzasadnienie przy `.zadanie-veil`
 * na gorze pliku): „nie zabiera calego widoku" znaczy, ze plansza zostaje
 * widoczna, a nie ze robi sie z niej szara plama. Zadna z tych warstw nie
 * zmienia `grid-template-columns` ani wysokosci paska nad plansza.
 */
@media (min-width: 900px) {
  /* Wynik zajmuje kolumne kontekstowa w calosci. Bez tego stawka i polecenie
     wystawaly spod karty wyniku i wygladaly jak druga, niedomknieta warstwa. */
  .zadanie:has(> .zadanie-result:not([hidden])) > .side-panel { display: none; }

  .zadanie.play-layout > .zadanie-result {
    grid-column: 2;
    grid-row: 1;
    /* Statycznie, dokladnie z tego samego powodu co kolumna kontekstowa:
       wynik ma zaczynac sie rowno z pasem nad plansza, a plansza pod nim ma
       ani drgnac. */
    position: static;
    max-height: calc(100dvh - 96px);
  }
  .zadanie-result__inner { padding: var(--sp-4) var(--sp-3); gap: var(--sp-2); }
  .zadanie-result__mascot { width: 68px; }
  .zadanie-card { padding: var(--sp-3); }
  .zadanie-result__go { min-height: 46px; }
  .zadanie-result__retry { min-height: 44px; }

  /* ================= FALA 3: EKRAN ZADANIE W SYSTEMIE ZE STARTU =============
   * Slownik jest ten sam, co na Starcie: karty na `--bg-raised`, obwodka 1 px
   * `--border`, promien `--radius-lg`, liczby w Geist Mono, zielen WYLACZNIE
   * na postepie i na jednej akcji pierwszoplanowej. Plansza zostaje kotwica
   * (x=342 y=118 w=640 przy 1440x900): ten blok nie rusza siatki powloki,
   * wysokosci `--board-head` ani `.board-wrap`.
   */

  /* ---- pasek nad plansza: nazwa kategorii, trudnosc, licznik ----
     Flex zamiast siatki, bo pasek ma zmienna liczbe dzieci: „Zakoncz sesje"
     dochodzi w treningu rankingowym, a odznaka trudnosci znika, gdy zadanie
     jej nie ma. Wysokosc pasa (46 px) zostaje bez zmian. */
  .zadanie .zadanie-topbar {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
  }

  .zadanie .zadanie-topbar__title {
    flex: 0 1 auto;
    font-size: 19px;
    text-align: left;
  }

  .zadanie-topbar__difficulty { display: inline-flex; flex: none; }
  .zadanie-topbar__difficulty[hidden] { display: none; }

  /* Licznik odchodzi na prawa krawedz planszy, tuz przed ikone ustawien. */
  .zadanie .zadanie-topbar__progress { margin-left: auto; }

  /* ⚠️ USTERKA U1 z audytu 02.09.2026 (audyt-zadania-rankingowy-1440.png).
     „Zakoncz sesje" wchodzi do paska WYLACZNIE w treningu rankingowym i bez
     wlasnej reguly zachowywal sie jak zwykly element flexa: kurczyl sie
     ponizej wlasnej tresci, lamal napis na dwie linie, nachodzil na strzalke
     powrotu i odbieral tytulowi tyle miejsca, ze „Trening rankingowy" konczyl
     sie wielokropkiem. Kadr mial 1440 px, wiec to nie byl problem waskiego
     ekranu, tylko brakujacego flex none. Przycisk stoi teraz przy prawej
     krawedzi, obok licznika i ustawien (kolejnosc pilnuje js/views/practice.js,
     ktory wstawia go w dokumencie tuz przed ikona ustawien). */
  .zadanie .zadanie-topbar [data-action="end-rated-session"] {
    flex: none;
    min-width: 0;
    min-height: 34px;
    padding-block: 4px;
    padding-inline: var(--sp-3);
    font-size: var(--fs-meta);
    white-space: nowrap;
  }

  /* ---- pasek CZTERECH KAFLI pod plansza (kontrakt sekcja 3) ----
     „Pasek dolny to te same cztery kafle co na telefonie". Do 03.09.2026
     komputer mial tu rzad przyciskow z ikona OBOK napisu, a telefon kafle
     z ikona NAD napisem: dwa wyglady jednej rzeczy. Zostaje jeden, ten
     z makiety. ZADNEGO zielonego przycisku: jedyna akcja pierwszoplanowa
     zadania w toku to ruch na planszy (K3). */
  .zadanie-strip {
    display: block;
    width: min(100%, var(--board-size));
  }

  .zadanie-strip .zadanie-actions {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--sp-2);
  }

  .zadanie-strip .zadanie-action {
    min-height: 62px;
    gap: 5px;
    padding: var(--sp-2) var(--sp-3);
    font-size: var(--fs-micro);
    font-weight: 550;
  }

  .zadanie-strip .zadanie-action svg { width: 21px; height: 21px; }

  /* ---- kolumna kontekstowa: trzy karty ----
     Karty stoja jedna pod druga od GORY kolumny, dokladnie jak „Dzis",
     „Najczestsze bledy" i „Poziom" na Starcie. Rozciagania ostatniej karty do
     dolu probowano i odrzucono: karta motywu z trzema linijkami tekstu
     i 200 px pustki w srodku wyglada gorzej niz tlo strony pod kartami.

     `position: static` zamiast lepkiego `top: 78px` z powloki: ekran sesji
     miesci sie w jednym kadrze, a lepkosc spychala cala kolumne 26 px nizej
     niz pas nad plansza (element lepki, ktory jeszcze nie doszedl do swojego
     `top`, jest przez nie PRZESUWANY W DOL). Kontrakt kaze wyrownac kolumne
     do GORY tego pasa. Selektor musi byc mocniejszy niz `.play-layout
     .side-panel` z powloki, stad `.zadanie.play-layout`. */
  .zadanie.play-layout > .side-panel {
    position: static;
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    align-content: start;
  }

  /* Trudnosc stoi teraz w pasku nad plansza. Slot w bloku „Zycia" ZOSTAJE
     w DOM (inwentarz, sekcja 3) i obsluguje telefon, ale na desktopie ta sama
     liczba dwa razy w jednym kadrze bylaby szumem. */
  .zadanie-lives [data-role="practice-difficulty"],
  .zadanie-prompt__head [data-role="practice-difficulty"] { display: none; }

  /* Odznaka stawki w wariancie „postep kategorii" mowi dokladnie to samo, co
     licznik nad paskiem („0 z 9"). Dwa razy ta sama liczba, w tym raz na
     bursztynie, byloby najglosniejszym elementem ekranu bez zadnej nowej
     tresci. Warianty „termin powtorki" i plakietka ratingu zostaja. */
  .zadanie-lives .zadanie-stake[data-stake="progress"] { display: none; }

  /* Polecenie i sloty ruchu to JEDNA karta: sloty sa ciagiem dalszym tego
     samego zdania, a dwie ramki pod soba czytaly sie jak dwie sprawy. */
  .zadanie-prompt:has(+ .zadanie-slots:not([hidden])) {
    padding-bottom: var(--sp-3);
    border-bottom: 0;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
  }

  .zadanie .zadanie-slots {
    padding: 0 var(--sp-4) var(--sp-4);
    border: 1px solid var(--border);
    border-top: 0;
    border-bottom-left-radius: var(--radius-lg);
    border-bottom-right-radius: var(--radius-lg);
    background: var(--bg-raised);
  }
  .zadanie .zadanie-slots[hidden] { display: none; }

  /* Karta polecenia powtarza hierarchie z telefonu, co do pietra (kontrakt
     sekcja 3): tytul, zdanie, linia, czyj ruch. */
  .zadanie-prompt__turn {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 8px 0 0;
    padding-top: var(--sp-3);
    border-top: 1px solid var(--border);
    color: var(--text);
    font-size: var(--fs-body-sm);
    font-weight: 500;
  }
  .zadanie-prompt__turn[hidden] { display: none; }

  /* ---- PRAWA SZYNA: JEDNA WYSOKA KARTA (kontrakt sekcja 3) ----
   *
   * Bylo do 03.09.2026: trzy luzne karty jedna pod druga („Postep sesji",
   * kaskada podpowiedzi, „Motyw"), kazda z wlasna obwodka 1 px i wlasnym
   * promieniem. Kadr 1440x900 liczyl w prawej kolumnie SZESC krawedzi
   * poziomych na 340 px szerokosci.
   *
   * Jest: jedna karta, w niej cztery bloki rozdzielone WLOSOWA linia, rytm
   * z `szturm-desktop-dark.png`: etykieta wersalikami w monospace, pod nia
   * wartosc, cienka linia, nastepny blok. Krawedzi poziomych jest teraz
   * dwie (gora i dol karty) plus trzy wlosy w srodku.
   */
  .zadanie-rail {
    display: flex;
    flex-direction: column;
    /* Pojemnik blokow z wlasnymi odstepami, nie karta z trescia. */
    padding: 0;
  }

  .zadanie-block {
    display: grid;
    gap: var(--sp-2);
    padding: var(--sp-5);
  }
  .zadanie-block + .zadanie-block { border-top: 1px solid var(--border); }

  .zadanie-block__label {
    display: block;
    margin: 0;
    color: var(--text-dim);
    font: 700 var(--fs-label) var(--font-mono);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
  }

  /* Duza wartosc bloku, w rytmie „SERIA 5" z makiety pulpitu szturmu. */
  .zadanie-block__big {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0;
    color: var(--text);
    font: 700 26px var(--font-mono);
    line-height: 1;
    font-variant-numeric: tabular-nums;
  }
  .zadanie-run { display: grid; }

  /* ---- blok „Postep sesji" ---- */
  .zadanie-session {
    display: grid;
    gap: 10px;
  }

  .zadanie-session__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-3);
  }

  .zadanie-session__count {
    color: var(--text);
    font: 700 var(--fs-meta) var(--font-mono);
    font-variant-numeric: tabular-nums;
  }

  /* Pasek postepu: natywny <progress>, ten sam ksztalt co na Starcie. */
  .zadanie-session__bar {
    -webkit-appearance: none;
    appearance: none;
    display: block;
    width: 100%;
    height: 6px;
    border: 0;
    border-radius: var(--radius-pill);
    background: var(--bg-sunken);
    color: var(--accent);
  }
  .zadanie-session__bar::-webkit-progress-bar { border-radius: var(--radius-pill); background: var(--bg-sunken); }
  .zadanie-session__bar::-webkit-progress-value { border-radius: var(--radius-pill); background: var(--accent); }
  .zadanie-session__bar::-moz-progress-bar { border-radius: var(--radius-pill); background: var(--accent); }

  /* Kropki ostatnich rozstrzygniec. Stan czytelny BEZ koloru: trafienie to
     kolo pelne, pomylka kwadrat, pominiecie kolo puste (WCAG 1.4.1). */
  .zadanie-session__dots {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .zadanie-session__dots[hidden] { display: none; }

  .zadanie-session__dot {
    width: 11px;
    height: 11px;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background: transparent;
  }
  .zadanie-session__dot.is-ok { border-color: var(--accent); background: var(--accent); }
  .zadanie-session__dot.is-miss { border-radius: var(--radius-xs); border-color: var(--reward); background: var(--reward); }
  .zadanie-session__dot.is-skip { border-color: var(--text-dim); background: transparent; }
  .zadanie-session__dot.is-pending { border-color: var(--border); background: color-mix(in srgb, var(--text-dim) 42%, transparent); }

  /* Serca i odznaki w jednym ciagu od lewej: `space-between` z ukladu
     mobilnego rozrzucalo dwa elementy na przeciwne krawedzie karty. */
  .zadanie-lives .zadanie-stakes {
    justify-content: flex-start;
    gap: var(--sp-2);
  }

  /* ---- blok „Motyw" z odeslaniem do Pojec ---- */
  .zadanie-theme {
    display: grid;
    justify-items: start;
    gap: 5px;
  }

  .zadanie-theme__title {
    margin: 0;
    color: var(--text);
    font-size: 15px;
    font-weight: 700;
    line-height: 1.3;
  }

  .zadanie-theme__desc {
    margin: 0;
    color: var(--text-dim);
    font-size: var(--fs-body-sm);
    line-height: 1.5;
  }

  .zadanie-theme__link {
    justify-self: start;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding-block: 0;
    color: var(--accent-strong);
    font-size: var(--fs-micro);
    font-weight: 700;
    text-decoration: underline;
    text-underline-offset: 3px;
  }

  /* Stopka na czas sesji: css/layout.css (D-F1-07). */
}

@media (prefers-reduced-motion: reduce) {
  .zadanie-result:not([hidden]) { animation: none; }
  .zadanie-action:active:not(:disabled) { transform: none; }
}

/* Odtwarzacz zadania z atrybutem hidden ma byc niewidoczny takze dla CSS
   (szlif UX faza 4, D-F4-02). Reguly ukladu (.play-layout, .lessons-player)
   ustawialy display i wygrywaly z [hidden]: pasek kafli `.zadanie-strip`
   (position: fixed) lezal pod paskiem zakladek na PRZEGLADZIE kategorii,
   a Lighthouse liczyl jego kafle jako cele dotyku bez miejsca. */
#view-practice .lessons-player.play-layout.zadanie[hidden] { display: none; }
