/* ========================================================================= KUCHAŘKA KAMILY PEŠEK // PASCAL 7.0 WEB ENGINE (331 RECEPTŮ & 568 JÍDEL) Kulinářská paměť Kamily Pešek & Software-salon ALTÁN (Helena Heroutová) ========================================================================= */ // Audio engine (Retro PC Speaker via Web Audio API) let audioCtx = null; let soundEnabled = true; function playSpeaker(freq = 800, duration = 0.04, type = 'square') { if (!soundEnabled) return; try { if (!audioCtx) { audioCtx = new (window.AudioContext || window.webkitAudioContext)(); } if (audioCtx.state === 'suspended') { audioCtx.resume(); } const osc = audioCtx.createOscillator(); const gain = audioCtx.createGain(); osc.type = type; osc.frequency.setValueAtTime(freq, audioCtx.currentTime); gain.gain.setValueAtTime(0.08, audioCtx.currentTime); gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + duration); osc.connect(gain); gain.connect(audioCtx.destination); osc.start(); osc.stop(audioCtx.currentTime + duration); } catch (e) {} } // Data references loaded from data.js const KNIHA_RECEPTU = window.KNIHA_RECEPTU || []; const HISTORICKA_JIDLA = window.HISTORICKA_JIDLA || []; // App State let currentView = 'menu'; // 'menu', 'recept', 'recepty_list', 'hledat', 'suroviny', 'davno', 'oblibena', 'kronika', 'altan' let currentRecipeId = 1; let currentCategory = 'Vše'; let listPage = 0; const PAGE_SIZE = 12; const screenEl = document.getElementById('screen-content'); const winTitleEl = document.getElementById('win-title'); const timeEl = document.getElementById('time-display'); // Clock setInterval(() => { const d = new Date(); timeEl.textContent = d.toTimeString().split(' ')[0]; }, 1000); // ========================================================================= // CZECH TEXT NORMALIZATION & FULLTEXT SEARCH ENGINE // ========================================================================= // Normalizace: malá písmena, odstranění diakritiky function norm(str) { return (str || "").toLowerCase() .normalize("NFD").replace(/[\u0300-\u036f]/g, ""); } // Český lehký stemmer (odstranění pádových a slovesných koncovek pro dokonalou flexi) function stem(word) { let w = norm(word).replace(/[^a-z0-9]/g, ""); if (w.length <= 3) return w; // Dlouhé přídavné a slovesné koncovky w = w.replace(/(ovy|ova|ove|ymi|ych|ich|ovi|ami|ach|ech|eho|emu|ajici|ejici)$/, ""); if (w.length > 3) { // Slovesa a podstatná jména w = w.replace(/(ime|ite|eme|ete|aji|eji|ala|alo|ali|ila|ilo|ili|ula|ulo|uli)$/, ""); } if (w.length > 3) { // Dvojpísmenné koncovky w = w.replace(/(em|ou|am|um|ym|im|ky|ka|ku|ek|ce|ci|ho|mu|mi|es|as|at|et|it|ut|ti|al|il|ul|ne|na|ny)$/, ""); } if (w.length > 3) { // Krátké samohlásky w = w.replace(/[aeiouy]$/, ""); } return w; } // Rozdělení dotazu na čistá slova function tokenize(str) { return norm(str) .split(/[\s,.;:()!?"'\/\\+*#%&<=>[\]{}|~_`^$]+/) .filter(t => t.length > 0); } // Kontrola shody slova: function wordMatches(targetWord, queryWord, queryStem) { const tw = norm(targetWord); if (tw === queryWord) return true; if (tw.startsWith(queryWord) || queryWord.startsWith(tw)) return true; const ts = stem(targetWord); if (ts === queryStem) return true; if (queryStem.length >= 3 && ts.startsWith(queryStem)) return true; if (ts.length >= 3 && queryStem.startsWith(ts)) return true; return false; } // Zvýraznění shod v textu (HTML mark) function highlightMatches(text, query) { if (!query || !text) return text; const tokens = tokenize(query).filter(t => t.length > 1); if (tokens.length === 0) return text; const stems = tokens.map(stem); const parts = text.split(/(\s+|[.,;()\-+*\/:"'!?<>])/); return parts.map(part => { if (!part.trim()) return part; const np = norm(part); const sp = stem(part); const isMatch = tokens.some((tok, idx) => wordMatches(part, tok, stems[idx])); if (isMatch) { return `${part}`; } return part; }).join(""); } // Robustní vyhledávání v sešitu Kamily Pešek function searchKniha(query, categoryFilter = 'Vše') { if (!query || !query.trim()) return []; const tokens = tokenize(query); if (tokens.length === 0) return []; const stems = tokens.map(stem); const source = categoryFilter === 'Vše' ? KNIHA_RECEPTU : KNIHA_RECEPTU.filter(r => r.kategorie === categoryFilter); const results = []; source.forEach(r => { const titleWords = tokenize(r.nazev); const surWords = tokenize((r.suroviny || []).join(" ")); const posWords = tokenize(r.postup || ""); const katWords = tokenize(r.kategorie || ""); let score = 0; let matchedTokens = 0; let snippet = ""; tokens.forEach((tok, idx) => { const st = stems[idx]; let hit = false; // 1. Shoda v názvu (priorita #1) if (titleWords.some(tw => wordMatches(tw, tok, st))) { score += 150; hit = true; } // 2. Shoda v surovinách if (surWords.some(sw => wordMatches(sw, tok, st))) { score += 50; hit = true; if (!snippet) { const found = (r.suroviny || []).find(s => tokenize(s).some(sw => wordMatches(sw, tok, st))); if (found) snippet = "Surovina: " + found; } } // 3. Shoda v kategorii if (katWords.some(kw => wordMatches(kw, tok, st))) { score += 25; hit = true; } // 4. Shoda v postupu if (posWords.some(pw => wordMatches(pw, tok, st))) { score += 20; hit = true; if (!snippet && r.postup) { snippet = "Postup: " + r.postup.substring(0, 110) + "..."; } } if (hit) matchedTokens++; }); // Masivní bonus za pokrytí všech hledaných slov (AND logika) if (matchedTokens === tokens.length) { score += 500 * tokens.length; } if (score > 0) { results.push({ recipe: r, score: score, matchedCount: matchedTokens, snippet: snippet }); } }); // Seřadit: nejdřív ty, co splňují všechny tokeny, pak podle skóre results.sort((a, b) => { const fullA = a.matchedCount === tokens.length ? 1 : 0; const fullB = b.matchedCount === tokens.length ? 1 : 0; if (fullA !== fullB) return fullB - fullA; return b.score - a.score || a.recipe.id - b.recipe.id; }); return results; } // Categories list const KATEGORIE = [ 'Vše', 'Polévky', 'Masitá jídla', 'Vánoční cukroví', 'Moučníky a sladké', 'Přílohy a bezmasá', 'Omáčky', 'Saláty a zelenina', 'Ostatní' ]; // ========================================================================= // VIEWS & CONTROLLERS // ========================================================================= // 1. HLAVNÍ NABÍDKA function renderMainMenu() { currentView = 'menu'; winTitleEl.textContent = "KUCHAŘKA KAMILY PEŠEK // HLAVNÍ NABÍDKA PASCAL 7.0"; let html = `
════════════════════════════════════════════════════════════════════════════════ KUCHAŘKA KAMILY PEŠEK // AUTENTICKÝ SEŠIT RECEPTŮ (1998–2026) Software-salon ALTÁN (Ing. Helena Heroutová, Dejvice) & Konzdat ════════════════════════════════════════════════════════════════════════════════
Vítejte v rodinném gastronomickém archivu babičky Kamily Pešek. Tento systém obsahuje ${KNIHA_RECEPTU.length} přepsaných receptů z jejího ručně psaného sešitu (strany 1–43) a ${HISTORICKA_JIDLA.length} záznamů rodinného jídelníčku z let 1998–2021.
── RYCHLÉ VYHLEDÁVÁNÍ V KUCHAŘCE ───────────────────────────────────────────
HLEDAT:
── HLAVNÍ PROGRAMOVÉ MODULY ────────────────────────────────────────────────
[H / /] >> FULLTEXTOVÉ HLEDÁNÍ V CELÉM SEŠITU (${KNIHA_RECEPTU.length} receptů) <<
[R] Procházet receptář Kamily Pešek podle kategorií
[S] Vařit podle surovin ve špajzu a lednici (Algoritmus KUCHARKA.EXE)
[N] Náhodný recept pro dnešní den (Inspirace ze sešitu)
[D] Doporučení: Dávno nevařeno (Prevence stereotypu - DoporucD)
[O] Železná statistika oblíbených jídel rodinného stolu (DoporucO)
[K] Kronika rodinného stolu (${HISTORICKA_JIDLA.length} záznamů Bohnice a Dejvice)
[A] O programu & Software-salon ALTÁN (Historie Dejvic & Bohnic)
── RYCHLÝ VÝBĚR DLE KATEGORIE ──────────────────────────────────────────────
`; KATEGORIE.slice(1).forEach((cat, idx) => { const count = KNIHA_RECEPTU.filter(r => r.kategorie === cat).length; html += ``; }); html += `
Zvolte klávesu [H, R, S, N, D, O, K, A, /] nebo kategorii [1-8]. Na mobilu klepněte prstem.
`; screenEl.innerHTML = html; const quickInput = document.getElementById('menu-quick-search'); if (quickInput) { quickInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') triggerMenuSearch(); }); } } function triggerMenuSearch() { const input = document.getElementById('menu-quick-search'); if (input && input.value.trim()) { openSearch(input.value.trim()); } else { openSearch(); } } // 2. FULLTEXTOVÉ VYHLEDÁVÁNÍ (DEDIKOVANÉ ROZHRANÍ) function openSearch(defaultQuery = "") { currentView = 'hledat'; playSpeaker(750, 0.05); winTitleEl.textContent = `HLEDÁNÍ V KUCHAŘCE KAMILY PEŠEK // FULLTEXT ENGINE`; let html = `
════════════════════════════════════════════════════════════════════════════════ FULLTEXTOVÉ VYHLEDÁVÁNÍ // RECEPTÁŘ KAMILY PEŠEK (${KNIHA_RECEPTU.length} RECEPTŮ) ════════════════════════════════════════════════════════════════════════════════
Zadejte hledaný název jídla, surovinu nebo kousek postupu (např. kuře, bábovka, kmínová, guláš, česnek, ořechy, brambory). Vyhledávač automaticky ohýbá česká slova a prohledává všech ${KNIHA_RECEPTU.length} receptů ze sešitu.
HLEDAT V RECEPTÁŘI:
Časté dotazy:
`; screenEl.innerHTML = html; const input = document.getElementById('global-search-input'); input.focus(); input.setSelectionRange(input.value.length, input.value.length); input.addEventListener('input', () => { executeGlobalSearch(); }); input.addEventListener('keydown', (e) => { if (e.key === 'Enter') executeGlobalSearch(); }); if (defaultQuery) { executeGlobalSearch(); } } function quickQuery(q) { const input = document.getElementById('global-search-input'); if (input) { input.value = q; executeGlobalSearch(); input.focus(); } } function executeGlobalSearch() { const input = document.getElementById('global-search-input'); const resEl = document.getElementById('global-search-results'); if (!input || !resEl) return; const query = input.value.trim(); if (!query) { resEl.innerHTML = `
Zadejte alespoň 2 písmena pro vyhledání v sešitu Kamily Pešek...
`; return; } playSpeaker(850, 0.03); const results = searchKniha(query, 'Vše'); let html = ""; if (results.length > 0) { html += `
★ Nalezeno ${results.length} receptů pro dotaz "${query}":
`; html += `
`; results.slice(0, 20).forEach(item => { const r = item.recipe; const highlightedTitle = highlightMatches(r.nazev, query); const highlightedSnippet = item.snippet ? highlightMatches(item.snippet, query) : ""; html += `
[${r.id}] ${highlightedTitle} Str. ${r.strana} | ${r.kategorie}
${highlightedSnippet ? `
${highlightedSnippet}
` : ''}
`; }); html += `
`; if (results.length > 20) { html += `
...a dalších ${results.length - 20} receptů. Upřesněte dotaz pro zúžení výběru.
`; } } else { html += `
Pro dotaz "${query}" nebyl v sešitu Kamily Pešek nalezen žádný recept.
`; // Prohledat i kroniku 568 jídel jako zálohu const histMatches = HISTORICKA_JIDLA.filter(j => norm(j.jidlo).includes(norm(query))); if (histMatches.length > 0) { html += `
📜 Nalezeno ale v Kronice rodinného stolu (1998–2021):
`; histMatches.slice(0, 8).forEach(j => { html += `
${j.jidlo} [${j.datum}, ${j.typ}]
`; }); } } resEl.innerHTML = html; } // 3. SEZNAM RECEPTŮ PODLE KATEGORIÍ S INTEGROVANÝM VYHLEDÁVÁNÍM function openReceptyList(category = 'Vše', page = 0, initialQuery = "") { currentView = 'recepty_list'; currentCategory = category; listPage = page; playSpeaker(700, 0.04); const baseList = category === 'Vše' ? KNIHA_RECEPTU : KNIHA_RECEPTU.filter(r => r.kategorie === category); const totalPages = Math.ceil(baseList.length / PAGE_SIZE); const pageItems = baseList.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE); winTitleEl.textContent = `RECEPTÁŘ KAMILY PEŠEK // ${category.toUpperCase()} (${baseList.length} RECEPTŮ)`; let html = `
════════════════════════════════════════════════════════════════════════════════ RECEPTÁŘ KAMILY PEŠEK // KATEGORIE: ${category.toUpperCase()} (Strana ${page + 1}/${totalPages || 1}) ════════════════════════════════════════════════════════════════════════════════
`; KATEGORIE.forEach(cat => { const activeClass = cat === category ? 'style="background-color:var(--dos-yellow); color:var(--dos-black)"' : ''; html += ``; }); html += `
`; pageItems.forEach((r) => { html += `
[${r.id}] ${r.nazev} Str. ${r.strana} | ${r.kategorie}
`; }); html += `
${page > 0 ? `` : ''} ${page < totalPages - 1 ? `` : ''}
Celkem ${baseList.length} receptů v této kategorii
`; screenEl.innerHTML = html; // Search input live filtering const searchInput = document.getElementById('recipe-search-input'); const container = document.getElementById('recipe-items-container'); const pagination = document.getElementById('recipe-pagination'); const statusBar = document.getElementById('search-status-bar'); const handleSearch = () => { const q = searchInput.value.trim(); if (!q) { statusBar.innerHTML = ""; pagination.style.display = "flex"; let defaultHtml = ""; pageItems.forEach((r) => { defaultHtml += `
[${r.id}] ${r.nazev} Str. ${r.strana} | ${r.kategorie}
`; }); container.innerHTML = defaultHtml; return; } // Hledat primárně v celé knize, pokud uživatel píše dotaz const matched = searchKniha(q, 'Vše'); pagination.style.display = "none"; statusBar.innerHTML = `Nalezeno ${matched.length} receptů v celém sešitu pro dotaz "${q}":`; let mHtml = ""; matched.slice(0, 25).forEach(item => { const r = item.recipe; const highlightedTitle = highlightMatches(r.nazev, q); const snippet = item.snippet ? highlightMatches(item.snippet, q) : ""; mHtml += `
[${r.id}] ${highlightedTitle} Str. ${r.strana} | ${r.kategorie}
${snippet ? `
${snippet}
` : ''}
`; }); if (matched.length === 0) { mHtml = `
Žádný recept v sešitu neodpovídá hledanému výrazu "${q}".
`; } container.innerHTML = mHtml; }; searchInput.addEventListener('input', handleSearch); if (initialQuery) { handleSearch(); } } function clearRecipeSearch(category) { openReceptyList(category, 0); } // 4. DETAIL RECEPTU function openRecipe(id) { const r = KNIHA_RECEPTU.find(x => x.id === id); if (!r) return; currentView = 'recept'; currentRecipeId = id; playSpeaker(900, 0.05); winTitleEl.textContent = `RECEPT [${r.id}/${KNIHA_RECEPTU.length}]: ${r.nazev.toUpperCase()}`; let html = `
════════════════════════════════════════════════════════════════════════════════ RECEPT Č. ${r.id}: ${r.nazev} Původní sešit Kamily Pešek: Strana ${r.strana} | Kategorie: ${r.kategorie} ════════════════════════════════════════════════════════════════════════════════
── POTŘEBNÉ SUROVINY ZE SEŠITU ─────────────────────────────────────────────
── POSTUP PŘÍPRAVY ZE SEŠITU KAMILY PEŠEK ─────────────────────────────────
${r.postup || "Tradiční rodinný postup podle zápisu Kamily Pešek."}
★ TAJEMSTVÍ KAMILY PEŠEK:
"${r.tajemstvi}"
${id > 1 ? `` : ''} ${id < KNIHA_RECEPTU.length ? `` : ''}
`; screenEl.innerHTML = html; } // 5. NÁHODNÝ RECEPT function openRandomRecipe() { if (KNIHA_RECEPTU.length === 0) return; const randomId = Math.floor(Math.random() * KNIHA_RECEPTU.length) + 1; openRecipe(randomId); } // 6. VAŘENÍ ZE SUROVIN VE ŠPAJZU (ALGORITMUS) function openSuroviny(defaultQuery = "") { currentView = 'suroviny'; playSpeaker(700, 0.06); winTitleEl.textContent = "ALGORITMUS: VAŘENÍ PODLE SUROVIN VE ŠPAJZU A LEDNICI"; let html = `
════════════════════════════════════════════════════════════════════════════════ VAŘENÍ PODLE SUROVIN // ROZHODOVACÍ SYSTÉM PRO HOSPODYNI (KUCHARKA.EXE) ════════════════════════════════════════════════════════════════════════════════
Zadejte suroviny, které máte právě doma ve špajzu a lednici (oddělené čárkou či mezerou). Algoritmus prohledá všech ${KNIHA_RECEPTU.length} receptů Kamily Pešek i ${HISTORICKA_JIDLA.length} jídel z kroniky.
MÁM DOMA:
Rychlé koše:
`; screenEl.innerHTML = html; const input = document.getElementById('suroviny-input'); input.focus(); input.addEventListener('keydown', (e) => { if (e.key === 'Enter') doSearchSuroviny(); }); if (defaultQuery) { doSearchSuroviny(); } } function fillPantry(str) { const input = document.getElementById('suroviny-input'); if (input) { input.value = str; doSearchSuroviny(); } } function doSearchSuroviny() { const query = document.getElementById('suroviny-input').value.trim(); const resEl = document.getElementById('vysledky-hledani'); if (!query) { resEl.innerHTML = `
Zadejte alespoň jednu surovinu!
`; return; } playSpeaker(1000, 0.04); const tokens = tokenize(query); const stems = tokens.map(stem); // Score Recipes (suroviny, nazev, postup) const scoredRecipes = KNIHA_RECEPTU.map(r => { let matches = []; const normFull = norm(r.nazev + " " + (r.suroviny || []).join(" ") + " " + (r.postup || "")); tokens.forEach((tok, idx) => { const st = stems[idx]; if (normFull.includes(tok) || (st.length >= 3 && normFull.includes(st))) { matches.push(tok); } }); matches = [...new Set(matches)]; return { recipe: r, score: matches.length, matchedTokens: matches }; }).filter(x => x.score > 0).sort((a, b) => b.score - a.score || a.recipe.id - b.recipe.id); // Score Historical Database const scoredHist = HISTORICKA_JIDLA.map(j => { let matches = []; const nJidlo = norm(j.jidlo); tokens.forEach((tok, idx) => { const st = stems[idx]; if (nJidlo.includes(tok) || (st.length >= 3 && nJidlo.includes(st))) { matches.push(tok); } }); matches = [...new Set(matches)]; return { jidlo: j, score: matches.length, matchedTokens: matches }; }).filter(x => x.score > 0).sort((a, b) => b.score - a.score); let html = `
VÝSLEDEK SHODY PRO: "${query}" (Nalezeno ${scoredRecipes.length} receptů Kamily Pešek)
`; if (scoredRecipes.length > 0) { html += `
★ NALEZENÉ RECEPTY ZE SEŠITU KAMILY PEŠEK:
`; scoredRecipes.slice(0, 15).forEach(item => { html += `
[${item.recipe.id}] ${item.recipe.nazev} Shoda: ${item.score} surovin (${item.matchedTokens.join(', ')})
`; }); } if (scoredHist.length > 0) { html += `
📜 ZÁZNAMY Z HISTORICKÉHO JÍDELNÍČKU (1998–2021):
`; scoredHist.slice(0, 8).forEach(item => { html += `
${item.jidlo.jidlo} [${item.jidlo.datum}, ${item.jidlo.typ}] shoda: ${item.matchedTokens.join(', ')}
`; }); } if (scoredRecipes.length === 0 && scoredHist.length === 0) { html += `
Pro tyto suroviny nebyla v databázi nalezena přímá shoda. Zkuste zadat základní ingredience jako: brambory, maso, vejce, smetana, kuře.
`; } resEl.innerHTML = html; } // 7. DÁVNO NEVAŘENO function openDavno() { currentView = 'davno'; playSpeaker(600, 0.05); winTitleEl.textContent = "DOPORUČENÍ: DÁVNO NEVAŘENO // PREVENCE STEREOTYPU"; let html = `
════════════════════════════════════════════════════════════════════════════════ DOPORUČENÍ: DÁVNO NEVAŘENO // HISTORICKÝ CYKLUS RODINY (DoporucD) ════════════════════════════════════════════════════════════════════════════════
Tento modul dekompilovaný z původního Delphi programu prochází archiv datumu a vyhledává pokrmy, které se na stole neobjevily nejdéle, aby se jídelníček netočil.
DOPORUČENÁ JÍDLA S NEJDELŠÍM ČASOVÝM ODSTUPEM:
`; HISTORICKA_JIDLA.slice(0, 12).forEach((j, idx) => { html += `
${idx + 1}. ${j.jidlo} Naposledy: ${j.datum} | ${j.typ}
`; }); html += `
`; screenEl.innerHTML = html; } // 8. OBLÍBENÁ JÍDLA function openOblibena() { currentView = 'oblibena'; playSpeaker(850, 0.05); winTitleEl.textContent = "OBLÍBENÁ JÍDLA // ŽELEZNÁ STATISTIKA STOLU"; const freq = {}; HISTORICKA_JIDLA.forEach(j => { const title = j.jidlo.split(',')[0].trim(); freq[title] = (freq[title] || 0) + 1; }); const top = Object.entries(freq).sort((a, b) => b[1] - a[1]).slice(0, 12); let html = `
════════════════════════════════════════════════════════════════════════════════ ŽELEZNÁ STATISTIKA OBLÍBENÝCH JÍDEL RODINNÉHO STOLU (DoporucO) ════════════════════════════════════════════════════════════════════════════════
Frekvenční žebříček z ${HISTORICKA_JIDLA.length} záznamů rodinného jídelníčku z let 1998–2021:
`; const maxVal = top[0] ? top[0][1] : 1; top.forEach(([name, count], idx) => { const barWidth = Math.max(2, Math.round((count / maxVal) * 24)); const bar = "█".repeat(barWidth); html += `
${idx + 1}. ${name} ${bar} ${count}×
`; }); html += `
`; screenEl.innerHTML = html; } // 9. KRONIKA RODINNÉHO STOLU function openKronika(page = 0) { currentView = 'kronika'; playSpeaker(700, 0.04); winTitleEl.textContent = `KRONIKA STOLU BOHNICE & DEJVICE (${HISTORICKA_JIDLA.length} ZÁZNAMŮ)`; const totalPages = Math.ceil(HISTORICKA_JIDLA.length / 20); const items = HISTORICKA_JIDLA.slice(page * 20, (page + 1) * 20); let html = `
════════════════════════════════════════════════════════════════════════════════ KRONIKA RODINNÉHO STOLU // BOHNICE & DEJVICE (Strana ${page + 1}/${totalPages}) ════════════════════════════════════════════════════════════════════════════════
Kompletní záznamy o tom, co se skutečně vařilo a jedlo v rodině Kamily Pešek v letech 1998–2021.
`; items.forEach((j) => { html += `
${j.datum}: ${j.jidlo} ${j.typ}
`; }); html += `
${page > 0 ? `` : ''} ${page < totalPages - 1 ? `` : ''}
Záznam ${page * 20 + 1}–${Math.min((page + 1) * 20, HISTORICKA_JIDLA.length)} z ${HISTORICKA_JIDLA.length}
`; screenEl.innerHTML = html; } // 10. ALTÁN / NÁPOVĚDA function openAltan() { currentView = 'altan'; playSpeaker(750, 0.05); winTitleEl.textContent = "SOFTWARE-SALON ALTÁN // DEJVICE & BOHNICE"; let html = `
════════════════════════════════════════════════════════════════════════════════ SOFTWARE-SALON ALTÁN // VÁCLAVKOVA 2, PRAHA 6 (DEJVICE) ════════════════════════════════════════════════════════════════════════════════
PŮVODNÍ PROGRAMÁTORSKÁ STOPA Z JEDNOTKY TURBO PASCALU (POMUCKY.BAK):

const rec : array[1..3] of string = (
  'S PŘIPOMÍNKAMI A DOTAZY SE OBRACEJTE NA ADRESU:',
  ' Ing. B. Mikulecký, CSc., Ing. H. Heroutová',
  ' Software-salon ALTÁN ',
  ' Václavkova 2, 160 00 Praha 6, tel. 02/311 13 25');


Ing. Helena Heroutová patřila k průkopnické generaci českých softwarových inženýrek, které v 80. a 90. letech tvořily základní procedurální knihovny pro Turbo Pascal a DOS v dejvickém ateliéru na Václavkově ulici.

Když se na přelomu tisíciletí objevilo vývojové prostředí Borland Delphi, koncept rodinné kuchařky se přetavil do plnohodnotné 32bitové aplikace KUCHARKA.EXE.

Tato webová aplikace věrně propojuje kulinářské dědictví babičky Kamily Pešek (kompletní rukopisný sešit čítající ${KNIHA_RECEPTU.length} receptů) s procedurální logikou Turbo Pascalu pro budoucí generace.
`; screenEl.innerHTML = html; } // ========================================================================= // GLOBAL KEYBOARD & TOUCH NAVIGATION // ========================================================================= window.addEventListener('keydown', (e) => { // If typing in input, only ESC blurs if (document.activeElement && document.activeElement.tagName === 'INPUT') { if (e.key === 'Escape') { document.activeElement.blur(); renderMainMenu(); } return; } playSpeaker(800, 0.03); switch (e.key) { case '/': case 'h': case 'H': e.preventDefault(); openSearch(); break; case 'r': case 'R': case 'F2': e.preventDefault(); openReceptyList('Vše'); break; case 's': case 'S': case 'F3': e.preventDefault(); openSuroviny(); break; case 'n': case 'N': openRandomRecipe(); break; case 'd': case 'D': case 'F4': e.preventDefault(); openDavno(); break; case 'o': case 'O': openOblibena(); break; case 'k': case 'K': case 'F5': e.preventDefault(); openKronika(); break; case 'a': case 'A': case 'F1': e.preventDefault(); openAltan(); break; case 'Escape': renderMainMenu(); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': if (currentView === 'menu') { const idx = parseInt(e.key); if (KATEGORIE[idx]) openReceptyList(KATEGORIE[idx]); } break; } }); // Touch / Navigation controls handler document.querySelectorAll('[data-act]').forEach(el => { el.addEventListener('click', () => { const act = el.getAttribute('data-act'); if (act === 'menu') renderMainMenu(); else if (act === 'hledat') openSearch(); else if (act === 'recepty') openReceptyList('Vše'); else if (act === 'suroviny') openSuroviny(); else if (act === 'davno') openDavno(); else if (act === 'oblibena') openOblibena(); else if (act === 'kronika') openKronika(); else if (act === 'altan') openAltan(); }); }); // Sound toggle document.getElementById('sound-btn').addEventListener('click', () => { soundEnabled = !soundEnabled; document.getElementById('sound-btn').textContent = soundEnabled ? '🔊 ZVUK: ON' : '🔈 ZVUK: OFF'; if (soundEnabled) playSpeaker(1200, 0.08); }); // Initial boot renderMainMenu();