const workspace = document.getElementById('workspace'); const spawnBtns = document.querySelectorAll('.spawn-btn'); const clearDeskBtn = document.getElementById('clear-desk-btn'); const discoveryBook = document.getElementById('discovery-book'); const discoveryProgress = document.getElementById('discovery-progress'); const atomCountEl = document.getElementById('atom-count'); const moleculeCountEl = document.getElementById('molecule-count'); const deskTitle = document.getElementById('desk-title'); const deskSubtitle = document.getElementById('desk-subtitle'); // Main Modal Elements const infoModal = document.getElementById('info-modal'); const modalTitle = document.getElementById('modal-title'); const modalFormula = document.getElementById('modal-formula-badge'); const modalName = document.getElementById('modal-molecule-name'); const modalDesc = document.getElementById('modal-description'); const modalCloseBtn = document.getElementById('modal-close-btn'); const modalOverlay = document.querySelector('#info-modal .modal-overlay'); const modalCloseIcon = document.querySelector('#info-modal .modal-close-icon'); // Story Success Modal Elements const storySuccessModal = document.getElementById('story-success-modal'); const storySuccessLevelName = document.getElementById('story-success-level-name'); const storySuccessText = document.getElementById('story-success-text'); const storyNextLevelBtn = document.getElementById('story-next-level-btn'); const storySuccessCloseIcon = document.querySelector('#story-success-modal .modal-close-icon'); const storySuccessOverlay = document.querySelector('#story-success-modal .modal-overlay'); // PSE Modal Elements const pseToggleBtn = document.getElementById('pse-toggle-btn'); const pseModal = document.getElementById('pse-modal'); const pseCloseBtn = document.getElementById('pse-close-btn'); const pseCloseIcon = document.getElementById('pse-close-icon'); const pseOverlay = document.querySelector('#pse-modal .modal-overlay'); const pseSpawnBtn = document.getElementById('pse-spawn-btn'); let elementsOnDesk = []; let draggingElement = null; let offsetX = 0; let offsetY = 0; let gameMode = 'sandbox'; // 'sandbox' oder 'story' let selectedPSEElement = null; // Geladene Entdeckungen aus dem LocalStorage let discoveredMolecules = new Set(JSON.parse(localStorage.getItem('chem_lab_discoveries') || '[]')); let currentLevelIndex = parseInt(localStorage.getItem('chem_lab_story_level') || '0'); let completedLevels = JSON.parse(localStorage.getItem('chem_lab_story_completed') || '[]'); let currentAllowedAtoms = []; let playerEnergy = parseInt(localStorage.getItem('chem_lab_energy') || '0'); // Elemente Datenbank für Spawnen (Symbole, Farben, Namen) const elementDetails = { 'H': { color: '#ff7675', name: 'Wasserstoff' }, 'He': { color: '#e84393', name: 'Helium' }, 'O': { color: '#74b9ff', name: 'Sauerstoff' }, 'C': { color: '#2d3436', name: 'Kohlenstoff' }, 'N': { color: '#a29bfe', name: 'Stickstoff' }, 'Na': { color: '#ffeaa7', name: 'Natrium' }, 'Cl': { color: '#55efc4', name: 'Chlor' }, 'S': { color: '#fdcb6e', name: 'Schwefel' }, 'Fe': { color: '#b2bec3', name: 'Eisen' } }; // Periodensystem Elemente Datenbank (Wissenschaftliche Details & Schalenmodell) const pseElements = [ { number: 1, symbol: 'H', name: 'Wasserstoff', mass: '1.008 u', category: 'nichtmetall', row: 1, col: 1, playable: true, electrons: [1], desc: 'Das häufigste und leichteste Element im Universum. Es bildet den primären Kernbrennstoff für alle leuchtenden Sterne.' }, { number: 2, symbol: 'He', name: 'Helium', mass: '4.003 u', category: 'edelgas', row: 1, col: 18, playable: true, electrons: [2], desc: 'Ein absolut reaktionsträges Edelgas. Es brennt nicht und ist viel leichter als Luft – perfekt für Ballons und lässt Stimmen lustig hoch klingen!' }, { number: 3, symbol: 'Li', name: 'Lithium', mass: '6.94 u', category: 'alkalimetall', row: 2, col: 1, playable: true, electrons: [2, 1], desc: 'Ein extrem leichtes, reaktives Metall. Es ist das Herzstück moderner Lithium-Ionen-Akkus für Handys, Laptops und Elektroautos.' }, { number: 4, symbol: 'Be', name: 'Beryllium', mass: '9.012 u', category: 'erdalkali', row: 2, col: 2, playable: true, electrons: [2, 2], desc: 'Ein seltenes, hochgiftiges Erdalkalimetall. Es ist extrem steif und temperaturbeständig und wird deshalb im Weltraumteleskop-Bau (z.B. James Webb) eingesetzt.' }, { number: 5, symbol: 'B', name: 'Bor', mass: '10.81 u', category: 'metalloid', row: 2, col: 13, playable: true, electrons: [2, 3], desc: 'Ein hartes, hitzebeständiges Halbmetall. Es wird für extrem widerstandsfähiges Glas (Borosilikatglas) und im Raketentreibstoff-Sektor verwendet.' }, { number: 6, symbol: 'C', name: 'Kohlenstoff', mass: '12.011 u', category: 'nichtmetall', row: 2, col: 14, playable: true, electrons: [2, 4], desc: 'Die chemische Basis allen Lebens auf der Erde! Kohlenstoff kommt in reiner Form sowohl als weicher Graphit (Bleistift) als auch als extrem harter Diamant vor.' }, { number: 7, symbol: 'N', name: 'Stickstoff', mass: '14.007 u', category: 'nichtmetall', row: 2, col: 15, playable: true, electrons: [2, 5], desc: 'Stickstoff bildet fast 78% unserer Atemluft! Er reagiert unter normalen Bedingungen kaum und schützt die Erde vor unkontrollierbaren Bränden.' }, { number: 8, symbol: 'O', name: 'Sauerstoff', mass: '15.999 u', category: 'nichtmetall', row: 2, col: 16, playable: true, electrons: [2, 6], desc: 'Lebensnotwendig für fast alle Tiere. Es ist hochreaktiv und verbindet sich leidenschaftlich gern mit anderen Elementen (Rosten von Eisen, Verbrennung).' }, { number: 9, symbol: 'F', name: 'Fluor', mass: '18.998 u', category: 'halogen', row: 2, col: 17, playable: true, electrons: [2, 7], desc: 'Das reaktivste aller chemischen Elemente! Fluor-Gas zerfrisst fast jeden Stoff sofort unter Flammenbildung. Spuren von Fluorid schützen unseren Zahnschmelz.' }, { number: 10, symbol: 'Ne', name: 'Neon', mass: '20.180 u', category: 'edelgas', row: 2, col: 18, playable: true, electrons: [2, 8], desc: 'Ein extrem reaktionsträges Edelgas. Unter Hochspannung leuchtet es intensiv rötlich-orange, weshalb es der Namensgeber für alle Leuchtreklamen ist.' }, { number: 11, symbol: 'Na', name: 'Natrium', mass: '22.990 u', category: 'alkalimetall', row: 3, col: 1, playable: true, electrons: [2, 8, 1], desc: 'Ein extrem reaktionsfreudiges, weiches Alkalimetall. Es reagiert explosionsartig mit Wasser und muss daher in zähem Öl (Petroleum) gelagert werden.' }, { number: 12, symbol: 'Mg', name: 'Magnesium', mass: '24.305 u', category: 'erdalkali', row: 3, col: 2, playable: true, electrons: [2, 8, 2], desc: 'Ein leichtes Erdalkalimetall. Es brennt mit einer extrem hellen, blendend weißen Flamme und ist wichtig für die Muskel- und Nervenfunktion im Körper.' }, { number: 13, symbol: 'Al', name: 'Aluminium', mass: '26.982 u', category: 'metall', row: 3, col: 13, playable: true, electrons: [2, 8, 3], desc: 'Das dritthäufigste Element der Erdkruste. Es ist leicht, rostfrei und wird für Flugzeuge, Alufolie, Getränkedosen und Autoteile verwendet.' }, { number: 14, symbol: 'Si', name: 'Silicium', mass: '28.085 u', category: 'metalloid', row: 3, col: 14, playable: true, electrons: [2, 8, 4], desc: 'Das Element, das unsere Computertechnologie antreibt! Silicium is ein Halbleiter und die absolute Basis aller Mikrochips und Solarzellen.' }, { number: 15, symbol: 'P', name: 'Phosphor', mass: '30.974 u', category: 'nichtmetall', row: 3, col: 15, playable: true, electrons: [2, 8, 5], desc: 'Ein lebenswichtiges Element, das im menschlichen Erbgut (DNA) und in Knochen vorkommt. Roter Phosphor wird auf Streichholz-Reibflächen verwendet.' }, { number: 16, symbol: 'S', name: 'Schwefel', mass: '32.06 u', category: 'nichtmetall', row: 3, col: 16, playable: true, electrons: [2, 8, 6], desc: 'Ein zitronengelber, geruchloser Feststoff. Seine organischen Verbindungen riechen oft extrem faulig (z.B. faule Eier). Schwefel ist wichtig für Haare und Proteine.' }, { number: 17, symbol: 'Cl', name: 'Chlor', mass: '35.45 u', category: 'halogen', row: 3, col: 17, playable: true, electrons: [2, 8, 7], desc: 'Ein giftiges, stechend riechendes gelbgrünes Gas. Chlor ist extrem reaktiv und wird weltweit zur Desinfektion von Trinkwasser und Pools genutzt.' }, { number: 18, symbol: 'Ar', name: 'Argon', mass: '39.948 u', category: 'edelgas', row: 3, col: 18, playable: true, electrons: [2, 8, 8], desc: 'Das dritthäufigste Gas in unserer Atmosphäre. Argon wird als ungiftiges Schutzgas beim Schweißen und in Doppelglasscheiben zur Wärmeisolierung eingesetzt.' }, { number: 19, symbol: 'K', name: 'Kalium', mass: '39.098 u', category: 'alkalimetall', row: 4, col: 1, playable: true, electrons: [2, 8, 8, 1], desc: 'Ein weiches, hochreaktives Alkalimetall. Es reagiert noch heftiger mit Wasser als Natrium und ist essenziell für die Weiterleitung von Nervensignalen.' }, { number: 20, symbol: 'Ca', name: 'Calcium', mass: '40.078 u', category: 'erdalkali', row: 4, col: 2, playable: true, electrons: [2, 8, 8, 2], desc: 'Der elementare Baustein für Skelette und Zähne! Calcium bildet Knochen, Eierschalen, Muscheln und Kreide und ist wichtig für die Muskelarbeit.' }, { number: 26, symbol: 'Fe', name: 'Eisen', mass: '55.845 u', category: 'uebergang', row: 4, col: 8, playable: true, electrons: [2, 8, 14, 2], desc: 'Das am häufigsten genutzte Metall der Menschheit. Eisen bildet das Zentrum unseres Erdkerns (Magnetfeld) und transportiert Sauerstoff in unserem Blut (Hämoglobin).' }, { number: 31, symbol: 'Ga', name: 'Gallium', mass: '69.723 u', category: 'metall', row: 4, col: 13, playable: true, electrons: [2, 8, 18, 3], desc: 'Ein faszinierendes Metall mit einem sehr niedrigen Schmelzpunkt von 29.76 °C. Es schmilzt sprichwörtlich in der warmen Hand!' }, { number: 32, symbol: 'Ge', name: 'Germanium', mass: '72.63 u', category: 'metalloid', row: 4, col: 14, playable: true, electrons: [2, 8, 18, 4], desc: 'Ein glänzendes, hartes Halbmetall. Es ist ein wichtiger Halbleiter und wird oft in Infrarot-Optiken und Glasfaserkabeln eingesetzt.' }, { number: 33, symbol: 'As', name: 'Arsen', mass: '74.922 u', category: 'metalloid', row: 4, col: 15, playable: true, electrons: [2, 8, 18, 5], desc: 'Ein berüchtigtes, hochgiftiges Halbmetall. Historisch als König der Gifte bekannt, wird es heute in Halbleitern und Speziallegierungen verwendet.' }, { number: 34, symbol: 'Se', name: 'Selen', mass: '78.97 u', category: 'nichtmetall', row: 4, col: 16, playable: true, electrons: [2, 8, 18, 6], desc: 'Ein wichtiges Spurenelement, das für Lebewesen essenziell ist. Selen ist lichtempfindlich und leitet Strom besser bei Belichtung (Kopiergeräte).' }, { number: 35, symbol: 'Br', name: 'Brom', mass: '79.904 u', category: 'halogen', row: 4, col: 17, playable: true, electrons: [2, 8, 18, 7], desc: 'Das einzige flüssige Nichtmetall bei Raumtemperatur! Es ist eine rotbraune, ätzende Flüssigkeit mit einem extrem stechenden, unangenehmen Geruch.' }, { number: 36, symbol: 'Kr', name: 'Krypton', mass: '83.798 u', category: 'edelgas', row: 4, col: 18, playable: true, electrons: [2, 8, 18, 8], desc: 'Ein seltenes Edelgas. Unter Hochspannung leuchtet es weiß-violett und wird in hocheffizienten Glühlampen sowie Blitzlichtern für Kameras genutzt.' }, { number: 37, symbol: 'Rb', name: 'Rubidium', mass: '85.468 u', category: 'alkalimetall', row: 5, col: 1, playable: true, electrons: [2, 8, 18, 8, 1], desc: 'Ein extrem reaktives Alkalimetall. Es entzündet sich bei Kontakt mit Luft sofort selbst und reagiert explosionsartig mit Wasser.' }, { number: 38, symbol: 'Sr', name: 'Strontium', mass: '87.62 u', category: 'erdalkali', row: 5, col: 2, playable: true, electrons: [2, 8, 18, 8, 2], desc: 'Ein reaktives Erdalkalimetall. Seine Salze brennen mit einer intensiv roten Flamme und sind daher in roten Feuerwerkskörpern unentbehrlich.' }, { number: 49, symbol: 'In', name: 'Indium', mass: '114.818 u', category: 'metall', row: 5, col: 13, playable: true, electrons: [2, 8, 18, 18, 3], desc: 'Ein sehr weiches, silbriges Metall. Es wird als Indiumzinnoxid (ITO) zur Herstellung von transparenten Elektroden für Touchscreens verwendet.' }, { number: 50, symbol: 'Sn', name: 'Zinn', mass: '118.71 u', category: 'metall', row: 5, col: 14, playable: true, electrons: [2, 8, 18, 18, 4], desc: 'Ein silberweißes Metall. Beim Biegen einer Zinnstange hört man ein charakteristisches Knistern, das sogenannte "Zinn-Schreien".' }, { number: 51, symbol: 'Sb', name: 'Antimon', mass: '121.76 u', category: 'metalloid', row: 5, col: 15, playable: true, electrons: [2, 8, 18, 18, 5], desc: 'Ein sprödes, glänzendes Halbmetall. Es dehnt sich beim Erstarren aus und wird für Legierungen sowie feuerhemmende Materialien eingesetzt.' }, { number: 52, symbol: 'Te', name: 'Tellur', mass: '127.6 u', category: 'metalloid', row: 5, col: 16, playable: true, electrons: [2, 8, 18, 18, 6], desc: 'Ein sehr seltenes, silbrig-glänzendes Halbmetall. Es wird hauptsächlich zur Legierung von Metallen verwendet, um deren Festigkeit zu steigern.' }, { number: 53, symbol: 'I', name: 'Iod', mass: '126.904 u', category: 'halogen', row: 5, col: 17, playable: true, electrons: [2, 8, 18, 18, 7], desc: 'Ein violett-schwarzer Feststoff. Iod sublimiert beim Erwärmen zu prächtigen violetten Dämpfen. Es ist lebenswichtig für unsere Schilddrüse.' }, { number: 54, symbol: 'Xe', name: 'Xenon', mass: '131.293 u', category: 'edelgas', row: 5, col: 18, playable: true, electrons: [2, 8, 18, 18, 8], desc: 'Das schwerste stabile Edelgas. Es leuchtet intensiv blau-violett und wird in Hochleistungsscheinwerfern (Xenonlicht) und in der Medizin als Narkosemittel genutzt.' }, { number: 55, symbol: 'Cs', name: 'Caesium', mass: '132.905 u', category: 'alkalimetall', row: 6, col: 1, playable: true, electrons: [2, 8, 18, 18, 8, 1], desc: 'Das reaktivste aller stabilen Metalle! Es schmilzt bereits bei 28.4 °C und reagiert mit Wasser so extrem heftig, dass es meist das Gefäß zersprengt.' }, { number: 56, symbol: 'Ba', name: 'Barium', mass: '137.327 u', category: 'erdalkali', row: 6, col: 2, playable: true, electrons: [2, 8, 18, 18, 8, 2], desc: 'Ein weiches, hochreaktives Erdalkalimetall. Bariumsulfat wird wegen seiner Unlöslichkeit in der Medizin als Kontrastmittel für Röntgenbilder eingesetzt.' }, { number: 81, symbol: 'Tl', name: 'Thallium', mass: '204.38 u', category: 'metall', row: 6, col: 13, playable: true, electrons: [2, 8, 18, 32, 18, 3], desc: 'Ein extrem giftiges Schwermetall. Es wurde früher oft als Rattengift verwendet. Der Kontakt mit Thallium führt beim Menschen zu Haarausfall und Nervenschäden.' }, { number: 82, symbol: 'Pb', name: 'Blei', mass: '207.2 u', category: 'metall', row: 6, col: 14, playable: true, electrons: [2, 8, 18, 32, 18, 4], desc: 'Ein schweres, weiches und giftiges Metall. Es lässt sich leicht verformen und schützt in Bleischürzen hocheffektiv vor radioaktiver Strahlung.' }, { number: 83, symbol: 'Bi', name: 'Bismut', mass: '208.980 u', category: 'metall', row: 6, col: 15, playable: true, electrons: [2, 8, 18, 32, 18, 5], desc: 'Ein rötlich-weißes, ungiftiges Schwermetall. Seine Kristalle laufen an Luft in schillernden Regenbogenfarben an und bilden wunderschöne Treppenstrukturen.' }, { number: 84, symbol: 'Po', name: 'Polonium', mass: '209 u', category: 'metalloid', row: 6, col: 16, playable: true, electrons: [2, 8, 18, 32, 18, 6], desc: 'Ein extrem seltenes, hochradioaktives und tödlich giftiges Halbmetall. Es wurde von Marie Curie entdeckt und nach ihrem Heimatland Polen benannt.' }, { number: 85, symbol: 'At', name: 'Astat', mass: '210 u', category: 'halogen', row: 6, col: 17, playable: true, electrons: [2, 8, 18, 32, 18, 7], desc: 'Das seltenste natürlich vorkommende Element der Erdkruste. Ein sichtbares Stück Astat würde aufgrund der extremen Radioaktivität sofort verdampfen.' }, { number: 86, symbol: 'Rn', name: 'Radon', mass: '222 u', category: 'edelgas', row: 6, col: 18, playable: true, electrons: [2, 8, 18, 32, 18, 8], desc: 'Ein unsichtbares, geruchloses und hochradioaktives Edelgas. Es kann aus dem Boden austreten und sich gefährlich in schlecht belüfteten Kellern anreichern.' }, { number: 87, symbol: 'Fr', name: 'Francium', mass: '223 u', category: 'alkalimetall', row: 7, col: 1, playable: true, electrons: [2, 8, 18, 32, 18, 8, 1], desc: 'Das zweitseltenste Element in der Erdkruste nach Astat. Es ist extrem radioaktiv und so instabil, dass man bisher nie eine sichtbare Menge herstellen konnte.' }, { number: 88, symbol: 'Ra', name: 'Radium', mass: '226 u', category: 'erdalkali', row: 7, col: 2, playable: true, electrons: [2, 8, 18, 32, 18, 8, 2], desc: 'Ein stark radioaktives Erdalkalimetall, das im Dunkeln bläulich leuchtet. Marie Curie entdeckte es; früher wurde es fälschlicherweise in Leuchtfarben genutzt.' }, { number: 113, symbol: 'Nh', name: 'Nihonium', mass: '286 u', category: 'metall', row: 7, col: 13, playable: true, electrons: [2, 8, 18, 32, 32, 18, 3], desc: 'Ein künstlich erzeugtes superschweres Element. Es wurde am RIKEN-Institut in Japan entdeckt und ist nach dem japanischen Wort "Nihon" (Japan) benannt.' }, { number: 114, symbol: 'Fl', name: 'Flerovium', mass: '289 u', category: 'metall', row: 7, col: 14, playable: true, electrons: [2, 8, 18, 32, 32, 18, 4], desc: 'Ein künstlich hergestelltes, extrem radioaktives künstliches Element. Es wurde nach dem Flerow-Labor für Kernreaktionen in Russland benannt.' }, { number: 115, symbol: 'Mc', name: 'Moscovium', mass: '290 u', category: 'metall', row: 7, col: 15, playable: true, electrons: [2, 8, 18, 32, 32, 18, 5], desc: 'Ein künstliches, extrem instabiles superschweres Element, benannt nach der russischen Region Moskau, in der sich das Forschungszentrum Dubna befindet.' }, { number: 116, symbol: 'Lv', name: 'Livermorium', mass: '293 u', category: 'metall', row: 7, col: 16, playable: true, electrons: [2, 8, 18, 32, 32, 18, 6], desc: 'Ein künstliches, hochgradig radioaktives Element. Es wurde gemeinschaftlich in Dubna (Russland) und in Livermore (USA) hergestellt.' }, { number: 117, symbol: 'Ts', name: 'Tenness', mass: '294 u', category: 'halogen', row: 7, col: 17, playable: true, electrons: [2, 8, 18, 32, 32, 18, 7], desc: 'Ein superschweres, künstliches Halogen. Es wurde 2010 synthetisiert und ist nach dem US-Bundesstaat Tennessee benannt.' }, { number: 118, symbol: 'Og', name: 'Oganesson', mass: '294 u', category: 'edelgas', row: 7, col: 18, playable: true, electrons: [2, 8, 18, 32, 32, 18, 8], desc: 'Das schwerste bekannte Element im Periodensystem mit der Ordnungszahl 118. Es ist extrem kurzlebig und nach dem Physiker Juri Oganesjan benannt.' } ]; // Rezepturenbuch (die Formeln müssen genau den Kombinationen der Symbole entsprechen) const recipes = [ { id: 'h2o', ingredients: ['H', 'H', 'O'], // 2x Wasserstoff, 1x Sauerstoff result: 'H₂O (Wasser)', color: '#3498db', desc: 'Wasser ist die absolute Grundlage allen bekannten Lebens! Über 70% der Erdoberfläche sind mit Wasser bedeckt, und auch unser eigener Körper besteht zu mehr als der Hälfte daraus.' }, { id: 'nacl', ingredients: ['Cl', 'Na'], // 1x Natrium, 1x Chlor result: 'NaCl (Kochsalz)', color: '#f5f6fa', desc: 'Natriumchlorid kennen wir alle als einfaches Speisesalz. Faszinierend: Natrium ist ein explosives, hochreaktives Metall und Chlor ein giftiges Gas – zusammen ergeben sie ein absolut lebenswichtiges und leckeres Gewürz!' }, { id: 'o2', ingredients: ['O', 'O'], // 2x Sauerstoff result: 'O₂ (Sauerstoff-Molekül)', color: '#a8dadc', desc: 'Der molekulare Sauerstoff, den wir jede Sekunde atmen. Pflanzen produzieren ihn als Abfallprodukt bei der Photosynthese, während sie Kohlendioxid abbauen.' }, { id: 'co2', ingredients: ['C', 'O', 'O'], // 1x Kohlenstoff, 2x Sauerstoff result: 'CO₂ (Kohlendioxid)', color: '#7f8c8d', desc: 'Ein farb- und geruchloses Treibhausgas. Wir atmen es ständig aus. Obwohl es die Erderwärmung anheizt, ist es für Pflanzen lebenswichtig, da sie es zur Photosynthese benötigen.' }, { id: 'ch4', ingredients: ['C', 'H', 'H', 'H', 'H'], // 1x Kohlenstoff, 4x Wasserstoff result: 'CH₄ (Methan)', color: '#fdcb6e', desc: 'Methan ist das einfachste Alkan und der Hauptbestandteil von brennbarem Erdgas. Es brennt sauber ab, ist aber als Treibhausgas in der Atmosphäre rund 25-mal klimaschädlicher als CO₂!' }, { id: 'nh3', ingredients: ['N', 'H', 'H', 'H'], // 1x Stickstoff, 3x Wasserstoff result: 'NH₃ (Ammoniak)', color: '#9b59b6', desc: 'Ein stechend riechendes, farbloses Gas. Ammoniak ist extrem wichtig für die chemische Industrie, da es die Grundlage für fast alle Kunstdünger bildet (erfunden durch das Haber-Bosch-Verfahren).' }, { id: 'hcl', ingredients: ['Cl', 'H'], // 1x Chlor, 1x Wasserstoff result: 'HCl (Salzsäure)', color: '#e17055', desc: 'Chlorwasserstoff ist ein stechendes Gas. In Wasser gelöst bildet es die extrem ätzende Salzsäure – diese ist auch ein wichtiger Bestandteil unseres eigenen Magensaftes, um Nahrung zu zersetzen!' }, { id: 'naoh', ingredients: ['H', 'Na', 'O'], // 1x Natrium, 1x Sauerstoff, 1x Wasserstoff result: 'NaOH (Natronlauge)', color: '#fd79a8', desc: 'Natriumhydroxid ist eine extrem starke Base. In Wasser gelöst wird es als Natronlauge bezeichnet, die Haare und Fett auflösen kann, weshalb man sie oft in Abflussreinigern findet. Sie wird auch für echte Seife genutzt.' }, { id: 'h2s', ingredients: ['H', 'H', 'S'], // 2x Wasserstoff, 1x Schwefel result: 'H₂S (Schwefelwasserstoff)', color: '#ffeaa7', desc: 'Dieses hochentzündliche und extrem giftige Gas riecht unverkennbar nach faulen Eiern! Es entsteht bei Fäulnisprozessen von Proteinen, im Darm und in vulkanischen Gasen.' }, { id: 'fes', ingredients: ['Fe', 'S'], // 1x Eisen, 1x Schwefel result: 'FeS (Eisensulfid)', color: '#2d3436', desc: 'Ein dunkelbrauner/schwarzer Feststoff. Das Mischen und Erhitzen von Eisenpulver und Schwefelpulver ist der absolute Klassiker im Chemie-Unterricht, um eine chemische Synthese zu demonstrieren.' }, { id: 'so2', ingredients: ['O', 'O', 'S'], // 1x Schwefel, 2x Sauerstoff result: 'SO₂ (Schwefeldioxid)', color: '#b2bec3', desc: 'Ein stechend riechendes, saures Gas, das beim Verbrennen von schwefelhaltigen fossilen Brennstoffen entsteht. Es schädigt die Atemwege und trägt in Wolken zur Bildung von saurem Regen bei.' }, { id: 'co', ingredients: ['C', 'O'], // 1x Kohlenstoff, 1x Sauerstoff result: 'CO (Kohlenmonoxid)', color: '#636e72', desc: 'Ein unsichtbares, geruchloses und hochgradig tödliches Gas! Es entsteht bei der unvollständigen Verbrennung von Kohle oder Holz und blockiert die Sauerstoffaufnahme im menschlichen Blutkreislauf.' }, { id: 'h2o2', ingredients: ['H', 'H', 'O', 'O'], // 2x Wasserstoff, 2x Sauerstoff result: 'H₂O₂ (Wasserstoffperoxid)', color: '#74b9ff', desc: 'Wasserstoffperoxid ist ein extrem starkes Bleichmittel und Oxidationsmittel. Es wird zum Blondieren von Haaren, zum Desinfizieren von Wunden und industriell zum Bleichen von Papier genutzt.' }, { id: 'hcn', ingredients: ['C', 'H', 'N'], // 1x Wasserstoff, 1x Kohlenstoff, 1x Stickstoff result: 'HCN (Blausäure)', color: '#d63031', desc: 'Cyanwasserstoff ist ein extrem giftiges Gas, das gelöst in Wasser als Blausäure bezeichnet wird. Es riecht für manche Menschen charakteristisch nach bitteren Mandeln und wirkt in Sekunden tödlich.' }, { id: 'n2', ingredients: ['N', 'N'], // 2x Stickstoff result: 'N₂ (Stickstoff)', color: '#a29bfe', desc: 'Stickstoff ist ein extrem reaktionsträges (inertes) Gas und bildet fast 78% der Luft, die wir atmen! Er schützt unseren Planeten vor verheerenden globalen Bränden, die in reinem Sauerstoff wüten würden.' }, { id: 'cl2', ingredients: ['Cl', 'Cl'], // 2x Chlor result: 'Cl₂ (Chlor)', color: '#55efc4', desc: 'Chlor-Gas ist giftig, hat einen stechenden Geruch und eine grüngelbe Farbe. Es wurde im Ersten Weltkrieg als Kampfgas eingesetzt, rettet heute aber als Desinfektionsmittel in Trinkwasser und Pools genutzt.' }, { id: 'h2', ingredients: ['H', 'H'], // 2x Wasserstoff result: 'H₂ (Wasserstoff)', color: '#ff7675', desc: 'Das häufigste, einfachste und leichteste Element im Universum. Wasserstoff ist hochentzündlich (Knallgas-Reaktion) und bildet den primären Kernbrennstoff für alle leuchtenden Sterne.' }, { id: 'c2h4', ingredients: ['C', 'C', 'H', 'H', 'H', 'H'], // 2x Kohlenstoff, 4x Wasserstoff result: 'C₂H₄ (Ethen)', color: '#ffeaa7', desc: 'Ethen (Ethylen) ist ein gasförmiges Pflanzenhormon, das Früchte reifen lässt. Industriell ist es der absolut wichtigste Baustein zur Herstellung des Kunststoffs Polyethylen (PE).' }, { id: 'nh4cl', ingredients: ['Cl', 'H', 'H', 'H', 'H', 'N'], result: 'NH₄Cl (Ammoniumchlorid)', color: '#ffffff', desc: 'Ammoniumchlorid (Salmiak) ist ein weißes, feinkristallines Salz. Es schmeckt extrem salzig-sauer und wird traditionell in Nordeuropa für die Herstellung von echtem, starkem Salzlakritz verwendet!' }, { id: 'h2so3', ingredients: ['H', 'H', 'O', 'O', 'O', 'S'], result: 'H₂SO₃ (Schweflige Säure)', color: '#e74c3c', desc: 'Schweflige Säure entsteht, wenn Schwefeldioxid mit Wasser reagiert. Sie ist eine unbeständige, säuerliche Flüssigkeit, die stark reduzierend wirkt und zum Bleichen oder Konservieren genutzt wird.' }, { id: 'h2co3', ingredients: ['C', 'H', 'H', 'O', 'O', 'O'], result: 'H₂CO₃ (Kohlensäure)', color: '#1abc9c', desc: 'Kohlensäure entsteht, wenn sich CO₂ in Wasser löst. Sie ist eine schwache Säure, die für das erfrischende Prickeln in Getränken sorgt. Im Körper ist sie wichtig für den Säure-Basen-Haushalt.' }, { id: 'fecl2', ingredients: ['Cl', 'Cl', 'Fe'], result: 'FeCl₂ (Eisenchlorid)', color: '#2ecc71', desc: 'Eisen(II)-chlorid ist ein blassgrünes Salz. Seine sauren Lösungen werden in der Industrie zur Abwasserreinigung (als Fällungsmittel) und zum präzisen Ätzen von Leiterplatten eingesetzt.' } ]; // Fortgeschrittene Molekül-Reaktionen Datenbank (Phase 4: Säure-Base & komplexe Reaktionen) const advancedRecipes = [ { id: 'neutralisation', ingredients: ['hcl', 'naoh'], // Salzsäure + Natronlauge results: ['nacl', 'h2o'], // ergibt Kochsalz + Wasser name: 'Säure-Base-Neutralisation', desc: 'Eine der klassischsten Reaktionen der Chemie! Die stark saure Salzsäure (HCl) und die aggressive, basische Natronlauge (NaOH) neutralisieren sich gegenseitig vollständig zu harmlosem Kochsalz (NaCl) und reinem Wasser (H₂O). Die Lösung erwärmt sich dabei durch die freiwerdende Neutralisationswärme stark!' }, { id: 'methan_verbrennung', ingredients: ['ch4', 'o2', 'o2'], // Methan + 2x Sauerstoff results: ['co2', 'h2o', 'h2o'], // ergibt Kohlendioxid + 2x Wasser name: 'Methangas-Verbrennung', desc: 'Methan (CH₄), der Hauptbestandteil von gasförmigem Erdgas, reagiert intensiv mit Sauerstoff (O₂). Bei dieser stark exothermen Verbrennungsreaktion entstehen Kohlendioxid (CO₂) und Wasserdampf (H₂O). Dies ist die treibende Kraft hinter vielen häuslichen Gasheizungen!' }, { id: 'salmiak_rauch', ingredients: ['nh3', 'hcl'], // Ammoniak + Salzsäure (Chlorwasserstoff) results: ['nh4cl'], // ergibt Ammoniumchlorid name: 'Ammoniumchlorid-Synthese (Salmiak-Rauch)', desc: 'Wenn das stechend riechende Ammoniakgas (NH₃) und Chlorwasserstoffgas (HCl) direkt aufeinandertreffen, findet eine Gasphasenreaktion statt. Es bildet sich sofort ein dichter weißer Rauch aus feinsten Ammoniumchlorid-Salzkristallen (NH₄Cl), auch bekannt als Salmiak!' }, { id: 'saurer_regen', ingredients: ['so2', 'h2o'], // Schwefeldioxid + Wasser results: ['h2so3'], // ergibt Schweflige Säure name: 'Saure-Regen-Bildung', desc: 'Schwefeldioxid (SO₂) entsteht bei der Verbrennung fossiler Brennstoffe. Wenn dieses Gas in der Atmosphäre mit Regenwasser (H₂O) reagiert, bildet sich Schweflige Säure (H₂SO₃). Dies führt zum berüchtigten "sauren Regen", der Böden, Wälder und historische Bauten schädigt.' }, { id: 'kohlensaeure_bildung', ingredients: ['co2', 'h2o'], // Kohlendioxid + Wasser results: ['h2co3'], // ergibt Kohlensäure name: 'Kohlensäure-Bildung', desc: 'Kohlendioxid (CO₂) löst sich zu einem kleinen Prozentsatz physikalisch-chemisch in Wasser (H₂O) und bildet Kohlensäure (H₂CO₃). Sie sorgt für das spritzige Prickeln in Mineralwasser und sprudelnden Erfrischungsgetränken!' }, { id: 'eisen_saeure', ingredients: ['Fe', 'hcl', 'hcl'], // Eisen + 2x Salzsäure results: ['fecl2', 'h2'], // ergibt Eisenchlorid + Wasserstoff name: 'Säureangriff auf Metalle', desc: 'Unedle Metalle wie Eisen (Fe) werden von Säuren wie der Salzsäure (HCl) angegriffen. Dabei oxidiert das Eisen zu löslichem Eisenchlorid (FeCl₂), während der Wasserstoff der Säure als hochentzündliches Wasserstoff-Gas (H₂) entweicht. Es sprudelt!' }, { id: 'chlorknallgas', ingredients: ['h2', 'cl2'], // Wasserstoff-Molekül + Chlor-Molekül results: ['hcl', 'hcl'], // ergibt 2x Salzsäure-Gas name: 'Chlorknallgas-Reaktion', desc: 'Wenn reines Wasserstoff-Gas (H₂) und Chlor-Gas (Cl₂) gemischt werden, genügt ein kurzer Lichtblitz oder Funke, um eine extrem heftige, explosive Kettenreaktion auszulösen. Dabei entsteht gasförmiger Chlorwasserstoff (HCl), der in Wasser gelöst Salzsäure bildet!' } ]; // Story-Modus Level-Datenbank const levels = [ { id: 1, title: "Die salzige Suppe", goalFormula: "nacl", allowedAtoms: ['Na', 'Cl'], intro: "Hallo Lehrling! Schön dich im Labor zu sehen. Der herzhafte Eintopf unseres Kantinenkochs schmeckt heute nach gar nichts... Er hat das Salz vergessen! Kannst du ihm helfen und 1x Kochsalz (NaCl) synthetisieren? Ziehe einfach ein Natrium-Atom (Na) und ein Chlor-Atom (Cl) auf dem Tisch zusammen!", successText: "Großartig! Der Eintopf ist gerettet und schmeckt hervorragend. Du hast soeben gelernt, dass aus zwei gefährlichen Reinstoffen (explosives Metall und giftiges Gas) ein lebenswichtiges Gewürz entstehen kann. Bereit für die nächste Herausforderung?", reward: "Schaltet Level 2 frei" }, { id: 2, title: "Das Lebenselixier", goalFormula: "h2o", allowedAtoms: ['H', 'O'], intro: "Hervorragend gemacht! Jetzt haben wir aber ein anderes Problem: Der Wasserspender im Labor ist leer und die Hitze heute ist unerträglich. Wir brauchen dringend frisches Wasser (H₂O)! Synthetisiere uns ein Wassermolekül aus zwei Wasserstoff-Atomen (H) und einem Sauerstoff-Atom (O).", successText: "Ah, erfrischend! Kaltes, sauberes H₂O. Wusstest du, dass Wassermoleküle wegen ihrer Polarität so genial zusammenhalten? Du bist auf dem besten Weg zum Meister-Alchemisten!", reward: "Schaltet Level 3 frei" }, { id: 3, title: "Der Mülleimerbrand", goalFormula: "co2", allowedAtoms: ['C', 'O'], intro: "Achtung! Ein Missgeschick ist passiert: Jemand hat ein heißes Streichholz in den Mülleimer geworfen und es brennt! Wasser nützt hier nichts, wir brauchen ein erstickendes Gas. Synthetisiere schnell 1x Kohlendioxid (CO₂) aus einem Kohlenstoff-Atom (C) und zwei Sauerstoff-Atomen (O), um die Flammen zu löschen!", successText: "Puh, gerettet! Das CO₂ hat den Sauerstoff verdrängt und das Feuer im Handumdrehen erstickt. Ein echter Lebensretter-Einsatz! Aber lüfte danach gut durch.", reward: "Schaltet Level 4 frei" }, { id: 4, title: "Dünger für die Ernte", goalFormula: "nh3", allowedAtoms: ['N', 'H'], intro: "Ein lokaler Bauer hat uns um Hilfe gebeten. Seine Nutzpflanzen wachsen schlecht und er benötigt dringend Dünger. Der wichtigste Rohstoff dafür ist Ammoniak (NH₃). Synthetisiere ein Ammoniak-Molekül aus einem Stickstoff-Atom (N) und drei Wasserstoff-Atomen (H)!", successText: "Hervorragende Arbeit! Das NH₃ ist fertig. Es riecht zwar extrem stechend nach Urin, aber ohne diesen Kunstdünger (Haber-Bosch-Verfahren) könnten wir heute nicht die gesamte Weltbevölkerung ernähren!", reward: "Schaltet Level 5 frei" }, { id: 5, title: "Die Verdauungshilfe", goalFormula: "hcl", allowedAtoms: ['H', 'Cl'], intro: "Unser Labor-Maskottchen (ein kleiner gefräßiger Drache) hat Bauchschmerzen, weil er zu viel gefressen hat. Wir müssen seine Verdauung ankurbeln! Synthetisiere Salzsäure (HCl) aus einem Wasserstoff-Atom (H) und einem Chlor-Atom (Cl), um seinen Magensaft zu verstärken!", successText: "Perfekt! Dem kleinen Drachen geht es schon viel besser. Salzsäure ist extrem sauer und zersetzt selbst zähes Fleisch im Handumdrehen. Nun bist du bereit für fortgeschrittenere Synthesen!", reward: "Schaltet Level 6 frei" }, { id: 6, title: "Die weiße Rauchbombe", goalFormula: "salmiak_rauch", allowedAtoms: ['N', 'H', 'Cl'], intro: "Hervorragend, Alchemist! Jetzt wird es spektakulär: Wir bereiten einen Show-Effekt für den Tag der offenen Tür vor. Wir wollen dichten, weißen Nebel erzeugen! Synthetisiere zuerst Ammoniak (NH₃) aus 1x N und 3x H, und Salzsäure (HCl) aus 1x H und 1x Cl. Ziehe dann beide Moleküle zusammen, um feinstes Ammoniumchlorid-Salz (NH₄Cl) als Nebel entstehen zu lassen!", successText: "Sensationell! Ein dichter weißer Rauch steigt auf. Du hast soeben deine erste zweistufige Synthese gemeistert! Aus Stickstoff, Wasserstoff und Chlor hast du zuerst Gase erzeugt und diese dann zu feinem Ammoniumchlorid-Salz neutralisiert.", reward: "Schaltet Level 7 frei" }, { id: 7, title: "Das saure Umweltproblem", goalFormula: "saurer_regen", allowedAtoms: ['S', 'O', 'H'], intro: "Sehr gut! Ein Naturschutzverein bittet uns um Hilfe: Sie vermuten sauren Regen als Ursache für ein Waldsterben. Kannst du im Labor demonstrieren, wie dieser gebildet wird? Synthetisiere Schwefeldioxid (SO₂) aus 1x S und 2x O, sowie Wasser (H₂O) aus 2x H und 1x O. Ziehe dann beide Moleküle zusammen, um Schweflige Säure (H₂SO₃) zu erzeugen!", successText: "Perfekt demonstriert! Schwefeldioxid (SO₂) verbindet sich mit dem Regenwasser (H₂O) zu Schwefliger Säure (H₂SO₃). Dank deiner Veranschaulichung versteht das Team das Problem nun genau und kann gezielte Filteranlagen fordern!", reward: "Schaltet Level 8 frei" }, { id: 8, title: "Die Säure-Base-Schlacht", goalFormula: "neutralisation", allowedAtoms: ['H', 'Cl', 'Na', 'O'], intro: "Willkommen zum großen Meisterstück der Alchemie! Ein wahrer Meister muss aggressive Säuren und Basen bändigen. Wir haben ätzende Salzsäure (HCl) und hochreaktive Natronlauge (NaOH). Neutralisiere sie! Synthetisiere zuerst HCl und NaOH, und bringe sie dann zusammen, um harmloses Kochsalz (NaCl) und reines Wasser (H₂O) zu erhalten!", successText: "Unglaublich! Du hast es geschafft! Die heftige Reaktion hat Energie freigesetzt, aber am Ende blieben nur Speisesalz und klares Wasser übrig. Du hast die Kunst der Neutralisation gemeistert und bist nun ein anerkannter Großmeister der molekularen Alchemie!", reward: "Story-Modus abgeschlossen! 🎉" } ]; // Initiales Laden updateStats(); renderDiscoveryBook(); // Button-Klicks registrieren für Spawnen in Sidebar spawnBtns.forEach(btn => { btn.addEventListener('click', () => { const symbol = btn.dataset.element; const color = btn.dataset.color; spawnAtom(symbol, color); }); }); // Tisch leeren Button clearDeskBtn.addEventListener('click', () => { const elementsToRemove = workspace.querySelectorAll('.atom, .molecule'); elementsToRemove.forEach(el => el.remove()); elementsOnDesk = []; reactorAtoms = []; reactorMolecules = []; updateStats(); updateReactorUI(); }); // Reaktor-Box Buttons document.getElementById('reactor-synth-btn').addEventListener('click', synthesizeReactor); document.getElementById('reactor-decompose-btn').addEventListener('click', decomposeReactor); // Machine Toggles in Reaktor Box const heatToggle = document.getElementById('reactor-heat-toggle'); const elecToggle = document.getElementById('reactor-elec-toggle'); if (heatToggle) { heatToggle.addEventListener('change', () => { if (heatToggle.checked) { setAssistantText("Brenner gezündet! 🔥 Hitze liefert die nötige Aktivierungsenergie, um reaktionsträge Dreifachbindungen anzuregen."); } else { setAssistantText("Brenner aus. Der Reaktor kühlt langsam ab."); } }); } if (elecToggle) { elecToggle.addEventListener('change', () => { if (elecToggle.checked) { setAssistantText("Strom ein! ⚡ Die Elektrolyse zwingt Elektronen auf Bahnen und spaltet selbst extrem stabile Moleküle."); } else { setAssistantText("Strom aus. Die Ionenbewegung normalisiert sich."); } }); } // Particle Accelerator fire event const accFireBtn = document.getElementById('acc-fire-btn'); if (accFireBtn) { accFireBtn.addEventListener('click', fireAccelerator); } // ========================================= // MODALS LOGIC // ========================================= // Info-Modal (Entdeckungen) Schließen modalCloseBtn.addEventListener('click', closeModal); modalOverlay.addEventListener('click', closeModal); modalCloseIcon.addEventListener('click', closeModal); function closeModal() { infoModal.classList.add('hidden'); } // PSE Modal Steuerung pseToggleBtn.addEventListener('click', () => { pseModal.classList.remove('hidden'); renderPSEGrid(); }); pseCloseBtn.addEventListener('click', closePSE); pseCloseIcon.addEventListener('click', closePSE); pseOverlay.addEventListener('click', closePSE); function closePSE() { pseModal.classList.add('hidden'); } function getElementColor(symbol) { if (elementDetails[symbol]) { return elementDetails[symbol].color; } const el = pseElements.find(e => e.symbol === symbol); if (el) { const categoryColors = { 'alkalimetall': '#ff7675', 'erdalkali': '#e17055', 'uebergang': '#b2bec3', 'metalloid': '#fdcb6e', 'nichtmetall': '#74b9ff', 'halogen': '#55efc4', 'edelgas': '#e84393', 'metall': '#ffeaa7' }; return categoryColors[el.category] || '#b2bec3'; } return '#b2bec3'; } // PSE Atom Spawnen Event pseSpawnBtn.addEventListener('click', () => { if (selectedPSEElement) { spawnAtom(selectedPSEElement.symbol, getElementColor(selectedPSEElement.symbol)); closePSE(); } }); // ========================================= // GAMEPLAY CORE LOGIC // ========================================= function spawnAtom(symbol, color) { const el = document.createElement('div'); el.classList.add('atom'); el.innerText = symbol; el.dataset.symbol = symbol; el.style.backgroundColor = color; // Farblich angepasster Text für dunkle/kontrastreiche Elemente if (symbol === 'C' || symbol === 'Fe') { el.style.color = '#fff'; } else { el.style.color = '#333'; } // Zufällige Position auf dem Tisch const x = Math.random() * (workspace.clientWidth - 60); const y = Math.random() * (workspace.clientHeight - 60); el.style.left = x + 'px'; el.style.top = y + 'px'; makeDraggable(el); workspace.appendChild(el); elementsOnDesk.push(el); updateStats(); // Animation beim Erscheinen el.animate([ { transform: 'scale(0)' }, { transform: 'scale(1.1)' }, { transform: 'scale(1)' } ], { duration: 250, easing: 'ease-out' }); } function makeDraggable(el) { el.addEventListener('mousedown', (e) => { draggingElement = el; const rect = el.getBoundingClientRect(); offsetX = e.clientX - rect.left; offsetY = e.clientY - rect.top; el.style.zIndex = 1000; // Füge Schatten beim Ziehen hinzu el.style.boxShadow = '0 10px 20px rgba(0,0,0,0.4)'; }); } document.addEventListener('mousemove', (e) => { if (draggingElement) { const workspaceRect = workspace.getBoundingClientRect(); let newX = e.clientX - workspaceRect.left - offsetX; let newY = e.clientY - workspaceRect.top - offsetY; // Grenzen des Workspaces beachten newX = Math.max(0, Math.min(newX, workspaceRect.width - draggingElement.offsetWidth)); newY = Math.max(0, Math.min(newY, workspaceRect.height - draggingElement.offsetHeight)); draggingElement.style.left = newX + 'px'; draggingElement.style.top = newY + 'px'; } }); document.addEventListener('mouseup', () => { if (draggingElement) { draggingElement.style.zIndex = ''; draggingElement.style.boxShadow = ''; handleElementDrop(); draggingElement = null; } }); let reactorAtoms = []; let reactorMolecules = []; function isElementOverReactor(el) { const reactorBox = document.getElementById('reactor-box'); if (!reactorBox) return false; const r1 = el.getBoundingClientRect(); const r2 = reactorBox.getBoundingClientRect(); return !(r1.right < r2.left || r1.left > r2.right || r1.bottom < r2.top || r1.top > r2.bottom); } function handleElementDrop() { if (!draggingElement) return; // Check if element is dropped over the reactor box if (isElementOverReactor(draggingElement)) { // Add to reactor state if (draggingElement.classList.contains('atom')) { const symbol = draggingElement.dataset.symbol; reactorAtoms.push(symbol); } else if (draggingElement.classList.contains('molecule')) { const recipeId = draggingElement.dataset.recipeId; const recipe = recipes.find(r => r.id === recipeId); if (recipe) { reactorMolecules.push(recipe); } } // Remove from desk workspace.removeChild(draggingElement); elementsOnDesk = elementsOnDesk.filter(el => el !== draggingElement); updateStats(); updateReactorUI(); // Remove visual feedback highlight const reactorBox = document.getElementById('reactor-box'); if (reactorBox) reactorBox.classList.remove('drag-over'); } } function updateReactorUI() { const summary = document.getElementById('reactor-contents-summary'); if (!summary) return; summary.innerHTML = ''; if (reactorAtoms.length === 0 && reactorMolecules.length === 0) { summary.innerHTML = 'Atome/Moleküle hierher ziehen!'; return; } // Group atoms by symbol for compact display const atomCounts = {}; reactorAtoms.forEach(sym => { atomCounts[sym] = (atomCounts[sym] || 0) + 1; }); // Render atom badges Object.keys(atomCounts).forEach(sym => { const count = atomCounts[sym]; const badge = document.createElement('div'); badge.classList.add('reactor-badge', 'atom-badge'); badge.style.backgroundColor = getElementColor(sym); badge.title = `Klicke zum Auswerfen`; badge.innerHTML = `${count}x ${sym}`; // Dark/light text color contrast if (sym === 'C' || sym === 'Fe') { badge.style.color = '#fff'; } else { badge.style.color = '#333'; } badge.addEventListener('click', () => { ejectAtomFromReactor(sym); }); summary.appendChild(badge); }); // Render molecule badges reactorMolecules.forEach((recipe, idx) => { const badge = document.createElement('div'); badge.classList.add('reactor-badge', 'molecule-badge'); badge.style.backgroundColor = recipe.color; badge.title = `Klicke zum Auswerfen`; // Show chemical formula (e.g. H2O) const formula = recipe.id.toUpperCase().replace(/\d/g, m => '' + m + ''); badge.innerHTML = `${formula}`; badge.style.color = '#fff'; badge.addEventListener('click', () => { ejectMoleculeFromReactor(idx); }); summary.appendChild(badge); }); } function ejectAtomFromReactor(symbol) { const idx = reactorAtoms.indexOf(symbol); if (idx > -1) { reactorAtoms.splice(idx, 1); // Position back on desk near reactor const reactorBox = document.getElementById('reactor-box'); const rx = parseFloat(reactorBox.style.left || (workspace.clientWidth - 340)) - 60 - Math.random() * 40; const ry = parseFloat(reactorBox.style.top || (workspace.clientHeight - 190)) + Math.random() * 40; spawnAtom(symbol, getElementColor(symbol)); const lastEl = elementsOnDesk[elementsOnDesk.length - 1]; if (lastEl) { lastEl.style.left = Math.max(10, rx) + 'px'; lastEl.style.top = Math.max(10, ry) + 'px'; } updateReactorUI(); } } function ejectMoleculeFromReactor(idx) { const recipe = reactorMolecules[idx]; if (recipe) { reactorMolecules.splice(idx, 1); // Position back on desk near reactor const reactorBox = document.getElementById('reactor-box'); const rx = parseFloat(reactorBox.style.left || (workspace.clientWidth - 340)) - 100 - Math.random() * 40; const ry = parseFloat(reactorBox.style.top || (workspace.clientHeight - 190)) + Math.random() * 40; createMolecule(recipe, Math.max(10, rx), Math.max(10, ry)); updateReactorUI(); } } function analyzeFailedSynthesis() { const counts = {}; reactorAtoms.forEach(sym => { counts[sym] = (counts[sym] || 0) + 1; }); if (counts['N'] && counts['H'] && counts['H'] && counts['H'] !== 3) { setAssistantText("Achtung! Stickstoff (N) benötigt genau 3 Wasserstoff-Atome (H) für Ammoniak (NH₃). Deine Mischung lässt freie Valenzen ungesättigt. Füge noch ein H hinzu!", true); } else if (counts['H'] === 1 && counts['O'] === 1) { setAssistantText("Wasserstoff (H) und Sauerstoff (O) können nicht im Verhältnis 1:1 binden. Sie brauchen entweder 2x H und 1x O für Wasser (H₂O) oder 2x H und 2x O für Wasserstoffperoxid (H₂O₂).", true); } else if (counts['C'] && counts['O'] && counts['C'] === 1 && counts['O'] !== 1 && counts['O'] !== 2) { setAssistantText("Kohlenstoff (C) bindet sich mit Sauerstoff (O) entweder zu Kohlenmonoxid (CO, 1:1) oder Kohlendioxid (CO₂, 1:2). Passe dein Verhältnis an!", true); } else { setAssistantText("Diese Atome können sich nicht zu einem stabilen Molekül verbinden. Achte auf die Oktettregel und die Wertigkeiten (H=1, O=2, N=3, C=4, Na=1, Cl=1)!", true); } } function synthesizeReactor() { if (reactorAtoms.length === 0) { alert("Der Reaktor enthält keine freien Atome für die Synthese!"); return; } const hasNitrogen = reactorAtoms.includes('N'); const heatOn = document.getElementById('reactor-heat-toggle').checked; const elecOn = document.getElementById('reactor-elec-toggle').checked; if (hasNitrogen && !heatOn && !elecOn) { setAssistantText("Halt! Stickstoff (N) ist extrem reaktionsträge aufgrund seiner starken Dreifachbindung! Um ihn zur Reaktion zu bringen, benötigst du zusätzliche Aktivierungsenergie. Schalte die Brenner-Station (Hitze) oder die Elektrolyse-Kammer (Strom) hinzu!", true); alert("Synthese blockiert: Aktivierungsenergie fehlt für Stickstoff!"); return; } // Sort recipes by ingredient length descending so we build larger molecules first const sortedRecipes = [...recipes].sort((a, b) => b.ingredients.length - a.ingredients.length); let synthesizedAny = false; let keepMatching = true; while (keepMatching) { keepMatching = false; const availableCounts = {}; reactorAtoms.forEach(sym => { availableCounts[sym] = (availableCounts[sym] || 0) + 1; }); for (const recipe of sortedRecipes) { const recipeCounts = {}; recipe.ingredients.forEach(sym => { recipeCounts[sym] = (recipeCounts[sym] || 0) + 1; }); let match = true; for (const sym of Object.keys(recipeCounts)) { if (!availableCounts[sym] || availableCounts[sym] < recipeCounts[sym]) { match = false; break; } } if (match) { // Match found! Consume atoms recipe.ingredients.forEach(sym => { const idx = reactorAtoms.indexOf(sym); if (idx > -1) { reactorAtoms.splice(idx, 1); } }); // Spawn molecule near the reactor const reactorBox = document.getElementById('reactor-box'); const rx = parseFloat(reactorBox.style.left || (workspace.clientWidth - 340)) - 100 - Math.random() * 40; const ry = parseFloat(reactorBox.style.top || (workspace.clientHeight - 190)) + Math.random() * 40; createMolecule(recipe, Math.max(10, rx), Math.max(10, ry)); // Award energy const energyAwarded = recipe.ingredients.length * 15; playerEnergy += energyAwarded; localStorage.setItem('chem_lab_energy', playerEnergy); // Explosion at the reactor center const rect = reactorBox.getBoundingClientRect(); const workspaceRect = workspace.getBoundingClientRect(); const rx_exp = rect.left - workspaceRect.left + rect.width / 2; const ry_exp = rect.top - workspaceRect.top + rect.height / 2; triggerExplosion(rx_exp, ry_exp, recipe.color); // Discovery check const isNew = !discoveredMolecules.has(recipe.id); if (isNew) { discoveredMolecules.add(recipe.id); localStorage.setItem('chem_lab_discoveries', JSON.stringify([...discoveredMolecules])); renderDiscoveryBook(); } // Story check if (gameMode === 'story') { const currentLevel = levels[currentLevelIndex]; if (recipe.id === currentLevel.goalFormula) { handleLevelSuccess(currentLevel, recipe); } } showModal(recipe, isNew); const cleanName = recipe.result.substring(recipe.result.indexOf('(') + 1, recipe.result.indexOf(')')); setAssistantText(`Sensationell! Wir haben ${cleanName} synthetisiert und dabei ${energyAwarded} J Energie freigesetzt!`); synthesizedAny = true; keepMatching = true; break; } } } if (synthesizedAny) { updateReactorUI(); } else { analyzeFailedSynthesis(); } } function setAssistantText(text, isWarning = false) { const avatar = document.querySelector('.assistant-avatar'); const textEl = document.getElementById('assistant-text'); if (!avatar || !textEl) return; avatar.innerText = isWarning ? "⚠️" : "🔬"; textEl.innerText = text; } function decomposeReactor() { if (reactorMolecules.length === 0) { alert("Es befinden sich keine Moleküle in der Reaktor-Box, die zerlegt werden können!"); return; } let decomposedAny = false; const reactorBox = document.getElementById('reactor-box'); while (reactorMolecules.length > 0) { const recipe = reactorMolecules.pop(); recipe.ingredients.forEach(sym => { reactorAtoms.push(sym); }); // Trigger grey decomposition particle explosion const rect = reactorBox.getBoundingClientRect(); const workspaceRect = workspace.getBoundingClientRect(); const rx_exp = rect.left - workspaceRect.left + rect.width / 2; const ry_exp = rect.top - workspaceRect.top + rect.height / 2; triggerExplosion(rx_exp, ry_exp, '#b2bec3'); decomposedAny = true; } if (decomposedAny) { updateReactorUI(); const summary = document.getElementById('reactor-contents-summary'); if (summary) { summary.animate([ { transform: 'scale(1)' }, { transform: 'scale(1.05)' }, { transform: 'scale(1)' } ], { duration: 200, easing: 'ease-out' }); } } } function createMolecule(recipe, x, y) { const el = document.createElement('div'); el.classList.add('molecule'); el.innerText = recipe.result.split(' ')[0]; // Zeigt z.B. H₂O an el.dataset.symbol = recipe.result; el.dataset.recipeId = recipe.id; el.style.backgroundColor = recipe.color; // Grenzen im Workspace einhalten const maxLeft = workspace.clientWidth - 120; const maxTop = workspace.clientHeight - 40; el.style.left = Math.max(0, Math.min(x, maxLeft)) + 'px'; el.style.top = Math.max(0, Math.min(y, maxTop)) + 'px'; makeDraggable(el); workspace.appendChild(el); elementsOnDesk.push(el); updateStats(); // Entstehungsanimation el.animate([ { transform: 'scale(0.5)' }, { transform: 'scale(1.2)' }, { transform: 'scale(1)' } ], { duration: 300, easing: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)' }); } function triggerExplosion(x, y, color) { const numParticles = 18; for (let i = 0; i < numParticles; i++) { const p = document.createElement('div'); p.classList.add('particle'); p.style.backgroundColor = color || '#ff7675'; p.style.left = x + 'px'; p.style.top = y + 'px'; workspace.appendChild(p); // Zufälliger Winkel und Geschwindigkeit für Explosion const angle = Math.random() * Math.PI * 2; const velocity = 40 + Math.random() * 80; const targetX = Math.cos(angle) * velocity; const targetY = Math.sin(angle) * velocity + 20; // Leichte Gravitation p.animate([ { transform: 'translate(0, 0) scale(1)', opacity: 1 }, { transform: `translate(${targetX}px, ${targetY}px) scale(0)`, opacity: 0 } ], { duration: 600 + Math.random() * 300, easing: 'cubic-bezier(0.1, 0.8, 0.3, 1)', fill: 'forwards' }); setTimeout(() => p.remove(), 1000); } } function showModal(recipe, isNew = true) { if (isNew) { modalTitle.innerText = "Molekül entdeckt! 🎉"; document.querySelector('#info-modal .modal-emoji').innerText = "🎉"; } else { modalTitle.innerText = "Molekül-Lexikon 📖"; document.querySelector('#info-modal .modal-emoji').innerText = "📖"; } // Subscripts für Formel schön rendern const prettyFormula = recipe.id.toUpperCase().replace(/\d/g, m => '' + m + ''); modalFormula.innerHTML = prettyFormula; modalFormula.style.backgroundColor = recipe.color; // Reiner Name (Text in Klammern aus z.B. "H₂O (Wasser)") const cleanName = recipe.result.substring(recipe.result.indexOf('(') + 1, recipe.result.indexOf(')')); modalName.innerText = cleanName; modalDesc.innerText = recipe.desc; infoModal.classList.remove('hidden'); } function showAdvancedReactionModal(advRecipe) { modalTitle.innerText = "Chemische Reaktivität! 💥"; document.querySelector('#info-modal .modal-emoji').innerText = "💥"; // Formel mit Tiefstellung formatieren (Sowohl Atome wie Fe als auch Moleküle wie h2o) const formatFormula = (id) => { const formulaText = id.toUpperCase(); return formulaText.replace(/\d/g, m => '' + m + ''); }; const reactantsText = advRecipe.ingredients.map(formatFormula).join(' + '); const productsText = advRecipe.results.map(formatFormula).join(' + '); modalFormula.innerHTML = `${reactantsText} → ${productsText}`; modalFormula.style.backgroundColor = '#ff9f43'; // Schöne orange exotherme Reaktionsfarbe modalName.innerText = advRecipe.name; modalDesc.innerText = advRecipe.desc; infoModal.classList.remove('hidden'); } function renderDiscoveryBook() { discoveryBook.innerHTML = ''; let count = 0; recipes.forEach(recipe => { const isDiscovered = discoveredMolecules.has(recipe.id); const item = document.createElement('div'); item.classList.add('book-item'); // Formel mit tiefgestellten Ziffern const prettyFormula = recipe.id.toUpperCase().replace(/\d/g, m => '' + m + ''); if (isDiscovered) { item.classList.add('unlocked'); // Reiner Name aus Rezept const cleanName = recipe.result.substring(recipe.result.indexOf('(') + 1, recipe.result.indexOf(')')); item.innerHTML = ` ${prettyFormula} ${cleanName} 🔓 `; item.addEventListener('click', () => { showModal(recipe, false); }); count++; } else { item.classList.add('locked'); item.innerHTML = ` 🧪 ??? Unbekannt 🔒 `; } discoveryBook.appendChild(item); }); discoveryProgress.innerText = `${count}/${recipes.length}`; } function checkPhysicsUnlock() { const physicsBtn = document.getElementById('tab-physics-btn'); if (!physicsBtn) return; if (playerEnergy >= 150) { physicsBtn.classList.remove('locked'); physicsBtn.disabled = false; physicsBtn.title = "Klicke, um den Teilchenbeschleuniger zu öffnen!"; physicsBtn.innerHTML = "⚛️ Physik"; } else { physicsBtn.classList.add('locked'); physicsBtn.disabled = true; physicsBtn.innerHTML = `⚛️ Physik 🔒 (${playerEnergy}/150J)`; } } function updateStats() { const atoms = elementsOnDesk.filter(el => el.classList.contains('atom')).length; const molecules = elementsOnDesk.filter(el => el.classList.contains('molecule')).length; atomCountEl.innerText = atoms; moleculeCountEl.innerText = molecules; const energyCountEl = document.getElementById('energy-count'); if (energyCountEl) { energyCountEl.innerText = playerEnergy; } localStorage.setItem('chem_lab_energy', playerEnergy); checkPhysicsUnlock(); } // ========================================= // INTERACTIVE PSE LOGIC // ========================================= function renderPSEGrid() { const grid = document.getElementById('pse-grid'); grid.innerHTML = ''; pseElements.forEach(el => { const div = document.createElement('div'); div.classList.add('pse-el'); div.style.gridRow = el.row; div.style.gridColumn = el.col; div.dataset.symbol = el.symbol; div.innerHTML = ` ${el.number} ${el.symbol} ${el.name} `; if (el.playable) { div.classList.add('active-el'); div.classList.add(el.category); div.addEventListener('click', () => { selectElementSteckbrief(el); }); } else { div.classList.add('locked-el'); div.addEventListener('click', () => { // Selektiert dekorative Elemente trotzdem für den Steckbrief (Lerneffekt!), aber deaktiviert Spawnen selectElementSteckbrief(el, false); }); } grid.appendChild(div); }); } function selectElementSteckbrief(el, canSpawn = true) { selectedPSEElement = el; const emptyDiv = document.querySelector('.steckbrief-empty'); const cardDiv = document.querySelector('.steckbrief-card'); emptyDiv.classList.add('hidden'); cardDiv.classList.remove('hidden'); const box = document.getElementById('steckbrief-box'); box.innerText = el.symbol; box.className = ''; // Zurücksetzen box.classList.add('active-el', el.category); // Spezieller Textkontrast für dunkle Elemente im Steckbrief if (el.symbol === 'C' || el.symbol === 'Fe') { box.style.color = '#fff'; } else { box.style.color = '#333'; } document.getElementById('steckbrief-name').innerText = el.name; // Kategoriennamen lesbar übersetzen const categoryNames = { 'nichtmetall': 'Nichtmetall', 'edelgas': 'Edelgas', 'alkalimetall': 'Alkalimetall', 'erdalkali': 'Erdalkalimetall', 'uebergang': 'Übergangsmetall', 'halogen': 'Halogen', 'metalloid': 'Halbmetall', 'metall': 'Metall' }; document.getElementById('steckbrief-category').innerText = categoryNames[el.category] || el.category; document.getElementById('steckbrief-category').className = ''; document.getElementById('steckbrief-category').classList.add(el.category); document.getElementById('steckbrief-number').innerText = el.number; document.getElementById('steckbrief-mass').innerText = el.mass; document.getElementById('steckbrief-desc').innerText = el.desc; // Spawnen-Button steuern if (canSpawn && (gameMode === 'sandbox' || currentAllowedAtoms.includes(el.symbol))) { pseSpawnBtn.classList.remove('hidden'); } else { pseSpawnBtn.classList.add('hidden'); } // Bohr-Modell Schalen visualisieren renderBohrModel(el.electrons); } function renderBohrModel(electronsArray) { const shellsContainer = document.getElementById('bohr-shells'); shellsContainer.innerHTML = ''; electronsArray.forEach((numElectrons, shellIndex) => { const shellDiv = document.createElement('div'); shellDiv.classList.add('bohr-shell'); // Dynamischer Schalendurchmesser basierend auf Schalenindex (Concentric Circles) const diameter = 40 + (shellIndex * 30); shellDiv.style.width = diameter + 'px'; shellDiv.style.height = diameter + 'px'; shellDiv.style.left = `calc(50% - ${diameter / 2}px)`; shellDiv.style.top = `calc(50% - ${diameter / 2}px)`; // Geschwindigkeit variieren für coole Dynamik shellDiv.style.animationDuration = (6 + shellIndex * 4) + 's'; // Elektronenpunkte auf der Kreisbahn berechnen & platzieren for (let i = 0; i < numElectrons; i++) { const electron = document.createElement('div'); electron.classList.add('bohr-electron'); // Winkel für Gleichverteilung berechnen const angle = (i / numElectrons) * Math.PI * 2; const radius = diameter / 2; const x = Math.cos(angle) * radius; const y = Math.sin(angle) * radius; // Auf der CSS-Kreisbahn zentrieren electron.style.left = `calc(50% + ${x}px - 3px)`; electron.style.top = `calc(50% + ${y}px - 3px)`; shellDiv.appendChild(electron); } shellsContainer.appendChild(shellDiv); }); } // ========================================= // STORY MODE LOGIC // ========================================= // Dom Tabs switching const tabSandboxBtn = document.getElementById('tab-sandbox-btn'); const tabStoryBtn = document.getElementById('tab-story-btn'); const tabPhysicsBtn = document.getElementById('tab-physics-btn'); const sandboxContentEl = document.getElementById('sandbox-content'); const storyContentEl = document.getElementById('story-content'); const physicsContentEl = document.getElementById('physics-content'); tabSandboxBtn.addEventListener('click', () => { switchMode('sandbox'); }); tabStoryBtn.addEventListener('click', () => { switchMode('story'); }); if (tabPhysicsBtn) { tabPhysicsBtn.addEventListener('click', () => { if (!tabPhysicsBtn.classList.contains('locked')) { switchMode('physics'); } }); } function switchMode(mode) { gameMode = mode; const elementsToRemove = workspace.querySelectorAll('.atom, .molecule'); elementsToRemove.forEach(el => el.remove()); elementsOnDesk = []; reactorAtoms = []; reactorMolecules = []; updateReactorUI(); updateStats(); closeModal(); closeStorySuccessModal(); if (mode === 'sandbox') { tabSandboxBtn.classList.add('active'); tabStoryBtn.classList.remove('active'); if (tabPhysicsBtn) tabPhysicsBtn.classList.remove('active'); sandboxContentEl.classList.remove('hidden'); storyContentEl.classList.add('hidden'); if (physicsContentEl) physicsContentEl.classList.add('hidden'); deskTitle.innerText = "Labor-Tisch (Sandbox)"; deskSubtitle.innerText = "Ziehe Atome in die Reaktor-Box, um Reaktionen auszulösen!"; currentAllowedAtoms = Object.keys(elementDetails); } else if (mode === 'story') { tabSandboxBtn.classList.remove('active'); tabStoryBtn.classList.add('active'); if (tabPhysicsBtn) tabPhysicsBtn.classList.remove('active'); sandboxContentEl.classList.add('hidden'); storyContentEl.classList.remove('hidden'); if (physicsContentEl) physicsContentEl.classList.add('hidden'); loadStoryLevel(currentLevelIndex); } else if (mode === 'physics') { tabSandboxBtn.classList.remove('active'); tabStoryBtn.classList.remove('active'); if (tabPhysicsBtn) tabPhysicsBtn.classList.add('active'); sandboxContentEl.classList.add('hidden'); storyContentEl.classList.add('hidden'); if (physicsContentEl) physicsContentEl.classList.remove('hidden'); deskTitle.innerText = "Labor-Tisch (Kernphysik)"; deskSubtitle.innerText = "Teilchenbeschleuniger geladen. Kollidiere Atome, um neue Elemente zu erschaffen!"; currentAllowedAtoms = Object.keys(elementDetails); populateAcceleratorDropdowns(); } } function loadStoryLevel(index) { if (index >= levels.length) { index = levels.length - 1; } currentLevelIndex = index; localStorage.setItem('chem_lab_story_level', currentLevelIndex); const level = levels[currentLevelIndex]; currentAllowedAtoms = level.allowedAtoms; deskTitle.innerText = `Labor-Tisch (Story: ${level.title})`; const recipe = recipes.find(r => r.id === level.goalFormula); const cleanName = recipe.result.substring(recipe.result.indexOf('(') + 1, recipe.result.indexOf(')')); deskSubtitle.innerText = `Ziel: Synthetisiere ${cleanName}`; // Level Auswahldots zeichnen renderLevelDots(); // Quest Panel updaten document.getElementById('quest-level-title').innerText = `Level ${level.id}: ${level.title}`; document.getElementById('quest-intro-text').innerText = level.intro; const prettyFormula = recipe.id.toUpperCase().replace(/\d/g, m => '' + m + ''); document.getElementById('quest-goal-text').innerHTML = `Erzeuge 1x ${prettyFormula} (${cleanName})`; // Checkbox zurücksetzen const checkbox = document.querySelector('.objective-checkbox'); const objectiveItem = document.querySelector('.objective-item'); if (checkbox) checkbox.innerText = "⬜"; if (objectiveItem) objectiveItem.classList.remove('completed'); // Spawnbare Atome im Story-Gitter rendern renderStorySpawnButtons(); } function renderLevelDots() { const container = document.querySelector('.level-dots-grid'); if (!container) return; container.innerHTML = ''; levels.forEach((lvl, idx) => { const dot = document.createElement('div'); dot.classList.add('level-dot'); dot.innerText = lvl.id; const isCompleted = completedLevels.includes(lvl.id); const isActive = idx === currentLevelIndex; const isLocked = idx > 0 && !completedLevels.includes(levels[idx - 1].id); if (isLocked) { dot.classList.add('locked'); } else { if (isCompleted) dot.classList.add('completed'); if (isActive) dot.classList.add('active'); dot.addEventListener('click', () => { const elementsToRemove = workspace.querySelectorAll('.atom, .molecule'); elementsToRemove.forEach(el => el.remove()); elementsOnDesk = []; reactorAtoms = []; reactorMolecules = []; updateReactorUI(); updateStats(); loadStoryLevel(idx); }); } container.appendChild(dot); }); const totalLevels = levels.length; document.getElementById('story-overall-progress').innerText = `${completedLevels.includes(totalLevels) ? totalLevels : Math.min(totalLevels, completedLevels.length + 1)}/${totalLevels}`; } function renderStorySpawnButtons() { const grid = document.getElementById('story-elements-grid'); if (!grid) return; grid.innerHTML = ''; currentAllowedAtoms.forEach(symbol => { const details = elementDetails[symbol]; if (details) { const btn = document.createElement('div'); btn.classList.add('spawn-btn'); btn.dataset.element = symbol; btn.dataset.color = details.color; btn.innerText = symbol; btn.title = details.name; btn.style.backgroundColor = details.color; if (symbol === 'C' || symbol === 'Fe') { btn.style.color = '#fff'; } else { btn.style.color = '#333'; } btn.addEventListener('click', () => { spawnAtom(symbol, details.color); }); grid.appendChild(btn); } }); } function completedMoleculesAdd(levelId) { if (!completedLevels.includes(levelId)) { completedLevels.push(levelId); localStorage.setItem('chem_lab_story_completed', JSON.stringify(completedLevels)); } } function handleLevelSuccess(level, recipe) { const checkbox = document.querySelector('.objective-checkbox'); const objectiveItem = document.querySelector('.objective-item'); if (checkbox) checkbox.innerText = "✅"; if (objectiveItem) objectiveItem.classList.add('completed'); completedMoleculesAdd(level.id); renderLevelDots(); // Zeige das große Level-Erfolgs-Modal nach einer kurzen Verzögerung setTimeout(() => { showStorySuccessModal(level, recipe); }, 600); } function showStorySuccessModal(level, recipe) { storySuccessLevelName.innerText = `Level ${level.id} abgeschlossen!`; storySuccessText.innerText = level.successText; if (currentLevelIndex === levels.length - 1) { storyNextLevelBtn.innerText = "🏆 Story-Modus beenden!"; } else { storyNextLevelBtn.innerText = "Nächstes Level ➡️"; } storySuccessModal.classList.remove('hidden'); } function closeStorySuccessModal() { storySuccessModal.classList.add('hidden'); } // Story Next Level Button Event storyNextLevelBtn.addEventListener('click', () => { closeStorySuccessModal(); const elementsToRemove = workspace.querySelectorAll('.atom, .molecule'); elementsToRemove.forEach(el => el.remove()); elementsOnDesk = []; reactorAtoms = []; reactorMolecules = []; updateReactorUI(); updateStats(); if (currentLevelIndex < levels.length - 1) { currentLevelIndex++; localStorage.setItem('chem_lab_story_level', currentLevelIndex); loadStoryLevel(currentLevelIndex); } else { alert("Glückwunsch! Du hast alle Level abgeschlossen. Der Sandkasten-Modus (Sandbox) steht dir weiterhin zur Verfügung!"); switchMode('sandbox'); } }); // Zusätzliche Modal Close-Events if (storySuccessCloseIcon) storySuccessCloseIcon.addEventListener('click', closeStorySuccessModal); if (storySuccessOverlay) storySuccessOverlay.addEventListener('click', closeStorySuccessModal); function populateAcceleratorDropdowns() { const s1 = document.getElementById('acc-source-1'); const s2 = document.getElementById('acc-source-2'); if (!s1 || !s2) return; s1.innerHTML = ''; s2.innerHTML = ''; const playable = pseElements.filter(el => el.playable); playable.forEach(el => { const opt1 = document.createElement('option'); opt1.value = el.symbol; opt1.innerText = `${el.symbol} (${el.name}, Z=${el.number})`; s1.appendChild(opt1); const opt2 = document.createElement('option'); opt2.value = el.symbol; opt2.innerText = `${el.symbol} (${el.name}, Z=${el.number})`; s2.appendChild(opt2); }); } function fireAccelerator() { if (playerEnergy < 20) { alert("Nicht genug Energie! Du benötigst mindestens 20 J, um den Teilchenbeschleuniger zu laden."); return; } const s1 = document.getElementById('acc-source-1'); const s2 = document.getElementById('acc-source-2'); if (!s1 || !s2) return; const sym1 = s1.value; const sym2 = s2.value; const el1 = pseElements.find(e => e.symbol === sym1); const el2 = pseElements.find(e => e.symbol === sym2); if (!el1 || !el2) return; // Cost playerEnergy -= 20; updateStats(); // Animate const animZone = document.getElementById('acc-animation-zone'); const fireBtn = document.getElementById('acc-fire-btn'); const resultBox = document.getElementById('acc-result-box'); if (animZone) animZone.classList.add('firing'); if (resultBox) resultBox.classList.add('hidden'); if (fireBtn) fireBtn.disabled = true; // Set labels const p1 = document.getElementById('acc-particle-1'); const p2 = document.getElementById('acc-particle-2'); if (p1) p1.innerText = el1.symbol; if (p2) p2.innerText = el2.symbol; setTimeout(() => { if (animZone) animZone.classList.remove('firing'); if (fireBtn) fireBtn.disabled = false; const totalZ = el1.number + el2.number; const resultEl = pseElements.find(e => e.number === totalZ); if (resultBox) resultBox.classList.remove('hidden'); const resSymbolEl = document.getElementById('acc-result-element'); const resDescEl = document.getElementById('acc-result-desc'); if (resultEl) { // SUCCESS! resultBox.classList.remove('decayed'); if (resSymbolEl) { resSymbolEl.innerText = resultEl.symbol; resSymbolEl.className = 'acc-result-circle'; resSymbolEl.style.backgroundColor = getElementColor(resultEl.symbol); } if (resDescEl) { resDescEl.innerText = `Kernfusion erfolgreich! Du hast ${resultEl.name} (Ordnungszahl ${totalZ}) erschaffen.`; } // Spawn on desk! spawnAtom(resultEl.symbol, getElementColor(resultEl.symbol)); } else { // DECAY! resultBox.classList.add('decayed'); if (resSymbolEl) { resSymbolEl.innerText = "💥"; resSymbolEl.style.backgroundColor = "#e74c3c"; } if (resDescEl) { resDescEl.innerText = `Instabiler Kern! Das Element mit Ordnungszahl ${totalZ} ist sofort in leichtere Trümmer-Isotope zerfallen.`; } // Spawn random lighter elements as debris const count = 2 + Math.floor(Math.random() * 2); for (let i = 0; i < count; i++) { const randomLight = pseElements.filter(e => e.playable && e.number < 20); const randomEl = randomLight[Math.floor(Math.random() * randomLight.length)]; spawnAtom(randomEl.symbol, getElementColor(randomEl.symbol)); } } }, 800); }