/* PictoCook: style aplikacji. Wspólne dla index.html i styleguide.html. */
@font-face { font-family:'Roboto'; font-style:normal; font-weight:400 700; font-display:swap; src:url(/fonts/roboto-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF }
@font-face { font-family:'Roboto'; font-style:normal; font-weight:400 700; font-display:swap; src:url(/fonts/roboto-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD }
@font-face { font-family:'Nunito'; font-style:normal; font-weight:400 900; font-display:swap; src:url(/fonts/nunito-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF }
@font-face { font-family:'Nunito'; font-style:normal; font-weight:400 900; font-display:swap; src:url(/fonts/nunito-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD }
/* [hidden] zawsze chowa: `display:` w klasie przesłaniałoby atrybut (UA ma niższą specyficzność), więc jedna globalna reguła zamiast łatek per klasa.
   Wyjątek: .clear[hidden] rezerwuje miejsce (visibility), patrz niżej. */
[hidden]:not(.clear) { display:none !important }
/* Skala: nowy styl = istniejący token. Wartości spoza tokenów widać w audycie na /styleguide.html. */
:root {
  color-scheme:only light; /* tylko jasny motyw (Kris 2026-10-17): opt-out z Auto Dark Chrome/WebView; kontrolki i paski przewijania jasne */
  --bg:#fbf8f2; --ink:#2b2622; --muted:#7a716a; --accent:#eb592e; --card:#fff; --line:#e6ddd0;
  --line-2:#cfc4b5;                 /* mocniejsza linia: ramka checkboxa, wyłączona gwiazdka */
  --soft:#f1e9dd;                   /* neutralne tło: przyciski drugorzędne, liczniki, placeholdery obrazków */
  --ok:#1f5e2a; --ok-soft:#e3efe3;  /* zrobione / timer */
  --qty:#fbe7d6; --qty-ink:#8a3b12; /* ilości (pigułka) */
  --fs-xs:12px; --fs-s:14px; --fs-m:16px; --fs-l:18px; --fs-xl:20px; --fs-2xl:26px;
  --r-xs:6px; --r-sm:10px; --r-md:14px; --r-lg:22px; --r-pill:999px;
  --app-w:520px;
  /* Yumicorn (strona główna i książka kategorii; ekran przepisu bez zmian): kremowe tło, czekoladowy tekst, pastelowe kafelki */
  --y-font:'Nunito',system-ui,sans-serif;  /* zaokrąglony sans (OFL), hostowany w public/fonts/ */
  --y-bg:#fdf8f1; --y-ink:#5b3320; --y-card:#fff;
  --y-sweet:#fbe1d2; --y-sweet-ink:#6e3519;       /* Słodkie: brzoskwinia */
  --y-snack:#dcebcf; --y-snack-ink:#235c1c;       /* Przekąski: pistacja */
  --y-drink:#e7ddf4; --y-drink-ink:#4b2a82;       /* Napoje: lawenda */
  --y-salty:#d5e7f5; --y-salty-ink:#174b74;       /* Słone: błękit */
  /* głębia (Kris, makieta): akcent kategorii = okrągły przycisk ze strzałką; podświetlenie górnej krawędzi kafelka */
  --y-sweet-acc:#ef6a5e; --y-snack-acc:#4fae3f; --y-drink-acc:#8a5cd6; --y-salty-acc:#2b86d1;
  --y-hi:rgba(255,255,255,.75);                    /* wewnętrzne światło u góry kafelka/karty */
  --y-tile-border:3px solid var(--y-card);         /* biała ramka kafelków, kart albumu/nagród i karty przepisu na kolorowym tle (Kris) */
  --y-sheet-lap:24px; --y-r-sheet:var(--r-xl);     /* arkusz strony głównej: nachodzi na hero, zaokrąglone górne rogi */
  /* krawędź arkusza na 1/3 wysokości górnego rzędu kafelków (Kris): kafelek = szer. kolumny × --y-tile-k + podpis + 2 ramki */
  /* naklejka z białym obrysem po kształcie (~3px, jak ramka kafelków): cztery ostre białe cienie, potem miękki ciemny */
  --y-sticker-filter:drop-shadow(2px 0 0 var(--y-card)) drop-shadow(-2px 0 0 var(--y-card)) drop-shadow(0 2px 0 var(--y-card)) drop-shadow(0 -2px 0 var(--y-card)) drop-shadow(0 4px 6px rgba(91,51,32,.35));
  --y-headsticker:38px;                             /* naklejka w nagłówku ~1,6 × wysokość wersalików tytułu */
  --y-tile-k:.7; --y-tile-label:56px;
  /* naklejka kategorii wystaje z kafelka (Kris, makieta): ~35% poza lewy górny róg → kafelki węższe (--y-tiles-pad) i większy odstęp */
  --y-tsticker:clamp(48px, 15.4vw, 64px); --y-tiles-pad:8px; --y-tiles-gap:24px;
  --y-occsticker:clamp(52px, 15vw, 64px);          /* naklejka okazji (dynia na Halloween) w prawym górnym rogu karty przepisu; wystaje jak --y-tsticker */
  --y-tiles-lift:calc(((min(100vw, var(--app-w)) - 32px - 2 * var(--y-tiles-pad) - var(--y-tiles-gap)) / 2 * var(--y-tile-k) + var(--y-tile-label) + 6px) / 3);
  --y-hero-shade:color-mix(in srgb, var(--y-ink) 50%, transparent); /* przyciemnienie góry hero (+ winieta w rogach) */
  --y-home-title-w:min(64vw, 250px);                /* tytuł „Yumicorn” na stronie głównej (home-title.webp) */
  --y-album:#fff1c9; --y-album-acc:#f0a91f; --y-awards:#efe5fb; --y-awards-acc:#9a6ad8; /* „Mój album” / „Moje nagrody” */
  --y-sky-white:40%;                                /* ile bieli w barwie nieba książki (łagodniej; Kris) */
  --y-sky-base:#fdf7ed; --y-sky-strip:195px;       /* niebo książki: gładki środek (próbka z csky-1) i wysokość pasów chmur (389 px obrazu ÷ 2) */
  --y-stitch:rgba(91,51,32,.22);                   /* przeszycie panelu z tytułem */
  --y-solo:#3fa94b; --y-adult:#ef7a2c;            /* plakietki: „Sam!” / „Z dorosłym” */
  --y-emboss:inset 0 1px 0 rgba(255,255,255,.45), inset 0 -2px 0 rgba(0,0,0,.12); /* lekki relief plakietek: światło u góry, cień u dołu */
  --y-muted:#8c6b58; --y-line:#eee1d3; --y-line-2:#d9c6b3; --y-soft:#f5eadf;  /* przepis dla dzieci: drugi plan, kreski, tła */
  --y-timer:#2f8a57; --y-timer-soft:#e1f1e6;      /* minutnik / czekanie */
  /* wysokość karty książki względem szerokości kartki (cqw): na wydłużonym telefonie karta nie rośnie w pionie bez końca */
  --y-card-max-3:72cqw;   /* 3 na kartce: obrazek ~2:1 + nazwa */
  --y-card-max-1:128cqw;  /* 1 na kartce: okładka ~kwadrat + nazwa */
  --y-card-gap:12px;
  --y-press-scale:.96; --y-press-dim:.93; --y-press-ms:120ms;  /* reakcja na dotyk (.press): lekko mniejsze i ciemniejsze */
  /* odznaki: kolor krążka grupy (Umiejętności koral, Zdrowie zieleń, Napoje błękit, Kamienie milowe miód, Specjalne lawenda) */
  --y-g-skill:#ffb39a; --y-g-health:#9fd98a; --y-g-drink:#97d0f2; --y-g-mile:#ffd277; --y-g-special:#cbb6f2;
  --y-glow:#fff6d8;  /* poświata za nową odznaką */
  --y-check:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E");
  --y-ap-peek:36px; /* podgląd zdjęcia w albumie: tyle zostaje po bokach, zerknięcie sąsiada = to minus --y-card-gap (24 px) */
  --y-next-h:64px; /* wysokość dużego „dalej” (.ybig, .next) i średnica okrągłego „wstecz” obok niego */
  --y-shine:rgba(255,255,255,.34); --y-shine-ms:5s;  /* „shine” na dużych przyciskach dalej: jasny pasek co kilka sekund */
  --y-sheet-ms:260ms; --y-wiggle-ms:250ms;  /* arkusz od dołu (wjazd/zjazd) · drgnięcie kłódki na karcie; JS czyta te same wartości */
  --y-warn-h:clamp(120px, 18dvh, 150px); /* wysokość Yumiego przy kroku dorosłego */
  /* JEDEN wygląd kart i obrazków Yumicorna (książka, podgląd, lista, krok, koniec, dymki): promień + cień */
  --ios-blue:#007aff;     /* systemowy niebieski iOS: napis „Dodaj” w instrukcji instalacji */
  --y-r-card:22px;        /* karty i duże obrazki */
  /* czas na karcie i podglądzie (TASK-31): ikona | pasek 3 segmentów | tekst dla dorosłego; podgląd większy (-pv) */
  --y-hand:72px; --y-swipe-ms:1.8s; /* podpowiedź przesuwania: palec i jeden cykl gestu (palec + karta) */
  --y-voice:56px; --y-hear:26px; --y-say-gap:12px; --y-voice-room:calc(var(--y-voice) + 20px); /* przełącznik głosu i miejsce na niego w nagłówkach */
  --y-star:#f5b82e; --y-star-off:var(--y-line-2); /* gwiazdki postępu odznak: zdobyta złota, pusta blady kontur */
  --y-time-ic:34px; --y-sv-ic-w:calc(var(--y-time-ic) * .94); --y-sv-ic-h:calc(var(--y-time-ic) * .76); /* talerz porcji z rozmiaru ikon czasu (pudełko poziome) */ --y-tbar-w:22px; --y-tbar-h:11px; --y-moon:#f6c945;
  --y-peek-w:104px;       /* „a kuku”: szerokość głowy/czapki Yumiego zza karty (na niskim ekranie JS zwęża ją, by nie wejść na tytuł) */
  --y-r-thumb:12px;       /* małe obrazki w karcie (składnik, naczynie, miniatura kroku) */
  --y-shadow:0 10px 24px -14px rgba(91,51,32,.5);
  --fs-3xl:30px; --y-fs-clock:46px; /* licznik przerwy z Yumim */
  --r-xl:28px;                    /* kolumna aplikacji na laptopie (apka jest mobilna) */
}
* { box-sizing:border-box }
/* pan-x pan-y, nie manipulation: manipulation zostawia pinch-zoom, a to on ma być zablokowany (TASK-76). Scroll-snap i swipe to pan, działają bez zmian. */
html,body { margin:0; height:100%; background:var(--bg); color:var(--ink); font-family:'Roboto',system-ui,-apple-system,sans-serif; -webkit-font-smoothing:antialiased; touch-action:pan-x pan-y }
button { font:inherit; color:inherit; cursor:pointer; -webkit-tap-highlight-color:transparent }
.screen { display:none }
.screen.active { display:flex; flex-direction:column }

/* ---- lista ---- */
#list.active { min-height:100dvh }
.appbar { position:sticky; top:0; z-index:5; background:var(--bg); padding:12px 16px 10px; transition:box-shadow .2s }
.appbar.scrolled { box-shadow:0 2px 12px rgba(0,0,0,.08) }
.barrow { display:flex; align-items:center; gap:8px }
.barrow .brand { flex:1 }
.iconbtn { flex:none; width:44px; height:44px; border-radius:50%; border:0; background:transparent; color:var(--ink); display:grid; place-items:center; padding:0 }
.iconbtn svg { width:24px; height:24px }
.iconbtn:active { background:var(--soft) }
.searchrow { display:flex; align-items:center; gap:6px; margin-top:10px }
.search::-webkit-search-cancel-button { -webkit-appearance:none; display:none }
.brand { display:flex; align-items:center; gap:12px }
.brand .logo { width:44px; height:44px; flex:none }
h1 { font-size:var(--fs-2xl); margin:0; letter-spacing:-.8px; line-height:1 }
h1 .wordmark { height:30px; width:auto; display:block }
.search { width:100%; padding:12px 14px; font-size:var(--fs-m); border:1px solid var(--line); border-radius:var(--r-sm); background:var(--card); color:var(--ink); outline:none }
.search:focus { border-color:var(--accent) }
.list { padding:4px 16px 32px; display:grid; gap:14px }
/* Karta = samo zdjęcie; dane na nim (chipy u góry, tytuł na gradiencie u dołu). */
.card { position:relative; display:block; width:100%; aspect-ratio:4/3.4; border:0; padding:0; border-radius:var(--r-lg); overflow:hidden; background:var(--soft); text-align:left; color:#fff;
        box-shadow:0 10px 28px -12px rgba(60,30,10,.45); transition:transform .25s cubic-bezier(.2,.8,.2,1), box-shadow .25s; -webkit-tap-highlight-color:transparent }
.card:active { transform:scale(.97); box-shadow:0 4px 14px -8px rgba(60,30,10,.5) }
.card img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; animation:drift 16s ease-in-out infinite alternate; animation-delay:calc(var(--i) * -3s) }
.card .shade { position:absolute; inset:auto 0 0 0; padding:56px 16px 16px; background:linear-gradient(transparent, rgba(20,12,6,.35) 35%, rgba(20,12,6,.82)) }
.card h2 { margin:0; font-size:var(--fs-2xl); font-weight:700; letter-spacing:-.4px; line-height:1.1; text-shadow:0 2px 10px rgba(0,0,0,.35) }
/* Trwające timery przepisu (jak dock w krokach), nad tytułem. */
.card .timers { display:flex; flex-direction:column; align-items:flex-start; gap:6px }
.card .timers:not(:empty) { margin-bottom:10px }
.card .timer { display:flex; align-items:center; gap:8px; max-width:100%; padding:6px 12px 6px 8px; border-radius:var(--r-pill); background:var(--ok);
        font-size:var(--fs-s); font-weight:500; box-shadow:0 4px 12px rgba(0,0,0,.25) }
.card .timer svg { width:18px; height:18px; flex:none }
.card .timer .t { white-space:nowrap; overflow:hidden; text-overflow:ellipsis }
.card .timer .left { font-variant-numeric:tabular-nums; font-weight:700 }
.card .meta { display:flex; align-items:center; gap:6px; margin-top:4px; font-size:var(--fs-s); opacity:.85 }
.card .meta svg { width:16px; height:16px; display:block }
/* Chipy zawsze w jednym wierszu: przy braku miejsca kurczy się tylko .fit (tekst → „…”), „Kontynuuj” zostaje cały. */
.card .chips { position:absolute; top:12px; left:12px; right:12px; display:flex; gap:6px }
.chip { display:inline-flex; align-items:center; gap:5px; padding:6px 10px; border-radius:var(--r-pill); font-size:var(--fs-s); font-weight:700; color:var(--ink);
        background:rgba(255,255,255,.8); -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px); box-shadow:0 2px 8px rgba(0,0,0,.12) }
.chip svg { width:15px; height:15px; flex:none }
.chip { flex:none; white-space:nowrap }
.chip.fit { flex:0 1 auto; min-width:0 }
.chip.fit span { overflow:hidden; text-overflow:ellipsis }
.card { container-type:inline-size }
@container (max-width:320px) { .chip.fit { display:none } } /* za mało miejsca nawet na „9…” (najdłuższy czas: „ok. 2 h 10 min”) */
.chip.go { margin-left:auto; background:var(--accent); color:#fff; animation:pulse 2.4s ease-in-out infinite }
.card .prog { position:absolute; left:0; bottom:0; height:5px; width:var(--p); background:var(--accent); border-radius:0 3px 3px 0 }
/* Wejście: karty wjeżdżają kolejno, chipy wyskakują, po zdjęciu przelatuje połysk. Tylko przy pierwszym renderze. */
.list.enter .card { animation:rise .7s cubic-bezier(.2,.8,.2,1) both; animation-delay:calc(var(--i) * 80ms) }
.list.enter .chip { animation:pop .45s cubic-bezier(.3,1.6,.5,1) both; animation-delay:calc(var(--i) * 80ms + 350ms) }
.list.enter .chip.go { animation:pop .45s cubic-bezier(.3,1.6,.5,1) calc(var(--i) * 80ms + 350ms) both, pulse 2.4s ease-in-out 1.5s infinite }
.list.enter .card::after { content:''; position:absolute; inset:0; pointer-events:none; background:linear-gradient(110deg, transparent 35%, rgba(255,255,255,.45) 50%, transparent 65%);
        transform:translateX(-120%); animation:shine 1.1s ease-out both; animation-delay:calc(var(--i) * 80ms + 300ms) }
@keyframes rise { from { opacity:0; transform:translateY(28px) scale(.96) } }
@keyframes pop { from { opacity:0; transform:scale(.4) } }
@keyframes shine { to { transform:translateX(120%) } }
@keyframes drift { from { transform:scale(1.02) } to { transform:scale(1.12) translate(-2%, -1%) } }
@keyframes pulse { 50% { box-shadow:0 0 0 6px rgba(235,89,46,.25) } }
@media (prefers-reduced-motion: reduce) { .card, .card *, .card::after, .list > *, .tile { animation:none !important } }
.empty { color:var(--muted); text-align:center; padding:32px }
/* Filtry: ulubione, ostatnie, kategorie. Przewijane poziomo, jeden aktywny naraz. */
.filters { display:flex; gap:8px; overflow-x:auto; margin:10px -16px 0; padding:0 16px 2px; scroll-padding-inline:16px; scrollbar-width:none }
.filters::-webkit-scrollbar { display:none }
.filter { flex:none; display:inline-flex; align-items:center; gap:5px; border:1px solid var(--line); background:var(--card); border-radius:var(--r-pill); padding:7px 13px; font-size:var(--fs-s); font-weight:500 }
.filter svg { width:15px; height:15px }
.filter[data-filter=home] { padding:7px 11px }
.filter[data-filter=home] svg { width:18px; height:18px }
.filter { transition:background .2s, border-color .2s, color .2s, transform .15s }
.filter:active { transform:scale(.93) }
.filter.on { background:var(--ink); border-color:var(--ink); color:#fff }
/* Sekcje strony głównej: „Kontynuuj” = duże karty, reszta = poziome rzędy małych kafelków. */
.sec { display:flex; align-items:baseline; justify-content:space-between; margin:14px 0 -4px }
.sec h2 { margin:0; font-size:var(--fs-xl); font-weight:700; letter-spacing:-.3px }
.sec button { border:0; background:none; color:var(--accent); font-size:var(--fs-s); font-weight:500; padding:4px 0 }
.row { display:flex; gap:10px; overflow-x:auto; margin:0 -16px; padding:0 16px 4px; scroll-snap-type:x proximity; scroll-padding:0 16px; scrollbar-width:none }
.row::-webkit-scrollbar { display:none }
.row .tile { flex:none; width:31%; min-width:104px; max-width:150px; scroll-snap-align:start }
.grid { display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:14px 10px }
.tile { display:block; align-self:start; border:0; background:none; padding:0; text-align:left; -webkit-tap-highlight-color:transparent } /* align-self: bez rozciągania — przycisk centruje treść w pionie i dwulinijkowy tytuł obniżał sąsiadów */
.tile .ph { position:relative; display:block; aspect-ratio:1; border-radius:var(--r-md); overflow:hidden; background:var(--soft); transition:transform .2s }
.tile:active .ph { transform:scale(.95) }
.tile img { width:100%; height:100%; object-fit:cover; display:block } /* miniatura = kadr okładki na danie (src/optimize.ts) */
.tile .fav { position:absolute; top:6px; right:6px; width:22px; height:22px; border-radius:50%; background:rgba(255,255,255,.85); color:var(--accent); display:grid; place-items:center }
.tile .fav svg { width:14px; height:14px }
.tile .veg { position:absolute; top:6px; left:6px; width:22px; height:22px; border-radius:50%; background:rgba(255,255,255,.85); color:var(--ok); display:grid; place-items:center }
.tile .veg svg { width:14px; height:14px }
.tile .prog { position:absolute; left:0; bottom:0; height:4px; width:var(--p); background:var(--accent) }
.tile b { display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; margin-top:6px; font-size:var(--fs-s); line-height:1.2 }
.tile small { display:flex; flex-wrap:wrap; column-gap:8px; margin-top:2px; font-size:var(--fs-xs); color:var(--muted) }
.tile small .lvl { display:inline-flex; align-items:center; gap:3px; white-space:nowrap }
.tile small .lvl svg { width:12px; height:12px }
.list.enter .tile { animation:rise .6s cubic-bezier(.2,.8,.2,1) both; animation-delay:calc(var(--i) * 40ms) }
/* Zmiana wyników (filtr, szukanie): krótkie wejście kafelków falą, tylko gdy zestaw faktycznie się zmienił. */
.list.swap > :not(.grid), .list.swap .grid .tile { animation:swap .32s cubic-bezier(.2,.8,.2,1) both; animation-delay:calc(min(var(--i, 0), 8) * 30ms) }
@keyframes swap { from { opacity:0; transform:translateY(10px) } }
/* Ulubione w przepisie */
.fav.on { color:var(--accent) }

/* ---- przepis ---- */
/* position:fixed + inset:0 = dokładnie widoczne okno. 100dvh w PWA na Androidzie bywa wyższe niż okno (pasek systemowy),
   wtedy przycisk „Gotowe” wystawał pod krawędź, a cała strona przewijała się w pionie. */
#recipe.active { position:fixed; inset:0; overflow:hidden }
/* Dok timerów: działające timery z innych kroków, widoczne na każdym ekranie; tap = skok do kroku. */
/* Pasek „dalej” pod slajdami: zawsze widoczny, niezależnie od długości opisu. Dok i podpowiedź wiszą nad nim. */
.nextbar { position:relative; flex:none; padding:8px 16px calc(8px + env(safe-area-inset-bottom)); background:var(--bg); box-shadow:0 -1px 0 var(--line) }
.nextbar.off { padding:0; box-shadow:none }
.next { width:100%; display:flex; align-items:center; justify-content:center; gap:10px; border:0; border-radius:var(--r-md); padding:16px; background:var(--accent); color:#fff;
        font-family:inherit; font-size:var(--fs-l); font-weight:700; box-shadow:0 6px 16px -8px rgba(0,0,0,.45); transition:transform .1s }
.next .arr { display:grid; font-style:normal; margin-left:2px }
/* tap: przycisk „pompuje”, strzałka wylatuje w prawo i wraca z lewej */
.next.go { animation:nextpush .35s ease-out }
.next.go .arr { animation:arrowfly .45s cubic-bezier(.5,0,.3,1) }
@keyframes nextpush { 40% { transform:scale(.95); filter:brightness(1.12) } }
@keyframes arrowfly { 45% { transform:translateX(28px); opacity:0 } 46% { transform:translateX(-18px); opacity:0 } }
@media (prefers-reduced-motion: reduce) { .next.go, .next.go .arr { animation:none } }
/* „Gotowe”, gdy pod spodem jest jeszcze nieprzeczytany opis: przygaszone, tap przewija w dół */
.next.wait { background:var(--line); color:var(--muted); box-shadow:none }
/* strzałka „przewiń niżej” + mgiełka nad paskiem */
.more { position:absolute; left:0; right:0; bottom:100%; height:56px; display:grid; place-items:end center; padding:0 0 6px; border:0; background:linear-gradient(to bottom, transparent, var(--bg) 85%); color:var(--accent); cursor:pointer }
.more svg { width:32px; height:32px; padding:5px; box-sizing:border-box; border-radius:50%; background:var(--card); box-shadow:0 2px 8px -2px rgba(0,0,0,.3); animation:nudgedown 1.2s ease-in-out infinite }
@keyframes nudgedown { 50% { transform:translateY(4px) } }
@media (prefers-reduced-motion: reduce) { .more svg { animation:none } }
.next svg { width:22px; height:22px; flex:none }
.dock { position:absolute; left:12px; right:12px; bottom:calc(100% + 12px); display:flex; flex-direction:column; align-items:center; gap:6px; pointer-events:none }
.dock button { pointer-events:auto; display:flex; align-items:center; gap:8px; max-width:100%; border:0; border-radius:var(--r-pill); padding:8px 14px 8px 10px; background:var(--ok); color:#fff;
               font-size:var(--fs-m); font-weight:500; box-shadow:0 6px 18px -4px rgba(0,0,0,.35); animation:dockin .35s cubic-bezier(.3,1.4,.5,1) }
.dock button svg { width:20px; height:20px; flex:none }
.dock .t { white-space:nowrap; overflow:hidden; text-overflow:ellipsis }
.dock .left { font-variant-numeric:tabular-nums; font-weight:700 }
#recipe.docked .slide { padding-bottom:72px }
@keyframes dockin { from { opacity:0; transform:translateY(20px) scale(.9) } }
/* Podpowiedź przesuwania bez tekstu (dziecko 6–10 lat): duży palec jedzie w lewo, track „zagląda” za nim na następny ekran i wraca;
   3 cykle w tym samym rytmie (--y-swipe-ms), potem znika (animationend) albo przy pierwszym dotyku. Mniej ruchu: palec stoi, obok strzałka. */
.hint { position:absolute; left:50%; bottom:calc(100% + 24px); transform:translateX(-50%); display:flex; align-items:center; gap:4px; color:var(--y-ink);
        pointer-events:none; filter:drop-shadow(0 4px 8px rgba(91,51,32,.35)) }
.hint svg { width:var(--y-hand); height:var(--y-hand); animation:swipefinger var(--y-swipe-ms) .8s ease-in-out 3 both }
.hint .hfill { fill:var(--y-card) }
.hint .harrow { display:none }
.hint .harrow svg { width:calc(var(--y-hand) / 2); height:calc(var(--y-hand) / 2); animation:none }
.track.peek { animation:peek var(--y-swipe-ms) .8s ease-in-out 3 }
@keyframes swipefinger { 0% { transform:translateX(56px); opacity:0 } 15% { transform:translateX(56px); opacity:1 } 50% { transform:translateX(-56px); opacity:1 } 70%, 100% { transform:translateX(-56px); opacity:0 } }
@keyframes peek { 0%, 15% { transform:none } 50% { transform:translateX(-56px) } 80%, 100% { transform:none } }
@media (prefers-reduced-motion: reduce) { .track.peek, .hint svg, .overlay { animation:none } .hint .harrow { display:block } }
.top { display:flex; align-items:center; gap:8px; padding:8px 12px 6px }
/* Ikona apki = powrót do listy (jak logo w pasku strony głównej). */
.back { flex:none; border:0; background:transparent; padding:0; width:36px; height:36px; border-radius:var(--r-sm); transition:transform .15s }
.back img { width:100%; height:100%; display:block }
.top .title { flex:1; margin:0 0 0 4px; font-size:var(--fs-l); font-weight:700; letter-spacing:-.2px; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis }
.counter { font-variant-numeric:tabular-nums; font-size:var(--fs-m); font-weight:700; padding:4px 10px; border-radius:var(--r-pill); background:var(--soft) }
.progress { height:4px; background:var(--line) }
.progress i { display:block; height:100%; background:var(--accent); transition:width .25s }

.track { flex:1; min-height:0; display:flex; overflow-x:auto; scroll-snap-type:x mandatory; scrollbar-width:none; -webkit-overflow-scrolling:touch }
.track::-webkit-scrollbar { display:none }
.slide { flex:0 0 100%; scroll-snap-align:start; scroll-snap-stop:always; padding:8px 16px 16px; display:flex; flex-direction:column; gap:10px; overflow-y:auto }
/* Slajd przewija się w pionie: dzieci nie mogą się ściskać, gdy treść przestaje się mieścić (np. .docked dokłada
   padding) — inaczej nagłówek kroku kurczy się o kilka px i treść podskakuje przy pojawieniu się timera. */
.slide > * { flex-shrink:0 }
.slide img { width:100%; aspect-ratio:1; border-radius:var(--r-md); position:relative; display:block; user-select:none; -webkit-user-drag:none }
.figure { position:relative }
/* Ładowanie obrazka bez JS: spinner leży POD obrazkiem (img jest przezroczysty, póki nie ma pikseli) i znika,
   gdy obrazek się namaluje. Pojawia się po chwili, żeby nie mrugał przy obrazkach z cache.
   .broken (onerror w index.html) chowa go, np. offline przy nieotwartym przepisie — zostaje pusta ramka. */
.figure:has(> img) { border-radius:var(--r-md); background:var(--soft) }
.figure:has(> img)::before { content:''; position:absolute; top:50%; left:50%; width:36px; height:36px; margin:-18px 0 0 -18px; box-sizing:border-box; border-radius:50%; border:3px solid var(--line); border-top-color:var(--accent); animation:spin .8s linear infinite, appear .2s .3s both }
.figure.broken::before, .figure.broken img { visibility:hidden } /* img: bez ikony „zepsuty obrazek”, ramka zostaje */
@keyframes spin { to { transform:rotate(1turn) } }
@keyframes appear { from { opacity:0 } }
.clockov { border:0; padding:6px 12px 6px 8px; border-radius:var(--r-pill); background:rgba(255,255,255,.92); color:var(--ok); font-weight:700; font-size:var(--fs-m); display:flex; align-items:center; gap:6px; box-shadow:0 1px 6px rgba(0,0,0,.18); font-variant-numeric:tabular-nums }
.clockov svg { width:26px; height:26px }
/* Krok dla dorosłego (przepisy dla dzieci): naklejka bez tła (czapka kucharza + wąsy), lekko pulsuje, żeby dziecko zawołało dorosłego. */
.adultov { width:72px; height:72px; animation:adult 1.8s ease-in-out infinite }
.adultov img { width:100%; height:100%; display:block; object-fit:contain; filter:drop-shadow(0 2px 4px rgba(0,0,0,.3)) }
/* Znacznik „ta część dla dorosłych”: ta sama naklejka w rogu ekranu zwróconego do rodzica (onboarding, paywall); dekoracja, nie łapie tapnięć. */
.adultmark { position:absolute; z-index:1; top:12px; width:52px; height:52px; object-fit:contain; transform:rotate(-8deg); pointer-events:none; filter:drop-shadow(0 2px 4px rgba(0,0,0,.3)) }
.onboard > .adultmark { top:calc(12px + env(safe-area-inset-top)); left:12px; transition:opacity .25s ease-out }
.onboard.bigmark > .adultmark { opacity:0 } /* karta z dużym piktogramem pod tekstem */
@media (prefers-reduced-motion: reduce) { .onboard > .adultmark { transition:none } }
.pwview { position:relative }
.pwview > .adultmark { top:-14px; right:48px }
.pwadult > .adultmark { top:-8px; right:0 }
.pwadult { position:relative }
.pwview:has(> .adultmark) > h3 { margin-right:104px }
@keyframes adult { 50% { transform:scale(1.08) } }
@media (prefers-reduced-motion: reduce) { .adultov { animation:none } }
.clockov.running { background:var(--ok); color:#fff }
.clockov.done { background:var(--soft); color:var(--muted) }
.clockov:not(.running):not(.done) { display:none } /* bez timera czas jest już w pigułce pod obrazkiem */
.finish .btn { margin-top:16px; border:0; background:var(--accent); color:#fff; border-radius:var(--r-sm); padding:14px 22px; font-size:var(--fs-l); font-weight:500 }
.slide { padding-bottom:calc(16px + env(safe-area-inset-bottom)) }
/* Nakładki na obrazku kroku: lewy górny róg numer (+ plakietka dorosłego pod nim), prawy faza (+ trwający timer).
   Kontener przepuszcza tapnięcia do obrazka (nawigacja), klikalne są tylko same plakietki. */
.ov { position:absolute; top:10px; display:flex; flex-direction:column; gap:8px; pointer-events:none }
.ov > * { pointer-events:auto }
.ov.l { left:10px; align-items:flex-start }
.ov.r { right:10px; align-items:flex-end }
.stepno { width:40px; height:40px; border-radius:50%; background:var(--accent); color:#fff; font-weight:700; font-size:var(--fs-l); display:grid; place-items:center; box-shadow:0 1px 6px rgba(0,0,0,.18) }
.phase { background:rgba(255,255,255,.92); color:var(--ink); font-size:var(--fs-xs); font-weight:500; padding:4px 10px; border-radius:var(--r-pill); letter-spacing:.3px; box-shadow:0 1px 6px rgba(0,0,0,.18) }
.meanwhile { display:flex; gap:10px; align-items:flex-start; background:#fff7e6; border:1px solid #f3dfb6; border-radius:var(--r-sm); padding:10px 12px; font-size:var(--fs-m); line-height:1.4; color:#6b4a12 }
.meanwhile svg { width:20px; height:20px; flex:none; margin-top:1px }
.stepper { display:flex; align-items:center; gap:8px; margin:2px 0 4px }
.stepper button { width:40px; height:40px; border-radius:50%; border:1px solid var(--line); background:#fff; font-size:var(--fs-xl); line-height:1 }
.stepper b { min-width:90px; text-align:center; font-size:var(--fs-l) }
.slide img.wide { aspect-ratio:3/2; object-fit:cover }
.slide h3 { margin:2px 0 0; font-size:var(--fs-xl); line-height:1.2 }
.actions { margin:0; padding:0; list-style:none; display:flex; flex-direction:column }
.actions li { display:flex; gap:12px; align-items:baseline; padding:10px 0; border-bottom:1px solid var(--line); font-size:var(--fs-l); line-height:1.4 }
.actions li:last-child { border-bottom:0 }
.actions li[data-say] { cursor:pointer; -webkit-user-select:none; user-select:none; -webkit-tap-highlight-color:transparent } /* tap = lektor czyta wiersz */
.actions li.speaking { background:var(--soft); margin:0 -8px; padding-left:8px; padding-right:8px; border-radius:var(--r-sm) }
.actions li.running { background:var(--ok-soft); margin:0 -8px; padding-left:8px; padding-right:8px; border-radius:var(--r-sm) }
.slide ul { margin:0; padding-left:20px; font-size:var(--fs-l); line-height:1.6 }
.pill { display:inline-flex; align-items:center; gap:4px; padding:1px 9px; border-radius:var(--r-pill); font-weight:500; white-space:nowrap; font-size:.92em; vertical-align:baseline }
.pill.qty { background:var(--qty); color:var(--qty-ink) }
.pill.time { background:var(--ok-soft); color:var(--ok) }
.pill svg { width:.95em; height:.95em; flex:none }
/* Start timera: duży przycisk na początku wiersza (zamiast numeru); w trakcie odlicza, po końcu ✓ */
.actions li.timed { align-items:center }
.tbtn { flex:none; display:inline-flex; align-items:center; justify-content:center; gap:4px; min-width:60px; height:40px; padding:0 12px; border:0; border-radius:var(--r-pill);
        background:var(--ok); color:#fff; font:inherit; font-size:var(--fs-m); font-weight:700; font-variant-numeric:tabular-nums; cursor:pointer; box-shadow:0 4px 10px -6px rgba(0,0,0,.5) }
.tbtn svg { width:18px; height:18px; flex:none }
.tbtn.running { animation:blink 1.2s infinite }
.tbtn.done { background:var(--ok-soft); color:var(--ok); box-shadow:none }
@keyframes blink { 50% { opacity:.75 } }
.next .left { display:inline-flex; align-items:center; gap:4px; padding:2px 10px; border-radius:var(--r-pill); background:rgba(255,255,255,.22); font-variant-numeric:tabular-nums }
.next .left svg { width:18px; height:18px }
.finish { text-align:center; margin:auto 0 }
.finish { display:flex; flex-direction:column; align-items:center; gap:6px; padding:0 8px }
.finish .thumb { width:62%; aspect-ratio:1; object-fit:cover; border-radius:50%; box-shadow:0 6px 24px rgba(0,0,0,.15); border:6px solid #fff; margin-bottom:14px }
.finish h3 { font-size:var(--fs-2xl); margin:0 }
.rate { margin:18px 0 4px; display:flex; flex-direction:column; align-items:center; gap:6px }
.rate .q { font-size:var(--fs-m); font-weight:500; color:var(--ink) }
.stars { display:flex; gap:4px }
.stars button { border:0; background:none; padding:4px; color:var(--line-2) }
.stars button svg { width:36px; height:36px }
.stars button.on { color:#e8a317 }
.rate .msg { font-size:var(--fs-s); color:var(--muted); min-height:1.2em; margin:0 }
.rate .msg.err { color:var(--accent) }
.finish p { font-size:var(--fs-l); line-height:1.45; color:var(--muted); margin:0; max-width:300px }


@media (hover:hover) and (min-width:700px) {
  body { max-width:var(--app-w); margin:0 auto; box-shadow:0 0 40px rgba(0,0,0,.08) }
  /* position:fixed liczy się od okna, nie od body — każdy taki ekran trzeba osobno zwęzić do kolumny */
  #recipe.active { left:calc(50% - var(--app-w) / 2); right:calc(50% - var(--app-w) / 2) }
  .overlay > * { width:100%; max-width:var(--app-w); margin-inline:auto } /* tło przyciemnia całe okno, talia w kolumnie */
  .overlay > .deckhead, .overlay > .deckrow { padding-inline:calc(var(--app-w) * .07) } /* 7% z mobile liczyłoby się od okna, nie od kolumny */
}
.slide ul.ing { display:flex; flex-direction:column; margin:0; padding:0; list-style:none }
.ing li { display:flex; gap:8px; align-items:baseline; flex-wrap:wrap; padding:7px 0; border-bottom:1px solid var(--line); font-size:var(--fs-l); line-height:1.35 }
.ing li:last-child { border-bottom:0 }
.ing .name { flex:1 1 40%; font-weight:500 }
/* Miniatura składnika (przepisy dla dzieci): na liście i w pigułce ilości w kroku — mąka ≠ cukier bez czytania. */
.ing li.pictured { align-items:center; flex-wrap:nowrap; gap:12px }
.ing li.pictured .txt { flex:1; min-width:0; display:flex; flex-direction:column; gap:2px }
.ing li.pictured .note { padding:0; margin:0 }
.ing .ipic { width:96px; height:96px; flex:none; border-radius:var(--r-md); background:#fff; object-fit:cover; box-shadow:0 0 0 1px var(--line) }
.pill .ppic { width:2.6em; height:2.6em; margin:2px .1em 2px -.7em; border-radius:var(--r-sm); background:#fff; object-fit:cover; flex:none; box-shadow:0 0 0 2px var(--qty) }
.pill:has(.ppic) { vertical-align:middle }
/* Akcja ze składnikiem z miniaturą: duży obrazek z ilością na plakietce prowadzi wiersz, tekst tylko dopowiada. */
.actions li.led { align-items:center }
.apic { position:relative; flex:none; width:84px; height:84px; margin-bottom:6px }
.apic img { width:100%; height:100%; border-radius:var(--r-md); background:#fff; object-fit:cover; box-shadow:0 0 0 1px var(--line) }
.qbadge { position:absolute; left:50%; bottom:-6px; transform:translateX(-50%); white-space:nowrap; padding:1px 8px; border-radius:var(--r-pill); background:var(--qty); color:var(--qty-ink); font-size:var(--fs-s) }
.ing .note { color:var(--muted); font-size:var(--fs-s) }
.ing .note { flex-basis:100%; padding-left:32px; margin-top:-2px }
.ing li.staple .name { color:var(--muted) }
.slide ul.ing + ul.ing { margin-top:12px }
.sub { margin:10px 0 0; font-size:var(--fs-xs); font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:.5px }
.ing li[data-check] { cursor:pointer; -webkit-user-select:none; user-select:none }
.box { flex:none; align-self:center; width:24px; height:24px; border-radius:var(--r-xs); border:2px solid var(--line-2); background:#fff; display:grid; place-items:center; transition:background .15s, border-color .15s }
.box svg { width:16px; height:16px; color:#fff; opacity:0; transition:opacity .15s }
li.checked .box { background:var(--ok); border-color:var(--ok) }
li.checked .box svg { opacity:1 }
li.checked .name, li.checked .txt { color:var(--muted); text-decoration:line-through; text-decoration-color:var(--line-2) }
li.checked .pill, li.checked .note { opacity:.45 }
.ing .txt { flex:1 }
.listhead { display:flex; align-items:baseline; gap:10px }
.listhead h3 { flex:1 }
.reset { flex:none; border:0; background:none; color:var(--muted); width:36px; height:36px; border-radius:50%; display:grid; place-items:center; padding:0 }
.reset svg { width:20px; height:20px }
/* ---- karta przepisu: overlay nad listą, talia jednej sekcji, sąsiednie karty wystają z boków ---- */
.overlay { position:fixed; inset:0; z-index:10; display:flex; flex-direction:column; justify-content:center; background:rgba(20,12,6,.55); animation:fade .2s }
body.locked { overflow:hidden }
@keyframes fade { from { opacity:0 } }
.deckhead { display:flex; justify-content:space-between; gap:8px; padding:calc(8px + env(safe-area-inset-top)) 7% 10px }
.deckhead .counter { background:var(--card); white-space:nowrap; overflow:hidden; text-overflow:ellipsis }
.deckrow { flex:none; max-height:calc(100dvh - 120px); display:flex; gap:12px; overflow-x:auto; padding:0 7% 8px; scroll-snap-type:x mandatory; scroll-padding:0 7%; scrollbar-width:none; -webkit-overflow-scrolling:touch }
.deckrow::-webkit-scrollbar { display:none }
.rcard { flex:0 0 100%; scroll-snap-align:center; scroll-snap-stop:always; display:flex; flex-direction:column; border-radius:var(--r-lg); overflow:hidden; background:var(--card); box-shadow:0 16px 40px -12px rgba(0,0,0,.5) }
.rcard .cover { position:relative; flex:none; background:var(--soft) }
.rcard .cover img { display:block; width:100%; aspect-ratio:1; object-fit:cover }
.rcard .shade { position:absolute; inset:auto 0 0 0; padding:48px 16px 14px; color:#fff; background:linear-gradient(transparent, rgba(20,12,6,.35) 35%, rgba(20,12,6,.82)) }
.rcard .cover .prog { position:absolute; left:0; bottom:0; height:5px; width:var(--p); background:var(--accent); border-radius:0 3px 3px 0 }
.rcard .favbtn { position:absolute; top:10px; right:10px; width:40px; height:40px; border:0; border-radius:50%; background:rgba(255,255,255,.85); color:var(--line-2); display:grid; place-items:center; padding:0; box-shadow:0 2px 8px rgba(0,0,0,.12) }
.rcard .favbtn svg { width:22px; height:22px }
.rcard .favbtn.on { color:var(--accent) }
.rcard .body { flex:1; min-height:0; overflow-y:auto; display:flex; flex-direction:column; gap:10px; padding:12px 16px 14px }
.rcard h2 { margin:0; font-size:var(--fs-2xl); font-weight:700; letter-spacing:-.4px; line-height:1.1; text-shadow:0 2px 10px rgba(0,0,0,.35) }
.rcard p { margin:0; font-size:var(--fs-s); line-height:1.4; color:var(--muted) }
.rcard .tags { display:flex; flex-wrap:wrap; gap:6px }
.tag { display:inline-flex; align-items:center; gap:5px; padding:5px 10px; border-radius:var(--r-pill); background:var(--soft); font-size:var(--fs-s); font-weight:500 }
.tag svg { width:15px; height:15px; flex:none }
.tag.veg { background:var(--ok-soft); color:var(--ok) }
.tags .tool { display:inline-flex; align-items:center; padding:0 2px }  /* sprzęt dorosłego: osobno, duży, bez pigułki */
.tags .tool svg { width:26px; height:26px }
.rcard .opts { margin-top:auto }
/* Przycisk karty: „Zaczynam gotować” / „Kontynuuj · Krok n z m” */
.opts { display:flex; flex-direction:column; gap:8px }
.opts button { border:0; border-radius:var(--r-sm); padding:13px; font-size:var(--fs-l); font-weight:500; background:var(--soft); color:var(--ink) }
.opts .primary { background:var(--accent); color:#fff }
.opts svg { width:18px; height:18px; vertical-align:-3px; margin-right:6px }
.reset.armed { width:auto; padding:0 12px; border-radius:var(--r-pill); background:var(--accent); color:#fff; font-size:var(--fs-s); font-weight:500 }
.reset:disabled { opacity:.35; cursor:not-allowed } /* np. lektor, gdy przeglądarka nie ma syntezy mowy */
.count { font-size:var(--fs-s); color:var(--muted); font-variant-numeric:tabular-nums }
.clear { border:0; background:none; color:var(--accent); font-size:var(--fs-s); padding:4px 0 }
.clear[hidden] { display:inline; visibility:hidden } /* rezerwuje miejsce: pojawienie się nie przesuwa layoutu */
.pill.taste { background:var(--soft); color:var(--muted); font-weight:500 }
.pill.temp { background:#fde2dc; color:var(--qty-ink) }
.during a { color:inherit; font-weight:500 }

/* ---- Yumicorn: strona główna (Yumi + 4 kafelki) i książka kategorii (kartki po 3 karty) ---- */
.yumi { font-family:var(--y-font); color:var(--y-ink); background:var(--y-bg) }
body:has(.yumi.active) { background:var(--y-bg) }
#home.active { height:100dvh; padding:0; gap:0; background:var(--y-bg) } /* stała wysokość: przy braku miejsca kurczy się hero, nie rośnie strona */
/* hero (~45% wysokości, cover od góry) + arkusz („blenda”) nachodzący na jego dół o --y-sheet-lap i rosnący do końca ekranu;
   na niskim ekranie maleje hero (min. 110 px), kafelki i przyciski zostają — bez przewijania od 360×568 */
.yhero { position:relative; flex:1 1 45dvh; min-height:110px; overflow:hidden } /* rośnie na wysokim ekranie (bez pustego kremu pod kafelkami), kurczy się na niskim */
/* ciemniejsza góra ekranu (Kris, makieta): ciepły brąz z koloru tekstu + winieta w górnych rogach; nad obrazem, pod tytułem i dymkiem;
   znika do 45% wysokości hero, twarz Yumiego bez zmian */
.yhero::after { content:''; position:absolute; inset:0 0 auto; height:45%; pointer-events:none;
  background:radial-gradient(ellipse 45% 70% at 0 0, var(--y-hero-shade), transparent), radial-gradient(ellipse 45% 70% at 100% 0, var(--y-hero-shade), transparent),
    linear-gradient(180deg, var(--y-hero-shade), transparent) }
.yheroimg { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:center 62% } /* na pełnej wysokości jak od góry; na niskim ekranie twarz Yumiego zostaje nad arkuszem */
.yheroimg.fallback { object-fit:contain; object-position:left bottom; padding:48px 40% var(--y-sheet-lap) 0 }
/* duży tytuł „Yumicorn” na spokojnej górze hero (Kris: ~62% szerokości, jak na makiecie); dymek pod nim, z prawej */
.yprivacy { position:absolute; z-index:2; top:calc(env(safe-area-inset-top) - 2px); left:calc(env(safe-area-inset-left) - 2px); display:grid; place-items:center; width:40px; height:40px; color:#fff; opacity:.8; filter:drop-shadow(0 1px 2px rgba(91,51,32,.6)) } /* polityka prywatności: delikatne „i” wciśnięte w róg (glif ~20 px, cel 40×40), bez tła; białe z cieniem, bo brąz ginął w hero */
.yprivacy svg { width:20px; height:20px }
.yhometitle { position:absolute; z-index:1; top:calc(8px + env(safe-area-inset-top)); left:0; right:0; margin:0; display:flex; justify-content:center; line-height:0 }
.yhometitle img { width:var(--y-home-title-w); height:auto; filter:drop-shadow(0 2px 6px rgba(255,255,255,.8)) }
.yhero .bubble { bottom:auto; top:calc(env(safe-area-inset-top) + 12px + var(--y-home-title-w) * .425) } /* .425 = proporcje home-title.webp (600×255); inne proporcje → popraw */
.ysheet { position:relative; z-index:1; flex:0 0 auto; display:flex; flex-direction:column; margin-top:calc(-1 * var(--y-sheet-lap));
  padding:0 16px calc(16px + env(safe-area-inset-bottom)); border-radius:var(--y-r-sheet) var(--y-r-sheet) 0 0;
  background:linear-gradient(180deg, var(--y-card) 0, var(--y-bg) 140px); box-shadow:0 -10px 22px -16px rgba(91,51,32,.45) }
.ybrand { display:flex; align-items:center; gap:8px; height:40px }
.ybrand .ylogo { width:36px; height:36px; border-radius:var(--r-sm) }
.ybrand .ywordmark { height:24px; width:auto; opacity:.9 }
/* strona główna bez przewijania (Kris): Yumi z dymkiem dostaje to, co zostaje po kafelkach i przyciskach; na niskim ekranie maleje */
.bubble { position:absolute; z-index:1; right:16px; bottom:max(calc(var(--y-sheet-lap) + 8px), calc(100% - 2.2em - 80px), 30%); /* prawa strona hero, nad arkuszem; na niskim hero nie wjeżdża na logo */ max-width:36%; min-height:calc(2.3em + 24px); display:flex; align-items:center; /* zawsze ≥ 2 linie, tekst wyśrodkowany (Kris: 1 linia wyglądała dziwnie) */ margin:0; padding:12px 16px; border-radius:var(--y-r-card); background:var(--y-card);
          font-size:clamp(var(--fs-m), min(4.6vw, 2.8dvh), var(--fs-l)); font-weight:800; line-height:1.15; /* mały jak na stronie przeglądu tła (Kris) */ box-shadow:var(--y-shadow); animation:pop .5s cubic-bezier(.3,1.6,.5,1) .35s both }
.bubble::before { content:''; position:absolute; left:-12px; top:55%; border:10px solid transparent; border-right:16px solid var(--y-card); border-left:0 }
.ytiles { display:grid; grid-template-columns:1fr 1fr; gap:12px }
#tiles.ytiles { gap:var(--y-tiles-gap); padding:0 var(--y-tiles-pad) } /* miejsce na wystające naklejki */
.ysheet .ytiles { margin-top:calc(-1 * var(--y-tiles-lift)) } /* rząd kafelków nachodzi na hero; zaokrąglona krawędź arkusza za ich środkiem */
.ytile { position:relative; display:flex; flex-direction:column; padding:0; border:var(--y-tile-border); border-radius:var(--y-r-card); overflow:visible; /* naklejka wystaje */ color:var(--tile-ink); text-align:left;
         background:linear-gradient(180deg, color-mix(in srgb, var(--tile) 55%, var(--y-card)) 0%, var(--tile) 55%, color-mix(in srgb, var(--tile) 88%, var(--tile-ink)) 100%);
         box-shadow:inset 0 2px 0 var(--y-hi), inset 0 -3px 0 color-mix(in srgb, var(--tile-acc) 18%, transparent), var(--y-shadow); transition:transform .2s cubic-bezier(.2,.8,.2,1); animation:rise .6s cubic-bezier(.2,.8,.2,1) both; animation-delay:calc(var(--i) * 80ms + 200ms) }
.ytile > img:not(.ytsticker) { width:100%; aspect-ratio:1 / var(--y-tile-k); object-fit:contain; object-position:center bottom; display:block } /* tile-*.webp 10:7 (przezroczyste, cień w marginesie): przy k .7 wypełnia całe pole; niższe pole (krótkie ekrany) → mniejsze, ale nic nie obcięte */ /* danie bez tła (przezroczysty WebP), tło daje kafelek */
.ytile span { display:flex; align-items:center; justify-content:space-between; min-height:var(--y-tile-label); padding:6px 10px 6px 14px; font:800 var(--fs-xl)/1.1 var(--y-font) }
.ytsticker { position:absolute; top:calc(-.35 * var(--y-tsticker)); left:calc(-.35 * var(--y-tsticker)); z-index:2; width:var(--y-tsticker); height:var(--y-tsticker); object-fit:contain; transform:rotate(-8deg);
              filter:var(--y-sticker-filter) }
/* naklejka kategorii w nagłówku wyboru przepisu (przed tytułem), ten sam obrys co na kafelku */
.yheadsticker { flex:none; width:var(--y-headsticker); height:var(--y-headsticker); object-fit:contain; transform:rotate(-8deg); filter:var(--y-sticker-filter) }
.yheadsticker:not([src]) { display:none }
/* okrągły przycisk ze strzałką w kolorze kategorii (kafelki, karty albumu i nagród) */
.ygo { flex:none; width:34px; height:34px; display:grid; place-items:center; border-radius:50%; background:var(--tile-acc, var(--y-ink)); color:var(--y-card);
       box-shadow:inset 0 2px 0 rgba(255,255,255,.35), 0 3px 6px -3px rgba(91,51,32,.5) }
.ygo svg { width:20px; height:20px }
.c-slodkie { --tile:var(--y-sweet); --tile-ink:var(--y-sweet-ink); --tile-acc:var(--y-sweet-acc) }
.c-przekaski { --tile:var(--y-snack); --tile-ink:var(--y-snack-ink); --tile-acc:var(--y-snack-acc) }
.c-napoje { --tile:var(--y-drink); --tile-ink:var(--y-drink-ink); --tile-acc:var(--y-drink-acc) }
.c-na-slono { --tile:var(--y-salty); --tile-ink:var(--y-salty-ink); --tile-acc:var(--y-salty-acc) }
@keyframes yhop { from { opacity:0; transform:translateY(40px) scale(.9) } }

/* książka: ekran = dokładnie okno (jak przepis), kartki przewijane w bok ze snapem, kropki pod spodem */
#book.active { position:fixed; inset:0; max-width:var(--app-w); margin:0 auto; overflow:hidden;
  background:linear-gradient(var(--y-sky-base), var(--y-sky-base)), color-mix(in srgb, color-mix(in srgb, var(--tile) 82%, var(--tile-acc)), var(--y-card) var(--y-sky-white)); background-blend-mode:luminosity }
/* malowane niebo (csky-1 od mockup-artist, bezszwowe w poziomie) w dwóch pasach: chmury u góry i u dołu, środek = gładkie tło nieba (--y-sky-base,
   próbka z obrazu). Pasy w skali ~1 piksel obrazu na piksel urządzenia przy DPR 2 (ostre, nie przeskalowane); barwa kategorii trybem luminosity
   (jasność z obrazu, barwa z kategorii). Barwa liczona w regułach, nie w tokenie na :root (--tile istnieje dopiero w .c-<kategoria>).
   Paralaksa w JS (moveSky): góra 0,08×, dół 0,12× przewinięcia kartek. */
.ysky { position:absolute; left:0; width:400%; height:var(--y-sky-strip); pointer-events:none; will-change:transform;
  background:var(--sky) 0 0 / auto 100% repeat-x, color-mix(in srgb, color-mix(in srgb, var(--tile) 82%, var(--tile-acc)), var(--y-card) var(--y-sky-white)); background-blend-mode:luminosity }
.ysky.top { top:0; --sky:url(/yumicorn/sky-top.webp) }
.ysky.bottom { bottom:0; --sky:url(/yumicorn/sky-bottom.webp) }
#book .ybookhead, #book .ypages, #book .ybooknav { position:relative; z-index:1 }
/* „a kuku” (peekPlay): okno od góry ekranu do górnej krawędzi karty, więc to, co niżej, zasłania karta; nad oknem nagłówek i kartki.
   Sprite'y czekają pod dolną krawędzią okna (translateY(100%)), ruch w Web Animations (JS) */
.ypeek { position:absolute; z-index:0; overflow:hidden; pointer-events:none }
.ypeek .yphat, .ypeek .yphead { position:absolute; left:0; bottom:0; width:var(--w, var(--y-peek-w)); transform:translateY(100%) }
.ypeek img { display:block; width:100% }
.ypeek .ypwink { position:absolute; inset:0; opacity:0 }
.ypbub { position:absolute; z-index:2; margin:0; padding:8px 14px; border-radius:var(--y-r-card); background:var(--y-card); box-shadow:var(--y-shadow);
  font-size:var(--fs-m); font-weight:800; line-height:1.2; opacity:0; pointer-events:none; transform-origin:100% 50% }
.ypbub::after { content:''; position:absolute; right:-12px; top:50%; margin-top:-8px; border:8px solid transparent; border-left:14px solid var(--y-card); border-right:0 } /* ogonek do głowy */
.ypbub.flip { transform-origin:0 50% }
.ypbub.flip::after { right:auto; left:-12px; border-left:0; border-right:14px solid var(--y-card) } /* dymek na prawo od głowy */
.ybookhead { display:flex; align-items:center; gap:8px; padding:calc(8px + env(safe-area-inset-top)) var(--y-voice-room) 4px 12px } /* z prawej miejsce na #voice */
.ybookhead h2 { margin:0; font:800 var(--fs-2xl)/1.1 var(--y-font) }
.yback { width:56px; height:56px; flex:none; display:grid; place-items:center; padding:0; border:0; border-radius:50%; background:var(--y-card); color:var(--y-ink); box-shadow:0 4px 12px -6px rgba(91,51,32,.5) }
.yback svg { width:28px; height:28px }
/* głos Yumiego (TASK-33): przypięty nad wszystkim w prawym górnym rogu kolumny aplikacji; w kole cała naklejka Yumi z profilu:
   z pomarańczowymi falami = mówi (voice-on.webp), zamknięta buzia bez fal + szarość = cicho (voice-off.webp) */
.yvoice { position:fixed; z-index:90; top:calc(8px + env(safe-area-inset-top)); right:max(12px, calc((100vw - var(--app-w)) / 2 + 12px));
  width:var(--y-voice); height:var(--y-voice); display:grid; place-items:center; padding:0; border:0; border-radius:50%; background:var(--y-card); box-shadow:0 4px 12px -6px rgba(91,51,32,.5) }
.yvoice > img { width:calc(var(--y-voice) - 6px); height:calc(var(--y-voice) - 6px); object-fit:contain; transition:filter .2s, opacity .2s }
.yvoice.off > img { filter:grayscale(1); opacity:.55 }
.yvoice:disabled { opacity:.4 }
body:has(#list.active) .yvoice, body:has(#recipe.active:not(.ykids)) .yvoice, body:has(#deck:not([hidden])) .yvoice { display:none } /* dorosły PictoCook nie mówi */
.ypages { flex:1; min-height:0; display:flex; overflow-x:auto; scroll-snap-type:x mandatory; scrollbar-width:none; overscroll-behavior-x:contain }
.ypages::-webkit-scrollbar { display:none }
.ypage { flex:0 0 100%; min-height:0; display:flex; flex-direction:column; justify-content:center; gap:var(--y-card-gap); padding:8px 16px; scroll-snap-align:center; scroll-snap-stop:always; container-type:inline-size }
/* karta: co najwyżej 1/3 kartki i co najwyżej --y-card-max-3; nadmiar wysokości idzie w odstęp nad i pod kartami (wyśrodkowane) */
.ypage .ycard { flex:0 1 calc((100% - 2 * var(--y-card-gap)) / 3); max-height:var(--y-card-max-3) }
.ycard { --y-card-in:var(--y-r-card); /* promień wnętrza (okładka, panel) */ position:relative; display:flex; flex-direction:column; min-height:0; padding:0; border:0; border-radius:var(--y-r-card); overflow:visible; /* naklejka okazji wystaje; rogi zaokrąglają okładka i panel */ background:var(--y-card); color:var(--y-ink); text-align:left;
         box-shadow:var(--y-shadow); transition:transform .2s cubic-bezier(.2,.8,.2,1); animation:rise .5s cubic-bezier(.2,.8,.2,1) both; animation-delay:calc(var(--i) * 70ms) }
.ycard > img:not(.ylock) { flex:1; min-height:0; width:100%; object-fit:cover; display:block; border-radius:var(--y-card-in) var(--y-card-in) 0 0 }
.ycard .yinfo { border-radius:0 0 var(--y-card-in) var(--y-card-in) }
/* wystaje tylko tyle, ile zmieści padding kartki (.ypage 8px 16px; przewijany pas obcina resztę); w trybie 1-karta więcej miejsca */
.ycard .yocc { --out-x:10px; --out-y:6px; position:absolute; z-index:2; top:calc(-1 * var(--out-y)); right:calc(-1 * var(--out-x)); width:var(--y-occsticker); height:var(--y-occsticker);
               background:center / contain no-repeat; transform:rotate(8deg); filter:var(--y-sticker-filter); pointer-events:none }
/* panel z tytułem = „chmurka”: falisty górny brzeg, przeszycie (przerywana linia), naklejka kategorii obok tytułu */
.ycard .yinfo { --panel:color-mix(in srgb, var(--tile, var(--y-sweet)) 45%, var(--y-card)); position:relative; display:flex; align-items:center; gap:8px; padding:8px 12px 10px; background:var(--panel) }
.ycard .yinfo::before { content:''; position:absolute; left:0; right:0; top:-11px; height:12px;
  background:radial-gradient(circle at 12px 12px, var(--panel) 11.5px, transparent 12px) 0 0/24px 12px repeat-x }
.ycard .yinfo::after { content:''; position:absolute; inset:5px 6px 6px; border:2px dashed var(--y-stitch); border-radius:calc(var(--y-r-card) - 8px); pointer-events:none }
.ycard .ytxt { flex:1; min-width:0; display:flex; flex-direction:column; gap:2px }
/* tytuł do 2 wierszy (długie nazwy dań nie są obcinane w pół słowa) */
.ycard b { display:flex; align-items:center; min-height:calc(2 * 1.15em); font-size:var(--fs-xl); font-weight:800; line-height:1.15 } /* miejsce na 2 linie: karty równej wysokości, 1 linia wyśrodkowana */
.ycard b > span { overflow:hidden; display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2 }
/* czas (TASK-31): wiersz = ikona | pasek 1-2-3 (robienie brązowe, czekanie pomarańczowe; puste segmenty = ten sam kolor, wyblakły)
   | dokładny czas małym tekstem dla dorosłego po prawej. Stałe szerokości ikony i paska: kolumny wierszy się zgadzają */
.ytime { display:flex; flex-direction:column; gap:4px; width:100%; font-size:var(--fs-xs) }
.trow { display:grid; grid-template-columns:var(--y-time-ic) auto 1fr; align-items:center; column-gap:8px; color:var(--y-ink) }
.trow.wait { color:var(--y-adult) }
.trow > img { display:block; width:var(--y-time-ic); height:var(--y-time-ic) }
.tbar { display:flex; gap:3px }
.tbar i { width:var(--y-tbar-w); height:var(--y-tbar-h); border-radius:var(--r-pill); background:currentColor; opacity:.2 }
.tbar i.on { opacity:1 }
.trow .moon { display:block; width:calc(2 * var(--y-tbar-h)); height:calc(2 * var(--y-tbar-h)); fill:var(--y-moon); stroke:var(--y-ink); stroke-width:2; stroke-linejoin:round }
.svrow > img { width:var(--y-sv-ic-w); height:var(--y-sv-ic-h); margin-inline:calc((var(--y-time-ic) - var(--y-sv-ic-w)) / 2); object-fit:contain } /* talerz jest poziomy: szersze pudełko, środek w kolumnie ikon czasu */
.svx { font:800 1.5em/1 var(--y-font); color:var(--y-ink) } /* „×6” wiersza porcji (TASK-30) */
.ttxt { color:var(--y-muted); font-weight:600; white-space:nowrap; text-align:right }
/* plakietka na rogu obrazka: nazwa dania ma pod spodem całą szerokość */
.ybadge { position:absolute; top:10px; right:10px; display:inline-flex; align-items:center; gap:6px; max-width:calc(100% - 20px); padding:8px 14px; box-shadow:var(--y-emboss), 0 4px 12px -4px rgba(0,0,0,.35); background:linear-gradient(color-mix(in srgb, var(--badge) 85%, #fff), var(--badge)); border-radius:var(--r-pill); color:#fff; font-weight:800; font-size:var(--fs-s); line-height:1.1 }
.ybadge svg { width:22px; height:22px; flex:none; filter:drop-shadow(0 1px 0 rgba(0,0,0,.2)) }
.ybadge > img { width:28px; height:28px; flex:none; object-fit:contain; margin:-6px 0 -6px -8px; filter:drop-shadow(0 1px 2px rgba(0,0,0,.3)) } /* naklejka „dorosły” wystaje poza pigułkę */
.ybadge.solo { --badge:var(--y-solo); font-size:var(--fs-l) }
.ybadge.adult { gap:8px; padding:8px 14px 8px 12px; --badge:var(--y-adult) }
.ybooknav { display:grid; grid-template-columns:1fr auto 1fr; align-items:center; column-gap:16px; padding:6px 16px calc(10px + env(safe-area-inset-bottom)) }
.ybooknav.single { visibility:hidden }
.ybooknav > :first-child { justify-self:end }  /* strzałki przy wewnętrznych krawędziach, środek (kropki albo „1 z X”) zawsze wyśrodkowany */
.ybooknav > :last-child { justify-self:start }
.ybooknav > .ydots, .ybooknav > .ycount { grid-area:1 / 2 } /* wykluczają się: kropki albo licznik */
.ybooknav > :first-child { grid-area:1 / 1 }
.ybooknav > :last-child { grid-area:1 / 3 }
.ynav { width:56px; height:56px; flex:none; display:grid; place-items:center; padding:0; border:0; border-radius:50%; background:var(--y-card); color:var(--y-ink); box-shadow:0 4px 12px -6px rgba(91,51,32,.5) }
.ynav svg { width:28px; height:28px }
.ynav:disabled { opacity:.35; box-shadow:none }
.ydots { display:flex; justify-content:center; gap:10px }
.ycount { font-size:var(--fs-l); font-weight:800; font-variant-numeric:tabular-nums }
.ycount:empty { display:none }
.ydots i { width:10px; height:10px; border-radius:50%; background:var(--y-ink); opacity:.25; transition:opacity .2s, transform .2s }
.ydots i.on { opacity:.9; transform:scale(1.3) }
.yempty { flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:16px; padding:24px; text-align:center }
.yempty img { width:60%; max-width:260px }
.yempty p { margin:0; font-size:var(--fs-xl); font-weight:800; line-height:1.25 }

.ysay { display:flex; align-items:center; gap:10px }
.ysay img { width:96px; height:auto; flex:none }
.ysay p { margin:0; padding:12px 16px; border-radius:var(--y-r-card); background:var(--y-card); font-size:var(--fs-l); font-weight:700; line-height:1.25; box-shadow:var(--y-shadow) }
.ybig { display:flex; align-items:center; justify-content:center; gap:10px; min-height:var(--y-next-h); border:0; border-radius:var(--r-pill); background:var(--y-ink); color:#fff; font:800 var(--fs-xl)/1 var(--y-font) }
.ybig svg { width:26px; height:26px }
a.ybig { padding:8px 14px; text-decoration:none; text-align:center } /* przycisk-link: „Otwórz w Chrome” (intent://); <a> nie ma domyślnego paddingu przycisku */
.instfoot .ybig.full { flex-basis:100% } /* trzeci przycisk pod parą: „Kopiuj link” po nieudanym przejściu do Chrome */

/* mniej ruchu: Yumicorn bez wjazdów i podskoków (system „ogranicz ruch”) */
@media (prefers-reduced-motion: reduce) {
  .ysky { transform:none !important }
  .bubble, .ytile, .ycard { animation:none }
  .ytile, .ycard, .ydots i { transition:none }
}

/* tryb 1-karta (TASK-16, test A/B: ?cards=1): kartka węższa od ekranu o 40 px, więc z prawej wystaje ~24 px następnej karty;
   odstęp po ostatniej kartce pozwala ją dociągnąć do lewej krawędzi */
.ypages.one .ypage { flex:0 0 calc(100% - 40px); padding-right:0; scroll-snap-align:start }
.ypages.one .ycard { --y-card-in:calc(var(--y-r-card) - 3px); flex:0 1 auto; max-height:100%; border:var(--y-tile-border); box-shadow:var(--y-shadow) } /* ta sama biała ramka co kafelki */ /* karta = kwadratowa okładka + panel tytułu, wyśrodkowana; wokół widać tło z chmurkami (Kris, runda 3) */
/* okładka na czystej bieli karty (Kris: zabarwienie + multiply gasiło akwarele) — tło karty to --y-card z reguły .ycard;
   zamknięte przepisy zostają na plamie w kolorze kategorii z multiply, żeby różniły się od grywalnych */
.ycard.locked { background:radial-gradient(ellipse 60% 40% at 28% 26%, color-mix(in srgb, var(--tile, var(--y-sweet)) 55%, var(--y-card)) 0%, transparent 70%),
  radial-gradient(ellipse 70% 50% at 74% 66%, color-mix(in srgb, var(--tile, var(--y-sweet)) 82%, var(--tile-ink, var(--y-ink))) 0%, transparent 75%),
  linear-gradient(180deg, color-mix(in srgb, var(--tile, var(--y-sweet)) 92%, var(--y-card)), color-mix(in srgb, var(--tile, var(--y-sweet)) 92%, var(--tile-ink, var(--y-ink)))) }
.ycard.locked > img:not(.ylock) { mix-blend-mode:multiply }
/* „Gotuję nowe przepisy!” (TASK-125): zapowiedź na końcu książki, nie przepis: bez cienia, przerywana ramka, spokojne tło,
   cały Yumi (contain) zamiast okładki, napis bez panelu-chmurki */
.ycard.ysoon, .ypages.one .ycard.ysoon { background:var(--y-soft); border:3px dashed var(--y-line-2); box-shadow:none }
.ycard.ysoon > img { object-fit:contain; padding-top:6px; border-radius:0 }
.ycard.ysoon .yinfo { --panel:transparent; justify-content:center; text-align:center; padding-top:4px }
.ycard.ysoon .yinfo::before, .ycard.ysoon .yinfo::after { content:none }
.ycard.ysoon b { justify-content:center; color:var(--y-muted) }
.ypages.one .ycard > img:not(.ylock) { flex:0 1 auto; width:100%; aspect-ratio:1 / 1; object-fit:contain } /* kwadrat; na niskim ekranie maleje (contain), panel zostaje */
.ypages.one::after { content:''; flex:0 0 40px }
.ypages.one .ycard .yocc { --out-x:calc(.3 * var(--y-occsticker)); --out-y:calc(.3 * var(--y-occsticker)) }
.ypages.one { -webkit-user-select:none; user-select:none } /* przeciąganie myszą nie zaznacza tekstu kart */
.ypages.one .ycard b { font-size:var(--fs-2xl) }
.ypages.one .ycard .yinfo { padding:12px 16px 14px }

/* ---- Yumicorn: przepis dla dzieci (TASK-18): podgląd przed startem, kroki, czekanie, koniec ---- */
/* Prototyp: zamiast przepisywać widżety przepisu, w #recipe.ykids przedefiniowujemy tokeny PictoCooka na wartości --y-*.
   Te same widżety (listy, pigułki, minutnik, pasek „dalej”) dostają barwy Yumicorna; przepisy dorosłych zostają bez zmian.
   Kolor kategorii (--tile / --tile-ink) daje klasa c-<kategoria> ustawiana w openRecipe. */
#recipe.ykids {
  --bg:var(--y-bg); --ink:var(--y-ink); --muted:var(--y-muted); --card:var(--y-card); --line:var(--y-line); --line-2:var(--y-line-2); --soft:var(--y-soft);
  --accent:var(--tile-ink); --ok:var(--y-timer); --ok-soft:var(--y-timer-soft); --qty:var(--tile); --qty-ink:var(--tile-ink);
  font-family:var(--y-font); background:var(--y-bg); color:var(--y-ink)
}
#recipe.ykids .fav, #recipe.ykids #reset { display:none } /* bez ulubionych (decyzja „bez serduszek”); od nowa: na podglądzie */
#recipe.ykids .top { padding:calc(8px + env(safe-area-inset-top)) var(--y-voice-room) 8px 12px }
#recipe.ykids .back { width:48px; height:48px; border-radius:50%; display:grid; place-items:center; background:var(--y-card); color:var(--y-ink); box-shadow:0 4px 12px -6px rgba(91,51,32,.5) }
#recipe.ykids .back svg { width:26px; height:26px }
#recipe.ykids .top .title { font-weight:800; font-size:var(--fs-l) }
#recipe.ykids .counter { font-size:var(--fs-xs); padding:3px 8px; background:var(--tile); color:var(--tile-ink) } /* drugorzędny */
#recipe.ykids .progress { height:6px; background:var(--y-line) }
#recipe.ykids .progress i { border-radius:0 var(--r-pill) var(--r-pill) 0 }
/* obrazek kroku = ten sam „obrazek w ramce” co okładka i karty; NIE dotyczy miniatur na liście (wcześniej przycinało produkty) */
#recipe.ykids .figure:has(> img), #recipe.ykids .figure > img { border-radius:var(--y-r-card) }
#recipe.ykids .figure:has(> img) { box-shadow:var(--y-shadow) }
#recipe.ykids .progress { display:none } /* pasek postępu odcinał pasek tytułu od strony; licznik w pasku zostaje */
#recipe.ykids .stepno { background:var(--tile); color:var(--tile-ink); font-weight:800; box-shadow:0 2px 8px -2px rgba(91,51,32,.35) }
#recipe.ykids .actions li { font-size:var(--fs-xl); font-weight:700; line-height:1.35 }
#recipe.ykids .slide h3 { font-weight:800; font-size:var(--fs-2xl) }
#recipe.ykids .ing .name { font-weight:700 }
/* pasek „dalej”: duża czekoladowa pigułka jak „Wróć do książki” */
#recipe.ykids .nextbar { display:flex; align-items:center; gap:12px; background:var(--y-bg); box-shadow:none }
#recipe.ykids .nextbar .prev { width:var(--y-next-h); height:var(--y-next-h) } /* koło = wysokość „dalej” */
#recipe.ykids .nextbar .next { flex:1; min-width:0; width:auto } /* „dalej” zajmuje resztę szerokości obok okrągłego „wstecz” (.prev) */
#recipe:not(.ykids) #prev { display:none } /* dorosły PictoCook bez przycisku wstecz */
#recipe.ykids .next { height:var(--y-next-h); min-height:var(--y-next-h); padding-block:0; border-radius:var(--r-pill); background:var(--y-ink); font-weight:800; font-size:var(--fs-xl); box-shadow:0 8px 20px -10px rgba(91,51,32,.6) }
#recipe.ykids .next.wait { background:var(--y-line); color:var(--y-muted); box-shadow:none }
#recipe.ykids .nextbar.off .dock { display:none } /* na ekranie końca nic nie wisi nad daniem */
/* krok dorosłego: ramka obrazka w kolorze dorosłego + Yumi z boku z ostrzeżeniem */
#recipe.ykids .slide.adult .figure { box-shadow:0 0 0 5px var(--y-adult), var(--y-shadow) }
/* niski telefon: obrazek kroku dorosłego oddaje trochę wysokości dużemu Yumiemu (pasek, „Dalej”, ~2 wiersze tekstu),
   zostaje wyśrodkowanym kwadratem; na wysokim telefonie min() daje pełną szerokość */
#recipe.ykids .slide.adult .figure { width:min(100%, calc(100dvh - var(--y-warn-h) - 250px)); align-self:center }
/* krok dorosłego: Yumi duży i czytelny (~150 px na wysokim telefonie, 120 px na niskim), obok obrazka kroku, nigdy na nim;
   dymek obok Yumiego, wyśrodkowany w pionie */
.ysay.ywarn { gap:6px }
.ysay.ywarn p { background:var(--y-adult); color:#fff; font-size:var(--fs-m); padding:10px 14px }
#recipe .ysay.ywarn img { width:auto; height:var(--y-warn-h); margin:-4px 0 -6px -6px }
/* Yumi nad listą składników / naczyń: mały, dymek obok; nie zasłania listy */
#recipe .ysay.ylist { margin-bottom:4px }
#recipe .ysay.ylist p { font-size:var(--fs-m); padding:10px 14px }
[data-yumi], #pvSay { cursor:pointer } /* tap w Yumiego albo dymek = powtórz kwestię */
#recipe .ysay img { width:72px; aspect-ratio:auto; border-radius:0 } /* nie jak obrazek kroku (.slide img) */
.slide.yfinblank { background:var(--y-bg) } /* koniec przepisu dla dzieci: pusta strona, treść = sekwencja ①–⑤ */

/* podgląd przepisu (#preview): mieści się bez przewijania od 375×667; przy mniejszym ekranie przewija się środek */
#preview.active { position:fixed; inset:0; max-width:var(--app-w); margin:0 auto; background:var(--tile) }
.pvbody { flex:1; min-height:0; overflow-y:auto; display:flex; flex-direction:column; gap:12px; padding:4px 16px 8px }
.pvcover { position:relative; flex:1 1 auto; min-height:140px; max-height:min(52dvh, 100cqw) }
.pvcover > img { display:block; width:100%; height:100%; object-fit:cover; border-radius:var(--y-r-card); box-shadow:var(--y-shadow) }
.pvbody { container-type:inline-size }
#pvSay { margin-top:auto } /* Yumi na dole, tuż nad „Zaczynamy!” */
.pvtime { margin:12px 32px 0 }
.pvtime .ytime { gap:8px; font-size:var(--fs-s) }
.pvfoot { display:flex; flex-direction:column; align-items:center; gap:4px; padding:4px 16px calc(12px + env(safe-area-inset-bottom)) }
.pvfoot .ybig { width:100% }

/* lista składników i naczyń dla dzieci: wiersz = karta jak w książce; miniatura produktu cała (contain), mały promień */
#recipe.ykids .slide ul.ing { gap:10px }
#recipe.ykids .ing li { padding:8px 12px 8px 10px; border:0; border-radius:var(--y-r-card); background:var(--y-card); box-shadow:var(--y-shadow); font-size:var(--fs-l) }
#recipe.ykids .ing li:last-child { border-bottom:0 }
#recipe.ykids .ing .ipic { width:76px; height:76px; padding:2px; object-fit:contain; border-radius:var(--y-r-thumb); background:transparent; box-shadow:none; aspect-ratio:auto }
#recipe.ykids .sub { margin-top:6px }
#recipe.ykids .ing .pill.qty { font-weight:800 }
#preview .pvcover { cursor:pointer } /* tap w okładkę = „Zaczynamy!” (dzieci tapią obrazek) */

/* wiersz listy dzieci: cały wiersz = jeden przycisk (.rowhear: miniatura, nazwa, ilość, ikonka „posłuchaj”), tap = Yumi czyta */
.ing li.hear, #recipe.ykids .ing li.hear { gap:0; padding:0; align-items:stretch }
.rowhear { display:flex; align-items:center; gap:12px; min-height:56px; margin:0; padding:8px 12px 8px 10px; border:0; background:none; color:inherit; font:inherit; text-align:left; cursor:pointer; -webkit-tap-highlight-color:transparent }
.rowhear { flex:1; min-width:0; display:grid; grid-template-columns:auto 1fr auto; column-gap:12px; row-gap:6px; align-items:center } /* miniatura | nazwa + ilość pod nią | ikonka: nazwa ma całą szerokość także przy 360 px */
.rowhear > .ipic { grid-row:1 / span 2 }
.ing li.pictured .rowhear .txt { grid-column:2; min-width:0 }
.rowhear > .pill { grid-column:2; grid-row:2; justify-self:start }

li.plain > .rowhear { grid-template-columns:1fr auto }
li.plain > .rowhear > .txt { grid-column:1; grid-row:1 }
li.plain > .rowhear > .pill { grid-column:1; grid-row:2 }
li.plain > .rowhear .hearicon { grid-column:2; grid-row:1 / span 2 }
.rowhear .hearicon { grid-column:3; grid-row:1 / span 2; margin-left:0 }
/* mała, cicha ikona: tu da się posłuchać (nagranie Yumiego) */
.hearicon { flex:none; display:grid; width:var(--y-hear); height:var(--y-hear); border-radius:50%; color:var(--y-adult); font-style:normal; /* mały przycisk: biała kulka z embossem, fale w kolorze akcentu */
  background:linear-gradient(var(--y-card), color-mix(in srgb, var(--y-card) 90%, var(--y-adult))); box-shadow:var(--y-emboss), 0 2px 5px -2px rgba(91,51,32,.4);
  transition:transform var(--y-press-ms) ease-out, box-shadow var(--y-press-ms) ease-out }
.ysay p:has(> .sayicon), .obsay:has(> .sayicon), .wyumi p:has(> .sayicon), .abub:has(> .sayicon), .ffbub:has(> .sayicon) { display:grid; grid-template-columns:1fr auto; align-items:center; column-gap:var(--y-say-gap) }
.bubble:has(> .sayicon) { gap:var(--y-say-gap) } /* dymek na home już jest flexem */
.sayicon { margin-left:0 } /* dymek z ikonką: siatka tekst | ikonka (tekst nigdy pod ikonką, bez paddingów, które nadpisują inne reguły dymków) */
.press:active:not(:disabled) .hearicon { transform:scale(.86); box-shadow:inset 0 2px 3px rgba(91,51,32,.3) } /* wciśnięcie razem z wierszem (.press) */
@media (prefers-reduced-motion: reduce) { .press:active:not(:disabled) .hearicon { transform:none } }
.hearicon svg { width:100%; height:100% }
.hearicon { pointer-events:none } /* przyciskiem jest cały dymek / wiersz: tap w ikonkę = tap w niego (to samo :active) */
@keyframes hearwave { 0%, 100% { opacity:.3 } 50% { opacity:1 } }
.talking > .hearicon svg path, li.speaking .hearicon svg path { animation:hearwave .9s ease-in-out infinite } /* ikonka „gra”, gdy Yumi czyta ten dymek / wiersz */
.talking > .hearicon svg path:nth-child(2), li.speaking .hearicon svg path:nth-child(2) { animation-delay:.15s }
.talking > .hearicon svg path:nth-child(3), li.speaking .hearicon svg path:nth-child(3) { animation-delay:.3s }
@media (prefers-reduced-motion: reduce) { .talking > .hearicon svg path, li.speaking .hearicon svg path { animation:none } }
.actions li .hearicon { margin-left:auto; align-self:center }
/* podgląd wersji (?preview=<id>@<N>, tylko dev): wiersz, którego nagranie nie pasuje do tekstu wersji, w miejscu ikonki „posłuchaj” */
.noclip { flex:none; align-self:center; margin-left:auto; font-style:normal; font-size:var(--fs-xs); font-weight:400; line-height:1.2; color:var(--muted); white-space:nowrap }
.rowhear .noclip { grid-column:3; grid-row:1 / span 2 }
li.plain > .rowhear .noclip { grid-column:2 }
/* plakietka podglądu wersji: mała, u góry na środku, nie łapie tapnięć */
.pvbadge { position:fixed; z-index:95; top:env(safe-area-inset-top); left:50%; transform:translateX(-50%); pointer-events:none;
  padding:1px 10px 2px; border-radius:0 0 var(--r-sm) var(--r-sm); background:color-mix(in srgb, var(--ink) 72%, transparent); color:var(--card); font-size:var(--fs-xs); font-weight:500; line-height:1.4; white-space:nowrap }
#recipe.ykids .ing li.speaking { box-shadow:0 0 0 3px var(--tile-ink), var(--y-shadow) } /* gra: obwódka (miniatury produktów mają białe tło, więc bez zmiany tła) */

/* JEDNA reakcja na dotyk dla wszystkiego, co w Yumicornie da się nacisnąć (Kris: każda interakcja ma subtelną odpowiedź).
   Klasa .press w znacznikach; audyt na /styleguide.html pokazuje klikalne elementy bez niej. Mniej ruchu: bez skali, tylko ciemniej. */
.press { transition:transform var(--y-press-ms) ease-out, filter var(--y-press-ms) ease-out; -webkit-tap-highlight-color:transparent }
.press:active:not(:disabled) { transform:scale(var(--y-press-scale)); filter:brightness(var(--y-press-dim)) }
@media (prefers-reduced-motion: reduce) { .press:active:not(:disabled) { transform:none } }

/* ---- zdjęcie dzieła i album (docs/design/photo-album-r1.md) ---- */
.pmodal { position:fixed; inset:0; z-index:60; max-width:var(--app-w); margin:0 auto; display:flex; flex-direction:column; gap:12px;
  padding:calc(12px + env(safe-area-inset-top)) 16px calc(12px + env(safe-area-inset-bottom)); background:var(--y-bg); color:var(--y-ink); font-family:var(--y-font) }
.pmyumi { flex:none; padding-right:calc(var(--y-voice-room) - 16px) } /* dymek nie wchodzi pod #voice (modal ma 16px własnego paddingu) */
/* podgląd zdjęcia albumu: pas kart ze snapem, kawałek sąsiedniego po bokach (jak kroki przepisu: --y-ap-peek, --y-card-gap) */
.apstrip { flex:0 1 auto; min-height:0; margin:0 -16px; display:flex; gap:var(--y-card-gap); overflow-x:auto; overflow-y:hidden; scroll-snap-type:x mandatory; scrollbar-width:none; overscroll-behavior-x:contain }
.apstrip::-webkit-scrollbar { display:none }
.apstrip::before, .apstrip::after { content:''; flex:0 0 calc(var(--y-ap-peek) - var(--y-card-gap)) }
.apslide { flex:0 0 calc(100% - 2 * var(--y-ap-peek)); scroll-snap-align:center; scroll-snap-stop:always }
.apslide img { display:block; width:100%; max-height:min(56dvh, 560px); aspect-ratio:4/5; object-fit:contain; border-radius:var(--y-r-card); box-shadow:var(--y-shadow); background:var(--y-soft) }
#albumPhoto { padding-top:0 } #albumPhoto .ybookhead { flex:none; margin:0 -16px } /* pasek ← jak w siatce albumu (ten sam .ybookhead, bez paddingu modala) */
.pmyumi img { width:56px; height:auto } .pmyumi p { font-size:var(--fs-m) }
.pmpreview { flex:0 1 auto; min-height:0; align-self:center; width:auto; max-width:100%; height:min(56dvh, calc((100vw - 32px) * 1.25));
  aspect-ratio:4/5; object-fit:contain; border-radius:var(--y-r-card); box-shadow:var(--y-shadow); background:var(--y-soft) }
.pmstrip { flex:none; position:relative; margin:0 -16px }
.pmfilters { display:flex; gap:12px; overflow-x:auto; padding:6px 16px; scroll-padding-inline:16px; scrollbar-width:none; scroll-snap-type:x proximity }
.pmfilters::-webkit-scrollbar { display:none }
.pmfilter { scroll-snap-align:start }
/* „są dalsze ramki”: zanik do tła + okrągła strzałka przy prawej krawędzi (znika na końcu paska) */
.pmstrip::after { content:''; position:absolute; top:0; right:0; bottom:0; width:72px; pointer-events:none;
  background:linear-gradient(to right, transparent, var(--y-bg) 75%); opacity:0; transition:opacity var(--y-press-ms) }
.pmmore { position:absolute; z-index:1; right:10px; top:28px; width:40px; height:40px; display:grid; place-items:center; padding:0; border:0;
  border-radius:50%; background:var(--y-card); color:var(--y-ink); box-shadow:var(--y-shadow); opacity:0; pointer-events:none; transition:opacity var(--y-press-ms) }
.pmmore svg { width:22px; height:22px }
.pmstrip.onward::after, .pmstrip.onward .pmmore { opacity:1 }
.pmstrip.onward .pmmore { pointer-events:auto }
.pmfilter { flex:none; display:flex; flex-direction:column; align-items:center; gap:4px; padding:0; border:0; background:none; color:var(--y-ink);
  font:700 var(--fs-xs)/1.1 var(--y-font) }
.pmfilter canvas { width:64px; height:80px; border-radius:var(--y-r-thumb); box-shadow:var(--y-shadow) }
.pmfilter.on canvas { outline:3px solid var(--y-adult); outline-offset:2px }
.pmerror { margin:0; padding:10px 14px; border-radius:var(--y-r-card); background:var(--y-adult); color:#fff; font-weight:700 }
.pmactions { flex:none; margin-top:auto; display:flex; flex-wrap:wrap; align-items:center; gap:10px }
.pmactions .ybig { flex:1 1 0; min-width:0 }
.ybig.ghost { background:var(--y-card); color:var(--y-ink); box-shadow:var(--y-shadow) }
.ybig.danger { background:var(--y-adult) }
.ybig input { display:none }
.apmeta { margin:0; text-align:center; font-weight:800; font-size:var(--fs-l) }
.apask { flex:1 0 100%; text-align:center; font-weight:800; font-size:var(--fs-l) }
/* strona główna: „Mój album” i „Moje nagrody” obok siebie (zawsze widoczne) */
/* niski telefon: niższe kafelki, żeby Yumi nie znikał (kafelek = obrazek + podpis) */
@media (max-height:700px) { :root { --y-tile-k:.6; --y-tile-label:48px } }
@media (max-height:600px) { :root { --y-tile-k:.5; --y-tile-label:44px; --y-home-title-w:180px; --y-tsticker:46px; --y-tiles-gap:18px } .ytile span { font-size:var(--fs-l) }
  .yheroimg { object-position:center 18% } } /* niski ekran: mniejszy tytuł i Yumi niżej, gwiazdki nad czapką (~6 px) */
.yduo { display:grid; grid-template-columns:minmax(0, 1fr) minmax(0, 1fr); gap:10px; margin-top:12px }
.yduob { position:relative; min-width:0; display:flex; align-items:center; gap:6px; min-height:68px; padding:10px 8px; border:var(--y-tile-border); border-radius:var(--y-r-card); color:var(--y-ink);
         background:linear-gradient(180deg, color-mix(in srgb, var(--duo) 50%, var(--y-card)), var(--duo)); box-shadow:inset 0 2px 0 var(--y-hi), var(--y-shadow); text-align:left; font:900 var(--fs-m)/1.1 var(--y-font) }
#homeAlbum { --duo:var(--y-album); --tile-acc:var(--y-album-acc) } #homeBadges { --duo:var(--y-awards); --tile-acc:var(--y-awards-acc) }
.yduob > span:not(.bdg):not(.yduoic) { flex:1; display:flex; flex-direction:column; gap:3px; min-width:0; font-size:clamp(var(--fs-s), 3.9vw, var(--fs-m)); white-space:nowrap }
.yduob .ygo { position:absolute; right:6px; bottom:6px; width:24px; height:24px } .yduob .ygo svg { width:15px; height:15px } /* w dolnym rogu: tytuł w jednej linijce na 360 px */
.yduob .bdg, .yduoic { --s:36px; width:36px; height:36px } .yduoic img { width:31px; height:31px }
.ymeter { display:block; width:calc(100% - 24px); height:8px; margin-top:2px; border-radius:var(--r-pill); background:var(--y-line-2); overflow:hidden } /* widoczny pusty tor */
.ymeter i { display:block; height:100%; min-width:7px; border-radius:var(--r-pill); background:linear-gradient(90deg, var(--y-g-mile), var(--y-album-acc)) }
.yduob small { font-size:var(--fs-xs); font-weight:700; color:var(--y-muted) }
.yduoic { width:46px; height:46px; flex:none; display:grid; place-items:center; border-radius:50%; background:var(--y-card) }
.yduoic img { width:40px; height:40px; object-fit:contain }
/* pusty album: Yumi z aparatem tłumaczy, co tu będzie */
.aempty { flex:1; display:flex; flex-direction:column; align-items:center; gap:12px; padding:16px 24px calc(20px + env(safe-area-inset-bottom)); text-align:center }
.aempty .abub { position:relative; margin:auto 0 0; padding:14px 16px; border-radius:var(--y-r-card); background:var(--y-card); box-shadow:var(--y-shadow); font-size:var(--fs-l); font-weight:800; line-height:1.3 }
.aempty .abub::after { content:''; position:absolute; left:50%; bottom:-10px; margin-left:-10px; border:10px solid transparent; border-bottom:0; border-top-color:var(--y-card) }
.aempty img { width:150px }
.aempty .ybig { width:100%; margin-top:auto }

/* ---- odznaki (nagrody): symbol (public/yumicorn/badges/<id>.webp) wyskakuje nad krążek w kolorze grupy (CSS) ---- */
.bdg { --s:84px; --c:var(--y-g-skill); position:relative; display:inline-block; width:var(--s); height:var(--s); flex:none }
.bdg[data-g=health] { --c:var(--y-g-health) } .bdg[data-g=drink] { --c:var(--y-g-drink) } .bdg[data-g=mile] { --c:var(--y-g-mile) } .bdg[data-g=special] { --c:var(--y-g-special) }
.bdg .disc { position:absolute; left:6%; right:6%; top:18%; bottom:0; border-radius:50%;
  background:radial-gradient(circle, rgba(255,255,255,.35) 1.2px, transparent 1.6px) 0 0/12px 12px,
    radial-gradient(circle at 35% 28%, #fff 0, color-mix(in srgb, var(--c) 55%, #fff) 38%, var(--c) 78%, color-mix(in srgb, var(--c) 82%, var(--y-ink)) 100%);
  box-shadow:inset 0 -4px 0 rgba(91,51,32,.12), 0 4px 10px -6px rgba(91,51,32,.5) }
.bdg img { position:absolute; left:-2%; top:-14%; width:104%; height:104%; object-fit:contain; pointer-events:none; filter:drop-shadow(0 3px 2px rgba(91,51,32,.28)) }
.bdg.off { filter:grayscale(1) opacity(.5) } /* niezdobyta */
.bdg.got::after { content:''; position:absolute; right:-2px; bottom:-2px; width:40%; height:40%; border-radius:50%; background:var(--y-solo) var(--y-check) center/70% no-repeat; box-shadow:0 0 0 2px var(--y-card) }
/* „Moje nagrody”: licznik, grupy, czysta siatka (bez półek) */
.bgbody { flex:1; min-height:0; overflow-y:auto; padding:4px 16px calc(24px + env(safe-area-inset-bottom)) }
.bgcount { display:flex; align-items:center; gap:12px; padding:12px 14px; border-radius:var(--y-r-card); background:var(--y-card); box-shadow:var(--y-shadow) }
.bgcount b { font-size:var(--fs-xl); font-weight:800; white-space:nowrap }
.bgmeter { flex:1; height:12px; border-radius:6px; background:var(--y-soft); overflow:hidden }
.bgmeter i { display:block; height:100%; border-radius:6px; background:linear-gradient(90deg, var(--y-g-skill), var(--y-g-mile)) }
.bggroup h3 { display:flex; align-items:center; gap:8px; margin:20px 0 8px; font:800 var(--fs-l)/1.2 var(--y-font) }
.bggroup h3 i { width:14px; height:14px; border-radius:50%; background:var(--c) }
.bggroup h3 small { margin-left:auto; font-size:var(--fs-s); font-weight:700; color:var(--y-muted) }
.bggrid { display:grid; grid-template-columns:repeat(3, 1fr); gap:14px 8px }
.bgcell { display:flex; flex-direction:column; align-items:center; gap:8px; padding:6px 2px; border:0; border-radius:var(--y-r-thumb); background:none; color:var(--y-ink) }
.bgcell span { font-size:var(--fs-xs); font-weight:800; line-height:1.15; text-align:center }
.bgcell.off span { color:var(--y-muted); font-weight:700 }
/* karta odznaki (arkusz jak w paywallu): duża odznaka, nazwa, grupa, za co / jak, Yumi */
.bsbody { display:flex; flex-direction:column; align-items:center; text-align:center }
.bsbody .bdg { --s:150px; margin:10px 0 8px }
.bsbody h3 { margin:0; font:800 var(--fs-2xl)/1.15 var(--y-font) }
.bgchip { margin:8px 0 10px; padding:3px 12px; border-radius:var(--r-pill); background:var(--c); font-size:var(--fs-s); font-weight:800 }
.bsbody .bshow { margin:0 0 14px; font-size:var(--fs-l); font-weight:700; line-height:1.35 }
.bsbody .ysay { align-self:stretch; text-align:left }
.sheetback.open .bsbody .bdg { animation:pwbounce .45s ease-out calc(var(--y-sheet-ms) * .6) both }
/* postęp odznaki: gwiazdki ★★☆ (do 5 razy; klasa .bgdots zostaje, kropki są tylko dla czasu) albo „n / need” (kamienie milowe 10, 25);
   nowa gwiazdka wskakuje (.new, opóźnienie --d). Gwiazdka = maska z kształtem (pełna / sam kontur), kolor z tokenów. */
.bgdots { display:inline-flex; gap:4px }
.bgdots i { --star-fill:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2.8l2.8 5.9 6.4.8-4.7 4.4 1.2 6.4L12 17.1l-5.7 3.2 1.2-6.4L2.8 9.5l6.4-.8z' stroke='%23000' stroke-width='1.6' stroke-linejoin='round'/%3E%3C/svg%3E");
  --star-line:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Cpath d='M12 2.8l2.8 5.9 6.4.8-4.7 4.4 1.2 6.4L12 17.1l-5.7 3.2 1.2-6.4L2.8 9.5l6.4-.8z' stroke='%23000' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E");
  position:relative; width:13px; height:13px }
.bgdots i::before { content:''; position:absolute; inset:0; background:var(--y-star-off); -webkit-mask:var(--star-line) center / contain no-repeat; mask:var(--star-line) center / contain no-repeat; transition:background-color .2s } /* maska na ::before, żeby iskierki w i.pgnext nie były ucinane */
.bgdots i.on::before { background:var(--y-star); -webkit-mask-image:var(--star-fill); mask-image:var(--star-fill) }
.bgfrac { font-size:var(--fs-xs); font-weight:800; color:var(--y-muted); font-variant-numeric:tabular-nums }
.bgcell .bgdots i { width:12px; height:12px }
.bsleft { display:flex; flex-direction:column; align-items:center; gap:6px; margin:0 0 8px }
.bsleft .bgdots i { width:22px; height:22px }
.bsleft b { font-size:var(--fs-l); font-weight:800; color:var(--y-adult) }
/* „Ćwiczysz umiejętności!”: lista odznak, które przepis posunął; wiersze wjeżdżają po kolei, nowa kropka wskakuje, „+1” odlatuje */
/* „Brawo! Ćwiczysz umiejętności”: start w stanie sprzed przepisu, potem wiersz po wierszu (.go z JS): podskok wiersza, „+1” odlatuje,
   kropka .next wskakuje z iskierkami, symbol na chwilę się koloruje; .fin = 3/3: symbol zostaje kolorowy, większy wybuch, „Gotowe!”.
   .pgend = koniec (liczniki się pojawiają); .instant = pominięte tapnięciem (bez animacji). */
.award.awprog { justify-content:flex-start }
.award.awprog h2 { margin:0 0 var(--y-card-gap); font-size:var(--fs-xl) } /* miejsce na wiersze + Yumiego (360×667); tytuł może zająć 2 linie przez miejsce na #voice */
.pglist { flex:1; min-height:0; overflow-y:auto; overflow-x:hidden; align-self:stretch; display:flex; flex-direction:column; gap:var(--y-card-gap); margin:0; padding:4px 4px 8px; list-style:none }
.pgrow { position:relative; display:flex; align-items:center; gap:16px; padding:10px 16px; border-radius:var(--y-r-card); background:var(--y-card); box-shadow:var(--y-shadow); text-align:left }
.pgbadge { position:relative; flex:none; display:grid; place-items:center }
.pgrow .bdg { --s:52px; transition:filter .3s }
.pgtxt { flex:1; min-width:0; display:flex; flex-direction:column; gap:8px }
.pgtxt .bgdots { gap:6px }
.pgtxt b { font-size:var(--fs-m); font-weight:800; line-height:1.15 }
.pgtxt .bgdots i { width:22px; height:22px }
.pgplus { position:absolute; right:14px; top:50%; margin-top:-.6em; font-size:var(--fs-2xl); font-weight:800; color:var(--y-adult); opacity:0; pointer-events:none }
.pgdone { flex:none; padding:3px 10px; border-radius:var(--r-pill); background:var(--y-solo); color:#fff; font-size:var(--fs-s); font-weight:800; opacity:0 }
.pgburst { position:absolute; left:50%; top:50%; width:0; height:0 }
.pgspark { position:absolute; left:-5px; top:-5px; width:10px; height:10px; background:var(--y-g-mile); clip-path:polygon(50% 0,62% 38%,100% 50%,62% 62%,50% 100%,38% 62%,0 50%,38% 38%); opacity:0 }
.pgbadge .pgspark { left:50%; top:50%; margin:-7px; width:14px; height:14px }
/* wydarzenie wiersza */
.pgrow.go { animation:pgbump .55s ease-out both }
.pgrow.go .pgplus { animation:pgplus .9s ease-out both }
.pgrow.go i.pgnext { animation:pgdot .45s cubic-bezier(.3,1.6,.5,1) .15s both }
.pgrow.go .pgspark { animation:awspark .7s ease-out .2s both }
.pgrow.go:not(.fin) .bdg.off { animation:pgglow .9s ease-out both }
.pgrow.fin.go .pgbadge .bdg { animation:awpop .7s cubic-bezier(.2,1.6,.4,1) .1s both }
.pgrow.fin.go .pgspark.big { animation:awspark .9s ease-out .25s both }
.pgrow.fin.go { background:color-mix(in srgb, var(--y-solo) 12%, var(--y-card)) }
.pgrow.fin.go .pgdone { opacity:1; animation:awup .4s ease-out .5s both } /* awup animuje OD zera, koniec = ta wartość */
.pgrow.fin.go .pgplus { color:var(--y-solo) }
@keyframes pgbump { 0% { transform:scale(1) } 35% { transform:scale(1.04); background:var(--y-glow) } 100% { transform:scale(1) } }
@keyframes pgplus { 0% { opacity:0; transform:translateY(6px) scale(.5) } 25% { opacity:1; transform:translateY(-6px) scale(1.25) } 100% { opacity:0; transform:translateY(-34px) scale(1) } }
@keyframes pgdot { 0% { transform:scale(0) } 60% { transform:scale(1.3) } 100% { transform:scale(1) } }
@keyframes pgglow { 0% { filter:grayscale(1) opacity(.5) } 35% { filter:grayscale(.2) opacity(1) drop-shadow(0 0 6px var(--y-g-mile)) } 100% { filter:grayscale(1) opacity(.5) } }
/* koniec / pominięte: stan końcowy bez animacji; liczniki dopiero po wierszach */
.pgrow.instant, .pgrow.instant * { animation:none !important }
.pgrow.fin.instant .pgdone { opacity:1 }
.pgrow.fin.instant { background:color-mix(in srgb, var(--y-solo) 12%, var(--y-card)) }
.award.awprog .pgcount { opacity:0; transition:opacity .4s }
.award.awprog.pgend .pgcount { opacity:1 }
@media (prefers-reduced-motion: reduce) { /* bez iskierek i odlotów: samo szybkie wypełnianie po kolei */
  .pgrow.go, .pgrow.go .pgplus, .pgrow.go .bdg.off, .pgrow.fin.go .pgbadge .bdg { animation:none }
  .pgspark, .pgplus { display:none }
  .pgrow.go i.pgnext { animation:fade .2s ease-out both }
  .pgrow.fin.go .pgdone { animation:fade .2s ease-out both }
}
/* liczniki (kamienie milowe, tęcza, kompas) w jednej linijce pod listą: mały symbol + „1 przepis · 1/5 kolorów · 1/4 kategorii” */
.pgcount { flex:none; display:flex; flex-wrap:nowrap; justify-content:center; align-items:center; gap:5px; margin:8px 0 0; font-size:var(--fs-xs); font-weight:800; color:var(--y-muted); white-space:nowrap }
.pgcount .bdg { --s:22px }
.pgcount span { display:inline-flex; align-items:center; gap:3px }
.pgcount i { font-style:normal }
.award.awprog .ybig { flex:none }
/* ③: Yumi na dole (nad „Dalej”) — od razu, mówi razem z animacją kropek */
.award.awprog .pgyumi { flex:none; margin-top:6px }
.pgyumi img { width:58px }
.pgyumi p { font-size:var(--fs-m); padding:9px 13px }
.award.awprog.play .pgyumi img { animation:pwbounce .45s ease-out both }
/* ikony na przyciskach (mapa ACTION w lib/icons.js): przyciski, które wcześniej miały sam tekst */
.obnext, .pwunlock { display:inline-flex; align-items:center; justify-content:center; gap:6px }
.pwunlock svg { width:18px; height:18px; flex:none }
.obnext svg { width:20px; height:20px; flex:none }
/* nagrody przepisu: Złota Czapka (jak na stronie głównej) + liczba odznak w prawym górnym rogu okładki; co kilka sekund lekko podskakuje */
.bgstack { position:absolute; top:6px; right:6px; padding:0; border:0; background:none }
.bgstack .bdg { --s:60px; animation:stackbob 4.5s ease-in-out 1.5s infinite }
.bgstack b { position:absolute; right:-4px; bottom:-2px; min-width:26px; height:26px; padding:0 6px; display:grid; place-items:center; border-radius:var(--r-pill);
             background:var(--y-adult); color:#fff; box-shadow:0 0 0 2px var(--y-card); font:800 var(--fs-s)/1 var(--y-font) }
@keyframes stackbob { 0%, 82%, 100% { transform:none } 88% { transform:translateY(-5px) rotate(-4deg) } 94% { transform:translateY(0) rotate(3deg) } }
#preview .bgstack { top:auto; bottom:6px } /* plakietka „Sam!” / dorosły u góry po prawej (jak na karcie), stosik odznak w prawym dolnym rogu: łatwo go dosięgnąć kciukiem */
.pwstack .bgstack { position:relative; top:auto; right:auto; display:block; margin:12px auto 0 } /* w arkuszu zamkniętego przepisu: w treści */
/* arkusz „Nagrody w tym przepisie”: wiersze jak na ekranie postępu, statyczne, klikalne */
.rbtitle { margin:0 48px 12px 4px; font:800 var(--fs-xl)/1.2 var(--y-font) }
.rblist { flex:none; max-height:min(62dvh, 470px) }
.rblist li { list-style:none }
/* plan przepisu dla dorosłego (#planSheet): kroki w kolejności; krok dorosłego = pomarańczowy pierścień + naklejka dorosłego, czekanie = pigułka z czasem */
.pvplanbtn { margin-left:auto }
.pllist { max-height:min(72dvh, 620px); overflow-y:auto; display:flex; flex-direction:column; gap:10px; margin:0; padding:4px 4px 8px; list-style:none }
.pllist li { display:flex; align-items:center; gap:12px; padding:8px; border-radius:var(--y-r-thumb); background:var(--y-card) }
.pllist li.adult { box-shadow:inset 0 0 0 2px var(--y-adult) }
.plpic { position:relative; flex:none; width:64px; height:64px }
.plpic > img { display:block; width:100%; height:100%; object-fit:cover; border-radius:var(--y-r-thumb) }
.plpic b { position:absolute; left:4px; top:4px; min-width:22px; height:22px; padding:0 5px; border-radius:var(--r-pill); background:var(--y-ink); color:#fff; font-size:var(--fs-xs); display:grid; place-items:center }
.pllist li.adult .plpic b { background:var(--y-adult) }
.plpic .pladult { position:absolute; right:-8px; bottom:-8px; width:30px; height:30px; object-fit:contain; filter:drop-shadow(0 1px 2px rgba(0,0,0,.3)) }
.plbody { min-width:0; display:flex; flex-direction:column; align-items:flex-start; gap:3px; font-size:var(--fs-s); color:var(--y-ink) }
.plbody b { font-size:var(--fs-m) }
.plwait { display:inline-flex; align-items:center; gap:5px; margin-top:2px; padding:3px 10px; border-radius:var(--r-pill); background:var(--y-adult); color:#fff; font-weight:800; font-size:var(--fs-xs) }
.plwait svg { width:16px; height:16px }
.rbrow { width:100%; border:0; color:var(--y-ink); font:inherit }
@media (prefers-reduced-motion: reduce) { .bgstack .bdg { animation:none } }
/* nowa odznaka: pełny ekran, promienie, iskierki, odznaka wskakuje z obrotem, potem nazwa */
.award { position:fixed; inset:0; z-index:55; /* pod modalem zdjęcia (60) — ② otwiera aparat nad sekwencją */ max-width:var(--app-w); margin:0 auto; display:flex; flex-direction:column; align-items:center; text-align:center;
         padding:calc(24px + env(safe-area-inset-top)) 16px calc(16px + env(safe-area-inset-bottom)); background:radial-gradient(circle at 50% 34%, var(--y-glow) 0, var(--y-bg) 60%) }
.award .kick { margin:0; font-size:var(--fs-m); font-weight:800; color:var(--y-muted); letter-spacing:.04em; text-transform:uppercase }
.award h2 { margin:4px 0 0; padding:0 var(--y-voice-room); font:800 var(--fs-3xl)/1.1 var(--y-font) } /* symetryczne miejsce na #voice: tytuł nie wchodzi pod przycisk */
.awstage { position:relative; flex:none; width:200px; height:200px; margin:clamp(8px, 3dvh, 22px) 0 4px; display:grid; place-items:center }
.awstage .bdg { --s:170px }
.awrays { position:absolute; inset:-30px; border-radius:50%; background:repeating-conic-gradient(color-mix(in srgb, var(--y-g-mile) 45%, transparent) 0 10deg, transparent 10deg 24deg);
          -webkit-mask:radial-gradient(circle, #000 30%, transparent 70%); mask:radial-gradient(circle, #000 30%, transparent 70%) }
.awspark { position:absolute; width:16px; height:16px; background:var(--y-g-mile); clip-path:polygon(50% 0,62% 38%,100% 50%,62% 62%,50% 100%,38% 62%,0 50%,38% 38%); opacity:0 }
.award .awname { margin:6px 0 0; font:800 var(--fs-2xl)/1.15 var(--y-font) }
.award .awhow { margin:4px 0 0; max-width:300px; font-size:var(--fs-m); font-weight:700; color:var(--y-muted) }
.award .ysay { margin-top:auto; align-self:stretch; text-align:left }
/* ④ dla 2+ odznak: jedna siatka „Nowe odznaki!” — odznaki wskakują po kolei (co 250 ms) z iskierkami; tap = karta odznaki */
.award.f-badges h2 { margin:4px 0 10px; font:800 var(--fs-3xl)/1.1 var(--y-font) }
.awgrid { align-self:stretch; display:grid; grid-template-columns:repeat(3, 1fr); gap:4px 6px }
.awgrid .bgcell { gap:4px; padding:2px }
.awcell { position:relative; display:grid; place-items:center }
.awgrid .bdg { --s:64px }
.awgrid .awspark { left:50%; top:50%; margin:-7px; width:14px; height:14px }
.award.play .awgrid .bgcell { animation:awpop .7s cubic-bezier(.2,1.6,.4,1) calc(var(--k) * 250ms + 150ms) both }
.award.play .awgrid .awspark { animation:awspark .8s ease-out calc(var(--k) * 250ms + 400ms) both }
@media (prefers-reduced-motion: reduce) { .award.play .awgrid .bgcell { animation:fade var(--y-sheet-ms) ease-out both } .awgrid .awspark { display:none } }
.award .ybig { width:100%; margin-top:0 }
/* sekwencja końca ①–⑤: kropki u góry, treść w środku, przyciski zawsze na dole (ten sam główny przycisk w tym samym miejscu) */
.award.ffenter { animation:ffin .34s cubic-bezier(.2,.8,.2,1) both } /* wejście w ① jak przejście między krokami */
@keyframes ffin { from { transform:translateX(100%) } }

.ffdots { flex:none; margin:0 0 10px }
.ffbody { position:relative; flex:1; min-height:0; align-self:stretch; display:flex; flex-direction:column; align-items:center }
.fffoot { flex:none; align-self:stretch; display:flex; flex-direction:column; gap:10px; margin-top:12px }
.fffoot .ybig .bdg { --s:40px }
.award.awprog .ffbody { align-items:stretch; text-align:center }
.award.f-cheer h2, .award.f-photo h2, .award.f-next h2 { margin:4px 0 12px; font:800 var(--fs-3xl)/1.1 var(--y-font) }
.ffdish { width:100%; max-height:34dvh; object-fit:cover; border-radius:var(--y-r-card); box-shadow:var(--y-shadow) }
.ffpose { width:min(52%, 220px); margin:auto 0 0 }
.ffbub { position:relative; margin:14px 0 auto; padding:14px 18px; border-radius:var(--y-r-card); background:var(--y-card); box-shadow:var(--y-shadow); font-size:var(--fs-xl); font-weight:800; line-height:1.25 }
.ffbub::before { content:''; position:absolute; left:50%; top:-12px; margin-left:-12px; border:12px solid transparent; border-bottom:12px solid var(--y-card); border-top:0 }
.award.play .ffpose { animation:pwbounce .45s ease-out .1s both }
.award.f-cheer.play .ysay img, .award.f-next.play .ysay img { animation-delay:.35s } /* Yumi od razu, nie po animacji odznaki */
.award.f-cheer.play .ysay p, .award.f-next.play .ysay p { animation-delay:.6s }
.award.play .ffbub { animation:pop .35s cubic-bezier(.3,1.6,.5,1) .4s both }
/* ① konfetti: kolorowe paski spadają raz */
.ffconf { position:absolute; inset:-24px -16px 0; overflow:hidden; pointer-events:none; z-index:1 }
.ffconf i { position:absolute; top:-16px; left:calc(var(--k) * 4.6%); width:8px; height:13px; border-radius:2px; background:var(--y-g-skill); opacity:0;
            animation:ffconf 2.6s ease-in calc(var(--k) * 70ms) both }
.ffconf i:nth-child(5n+2) { background:var(--y-g-mile) } .ffconf i:nth-child(5n+3) { background:var(--y-g-drink) }
.ffconf i:nth-child(5n+4) { background:var(--y-g-health) } .ffconf i:nth-child(5n) { background:var(--y-g-special) }
@keyframes ffconf { 0% { opacity:1; transform:translateY(0) rotate(0) } 90% { opacity:1 } 100% { opacity:0; transform:translateY(92dvh) rotate(540deg) } }
@media (prefers-reduced-motion: reduce) { .award.ffenter { animation:fade var(--y-sheet-ms) ease-out both } .ffconf { display:none } .award.play .ffpose, .award.play .ffbub { animation:fade var(--y-sheet-ms) ease-out both } }
.award.play .awrays { animation:awrays 1.6s ease-out both, awspin 18s linear infinite }
.award.play .awstage .bdg { animation:awpop .9s cubic-bezier(.2,1.6,.4,1) .15s both }
.award.play .awspark { animation:awspark 1s ease-out .55s both }
.award.play .awname, .award.play .awhow { animation:awup .5s ease-out .8s both }
.award.play .ysay img { animation:pwbounce .4s ease-out 1s both }
.award.play .ysay p { transform-origin:left center; animation:pop .35s cubic-bezier(.3,1.6,.5,1) 1.25s both }
@keyframes awpop { 0% { transform:scale(0) rotate(-25deg); opacity:0 } 60% { transform:scale(1.15) rotate(6deg); opacity:1 } 100% { transform:scale(1) rotate(0) } }
@keyframes awrays { from { opacity:0; transform:scale(.4) } to { opacity:1; transform:scale(1) } }
@keyframes awspin { to { rotate:360deg } }
@keyframes awspark { 0% { opacity:0; transform:translate(0,0) scale(.3) } 30% { opacity:1 } 100% { opacity:0; transform:translate(var(--dx),var(--dy)) scale(1) } }
@keyframes awup { from { opacity:0; transform:translateY(10px) } }
@media (prefers-reduced-motion: reduce) { /* bez wjazdów i obrotów: samo przenikanie, bez iskierek */
  .award.play .awrays, .award.play .awstage .bdg, .award.play .awname, .award.play .awhow, .award.play .ysay img, .award.play .ysay p,
  .sheetback.open .bsbody .bdg { animation:fade var(--y-sheet-ms) ease-out both }
  .awspark { display:none }
}
/* zamknięty przepis (paywall): karta przygaszona + kłódka; arkusz od dołu (Yumi dla dziecka, pod kreską cicha część dla dorosłego) */
.ycard.locked > img:not(.ylock) { filter:saturate(.6) brightness(.9) }
.ycard > img.ylock { position:absolute; top:8px; left:8px; flex:none; width:64px; height:64px; object-fit:contain; transform-origin:50% 20% } /* padlock.webp ma własną białą obwódkę */
.sheetback { position:fixed; inset:0; z-index:65; display:flex; align-items:flex-end; justify-content:center; background:rgba(91,51,32,0); transition:background-color var(--y-sheet-ms) ease-out }
.sheet { position:relative; width:100%; max-width:var(--app-w); padding:24px 16px calc(20px + env(safe-area-inset-bottom)); border-radius:var(--y-r-card) var(--y-r-card) 0 0; background:var(--y-bg); box-shadow:var(--y-shadow) }
/* animacja: tło ciemnieje, arkusz wjeżdża od dołu (.open), zjeżdża przy zamykaniu; Yumi wskakuje z podskokiem, potem dymek od strony Yumiego */
.sheet { transform:translateY(100%); transition:transform var(--y-sheet-ms) cubic-bezier(.2,.8,.2,1) }
.sheetback.open { background:rgba(91,51,32,.45) }
.sheetback:not(.open) { pointer-events:none } /* zjeżdżający arkusz nie łapie tapnięć (tap w tło zamknąłby książkę) */
.sheetback.open .sheet { transform:none }
.sheetback.open .ysay img { animation:pwbounce .4s ease-out calc(var(--y-sheet-ms) * .7) both }
.sheetback.open .ysay p { transform-origin:left center; animation:pop .35s cubic-bezier(.3,1.6,.5,1) calc(var(--y-sheet-ms) * .7 + .25s) both }
@keyframes pwbounce { 0% { opacity:0; transform:scale(.8) } 60% { opacity:1; transform:scale(1.05) } 100% { transform:scale(1) } }
.ylock.wiggle { animation:pwwiggle var(--y-wiggle-ms) ease-in-out }
@keyframes pwwiggle { 25% { transform:rotate(-14deg) } 50% { transform:rotate(11deg) } 75% { transform:rotate(-6deg) } }
@media (prefers-reduced-motion: reduce) { /* tylko przenikanie */
  .sheet { transform:none; opacity:0; transition:opacity var(--y-sheet-ms) ease-out }
  .sheetback.open .sheet { opacity:1 }
  .sheetback.open .ysay img, .sheetback.open .ysay p { animation:fade var(--y-sheet-ms) ease-out both }
  .ylock.wiggle { animation:none }
}
.sheetclose { position:absolute; z-index:2; top:8px; right:8px; width:44px; height:44px; display:grid; place-items:center; padding:0; border:0; border-radius:50%; background:none; color:var(--y-muted) }
.sheetclose svg { width:24px; height:24px }
.pwview h3 { margin:0 48px 16px 0; font:800 var(--fs-xl)/1.2 var(--y-font) }
.pwview > p { margin:0 0 20px; font-size:var(--fs-l); line-height:1.4; color:var(--y-muted) }
#pwKid .ysay { padding-right:36px }
.pwline { margin:20px 0 14px; border:0; border-top:1px solid var(--y-line) }
.pwadult { display:flex; flex-direction:column; align-items:flex-start; gap:10px }
/* ekran oferty (TASK-49, mockup 2026-10-24): akapit z pogrubioną obietnicą, kafelek „tyle co pizza”, przycisk z ceną (bez osobnej dużej kwoty: nie odciąga wzroku od reszty), drobny druk o zwrocie */
#pwPayText b, .pwpizza b { color:var(--y-ink) }
.pwpizza { display:flex; align-items:center; gap:12px; margin:0 0 24px; padding:14px 16px; border-radius:var(--r-md); background:var(--y-sweet); color:var(--y-sweet-ink) }
.pwpizza img { width:56px; height:56px; flex:none; filter:drop-shadow(0 2px 3px var(--y-stitch)) }
.pwpizza p { margin:0; font-size:var(--fs-l); line-height:1.4 }
#pwPayBtn { width:100% } /* główne wezwanie: na całą szerokość */
.pwview > p.pwfine, .pwfine { margin:0 0 12px; font-size:var(--fs-s); line-height:1.4; color:var(--y-muted) }
.pwview > p.pwrefund { margin:14px 0 0; text-align:center }
.pwform { display:grid; gap:10px }
.pwemail { min-height:48px; padding:0 16px; border:1px solid var(--y-line-2); border-radius:var(--r-pill); font:inherit; font-size:var(--fs-m); color:var(--y-ink); background:var(--y-card) }
.pwemail:focus { outline:2px solid var(--y-ink); outline-offset:1px }
.pwerr { margin:0; font-size:var(--fs-s); font-weight:700; color:var(--y-adult) }
.pwsent { margin:0 0 14px; font-size:var(--fs-l); font-weight:800; color:var(--y-ink) }
.pwunlock { min-height:44px; padding:0 18px; border:1px solid var(--y-line-2); border-radius:var(--r-pill); background:none; color:var(--y-ink); font:700 var(--fs-m)/1 var(--y-font) }
/* bramka rodzica (TASK-26): arkusz nad wszystkim (też nad paywallem i modalami), zadanie słowne, odpowiedź, duża klawiatura cyfr 3×4 */
.gate { z-index:80 }
.gq { margin:0 0 12px; font:800 var(--fs-xl)/1.25 var(--y-font); color:var(--y-ink) }
.pwview > .gq { font-size:var(--fs-xl); color:var(--y-ink) }
.gans { display:block; min-height:64px; margin:0 0 12px; padding:10px 16px; border-radius:var(--y-r-card); background:var(--y-soft); text-align:center; font:800 var(--fs-3xl)/1.4 var(--y-font); letter-spacing:.12em; font-variant-numeric:tabular-nums }
.gans.shake { animation:gshake .35s ease-in-out }
@keyframes gshake { 20%, 60% { transform:translateX(-8px) } 40%, 80% { transform:translateX(8px) } }
.gkeys { display:grid; grid-template-columns:repeat(3, 1fr); gap:10px }
.gkey { min-height:64px; border:0; border-radius:var(--r-pill); background:var(--y-card); color:var(--y-ink); box-shadow:var(--y-shadow); font:800 var(--fs-2xl)/1 var(--y-font); display:grid; place-items:center; padding:0 }
.gkey svg { width:28px; height:28px }
.gkey.gok { background:var(--y-ink); color:#fff }
@media (prefers-reduced-motion: reduce) { .gans.shake { animation:none } }
#pwDoor .ybig { width:100% }


/* onboarding dorosłych (docs/design/onboarding-adults-r1.md): karty 1–4 spokojne (bez Yumiego, bez animacji), karta 5 = świat Yumiego.
   Obrazek ~60% karty; na niskim ekranie maleje obrazek, nigdy tekst (karta się nie przewija). */
.onboard { position:fixed; inset:0; z-index:70; max-width:var(--app-w); margin:0 auto; display:flex; flex-direction:column; background:var(--y-card); color:var(--y-ink); font-family:var(--y-font) }
.obpages { flex:1; min-height:0; display:flex; overflow-x:auto; scroll-snap-type:x mandatory; scrollbar-width:none; overscroll-behavior-x:contain }
.obpages::-webkit-scrollbar { display:none }
.obcard { position:relative; flex:0 0 100%; min-height:0; display:flex; flex-direction:column; scroll-snap-align:center; scroll-snap-stop:always; overflow:hidden }
.obbrand { position:absolute; z-index:1; top:calc(8px + env(safe-area-inset-top) + var(--y-voice) + var(--y-say-gap)); left:0; right:0; margin:0; display:flex; justify-content:center; line-height:0; pointer-events:none } /* karta 1: logo z home (jak .yhometitle) pod paskiem ikon (przełącznik głosu: top 8 px + --y-voice), nad zeszytem; ilustracja przesunięta (OB_CARDS[0] center 15%) */
.obbrand img { width:var(--y-home-title-w); height:auto; filter:drop-shadow(0 2px 6px rgba(255,255,255,.8)) }
.obcard > img { flex:0 1 60%; min-height:0; width:100%; object-fit:cover; display:block }
.obtxt { flex:none; padding:20px 24px 0 }
.obtxt .obicon { display:block; width:104px; height:104px; margin:12px auto 0; object-fit:contain; transform:rotate(-4deg); filter:drop-shadow(0 2px 4px rgba(0,0,0,.3)) } /* piktogram dorosłego pod tekstem karty */
.obtxt h2 { margin:0 0 10px; font:800 var(--fs-2xl)/1.15 var(--y-font) }
.obtxt p { margin:0; font-size:var(--fs-l); line-height:1.45; color:var(--y-muted) }
/* karta 5: dymek Yumiego (pierwszy głos w apce) w miejscu tytułu i zdania — ten sam blok .obtxt, nic się nie przesuwa */
.obtxt .obsay { position:relative; margin:0; padding:14px 18px; border-radius:var(--y-r-card); background:var(--y-sweet); color:var(--y-ink); font:800 var(--fs-2xl)/1.15 var(--y-font); box-shadow:var(--y-shadow) } /* jak .obtxt h2 */
.obsay::before { content:''; position:absolute; left:28px; top:-12px; border:12px solid transparent; border-bottom:12px solid var(--y-sweet); border-top:0 }
.obfoot { flex:none; display:flex; align-items:center; justify-content:space-between; gap:16px; padding:12px 24px calc(16px + env(safe-area-inset-bottom)) }
.obnext { flex:none; width:9.5em; min-height:52px; padding:0 16px; border:0; border-radius:var(--r-pill); background:var(--y-ink); color:#fff; font:800 var(--fs-l)/1 var(--y-font) }
.onboard.last .obnext { background:var(--y-adult) } /* karta 5: ten sam przycisk (stała szerokość: kropki stoją w miejscu), tylko kolorowy akcent */
.onboard.last .ydots i.on { background:var(--y-adult) }
/* karta 5 bez kropek (Kris 2026-10-19); bez pytania o zgodę „Zaczynamy” zostaje na swoim miejscu (kropki niewidoczne, nie usunięte) */
.onboard.last .obfoot .ydots { visibility:hidden }
/* karta 5 z pytaniem o zgodę (TASK-117, .onboard.ask): linijka zgody pod dymkiem; w stopce [Nie zgadzam się] i [Zgadzam się →] obok siebie (DOM w tej samej kolejności),
   po równo, tej samej wysokości (odmowa równie dostępna); mieszczą się w 360 px bez łamania */
.obtxt .obconsent { margin:calc(var(--y-say-gap) * 2) 0 0; font-size:var(--fs-s); line-height:1.4 } /* odstęp od dymka Yumiego: token jak przerwa w dymku */
.onboard.ask .obfoot { gap:10px }
.onboard.ask .obfoot .ydots { display:none }
.onboard.ask .obnext, .onboard.ask .obno { flex:1 1 0; width:auto; min-width:0; min-height:52px; padding:0 10px; font-size:var(--fs-m); white-space:nowrap }
/* eksperyment „lean onboarding” (?ob=lean): arkusz .sheet nad stroną główną; punkty .olpoints wskakują po kolei (pop, --i) po wjeździe arkusza,
   potem zgoda .olconsent i para [Nie zgadzam się] (.ybig.ghost) + [Zgadzam się →] (.ybig.olyes, akcent dorosłego) po równo */
#oblean { z-index:95 } /* nad przełącznikiem głosu (.yvoice, 90): arkusz z przyciemnieniem zakrywa cały home, także ten przycisk */
.oblean > .adultmark { position:absolute; top:16px; right:16px; width:40px; height:40px }
.oblean h3 { margin:0 48px 14px 0; font:800 var(--fs-2xl)/1.15 var(--y-font) }
.olpoints { margin:0; padding:0; list-style:none; display:flex; flex-direction:column; gap:10px }
.olpoints li { position:relative; padding:12px 14px 12px 40px; border-radius:var(--y-r-card); background:var(--y-card); box-shadow:var(--y-shadow); font-size:var(--fs-m); line-height:1.4 }
.olpoints li::before { content:''; position:absolute; left:15px; top:19px; width:12px; height:12px; border-radius:50%; background:var(--y-adult) }
.olpoints .olicon { width:26px; height:26px; margin:-6px 2px; vertical-align:middle; object-fit:contain }
.sheetback.open .olpoints li { animation:pop .35s cubic-bezier(.3,1.6,.5,1) calc(var(--y-sheet-ms) + var(--i) * .45s) both; transform-origin:left center }
.olconsent { margin:14px 0 0; font-size:var(--fs-s); line-height:1.4 }
.olfoot { display:flex; gap:10px; margin-top:14px }
.olfoot .ybig { flex:1 1 0; min-width:0; min-height:52px; padding:0 10px; font-size:var(--fs-m); white-space:nowrap }
.olfoot .olyes { background:var(--y-adult) }
.olfoot .olyes svg { width:20px; height:20px; flex:none }
@media (prefers-reduced-motion: reduce) { .sheetback.open .olpoints li { animation:none } }
#album.active { position:fixed; inset:0; max-width:var(--app-w); margin:0 auto; background:var(--y-bg) }
.agrid { flex:1; min-height:0; overflow-y:auto; display:grid; grid-template-columns:1fr 1fr; align-content:start; gap:12px; padding:8px 16px 24px }
.acard { display:flex; flex-direction:column; padding:0 0 10px; border:0; border-radius:var(--y-r-card); overflow:hidden; background:var(--y-card);
  box-shadow:var(--y-shadow); color:var(--y-ink); text-align:left; font-family:var(--y-font) }
.acard img { width:100%; aspect-ratio:4/5; object-fit:cover; display:block }
.acard b { padding:8px 10px 0; font-size:var(--fs-s); font-weight:800; line-height:1.2 }
.acard small { padding:2px 10px 0; font-size:var(--fs-xs); color:var(--y-muted) }

/* ---- przerwa z Yumim: timer kroku u dzieci (docs/design/timer-overlay-r1.md) ---- */
.next.timer, #recipe.ykids .next.timer { background:var(--y-timer) }
#recipe.ykids .next.timer.wait { background:var(--y-line) } /* najpierw przewiń opis — jak zwykły „Dalej” */
/* czas już leci: sam licznik (tap = przerwa wraca), bez „Odmierz czas” — mieści się w jednej linii */
.next.counting > svg:first-child, .next.counting > span:not(.left) { display:none }
@media (max-height:700px) { .woverlay { --y-wait-yumi:26svh } } /* niski ekran (360×667): 3-linijkowa kwestia nie wypycha „Dalej” */
.woverlay { position:fixed; inset:0; z-index:60; max-width:var(--app-w); margin:0 auto; display:flex; flex-direction:column; align-items:center;
  gap:14px; padding:calc(20px + env(safe-area-inset-top)) 16px calc(16px + env(safe-area-inset-bottom)); background:var(--y-timer-soft);
  color:var(--y-ink); font-family:var(--y-font); text-align:center }
.wyumi { display:flex; flex-direction:column; align-items:center; gap:10px; border:0; background:none; color:inherit }
/* pudełko w proporcji yumi-wait-simple (866×1264, Yumi na garnku); timeup (866×1024) siedzi w nim przy dolnej krawędzi
   w tej samej skali, więc zmiana pozy nie przesuwa licznika. Wysokość od ekranu: niski telefon też się mieści. */
.wyumi img { height:min(var(--y-wait-yumi, 34svh), 300px); width:auto; aspect-ratio:866/1264; object-fit:contain; object-position:bottom;
  animation:wbob 2.4s ease-in-out infinite }
.wyumi p { margin:0; padding:12px 16px; border-radius:var(--y-r-card); background:var(--y-card); font-size:var(--fs-l); font-weight:700; line-height:1.3; box-shadow:var(--y-shadow) }
.wclock { position:relative; width:min(52vw, 210px); aspect-ratio:1; color:var(--y-timer) }
.wclock svg { width:100%; height:100% }
.wclock b { position:absolute; inset:0; display:grid; place-items:center; font-size:var(--y-fs-clock); font-weight:800; font-variant-numeric:tabular-nums; color:var(--y-ink) }
.wstep { margin:0; font-size:var(--fs-m); font-weight:700; color:var(--y-muted) }
.woverlay .ybig { margin-top:auto; width:100% }
.woverlay .ybig svg { width:24px; height:24px }
/* czas minął: licznik pełny, „Dalej” pulsuje */
.woverlay.done .wclock { color:var(--y-solo) }
.woverlay.done .ybig { background:var(--y-timer); animation:wpulse 1.2s ease-in-out infinite }
@keyframes wbob { 50% { transform:translateY(-6px) rotate(-2deg) } }
@keyframes wpulse { 50% { transform:scale(1.04) } }
@media (prefers-reduced-motion: reduce) { .wyumi img, .woverlay.done .ybig { animation:none } }

/* Shine: duże brązowe przyciski „dalej” (nie .ghost / .danger / :disabled / .wait, nie dorosły PictoCook). Pasek leci raz po wejściu na ekran
   (0,6 s zwłoki; ekran z display:none restartuje animację), potem co --y-shine-ms. Reduced motion: wyłączone. */
.ybig:not(.ghost, .danger, :disabled), #recipe.ykids .next:not(.wait, :disabled), .obnext { position:relative; overflow:hidden }
.ybig:not(.ghost, .danger, :disabled)::after, #recipe.ykids .next:not(.wait, :disabled)::after, .obnext::after {
  content:''; position:absolute; top:0; bottom:0; left:0; width:38%; pointer-events:none; filter:blur(3px);
  background:linear-gradient(90deg, transparent, var(--y-shine), transparent); transform:translateX(-160%) skewX(-22deg);
  animation:shine var(--y-shine-ms) ease-in-out .6s infinite }
@keyframes shine { 0% { transform:translateX(-160%) skewX(-22deg) } 18%, 100% { transform:translateX(380%) skewX(-22deg) } } /* ~0,9 s przelotu z 5 s */
@media (prefers-reduced-motion: reduce) { .ybig::after, #recipe.ykids .next::after, .obnext::after { animation:none; content:none } }

/* instalacja PWA (TASK-50): chip na home (ikona rodzica + „Zainstaluj”), arkusz nad wszystkim, kreator iOS z rysowanymi ikonami */
.yinstchip { display:flex; align-items:center; gap:8px; margin:14px auto 0; padding:6px 16px 6px 10px; border:1px solid var(--y-line-2); border-radius:var(--r-pill); background:none; color:var(--y-muted); font:700 var(--fs-m)/1 var(--y-font) }
.pwlink { font-size:var(--fs-s); font-weight:700; color:var(--y-muted); text-underline-offset:3px } /* link do polityki w arkuszu zgody */
.yinstchip img { width:var(--y-time-ic); height:var(--y-time-ic); object-fit:contain; filter:drop-shadow(0 2px 4px rgba(0,0,0,.3)) }
.sheetback.over { z-index:80 }
.sheetback.over .sheet { max-height:92dvh; overflow-y:auto }
#instBody p { margin:0 0 12px; font-size:var(--fs-l); line-height:1.4; color:var(--y-ink) }
.instrow { display:flex; align-items:center; gap:12px }
.instor { color:var(--y-muted); font-size:var(--fs-m) }
.igl { flex:none; display:grid; place-items:center; width:var(--y-voice); height:var(--y-voice); border-radius:50%; background:var(--y-soft); color:var(--y-ink) }
.igl svg { width:28px; height:28px }
.iglword { color:var(--ios-blue); font:600 var(--fs-s)/1 -apple-system,system-ui,sans-serif } /* „Dodaj” w pasku Safari: niebieski napis, bez ikony */
/* iOS: modal u góry ekranu (dół zostaje wolny dla systemowego panelu Udostępnij), 3 kroki naraz w .instlist */
.sheetback.pwtop { align-items:flex-start }
.sheetback.pwtop .sheet { padding:calc(20px + env(safe-area-inset-top)) 16px 20px; border-radius:0 0 var(--y-r-card) var(--y-r-card); transform:translateY(-100%) }
.sheetback.pwtop.open .sheet { transform:none }
.sheetback.pwtop .pwview > .adultmark { top:-6px }
body:has(.sheetback.pwtop.open) .yvoice { opacity:0; pointer-events:none } /* przełącznik głosu (z-index 90) stałby na ✕ modala */
.instlist { display:flex; flex-direction:column; gap:10px; margin:0 0 4px; padding:0; list-style:none }
.instlist li { display:flex; align-items:center; gap:10px; padding:8px 12px 8px 8px; border-radius:var(--y-r-card); background:var(--y-card); box-shadow:var(--y-shadow) }
.instnum { flex:none; display:grid; place-items:center; width:26px; height:26px; border-radius:50%; background:var(--y-ink); color:var(--y-bg); font:800 var(--fs-s)/1 var(--y-font) }
.instpic { display:flex; align-items:center; gap:6px }
.instto { font:800 var(--fs-xl)/1 var(--y-font); color:var(--y-muted) }
.insttxt { flex:1; font-weight:800; font-size:var(--fs-m); line-height:1.3; color:var(--y-ink) }
.instaddr { padding:10px 14px; border-radius:var(--y-r-card); background:var(--y-soft); font-weight:800; word-break:break-all }
.instfoot { display:flex; flex-wrap:wrap; gap:10px; margin-top:14px }
.instfoot .ybig { flex:1 1 0; min-width:0 }
#instCopy.ok { background:var(--y-solo); color:#fff }
.instlink { flex:1 0 100%; padding:10px 14px; border:1px solid var(--y-line-2); border-radius:var(--y-r-card); font:inherit; color:var(--y-ink); background:var(--y-card) }

/* grupa „Tylko dla dorosłego” na dole listy naczyń (TASK-61): nagłówek z ikoną dorosłego, wiersze w kolorze dorosłego jak ramka kroku dorosłego */
.sub.adultsub { display:flex; align-items:center; gap:8px; color:var(--y-adult) }
.adultsub img { width:var(--y-time-ic); height:var(--y-time-ic); object-fit:contain; filter:drop-shadow(0 2px 4px rgba(0,0,0,.3)) }
#recipe.ykids .ing.adultgear li { box-shadow:0 0 0 2px var(--y-adult), var(--y-shadow) }

/* Tylko jasny motyw: nie ma ciemnych tokenów. Blok istnieje celowo: Samsung Internet w trybie „Adaptive Force Dark” / „media query” pomija
   własne przyciemnianie, gdy strona deklaruje obsługę schematów (meta color-scheme i ta kwerenda), a w prefers-color-scheme: dark i tak
   zostajemy przy jasnych kolorach. Domyślny Force Dark Samsunga ignoruje to wszystko (NOTES „Tylko jasny motyw”). */
@media (prefers-color-scheme: dark) { :root { color-scheme:only light } }
