diff --git a/PLAN.md b/PLAN.md index 02f4647..2a74541 100644 --- a/PLAN.md +++ b/PLAN.md @@ -15,10 +15,10 @@ Dieses Dokument dokumentiert die erfolgreich abgeschlossenen Entwicklungsphasen - **3D-Scherenmodell:** Atome haben durch CSS-Radial-Gradients ein plastisches 3D-Kugel-Aussehen. ### Phase 2: Das interaktive PSE-Cockpit (Option 1) -- **Periodensystem-Overlay:** Ein Klick auf "📊 Periodensystem" öffnet ein vollflächiges, dunkles Periodensystem-Interfache (CSS Grid, 18 Spalten x 4 Zeilen). +- **Periodensystem-Overlay:** Ein Klick auf "📊 Periodensystem" öffnet ein vollflächiges, dunkles Periodensystem-Interface (CSS Grid, 18 Spalten x 7 Zeilen mit allen 50 Hauptgruppen-Elementen). - **Wissenschaftliche Steckbriefe:** Detaillierte Karten für jedes Element mit Ordnungszahl, Atommasse, Gruppenbezeichnung und Alltagsvorkommen. - **Aktives Schalenmodell (Bohr-Modell):** Eine dynamische Schalen-Visualisierung berechnet die Kreisbahnen der Elektronen trigonometrisch und lässt sie in flüssiger Bewegung rotieren. Jedes Atom hat seine reale Elektronenkonfiguration (z. B. Natrium: 2, 8, 1 Schalen). -- **Direktes Spawnen:** Elemente können direkt aus dem PSE-Steckbrief auf den Tisch gespawnt werden. +- **Direktes Spawnen:** Alle 50 Hauptgruppen-Elemente sowie Eisen können direkt aus dem PSE-Steckbrief auf den Tisch gespawnt werden (mit intelligentem, dynamischem Kategoriemuster-Farbschema). ### Phase 3: Der Story-Modus (Missions-Zentrale) - **Kampagnen-System:** Ein Umschalter zwischen "🧪 Sandbox" und "🏆 Story-Modus" in der Sidebar. diff --git a/app.js b/app.js index e30cb7d..5c72f4b 100644 --- a/app.js +++ b/app.js @@ -64,25 +64,55 @@ const elementDetails = { 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: false, 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: false, 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: false, electrons: [2, 3], desc: 'Ein hartes, hitzebeständiges Halbmetall. Es wird für extrem widerstandsfähiges Glas (Borosilikatglas) und im Raketentreibstoff-Sektor verwendet.' }, + { 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: false, 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: false, 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: 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: false, 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: false, 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: false, electrons: [2, 8, 4], desc: 'Das Element, das unsere Computertechnologie antreibt! Silicium ist 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: false, 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: 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: false, 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: false, 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: false, 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: 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) @@ -387,11 +417,19 @@ spawnBtns.forEach(btn => { // Tisch leeren Button clearDeskBtn.addEventListener('click', () => { - workspace.innerHTML = ''; + 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); + // ========================================= // MODALS LOGIC // ========================================= @@ -419,10 +457,31 @@ 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, elementDetails[selectedPSEElement.symbol].color); + spawnAtom(selectedPSEElement.symbol, getElementColor(selectedPSEElement.symbol)); closePSE(); } }); @@ -500,144 +559,204 @@ document.addEventListener('mouseup', () => { if (draggingElement) { draggingElement.style.zIndex = ''; draggingElement.style.boxShadow = ''; - checkForReactions(); + handleElementDrop(); draggingElement = null; } }); -function checkForReactions() { - if (!draggingElement) return; +let reactorAtoms = []; +let reactorMolecules = []; - // Finde alle Elemente, die sich berühren (inklusive des gezogenen Elements) - let cluster = [draggingElement]; - let added = true; +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; - while(added) { - added = false; - for (let el of elementsOnDesk) { - if (cluster.includes(el)) continue; - - // Prüfe Kollision mit irgendeinem Element im Cluster - let touches = cluster.some(cEl => { - const r1 = cEl.getBoundingClientRect(); - const r2 = el.getBoundingClientRect(); - return !(r1.right < r2.left || - r1.left > r2.right || - r1.bottom < r2.top || - r1.top > r2.bottom); + // 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 synthesizeReactor() { + if (reactorAtoms.length === 0) { + alert("Der Reaktor enthält keine freien Atome für die Synthese!"); + 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; }); - if (touches) { - cluster.push(el); - added = true; - } - } - } - - if (cluster.length > 1) { - // Reaktions-Keys extrahieren (Atome => Großbuchstaben-Symbol, Moleküle => Kleinbuchstaben-Rezept-ID) - const reactantKeys = []; - cluster.forEach(el => { - if (el.classList.contains('atom')) { - reactantKeys.push(el.dataset.symbol); - } else if (el.classList.contains('molecule')) { - reactantKeys.push(el.dataset.recipeId); - } - }); - reactantKeys.sort(); - - // ZUERST: Fortgeschrittene Molekül-Reaktionen prüfen - let advancedReactionFound = false; - for (const advRecipe of advancedRecipes) { - const advIngredients = [...advRecipe.ingredients].sort(); - - if (JSON.stringify(reactantKeys) === JSON.stringify(advIngredients)) { - // FORTGESCHRITTENE REAKTION ERFOLGREICH! - advancedReactionFound = true; - const midX = parseFloat(draggingElement.style.left) + draggingElement.offsetWidth / 2; - const midY = parseFloat(draggingElement.style.top) + draggingElement.offsetHeight / 2; - - // Lösche alle reactant-Elemente im Cluster vom Tisch - cluster.forEach(el => { - if (workspace.contains(el)) { - workspace.removeChild(el); - } - elementsOnDesk = elementsOnDesk.filter(e => e !== el); - }); - - // Dicke, bunte Explosion erzeugen - triggerExplosion(midX, midY, '#ff9f43'); - - // Erzeuge alle Produkt-Moleküle des fortgeschrittenen Rezepts - advRecipe.results.forEach((prodId, index) => { - const prodRecipe = recipes.find(r => r.id === prodId); - if (prodRecipe) { - // Platziere Produkte nebeneinander im Fusionszentrum - const offsetMultiplier = index - (advRecipe.results.length - 1) / 2; - const molX = midX - 60 + (offsetMultiplier * 80); - const molY = midY - 20; - createMolecule(prodRecipe, molX, molY); - - // Entdeckung registrieren - const isNew = !discoveredMolecules.has(prodRecipe.id); - if (isNew) { - discoveredMolecules.add(prodRecipe.id); - localStorage.setItem('chem_lab_discoveries', JSON.stringify([...discoveredMolecules])); - } - } - }); - - renderDiscoveryBook(); - - // Story-Modus Ziel prüfen (für fortgeschrittene Reaktionen) - if (gameMode === 'story') { - const currentLevel = levels[currentLevelIndex]; - if (advRecipe.id === currentLevel.goalFormula) { - handleLevelSuccess(currentLevel, advRecipe); - break; - } + let match = true; + for (const sym of Object.keys(recipeCounts)) { + if (!availableCounts[sym] || availableCounts[sym] < recipeCounts[sym]) { + match = false; + break; } - - // Info-Modal für die gesamte Reaktion anzeigen! - showAdvancedReactionModal(advRecipe); - break; } - } - - if (advancedReactionFound) return; - - // DANACH: Normale Atom-Fusion (Cluster darf KEINE Moleküle enthalten!) - const hasMolecule = cluster.some(el => el.classList.contains('molecule')); - if (hasMolecule) return; - - const symbols = cluster.map(el => el.dataset.symbol).sort(); - - // Prüfe gegen alle Rezepte - for (const recipe of recipes) { - const recipeSymbols = [...recipe.ingredients].sort(); - if (JSON.stringify(symbols) === JSON.stringify(recipeSymbols)) { - // REAKTION! - const midX = parseFloat(draggingElement.style.left) + draggingElement.offsetWidth / 2; - const midY = parseFloat(draggingElement.style.top) + draggingElement.offsetHeight / 2; - - // Lösche fusionierte Atome vom Tisch - cluster.forEach(el => { - if (workspace.contains(el)) { - workspace.removeChild(el); + if (match) { + // Match found! Consume atoms + recipe.ingredients.forEach(sym => { + const idx = reactorAtoms.indexOf(sym); + if (idx > -1) { + reactorAtoms.splice(idx, 1); } - elementsOnDesk = elementsOnDesk.filter(e => e !== el); }); - // Partikel-Explosion erzeugen - triggerExplosion(midX, midY, recipe.color); + // 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)); - // Neues Molekül erstellen - const molX = midX - 60; // Zentrieren - const molY = midY - 20; - createMolecule(recipe, molX, molY); + // 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); - // Entdeckung registrieren + // Discovery check const isNew = !discoveredMolecules.has(recipe.id); if (isNew) { discoveredMolecules.add(recipe.id); @@ -645,22 +764,66 @@ function checkForReactions() { renderDiscoveryBook(); } - // Story-Modus Ziel prüfen (für atomare Fusionen) + // Story check if (gameMode === 'story') { const currentLevel = levels[currentLevelIndex]; if (recipe.id === currentLevel.goalFormula) { handleLevelSuccess(currentLevel, recipe); - break; } } - // Info-Modal anzeigen (bei neuer Entdeckung) showModal(recipe, isNew); + synthesizedAny = true; + keepMatching = true; break; } } } + + if (synthesizedAny) { + updateReactorUI(); + } else { + alert("Aus den vorhandenen Atomen konnte kein bekanntes Molekül synthetisiert werden!"); + } +} + +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) { @@ -963,8 +1126,12 @@ tabStoryBtn.addEventListener('click', () => { function switchMode(mode) { gameMode = mode; - workspace.innerHTML = ''; + const elementsToRemove = workspace.querySelectorAll('.atom, .molecule'); + elementsToRemove.forEach(el => el.remove()); elementsOnDesk = []; + reactorAtoms = []; + reactorMolecules = []; + updateReactorUI(); updateStats(); closeModal(); closeStorySuccessModal(); @@ -1044,8 +1211,12 @@ function renderLevelDots() { if (isActive) dot.classList.add('active'); dot.addEventListener('click', () => { - workspace.innerHTML = ''; + const elementsToRemove = workspace.querySelectorAll('.atom, .molecule'); + elementsToRemove.forEach(el => el.remove()); elementsOnDesk = []; + reactorAtoms = []; + reactorMolecules = []; + updateReactorUI(); updateStats(); loadStoryLevel(idx); }); @@ -1129,8 +1300,12 @@ function closeStorySuccessModal() { // Story Next Level Button Event storyNextLevelBtn.addEventListener('click', () => { closeStorySuccessModal(); - workspace.innerHTML = ''; + const elementsToRemove = workspace.querySelectorAll('.atom, .molecule'); + elementsToRemove.forEach(el => el.remove()); elementsOnDesk = []; + reactorAtoms = []; + reactorMolecules = []; + updateReactorUI(); updateStats(); if (currentLevelIndex < levels.length - 1) { diff --git a/index.html b/index.html index 0b24070..18c993a 100644 --- a/index.html +++ b/index.html @@ -102,7 +102,23 @@ -
+
+ +
+
+

☢️ Reaktor-Box

+
+
+
+ Atome/Moleküle hierher ziehen! +
+
+ + +
+
+
+
@@ -163,6 +179,7 @@ Alkalimetalle Erdalkali Übergangsmetalle + Andere Metalle Halbmetalle Nichtmetalle Halogene diff --git a/style.css b/style.css index a7ffd95..61679b9 100644 --- a/style.css +++ b/style.css @@ -17,6 +17,7 @@ --color-nichtmetall: #74b9ff; --color-halogen: #55efc4; --color-edelgas: #e84393; + --color-metall: #ffeaa7; } * { @@ -757,7 +758,7 @@ body { #pse-grid { display: grid; grid-template-columns: repeat(18, 1fr); - grid-template-rows: repeat(4, 1fr); + grid-template-rows: repeat(7, 1fr); gap: 6px; padding: 10px; background-color: rgba(0, 0, 0, 0.15); @@ -839,6 +840,7 @@ body { .nichtmetall { background-color: var(--color-nichtmetall); color: #333; border-color: rgba(0,0,0,0.15); } .halogen { background-color: var(--color-halogen); color: #333; border-color: rgba(0,0,0,0.15); } .edelgas { background-color: var(--color-edelgas); color: #333; border-color: rgba(0,0,0,0.15); } +.metall { background-color: var(--color-metall); color: #333; border-color: rgba(0,0,0,0.15); } .pse-el.active-el[data-symbol="C"] { color: #fff; @@ -1043,3 +1045,135 @@ body { .hidden { display: none !important; } + +/* REAKTOR-BOX STYLES */ +#reactor-box { + position: absolute; + bottom: 20px; + right: 20px; + width: 320px; + background: rgba(30, 39, 46, 0.95); + border: 2px dashed #3498db; + border-radius: 12px; + padding: 15px; + box-shadow: var(--shadow); + z-index: 50; + display: flex; + flex-direction: column; + gap: 10px; + transition: border-color 0.2s, background-color 0.2s, transform 0.2s; + backdrop-filter: blur(8px); +} + +#reactor-box.drag-over { + border-color: #2ecc71; + background: rgba(46, 204, 113, 0.2); + transform: scale(1.02); +} + +.reactor-header h3 { + font-size: 1.05rem; + color: #fff; + margin: 0; + text-align: center; + letter-spacing: 0.5px; +} + +.reactor-body { + display: flex; + flex-direction: column; + gap: 12px; +} + +#reactor-contents-summary { + background: rgba(0, 0, 0, 0.4); + border: 1px solid var(--border-color); + border-radius: 8px; + padding: 10px; + min-height: 80px; + font-size: 0.85rem; + color: var(--text-muted); + display: flex; + flex-wrap: wrap; + gap: 8px; + align-content: flex-start; +} + +.reactor-buttons { + display: flex; + gap: 10px; +} + +.reactor-btn { + flex: 1; + background: #3498db; + color: white; + border: none; + border-radius: 6px; + padding: 10px 14px; + font-weight: bold; + cursor: pointer; + transition: background 0.15s, transform 0.1s; + font-size: 0.85rem; + box-shadow: 0 2px 4px rgba(0,0,0,0.15); +} + +.reactor-btn:hover { + background: #2980b9; +} + +.reactor-btn:active { + transform: scale(0.95); +} + +.reactor-btn.secondary { + background: #7f8c8d; +} + +.reactor-btn.secondary:hover { + background: #95a5a6; +} + +.reactor-badge { + display: inline-flex; + align-items: center; + padding: 6px 10px; + border-radius: 6px; + font-size: 0.8rem; + font-weight: bold; + cursor: pointer; + user-select: none; + box-shadow: 0 2px 4px rgba(0,0,0,0.2); + border: 1px solid rgba(0,0,0,0.15); + transition: transform 0.1s, box-shadow 0.1s; + background-image: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.15) 0%, rgba(0, 0, 0, 0.1) 100%); +} + +.reactor-badge:hover { + transform: scale(1.05); + box-shadow: 0 4px 8px rgba(0,0,0,0.3); +} + +.atom-badge { + border-radius: 6px; +} + +.molecule-badge { + border-radius: 6px; +} + +.badge-count { + margin-right: 6px; + opacity: 0.75; + background: rgba(0, 0, 0, 0.1); + padding: 1px 4px; + border-radius: 4px; +} + +.empty-text { + width: 100%; + text-align: center; + line-height: 60px; + font-style: italic; + color: #7f8c8d; +}