From 2050cc9ddf845e83ea9b88044b307e7e4bbd8467 Mon Sep 17 00:00:00 2001 From: Krystof Pesek Date: Sat, 7 Nov 2026 18:36:51 +0100 Subject: [PATCH] feat(kucharka): initial web resuscitation of Helena & Kamila Heroutova's Pascal cookbook --- app.js | 639 +++++++++++++++++++++++++++++++++++++++++++++++++++++ index.html | 69 ++++++ style.css | 322 +++++++++++++++++++++++++++ 3 files changed, 1030 insertions(+) create mode 100644 app.js create mode 100644 index.html create mode 100644 style.css diff --git a/app.js b/app.js new file mode 100644 index 0000000..ebd1bf7 --- /dev/null +++ b/app.js @@ -0,0 +1,639 @@ +/* ========================================================================= + KUCHAŘKA HELENY A KAMILY HEROUTOVÉ (1998–2026) // PASCAL 7.0 WEB ENGINE + Software-salon ALTÁN (Václavkova 2, Praha 6) & The Observatoř Konzdat + ========================================================================= */ + +// 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) {} +} + +// Full Authentic Recipes from Kamila Heroutová's handwritten notebook +const KNIHA_RECEPTU = [ + { + id: 1, + nazev: "Zavářená kmínová polévka pro dva", + kategorie: "Polévka", + doba: 30, + suroviny: [ + "1 malá cibule jemně nasekaná", + "Kousek másla na zpěnění", + "2 brambory nakrájené na drobné kostičky", + "1 lžička sladké a špetka pálivé papriky", + "Celý český kmín a sůl", + "1 litr mléka (nebo kysaná smetana) s lžící mouky" + ], + postup: "Cibuli zpěnit na másle do sklovata. Přidat brambory, papriku a kmín. Zalít vodou a uvařit doměkka. V mléce rozkvedlat lžíci hrubé mouky, vlažné vlít do vroucí polévky a nechat provařit.", + tajemstvi: "Před podáváním zjemnit lžící poctivé kysané smetany a celý kmín před vhozením promnout v dlani pro uvolnění silic." + }, + { + id: 2, + nazev: "Babiččino kuře na česneku a slanině", + kategorie: "Hlavní chod", + doba: 85, + suroviny: [ + "1 celé kuře naporcované na čtvrtky", + "15 dkg domácí uzené slaniny na kostičky", + "1 celá hlavička třeného českého česneku", + "Kousek másla a sůl s černým pepřem", + "Příloha: vařené brambory s petrželkou" + ], + postup: "Do litinového pekáče nasypat kostičky slaniny a česnek. Čtvrtky kuřete osolit, opepřit, položit kůží nahoru na lůžko, poklást plátky másla a pomalu péct přikryté.", + tajemstvi: "Posledních 15 minut odklopit poklop a zvednout žár v troubě, aby kůžička dokonale zkřupala a česnek zezlátl." + }, + { + id: 3, + nazev: "Vosí hnízda s rumovým krémem", + kategorie: "Vánoční cukroví", + doba: 50, + suroviny: [ + "16 dkg jemně rozdrcených piškotů", + "16 dkg moučkového cukru", + "6 dkg másla, 2 lžíce holandského kakaa", + "2 lžíce mléka a pořádná dávka tuzemského rumu", + "Krém: 5 dkg másla utřeného se žloutkem a vanilkovým cukrem", + "Celé dětské piškoty na přiklopení" + ], + postup: "Z těsta vyválet váleček. Kousky vmačkat do formiček vysypaných moučkovým cukrem, udělat důlek, naplnit žloutkovým krémem a zaklopit piškotem.", + tajemstvi: "Formičku před každým kouskem vyprášit moučkovým cukrem, hnízdo pak vyklouzne jedním lehkým klepnutím o vál." + }, + { + id: 4, + nazev: "Dělové koule (nepečené kakao)", + kategorie: "Cukroví", + doba: 40, + suroviny: [ + "10 dkg pravého změklého másla", + "10 lžic moučkového cukru", + "1 sáček vanilkového cukru", + "1 čerstvý vaječný žloutek", + "2 plné lžíce holandského kakaa", + "Strouhaný kokos nebo mleté vlašské ořechy na obalení" + ], + postup: "Máslo utřít s cukrem, kakaem a žloutkem do kompaktní hmoty. Tvarovat kuličky a obalovat v kokosu či ořeších. Nechat odležet v chladu.", + tajemstvi: "Přímo do kakaového základu kápnout tři kapky rumu pro sametový lesk a plnost čokoládové chuti." + }, + { + id: 5, + nazev: "Kočičí oči s rybízovou marmeládou", + kategorie: "Pečení", + doba: 45, + suroviny: [ + "10 dkg hladké mouky", + "8 dkg poctivého másla", + "3 dkg moučkového cukru", + "1 vaječný žloutek", + "Ostrá domácí rybízová marmeláda" + ], + postup: "Křehké těsto nechat odpočinout v chladu. Vyválet na tenko, vykrajovat plná kolečka a kolečka se třemi dírkami. Péct do světle růžova a slepovat rybízem.", + tajemstvi: "Rybízovou marmeládu před mazáním mírně nahřát v kastrůlku, aby se dokonale vpila do křehkého těsta." + }, + { + id: 6, + nazev: "Sváteční taštičky s vepřovým masem", + kategorie: "Sváteční pečení", + doba: 55, + suroviny: [ + "2 balíčky listového těsta", + "30 dkg mletého vepřového masa", + "1 cibule nasekaná najemno", + "Domácí slanina na kostičky", + "1 vejce do náplně, 1 vejce na potření", + "Jemně strouhaná citronová kůra a pepř" + ], + postup: "Mleté maso orestovat na cibulce se slaninou a citronovou kůrou. Z těsta vyválet čtverce, plnit masem, okraje stisknout vidličkou, potřít vejcem a péct zprudka v horké troubě.", + tajemstvi: "Citronová kůra dodá vepřové náplni neuvěřitelnou svěžest a lehkost (ochranná známka Kamily)." + }, + { + id: 7, + nazev: "Zapečené fleky se špenátem a uzeným masem", + kategorie: "Hlavní chod", + doba: 40, + suroviny: [ + "Těstoviny fleky", + "Listový špenát čerstvý či drcený", + "Uzené maso nebo klobása na kostičky", + "3 vejce a trochu plnotučného mléka", + "4 stroužky třeného českého česneku" + ], + postup: "Fleky uvařit al dente, špenát podusit na česneku. Promíchat s uzeným masem, rozprostřít do vymazaného pekáčku a zapéct zalité rozšlehaným vejcem s mlékem.", + tajemstvi: "Do vaječné zálivky přistrouhnout čerstvý muškátový oříšek a na povrch položit plátky uzeného boku." + }, + { + id: 8, + nazev: "Kuřecí srdíčka na smetaně s rýží", + kategorie: "Hlavní chod", + doba: 50, + suroviny: [ + "Čerstvá kuřecí srdíčka (500g)", + "Hustá 33% smetana ke šlehání", + "Rýže parboiled nebo jasmínová", + "Cibule a poctivé máslo", + "Nové koření, bobkový list a černý pepř" + ], + postup: "Srdíčka očistit a podusit na cibulce s divokým kořením doměkka. Vyjmout koření, zalít smetanou a nechat zredukovat do sametové omáčky.", + tajemstvi: "Omáčku nezahušťovat moukou! Nechat ji přirozeně zhoustnout pouhou redukcí poctivé smetany." + } +]; + +// Historical Database records (510 entries sample from 1998-2021 Bohnice) +const HISTORICKA_JIDLA = [ + { nazev: "PIZZA [založení deníku v Bohnicích]", datum: "03.08.1998", typ: "Večeře", vareni: 12, tagy: ["pizza", "syr", "testo"] }, + { nazev: "Špenát, uzené maso, bramborový knedlík", datum: "04.08.1998", typ: "Večeře", vareni: 19, tagy: ["spenat", "maso", "knedlik", "uzene"] }, + { nazev: "Kuře, nudle, ananas (Kryštofovo oblíbené)", datum: "06.09.1998", typ: "Oběd", vareni: 18, tagy: ["kure", "nudle", "ananas", "maso"] }, + { nazev: "Maso – uzený jazyk, brambory, obloha", datum: "13.09.1998", typ: "Oslava", vareni: 7, tagy: ["maso", "brambory", "jazyk"] }, + { nazev: "Smažený sýr, vařené brambory a tatarka", datum: "14.05.2021", typ: "Večeře", vareni: 32, tagy: ["syr", "brambory", "tatarka", "vejce"] }, + { nazev: "Špagety milánské se sýrem a masem", datum: "10.04.2021", typ: "Oběd", vareni: 29, tagy: ["spagety", "maso", "syr", "rajcata"] }, + { nazev: "Domácí lečo s klobásou a čerstvým chlebem", datum: "12.08.2020", typ: "Večeře", vareni: 27, tagy: ["leco", "vejce", "klobasa", "chleb"] }, + { nazev: "Rizoto se zeleninou, kuřecím masem a sýrem", datum: "02.03.2021", typ: "Oběd", vareni: 25, tagy: ["ryze", "kure", "zelenina", "syr"] }, + { nazev: "Smažený vepřový řízek s bramborovým salátem", datum: "23.02.2019", typ: "Oběd", vareni: 24, tagy: ["maso", "brambory", "vejce", "salat"] }, + { nazev: "Královská drůbeží sekaná s bramborovou kaší", datum: "15.01.2021", typ: "Oběd", vareni: 23, tagy: ["maso", "brambory", "kase", "mleko"] }, + { nazev: "Křupavý bramborák s česnekem a majoránkou", datum: "05.11.2020", typ: "Večeře", vareni: 22, tagy: ["brambory", "cesnek", "vejce", "majoranka"] }, + { nazev: "Fazolky na kyselo se smetanou a bramborem", datum: "18.06.2020", typ: "Oběd", vareni: 17, tagy: ["fazolky", "smetana", "brambory", "ocet"] }, + { nazev: "Hovězí guláš s cibulí a houskovým knedlíkem", datum: "20.10.2019", typ: "Oběd", vareni: 20, tagy: ["maso", "hovezi", "cibule", "knedlik"] }, + { nazev: "Palačinky s tvarohem a jahodovou marmeládou", datum: "11.04.2020", typ: "Večeře", vareni: 16, tagy: ["mleko", "mouka", "vejce", "tvaroh"] }, + { nazev: "Květákový mozeček s vařeným bramborem", datum: "28.05.2019", typ: "Oběd", vareni: 14, tagy: ["kvetak", "vejce", "brambory", "cibule"] } +]; + +// App State +let currentView = 'menu'; // 'menu', 'recept', 'recepty_list', 'suroviny', 'davno', 'oblibena', 'kronika', 'altan' +let currentRecipeId = 1; + +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); + +// Normalization function (strip accents) +function norm(str) { + return (str || "").toLowerCase() + .normalize("NFD").replace(/[\u0300-\u036f]/g, "") + .replace(/[^a-z0-9]/g, ""); +} + +// Views renderers +function renderMainMenu() { + currentView = 'menu'; + winTitleEl.textContent = "KUCHAŘKA HELENY A KAMILY HEROUTOVÉ // HLAVNÍ NABÍDKA"; + + let html = ` +
════════════════════════════════════════════════════════════════════════════════ + KUCHAŘKA HELENY A KAMILY HEROUTOVÉ // SOFTWARE-SALON ALTÁN (1998–2026) + Dejvice, Václavkova 2 & Bohnice | Rekonstrukce v Pascalu pro The Observatoř +════════════════════════════════════════════════════════════════════════════════
+ +
+ Vítejte v rodinném softwarovém archivu receptů a jídelníčků. + Tento systém propojil procedurální přesnost Turbo Pascalu s každodenní + péčí o teplo domova a společný stůl po více než dvě dekády. +
+ +
── RUČNĚ PSANÝ SEŠIT RECEPTŮ KAMILY HEROUTOVÉ ─────────────────────────────
+
+`; + + KNIHA_RECEPTU.forEach(r => { + html += `
+ [${r.id}] + ${r.nazev} + ${r.kategorie} (${r.doba} min) +
`; + }); + + html += `
+ +
── ALGORITMICKÉ MODULY & VAŘENÍ (KUCHARKA.EXE) ─────────────────────────────
+
+
+ [S] + >> VAŘIT PODLE SUROVIN VE ŠPAJZU << (Algoritmus prohledání lednice) +
+
+ [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 (Prohlížeč 510 záznamů JÍDLA 1998–2021) +
+
+ [A] + O programu & Software-salon ALTÁN (Historie Dejvic & Bohnic) +
+
+ +
+ Zvolte číslo [1-8] nebo klávesu [S, D, O, K, A]. Na mobilu klepněte prstem. +
+`; + screenEl.innerHTML = html; +} + +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}]: ${r.nazev.toUpperCase()}`; + + let html = ` +
════════════════════════════════════════════════════════════════════════════════ + RECEPT Č. ${r.id}: ${r.nazev} + Kategorie: ${r.kategorie} | Odhadovaná doba přípravy: ${r.doba} minut +════════════════════════════════════════════════════════════════════════════════
+ +
── POTŘEBNÉ SUROVINY ───────────────────────────────────────────────────────
+ + +
── POSTUP PŘÍPRAVY ZE SEŠITU ──────────────────────────────────────────────
+
+${r.postup} +
+ +
+ ★ TAJEMSTVÍ KAMILY HEROUTOVÉ:
+ "${r.tajemstvi}" +
+ +
+ + ${id > 1 ? `` : ''} + ${id < KNIHA_RECEPTU.length ? `` : ''} +
+`; + screenEl.innerHTML = html; +} + +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 porovná databázi receptů Kamily i 510 historických jídel a spočítá shodu. +
+ +
+ MÁM DOMA: + + +
+ +
+ +
+ +
+ +
+`; + screenEl.innerHTML = html; + + const input = document.getElementById('suroviny-input'); + input.focus(); + input.addEventListener('keydown', (e) => { + if (e.key === 'Enter') { + doSearchSuroviny(); + } + }); + + if (defaultQuery) { + 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 = query.toLowerCase().split(/[\s,]+/).filter(t => t.length > 1).map(norm); + + // Score Recipes + const scoredRecipes = KNIHA_RECEPTU.map(r => { + let matches = []; + r.suroviny.forEach(sur => { + const nSur = norm(sur); + tokens.forEach(tok => { + if (nSur.includes(tok)) { + 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); + + // Score Historical Database + const scoredHist = HISTORICKA_JIDLA.map(j => { + let matches = []; + j.tagy.forEach(tag => { + const nTag = norm(tag); + tokens.forEach(tok => { + if (nTag.includes(tok) || norm(j.nazev).includes(tok)) { + 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}"
`; + + if (scoredRecipes.length > 0) { + html += `
★ RECEPTY Z RUČNÍHO SEŠITU KAMILY:
`; + scoredRecipes.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.nazev} + [${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, kure.
`; + } + + resEl.innerHTML = html; +} + +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, 8).forEach((j, idx) => { + html += `
+ ${idx + 1}. ${j.nazev} + Naposledy: ${j.datum} | Celkem vařeno: ${j.vareni}× +
`; + }); + + html += `
+
+ +
+`; + screenEl.innerHTML = html; +} + +function openOblibena() { + currentView = 'oblibena'; + playSpeaker(850, 0.05); + winTitleEl.textContent = "OBLÍBENÁ JÍDLA // ŽELEZNÁ STATISTIKA STOLU"; + + const top = [...HISTORICKA_JIDLA].sort((a, b) => b.vareni - a.vareni); + + let html = ` +
════════════════════════════════════════════════════════════════════════════════ + ŽELEZNÁ STATISTIKA OBLÍBENÝCH JÍDEL RODINNÉHO STOLU (DoporucO) +════════════════════════════════════════════════════════════════════════════════
+
+ Frekvenční žebříček z 510 záznamů rodinného jídelníčku z let 1998–2021: +
+ +
+`; + top.slice(0, 10).forEach((j, idx) => { + const barWidth = Math.round((j.vareni / top[0].vareni) * 25); + const bar = "█".repeat(barWidth); + html += `
+ ${idx + 1}. + ${j.nazev} + ${bar} + ${j.vareni}× +
`; + }); + + html += `
+
+ +
+`; + screenEl.innerHTML = html; +} + +function openKronika() { + currentView = 'kronika'; + playSpeaker(650, 0.05); + winTitleEl.textContent = "KRONIKA RODINNÉHO STOLU // 510 ZÁZNAMŮ BOHNICE (1998–2021)"; + + let html = ` +
════════════════════════════════════════════════════════════════════════════════ + KRONIKA RODINNÉHO STOLU // BOHNICE & DEJVICE (1998–2021) +════════════════════════════════════════════════════════════════════════════════
+
+ Autentické záznamy z databázových souborů JIDLA.TXT a JIDLA-bohnice.TXT. + Od srpna 1998, přes dětská léta až po rok 2021. +
+ +
+`; + HISTORICKA_JIDLA.forEach(j => { + html += `
+ ${j.datum} + [${j.typ}] + ${j.nazev} +
`; + }); + + html += `
+
+ +
+`; + screenEl.innerHTML = html; +} + +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ě rekonstruuje veškeré algoritmy a zachovává + rodinný odkaz pro další generace. +
+ +
+ +
+`; + screenEl.innerHTML = html; +} + +// Global Keyboard Handler (Turbo Pascal Hotkeys) +window.addEventListener('keydown', (e) => { + // If in search input, don't hijack all keys except ESC + if (document.activeElement && document.activeElement.tagName === 'INPUT') { + if (e.key === 'Escape') { + document.activeElement.blur(); + renderMainMenu(); + } + return; + } + + playSpeaker(800, 0.03); + + switch (e.key) { + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': + openRecipe(parseInt(e.key)); + break; + case 's': case 'S': case 'F3': + e.preventDefault(); + openSuroviny(); + 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 'F2': + e.preventDefault(); + renderMainMenu(); + break; + case 'Escape': + renderMainMenu(); + break; + } +}); + +// Touch button handler +document.querySelectorAll('.t-btn').forEach(btn => { + btn.addEventListener('click', () => { + const key = btn.getAttribute('data-key'); + if (key === 'Escape') renderMainMenu(); + else if (key === 's') openSuroviny(); + else if (key === 'd') openDavno(); + else if (key === 'o') openOblibena(); + else if (key === 'k') openKronika(); + else { + const num = parseInt(key); + if (!isNaN(num)) openRecipe(num); + } + }); +}); + +// Menu bar clicks +document.querySelectorAll('.menu-item').forEach(item => { + item.addEventListener('click', () => { + const act = item.getAttribute('data-act'); + if (act === 'menu' || act === 'recepty') renderMainMenu(); + 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(); diff --git a/index.html b/index.html new file mode 100644 index 0000000..6b9c781 --- /dev/null +++ b/index.html @@ -0,0 +1,69 @@ + + + + + + KUCHAŘKA // Helena & Kamila Heroutová (1998–2026) + + + +
+ + + + +
+
+
+ [■] + KUCHAŘKA HELENY A KAMILY HEROUTOVÉ // PASCAL 7.0 + [1] +
+
+ +
+
+
+ + + + + +
+ F1 Nápověda + F2 Receptář + F3 Vařit ze špajzu + F4 Dávno nevařeno + F5 Kronika 510 + ESC Hlavní menu + 🔊 ZVUK: ON +
+
+ + + + diff --git a/style.css b/style.css new file mode 100644 index 0000000..83af6a9 --- /dev/null +++ b/style.css @@ -0,0 +1,322 @@ +/* ========================================================================= + KUCHAŘKA V PASCALU // BORLAND TURBO PASCAL 7.0 & FREE PASCAL CRT PALETTE + ========================================================================= */ + +@font-face { + font-family: 'VGAFont'; + src: local('IBM Plex Mono'), local('Courier New'), monospace; +} + +:root { + --dos-blue: #0000a8; + --dos-cyan: #00aaaa; + --dos-grey: #aaaaaa; + --dos-white: #ffffff; + --dos-yellow: #ffff55; + --dos-green: #55ff55; + --dos-red: #ff5555; + --dos-black: #000000; + --dos-darkgrey: #555555; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; + user-select: none; + -webkit-user-select: none; +} + +html, body { + width: 100%; + height: 100%; + background-color: #050510; + color: var(--dos-grey); + font-family: 'VGAFont', monospace; + font-size: 15px; + line-height: 1.35; + overflow: hidden; +} + +/* CRT Scanline & Phosphor Overlay */ +.crt-screen::before { + content: " "; + display: block; + position: absolute; + top: 0; left: 0; bottom: 0; right: 0; + background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.03), rgba(0, 255, 0, 0.01), rgba(0, 0, 255, 0.03)); + z-index: 99; + background-size: 100% 3px, 6px 100%; + pointer-events: none; +} + +#dos-container { + width: 100vw; + height: 100vh; + display: flex; + flex-direction: column; + background-color: var(--dos-blue); + position: relative; + box-shadow: inset 0 0 80px rgba(0, 0, 0, 0.6); +} + +/* Top Turbo Pascal Menu Bar */ +#menu-bar { + background-color: var(--dos-grey); + color: var(--dos-black); + height: 26px; + display: flex; + align-items: center; + padding: 0 10px; + font-weight: bold; + border-bottom: 1px solid var(--dos-black); + gap: 16px; + font-size: 14px; +} + +.menu-item { + cursor: pointer; + padding: 2px 6px; +} + +.menu-item:hover, .menu-item.active { + background-color: var(--dos-cyan); + color: var(--dos-white); +} + +.hotkey { + color: var(--dos-yellow); + text-shadow: 1px 0 0 var(--dos-black); +} + +.menu-spacer { + flex: 1; +} + +.time-display { + color: var(--dos-black); + font-weight: normal; + font-size: 13px; +} + +/* Main Terminal Window Frame */ +#terminal-window { + flex: 1; + padding: 10px; + display: flex; + overflow: hidden; +} + +.window-frame { + flex: 1; + border: 2px solid var(--dos-cyan); + background-color: var(--dos-blue); + display: flex; + flex-direction: column; + position: relative; + box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.4); +} + +.window-title-bar { + background-color: var(--dos-cyan); + color: var(--dos-white); + display: flex; + justify-content: space-between; + align-items: center; + padding: 2px 10px; + font-weight: bold; + font-size: 14px; +} + +.win-title { + color: var(--dos-yellow); + letter-spacing: 1px; +} + +.window-content { + flex: 1; + padding: 16px 20px; + overflow-y: auto; + white-space: pre-wrap; + color: var(--dos-white); + font-size: 15px; +} + +/* Scrollbar in DOS Style */ +.window-content::-webkit-scrollbar { + width: 14px; +} +.window-content::-webkit-scrollbar-track { + background: var(--dos-blue); + border-left: 1px solid var(--dos-cyan); +} +.window-content::-webkit-scrollbar-thumb { + background: var(--dos-cyan); +} + +/* Typographic Elements inside CRT */ +.dos-header { + color: var(--dos-yellow); + font-weight: bold; + margin-bottom: 12px; +} + +.dos-box { + border: 1px solid var(--dos-cyan); + padding: 10px 14px; + margin: 12px 0; + background-color: rgba(0, 0, 100, 0.4); +} + +.dos-menu-list { + margin: 12px 0; +} + +.dos-menu-item { + padding: 4px 8px; + cursor: pointer; + display: flex; + gap: 10px; +} + +.dos-menu-item:hover, .dos-menu-item.selected { + background-color: var(--dos-cyan); + color: var(--dos-black); + font-weight: bold; +} + +.dos-menu-item:hover .hotkey, .dos-menu-item.selected .hotkey { + color: var(--dos-white); + text-shadow: none; +} + +.dos-input-group { + display: flex; + align-items: center; + gap: 10px; + margin: 16px 0; +} + +.dos-input { + background-color: var(--dos-black); + color: var(--dos-yellow); + border: 1px solid var(--dos-cyan); + font-family: inherit; + font-size: 16px; + padding: 4px 8px; + flex: 1; + outline: none; +} + +.dos-btn { + background-color: var(--dos-cyan); + color: var(--dos-black); + border: 1px solid var(--dos-white); + padding: 4px 14px; + font-family: inherit; + font-weight: bold; + cursor: pointer; +} + +.dos-btn:hover { + background-color: var(--dos-yellow); +} + +.tag-badge { + background-color: rgba(0, 170, 170, 0.3); + color: var(--dos-cyan); + padding: 1px 6px; + border-radius: 2px; + font-size: 12px; +} + +.secret-badge { + color: var(--dos-yellow); + background-color: rgba(255, 255, 85, 0.15); + border-left: 3px solid var(--dos-yellow); + padding: 6px 12px; + margin: 10px 0; +} + +/* Touch controls on mobile */ +#touch-controls { + display: none; + background-color: var(--dos-black); + padding: 6px; + gap: 6px; + overflow-x: auto; + border-top: 1px solid var(--dos-cyan); +} + +.t-btn { + background-color: var(--dos-blue); + color: var(--dos-yellow); + border: 1px solid var(--dos-cyan); + padding: 6px 10px; + font-family: inherit; + font-size: 13px; + font-weight: bold; + white-space: nowrap; + border-radius: 2px; +} + +.t-btn.highlight { + background-color: var(--dos-cyan); + color: var(--dos-black); +} + +.t-btn.esc { + background-color: var(--dos-red); + color: var(--dos-white); +} + +/* Status Bar at bottom */ +#status-bar { + background-color: var(--dos-cyan); + color: var(--dos-black); + height: 26px; + display: flex; + align-items: center; + padding: 0 10px; + gap: 16px; + font-size: 13px; + font-weight: bold; + border-top: 1px solid var(--dos-black); +} + +.f-key { + display: flex; + gap: 4px; + cursor: pointer; +} + +.f-num { + color: var(--dos-white); + background-color: var(--dos-black); + padding: 0 4px; + border-radius: 2px; +} + +.sound-toggle { + margin-left: auto; + color: var(--dos-yellow); + cursor: pointer; +} + +/* Mobile responsive breakpoints */ +@media (max-width: 768px) { + #touch-controls { + display: flex; + } + #status-bar { + display: none; + } + #menu-bar { + font-size: 12px; + gap: 8px; + } + .window-content { + padding: 10px; + font-size: 13px; + } +}