Advanced Molecular Narrative Engine v3.0

* {
box-sizing: border-box;
margin: 0;
padding: 0;
}

body {
font-family: ‘Courier New’, monospace;
background: linear-gradient(135deg, #0a0a0a, #1a1a2e, #16213e);
color: #e0e0e0;
line-height: 1.4;
min-height: 100vh;
overflow-x: hidden;
}

.container {
max-width: 1600px;
margin: 0 auto;
padding: 20px;
}

.main-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-top: 20px;
}

@media (max-width: 1200px) {
.main-grid {
grid-template-columns: 1fr;
}
}

.panel {
background: rgba(0, 0, 0, 0.9);
padding: 25px;
border-radius: 15px;
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.8);
border: 1px solid rgba(255, 255, 255, 0.1);
}

.chromosome {
background: rgba(0, 30, 0, 0.4);
padding: 15px;
border-radius: 8px;
margin: 10px 0;
border: 1px solid #2e7d32;
position: relative;
transition: all 0.3s ease;
}

.chromosome:hover {
border-color: #4caf50;
box-shadow: 0 0 15px rgba(76, 175, 80, 0.3);
}

.chromosome-label {
position: absolute;
top: -10px;
left: 15px;
background: #0a0a0a;
padding: 0 8px;
color: #4caf50;
font-size: 0.8em;
font-weight: bold;
}

.gene {
background: rgba(76, 175, 80, 0.2);
border: 1px solid #4caf50;
border-radius: 4px;
margin: 5px 0;
padding: 8px;
position: relative;
transition: all 0.3s ease;
cursor: pointer;
}

.gene:hover {
transform: translateX(5px);
}

.gene.active {
border-color: #8bc34a;
background: rgba(139, 195, 74, 0.3);
animation: pulse 2s infinite;
}

.gene.silenced {
border-color: #666;
background: rgba(100, 100, 100, 0.2);
opacity: 0.5;
}

.gene.enhanced {
border-color: #ffeb3b;
background: rgba(255, 235, 59, 0.3);
box-shadow: 0 0 8px rgba(255, 235, 59, 0.3);
animation: glow 2s infinite;
}

@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.8; }
}

@keyframes glow {
0%, 100% { box-shadow: 0 0 8px rgba(255, 235, 59, 0.3); }
50% { box-shadow: 0 0 15px rgba(255, 235, 59, 0.5); }
}

.promoter {
background: #1976d2;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 0.7em;
margin-right: 5px;
}

.enhancer {
background: #ff9800;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 0.7em;
margin-right: 5px;
}

.silencer {
background: #f44336;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 0.7em;
margin-right: 5px;
}

.transcription-unit {
background: rgba(156, 39, 176, 0.2);
border: 1px solid #9c27b0;
border-radius: 6px;
padding: 12px;
margin: 10px 0;
position: relative;
overflow: hidden;
}

.transcription-unit::before {
content: ”;
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(156, 39, 176, 0.3), transparent);
animation: transcribe 3s infinite;
}

@keyframes transcribe {
100% { left: 100%; }
}

.mrna-strand {
background: rgba(156, 39, 176, 0.3);
padding: 10px;
border-radius: 6px;
margin: 8px 0;
font-family: ‘Courier New’, monospace;
letter-spacing: 1px;
font-size: 0.9em;
position: relative;
overflow: hidden;
}

.splice-variant {
background: rgba(233, 30, 99, 0.2);
border: 1px solid #e91e63;
border-radius: 4px;
padding: 8px;
margin: 5px 0;
transition: all 0.3s ease;
}

.splice-variant:hover {
background: rgba(233, 30, 99, 0.3);
}

.protein-complex {
background: rgba(63, 81, 181, 0.2);
border: 1px solid #3f51b5;
border-radius: 6px;
padding: 15px;
margin: 10px 0;
}

.story-output {
background: rgba(255, 255, 255, 0.05);
padding: 25px;
border-radius: 10px;
margin: 20px 0;
font-family: Georgia, serif;
line-height: 1.8;
min-height: 300px;
border-left: 4px solid #4caf50;
font-size: 1.1em;
color: #f0f0f0;
}

.story-output p {
margin-bottom: 15px;
}

.story-output .chapter-title {
font-size: 1.3em;
color: #81c784;
margin: 20px 0 10px 0;
font-weight: bold;
}

.regulatory-network {
background: rgba(0, 0, 50, 0.3);
border: 1px solid #2196f3;
border-radius: 8px;
padding: 15px;
margin: 15px 0;
}

.pathway-diagram {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 10px;
margin: 15px 0;
}

.pathway-step {
background: rgba(255, 255, 255, 0.1);
padding: 10px;
border-radius: 5px;
text-align: center;
border: 1px solid #607d8b;
position: relative;
transition: all 0.3s ease;
}

.pathway-step.active {
border-color: #4caf50;
background: rgba(76, 175, 80, 0.2);
transform: scale(1.05);
}

.controls {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 12px;
margin: 25px 0;
}

.btn {
background: linear-gradient(45deg, #1976d2, #1565c0);
color: white;
border: none;
padding: 12px 20px;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}

.btn::before {
content: ”;
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
transform: translate(-50%, -50%);
transition: width 0.5s, height 0.5s;
}

.btn:hover::before {
width: 300px;
height: 300px;
}

.btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
}

.btn.danger { background: linear-gradient(45deg, #d32f2f, #c62828); }
.btn.success { background: linear-gradient(45deg, #388e3c, #2e7d32); }
.btn.warning { background: linear-gradient(45deg, #f57c00, #ef6c00); }
.btn.special { background: linear-gradient(45deg, #6a1b9a, #4a148c); }

.molecular-log {
background: rgba(0, 0, 0, 0.5);
padding: 15px;
border-radius: 8px;
margin: 15px 0;
max-height: 250px;
overflow-y: auto;
font-size: 0.85em;
border: 1px solid #37474f;
}

.molecular-log::-webkit-scrollbar {
width: 8px;
}

.molecular-log::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.3);
}

.molecular-log::-webkit-scrollbar-thumb {
background: #4caf50;
border-radius: 4px;
}

.log-entry {
padding: 4px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.log-entry.error { color: #f44336; }
.log-entry.success { color: #4caf50; }
.log-entry.warning { color: #ff9800; }

.population-stats {
background: rgba(0, 30, 30, 0.4);
padding: 15px;
border-radius: 8px;
margin: 15px 0;
border: 1px solid #00695c;
}

.stat-row {
display: flex;
justify-content: space-between;
padding: 5px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.stat-row:last-child {
border-bottom: none;
}

.fitness-score {
color: #4caf50;
font-weight: bold;
font-size: 1.2em;
}

.epigenetic-marks {
background: rgba(255, 193, 7, 0.1);
border: 1px solid #ffc107;
border-radius: 4px;
padding: 8px;
margin: 8px 0;
font-size: 0.8em;
}

h1 {
text-align: center;
color: #4caf50;
margin-bottom: 20px;
text-shadow: 0 0 20px rgba(76, 175, 80, 0.5);
font-size: 2.5em;
}

h2 {
color: #81c784;
margin: 20px 0 10px 0;
font-size: 1.2em;
}

.section-title {
color: #81c784;
font-weight: bold;
margin: 25px 0 15px 0;
border-bottom: 2px solid #4caf50;
padding-bottom: 8px;
font-size: 1.1em;
}

.base-pair {
display: inline-block;
margin: 0 1px;
padding: 1px 3px;
border-radius: 2px;
font-size: 0.9em;
font-weight: bold;
}

.base-A { background: #f44336; color: white; }
.base-T { background: #2196f3; color: white; }
.base-G { background: #ff9800; color: white; }
.base-C { background: #4caf50; color: white; }
.base-U { background: #9c27b0; color: white; }

.reading-frame {
margin: 8px 0;
padding: 8px;
background: rgba(255, 255, 255, 0.05);
border-radius: 4px;
border-left: 3px solid #607d8b;
}

.reading-frame.active {
border-left-color: #4caf50;
background: rgba(76, 175, 80, 0.1);
}

.evolution-tree {
background: rgba(0, 0, 0, 0.5);
padding: 20px;
border-radius: 10px;
margin: 20px 0;
min-height: 200px;
border: 1px solid #37474f;
}

.generation-node {
background: rgba(255, 255, 255, 0.1);
padding: 10px;
border-radius: 5px;
margin: 5px;
display: inline-block;
border: 1px solid #4caf50;
}

.save-controls {
position: fixed;
bottom: 20px;
right: 20px;
display: flex;
gap: 10px;
z-index: 1000;
}

.save-btn {
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 10px 20px;
border-radius: 25px;
border: 1px solid #4caf50;
cursor: pointer;
transition: all 0.3s ease;
}

.save-btn:hover {
background: #4caf50;
transform: scale(1.05);
}

/* Loading animation */
.loading {
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 9999;
}

.loading.active {
display: block;
}

.dna-strand {
width: 60px;
height: 60px;
position: relative;
animation: rotate 2s linear infinite;
}

.dna-strand::before,
.dna-strand::after {
content: ”;
position: absolute;
width: 100%;
height: 100%;
border: 3px solid #4caf50;
border-radius: 50%;
opacity: 0.6;
}

.dna-strand::after {
animation: scale 2s linear infinite;
}

@keyframes rotate {
100% { transform: rotate(360deg); }
}

@keyframes scale {
0%, 100% { transform: scale(1); opacity: 0.6; }
50% { transform: scale(1.2); opacity: 0.3; }
}

/* Tooltip */
.tooltip {
position: relative;
display: inline-block;
}

.tooltip .tooltiptext {
visibility: hidden;
width: 200px;
background-color: rgba(0, 0, 0, 0.9);
color: #fff;
text-align: center;
border-radius: 6px;
padding: 8px;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -100px;
opacity: 0;
transition: opacity 0.3s;
font-size: 0.8em;
border: 1px solid #4caf50;
}

.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
}

/* Modal for gene details */
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.8);
}

.modal-content {
background-color: #0a0a0a;
margin: 10% auto;
padding: 20px;
border: 1px solid #4caf50;
width: 80%;
max-width: 600px;
border-radius: 10px;
position: relative;
}

.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
cursor: pointer;
}

.close:hover,
.close:focus {
color: #4caf50;
}

Advanced Molecular Narrative Engine v3.0

A complex genetic storytelling system with multi-chromosome organisms, gene regulation, evolution, and emergent narratives

Organism Genome
Evolutionary Tree

No evolutionary history yet…

Population Statistics
No organism generated

Regulatory Network Activity

No regulatory activity…

Metabolic Pathway

Gene Expression & Alternative Splicing

No genes being expressed…

Narrative Phenotype

Organism not yet expressed…

Generate New Organism
Transcribe Active Genes
Alternative Splicing
Translate & Express
Mutate Genome
Epigenetic Changes
Environmental Pressure
Sexual Reproduction
Horizontal Transfer
Complete Life Cycle
Evolve 10 Generations
Analyze Genome
Molecular Process Log

Save Organism
Load Organism

// Enhanced genetic architecture
const geneTypes = {
structural: [‘protagonist’, ‘antagonist’, ‘mentor’, ‘trickster’, ‘guardian’, ‘herald’, ‘shapeshifter’, ‘shadow’],
regulatory: [’emotion_enhancer’, ‘tension_promoter’, ‘pacing_silencer’, ‘style_modulator’, ‘theme_amplifier’, ‘mood_regulator’],
environmental: [‘time_period’, ‘location’, ‘atmosphere’, ‘weather’, ‘season’, ‘dimension’, ‘realm’],
metabolic: [‘plot_catalyst’, ‘character_development’, ‘theme_synthesis’, ‘narrative_energy’, ‘conflict_resolver’, ‘mystery_builder’]
};

const narrativeThemes = {
heroic: [‘courage’, ‘sacrifice’, ‘honor’, ‘destiny’],
tragic: [‘hubris’, ‘fate’, ‘loss’, ‘redemption’],
romantic: [‘love’, ‘passion’, ‘longing’, ‘union’],
mystery: [‘secrets’, ‘revelation’, ‘deception’, ‘truth’],
cosmic: [‘infinity’, ‘consciousness’, ‘existence’, ‘transcendence’]
};

const geneticCode = {
// Start and stop codons
‘ATG’: { start: true, element: ‘begins_journey’ },
‘TAA’: { stop: true }, ‘TAG’: { stop: true }, ‘TGA’: { stop: true },

// Character actions (A-heavy codons)
‘AAA’: ‘hero_awakens_from_dark_dreams’,
‘AAT’: ‘hero_decides_their_fate’,
‘AAG’: ‘hero_searches_for_truth’,
‘AAC’: ‘hero_discovers_hidden_power’,
‘ATA’: ‘villain_emerges_from_shadows’,
‘ATT’: ‘villain_threatens_the_realm’,
‘ATC’: ‘villain_retreats_to_darkness’,
‘ATG’: ‘journey_begins_at_dawn’,
‘AGA’: ‘allies_gather_in_secret’,
‘AGT’: ‘allies_pledge_their_support’,
‘AGG’: ‘crowd_witnesses_the_event’,
‘AGC’: ‘crowd_flees_in_terror’,
‘ACA’: ‘power_manifests_unexpectedly’,
‘ACT’: ‘magic_activates_ancient_seals’,
‘ACG’: ‘energy_flows_through_leylines’,
‘ACC’: ‘tension_builds_to_breaking’,

// Environmental elements (G-heavy codons)
‘GGG’: ‘within_ancient_forest_depths’,
‘GGA’: ‘inside_hidden_library_halls’,
‘GGT’: ‘among_forgotten_ruins’,
‘GGC’: ‘beneath_sacred_temple_stones’,
‘GAA’: ‘under_starlit_sky’,
‘GAT’: ‘through_deep_cavern_passages’,
‘GAG’: ‘across_mystical_labyrinth’,
‘GAC’: ‘beside_flowing_river’,
‘GTA’: ‘atop_towering_mountains’,
‘GTT’: ‘across_endless_desert_sands’,
‘GTG’: ‘within_misty_valley’,
‘GTC’: ‘upon_floating_city_platforms’,
‘GCA’: ‘at_reality_edge’,
‘GCT’: ‘where_time_nexus_forms’,
‘GCG’: ‘in_chaos_realm’,
‘GCC’: ‘through_void_space’,

// Relationships and emotions (C-heavy codons)
‘CCC’: ‘wise_mentor_shares_ancient_wisdom’,
‘CCA’: ‘enemy_reveals_true_nature’,
‘CCT’: ‘friend_offers_desperate_help’,
‘CCG’: ‘stranger_appears_with_warning’,
‘CAA’: ‘lost_child_cries_for_help’,
‘CAT’: ‘guardian_stands_firm’,
‘CAG’: ‘hero_falls_but_rises’,
‘CAC’: ‘darkness_consumes_the_light’,
‘CTA’: ‘love_blooms_against_odds’,
‘CTT’: ‘betrayal_cuts_deepest’,
‘CTG’: ‘sacrifice_changes_everything’,
‘CTC’: ‘redemption_arrives_at_last’,
‘CGA’: ‘truth_shatters_illusions’,
‘CGT’: ‘secrets_whisper_through_shadows’,
‘CGG’: ‘defiance_echoes_through_halls’,
‘CGC’: ‘mystery_unveils_its_face’,

// Mental states and transformations (T-heavy codons)
‘TTT’: ‘memories_flood_consciousness’,
‘TTA’: ‘realization_dawns_slowly’,
‘TTG’: ‘purpose_crystallizes_clearly’,
‘TTC’: ‘fear_grips_the_heart’,
‘TCT’: ‘hope_rises_like_phoenix’,
‘TCA’: ‘belief_strengthens_resolve’,
‘TCG’: ‘doubt_clouds_judgment’,
‘TCC’: ‘destiny_becomes_clear’,
‘TAT’: ‘visions_reveal_future’,
‘TAC’: ‘imagination_creates_reality’,
‘TGT’: ‘passion_ignites_souls’,
‘TGC’: ‘hatred_poisons_minds’,
‘TGG’: ‘desire_drives_action’,
‘TGA’: ‘transformation_completes_cycle’,

// Additional narrative elements for more variety
‘GGT’: ‘storm_gathers_strength’,
‘CTG’: ‘promise_binds_fate’,
‘GAT’: ‘shadow_lengthens_ominously’,
‘AGT’: ‘warrior_raises_sword’,
‘TCA’: ‘prophecy_unfolds_mysteriously’,
‘ACG’: ‘bridge_spans_worlds’,
‘CGT’: ‘whispers_echo_endlessly’,
‘GTC’: ‘portal_opens_suddenly’,
‘TAG’: ‘chapter_ends_dramatically’,
‘CAG’: ‘choice_defines_destiny’,
‘TGC’: ‘curse_takes_hold’,
‘GAC’: ‘river_changes_course’,
‘ATC’: ‘door_closes_forever’,
‘CGC’: ‘riddle_demands_answer’,
‘TAC’: ‘dream_becomes_reality’,
‘GCT’: ‘time_stops_momentarily’,
‘ACC’: ‘power_corrupts_absolutely’,
‘TCC’: ‘fate_seals_itself’,
‘CTC’: ‘bond_strengthens_eternally’,
‘GCC’: ‘void_gazes_back’
};

// Enhanced Chromosome class
class Chromosome {
constructor(id, length = 200, sequence = null) {
this.id = id;
this.sequence = sequence || this.generateSequence(length);
this.genes = this.identifyGenes();
this.regulatoryElements = this.generateRegulatoryElements();
this.epigeneticMarks = new Map();
this.methylationPattern = new Array(this.sequence.length).fill(false);
this.histoneModifications = new Map();
this.chromosomalRearrangements = [];
}

generateSequence(length) {
const bases = [‘A’, ‘T’, ‘G’, ‘C’];
let sequence = ”;

// Add promoter regions
sequence += ‘TATAAA’; // TATA box

// Generate sequence with structured gene regions
let i = 6;
while (i < length) {
// Increase probability of start codons periodically
if (i % 25 === 0 && Math.random() < 0.8) {
sequence += 'ATG';
i += 3;

// Generate gene body with appropriate length
const geneLength = 30 + Math.floor(Math.random() * 60);
for (let j = 0; j < geneLength && i < length; j++, i++) {
sequence += bases[Math.floor(Math.random() * bases.length)];
}

// Add stop codon
if (i < length – 3) {
const stopCodons = ['TAA', 'TAG', 'TGA'];
sequence += stopCodons[Math.floor(Math.random() * stopCodons.length)];
i += 3;
}
} else {
sequence += bases[Math.floor(Math.random() * bases.length)];
i++;
}
}

return sequence;
}

identifyGenes() {
const genes = [];
let i = 0;
let geneCount = 0;

while (i < this.sequence.length – 6) {
if (this.sequence.substring(i, i + 3) === 'ATG') {
let j = i + 3;
let geneSequence = 'ATG';
let foundStop = false;

// Find stop codon
while (j = 15) {
const geneTypeKeys = Object.keys(geneTypes);
// More intelligent gene type assignment based on sequence characteristics
let geneType;
const gcContent = (geneSequence.match(/[GC]/g) || []).length / geneSequence.length;

if (gcContent > 0.6) {
geneType = ‘environmental’; // GC-rich genes tend to be environmental
} else if (gcContent 60) {
geneType = ‘metabolic’; // Longer genes for complex processes
} else {
geneType = geneTypeKeys[geneCount % geneTypeKeys.length];
}

const geneOptions = geneTypes[geneType];
const geneName = geneOptions[Math.floor(Math.random() * geneOptions.length)];

genes.push({
id: `${this.id}_gene_${geneCount}`,
name: geneName,
type: geneType,
start: i,
end: j + 3,
sequence: geneSequence,
expression: 0.3 + Math.random() * 0.7, // Wider expression range
spliceVariants: this.generateSpliceVariants(geneSequence),
mutations: [],
conservationScore: Math.random()
});

geneCount++;
i = j + 3;
} else {
i++;
}
} else {
i++;
}
}

return genes;
}

generateSpliceVariants(sequence) {
const variants = [{
sequence: sequence,
name: ‘canonical’,
efficiency: 1.0
}];

if (sequence.length > 30) {
// Exon skipping variant
const skipStart = Math.floor(sequence.length * 0.3);
const skipEnd = Math.floor(sequence.length * 0.7);
variants.push({
sequence: sequence.substring(0, skipStart) + sequence.substring(skipEnd),
name: ‘exon_skip’,
efficiency: 0.8
});

// Alternative 3′ site
const altEnd = Math.floor(sequence.length * 0.8);
variants.push({
sequence: sequence.substring(0, altEnd) + ‘TAA’,
name: ‘alt_3prime’,
efficiency: 0.7
});

// Alternative 5′ site
if (sequence.length > 40) {
const altStart = 9;
variants.push({
sequence: ‘ATG’ + sequence.substring(altStart),
name: ‘alt_5prime’,
efficiency: 0.6
});
}
}

return variants;
}

generateRegulatoryElements() {
const elements = [];

for (let i = 0; i < this.genes.length; i++) {
const gene = this.genes[i];

// Core promoter
elements.push({
type: 'promoter',
subtype: 'core',
position: Math.max(0, gene.start – 30),
strength: 0.7 + Math.random() * 0.3,
target: gene.id,
sequence: 'TATAAA'
});

// Proximal promoter elements
if (Math.random() < 0.7) {
elements.push({
type: 'promoter',
subtype: 'proximal',
position: Math.max(0, gene.start – 100),
strength: Math.random(),
target: gene.id,
sequence: 'CAAT'
});
}

// Enhancers (can be far from gene)
if (Math.random() < 0.6) {
elements.push({
type: 'enhancer',
position: Math.floor(Math.random() * this.sequence.length),
strength: Math.random(),
target: gene.id,
distance_effect: true
});
}

// Silencers
if (Math.random() < 0.3) {
elements.push({
type: 'silencer',
position: Math.floor(Math.random() * this.sequence.length),
strength: Math.random(),
target: gene.id
});
}

// Insulators
if (Math.random() < 0.2) {
elements.push({
type: 'insulator',
position: Math.floor(Math.random() * this.sequence.length),
strength: Math.random(),
blocks: [gene.id]
});
}
}

return elements;
}

applyMethylation(position, length) {
for (let i = position; i < Math.min(position + length, this.methylationPattern.length); i++) {
this.methylationPattern[i] = true;
}
}

addHistoneModification(position, modification) {
if (!this.histoneModifications.has(position)) {
this.histoneModifications.set(position, []);
}
this.histoneModifications.get(position).push(modification);
}
}

// Enhanced Organism class
class Organism {
constructor(parentA = null, parentB = null) {
this.id = generateOrganismId();
this.chromosomes = [];

if (parentA && parentB) {
// Sexual reproduction
this.chromosomes = this.recombineChromosomes(parentA, parentB);
this.generation = Math.max(parentA.generation, parentB.generation) + 1;
this.parents = [parentA.id, parentB.id];
} else {
// De novo generation
this.chromosomes = [
new Chromosome('Chr1-Narrative', 300),
new Chromosome('Chr2-Characters', 280),
new Chromosome('Chr3-Environment', 260),
new Chromosome('Chr4-Regulation', 240),
new Chromosome('Chr5-Themes', 220),
new Chromosome('Chr6-Metacognition', 200)
];
this.generation = 1;
this.parents = [];
}

this.transcripts = new Map();
this.proteins = new Map();
this.metabolicState = {
energy: 100,
narrativeCoherence: 0,
characterDepth: 0,
plotComplexity: 0,
thematicResonance: 0
};
this.fitness = 0;
this.environmentalFactors = new Map();
this.phenotype = {
genre: null,
tone: null,
pacing: null,
themes: []
};
this.mutationRate = 0.01;
this.age = 0;
this.reproductiveSuccess = 0;
}

recombineChromosomes(parentA, parentB) {
const newChromosomes = [];

for (let i = 0; i < Math.min(parentA.chromosomes.length, parentB.chromosomes.length); i++) {
const chrA = parentA.chromosomes[i];
const chrB = parentB.chromosomes[i];

// Homologous recombination
const crossoverPoints = this.generateCrossoverPoints(chrA.sequence.length);
let newSequence = '';
let useA = true;

for (let j = 0; j < chrA.sequence.length; j++) {
if (crossoverPoints.includes(j)) {
useA = !useA;
}

if (j {
if (Math.random() < 0.7) {
newChr.epigeneticMarks.set(key, value);
}
});

newChromosomes.push(newChr);
}

return newChromosomes;
}

generateCrossoverPoints(length) {
const points = [];
const numCrossovers = 1 + Math.floor(Math.random() * 3);

for (let i = 0; i a – b);
}

getAllGenes() {
return this.chromosomes.flatMap(chr => chr.genes);
}

getActiveGenes() {
return this.getAllGenes().filter(gene => gene.expression > 0.3);
}

calculateGeneFitness() {
let totalFitness = 0;
let geneCount = 0;
const geneBalance = {};

// Count genes by type
this.chromosomes.forEach(chr => {
chr.genes.forEach(gene => {
if (!geneBalance[gene.type]) {
geneBalance[gene.type] = 0;
}
geneBalance[gene.type]++;

// Base fitness from expression
let geneFitness = gene.expression;

// Conservation bonus
geneFitness *= (1 + gene.conservationScore * 0.5);

// Type-specific bonuses
if (gene.type === ‘structural’) geneFitness *= 1.5;
if (gene.type === ‘regulatory’) geneFitness *= 1.2;

// Penalty for extreme expression
if (gene.expression > 0.9) geneFitness *= 0.8;
if (gene.expression = 4 ? 1.2 : 1.0;

// Metabolic state contribution
const metabolicFitness = (
this.metabolicState.narrativeCoherence * 0.3 +
this.metabolicState.characterDepth * 0.2 +
this.metabolicState.plotComplexity * 0.2 +
this.metabolicState.thematicResonance * 0.3
) / 100;

this.fitness = (totalFitness / geneCount) * balanceBonus * (0.7 + 0.3 * metabolicFitness);

// Age penalty
this.fitness *= Math.pow(0.95, this.age);

return this.fitness;
}

ageOrganism() {
this.age++;
this.metabolicState.energy *= 0.9;

// Accumulate mutations with age
if (Math.random() {
document.getElementById(‘loading’).classList.remove(‘active’);
}, 300);
}

function generateOrganism() {
showLoading();

currentOrganism = new Organism();
currentOrganism.calculateGeneFitness();

// Add to population
population.unshift(currentOrganism);

// Add to evolution history
evolutionHistory.push({
organism: currentOrganism,
timestamp: Date.now(),
event: ‘Generated’
});

displayOrganism();
updateEvolutionTree();
logMolecularEvent(`New organism ${currentOrganism.id} generated with ${currentOrganism.getAllGenes().length} genes`, ‘success’);

hideLoading();
}

function displayOrganism() {
if (!currentOrganism) return;

const container = document.getElementById(‘chromosomeDisplay’);
container.innerHTML = ”;

currentOrganism.chromosomes.forEach((chr, chrIndex) => {
const chrDiv = document.createElement(‘div’);
chrDiv.className = ‘chromosome’;
chrDiv.innerHTML = `

${chr.id}
Length: ${chr.sequence.length}bp |
Genes: ${chr.genes.length} |
GC Content: ${calculateGCContent(chr.sequence)}%
Sequence: ${displaySequence(chr.sequence.substring(0, 60))}…
Click on genes to see details

${chr.genes.map(gene => `

${chr.regulatoryElements.find(e => e.target === gene.id && e.type === ‘promoter’) ?
P‘ : ”}
${chr.regulatoryElements.find(e => e.target === gene.id && e.type === ‘enhancer’) ?
E‘ : ”}
${chr.regulatoryElements.find(e => e.target === gene.id && e.type === ‘silencer’) ?
S‘ : ”}
${gene.name} (${gene.type})

Expression: ${(gene.expression * 100).toFixed(0)}% | Conservation: ${(gene.conservationScore * 100).toFixed(0)}%
${chr.epigeneticMarks.has(gene.name) ?
`

Epigenetic: ${chr.epigeneticMarks.get(gene.name)}

` : ”}

`).join(”)}

`;
container.appendChild(chrDiv);
});

updatePopulationStats();
updateRegulatoryNetwork();
}

function displaySequence(sequence) {
return sequence.split(”).map(base =>
`${base}`
).join(”);
}

function calculateGCContent(sequence) {
const gcCount = (sequence.match(/[GC]/g) || []).length;
return ((gcCount / sequence.length) * 100).toFixed(1);
}

function getGeneClass(gene) {
if (gene.expression > 0.8) return ‘enhanced’;
if (gene.expression > 0.3) return ‘active’;
return ‘silenced’;
}

function showGeneDetails(geneId) {
selectedGeneId = geneId;
const gene = currentOrganism.getAllGenes().find(g => g.id === geneId);
if (!gene) return;

const detailsDiv = document.getElementById(‘geneDetails’);
detailsDiv.innerHTML = `

${gene.name}

Type: ${gene.type}

Expression Level: ${(gene.expression * 100).toFixed(1)}%

Conservation Score: ${(gene.conservationScore * 100).toFixed(1)}%

Position: ${gene.start}-${gene.end} (${gene.end – gene.start}bp)

Sequence:

${displaySequence(gene.sequence)}

Splice Variants: ${gene.spliceVariants.length}

${gene.spliceVariants.map((variant, i) => `

Variant ${i+1} (${variant.name}):
Efficiency: ${(variant.efficiency * 100).toFixed(0)}%
Length: ${variant.sequence.length}bp

`).join(”)}
`;

document.getElementById(‘geneModal’).style.display = ‘block’;
}

function closeModal() {
document.getElementById(‘geneModal’).style.display = ‘none’;
selectedGeneId = null;
}

function updatePopulationStats() {
if (!currentOrganism) return;

const container = document.getElementById(‘populationStats’);
const totalGenes = currentOrganism.getAllGenes().length;
const activeGenes = currentOrganism.getActiveGenes().length;

container.innerHTML = `

Organism ID:
${currentOrganism.id}
Generation:
${currentOrganism.generation}
Total Genes:
${totalGenes}
Active Genes:
${activeGenes}
Expression Rate:
${((activeGenes/totalGenes) * 100).toFixed(1)}%
Fitness Score:
${currentOrganism.fitness.toFixed(3)}
Environment:
${environmentalPressure}
Population Size:
${population.length}
Total Organisms Created:
${evolutionHistory.length}
Age:
${currentOrganism.age} cycles

`;
}

function getEnvironmentColor(env) {
const colors = {
‘high_stress’: ‘#f44336’,
‘low_energy’: ‘#ff9800’,
‘toxic’: ‘#9c27b0’,
‘optimal’: ‘#4caf50’,
‘neutral’: ‘#90a4ae’
};
return colors[env] || ‘#90a4ae’;
}

function updateRegulatoryNetwork() {
if (!currentOrganism) return;

const container = document.getElementById(‘regulatoryNetwork’);
const allElements = currentOrganism.chromosomes.flatMap(chr => chr.regulatoryElements);

// Group elements by type
const grouped = allElements.reduce((acc, element) => {
if (!acc[element.type]) acc[element.type] = [];
acc[element.type].push(element);
return acc;
}, {});

let networkHtml = ”;
Object.entries(grouped).forEach(([type, elements]) => {
networkHtml += `

${type.toUpperCase()}S (${elements.length}):
${elements.slice(0, 5).map(el => {
const strength = (el.strength * 100).toFixed(0);
const gene = currentOrganism.getAllGenes().find(g => g.id === el.target);
return `${gene ? gene.name : ‘unknown’} (${strength}%)`;
}).join(‘ ‘)}
${elements.length > 5 ? `… and ${elements.length – 5} more` : ”}

`;
});

container.innerHTML = networkHtml || ‘

No regulatory elements active

‘;
}

function getElementColor(type) {
const colors = {
‘promoter’: ‘#1976d2’,
‘enhancer’: ‘#ff9800’,
‘silencer’: ‘#f44336’,
‘insulator’: ‘#9c27b0’
};
return colors[type] || ‘#90a4ae’;
}

function updateEvolutionTree() {
const container = document.getElementById(‘evolutionTree’);
const recentHistory = evolutionHistory.slice(-20); // Show last 20 events for performance

if (recentHistory.length === 0) {
container.innerHTML = ‘

No evolutionary history yet…

‘;
return;
}

container.innerHTML = `

Showing ${recentHistory.length} of ${evolutionHistory.length} total events

` + recentHistory.map(entry => {
const time = new Date(entry.timestamp).toLocaleTimeString();
return `

${entry.organism.id}
Gen ${entry.organism.generation} | ${entry.event}
${time}

`;
}).join(”);
}

function transcribeGenes() {
if (!currentOrganism) {
logMolecularEvent(“No organism to transcribe”, ‘error’);
return;
}

showLoading();
currentTranscripts.clear();
let transcribedCount = 0;

currentOrganism.chromosomes.forEach(chr => {
chr.genes.forEach(gene => {
// Calculate transcription rate based on all factors
let transcriptionRate = gene.expression;

// Apply regulatory effects
chr.regulatoryElements.forEach(element => {
if (element.target === gene.id) {
if (element.type === ‘enhancer’) {
const distance = Math.abs(element.position – gene.start);
const distanceEffect = element.distance_effect ? Math.exp(-distance / 1000) : 1;
transcriptionRate *= (1 + element.strength * distanceEffect * 0.5);
} else if (element.type === ‘silencer’) {
transcriptionRate *= (1 – element.strength * 0.3);
} else if (element.type === ‘promoter’) {
transcriptionRate *= (1 + element.strength * 0.2);
}
}
});

// Apply epigenetic effects
if (chr.epigeneticMarks.has(gene.name)) {
const mark = chr.epigeneticMarks.get(gene.name);
if (mark === ‘methylated’) transcriptionRate *= 0.3;
if (mark === ‘acetylated’) transcriptionRate *= 1.8;
if (mark === ‘deacetylated’) transcriptionRate *= 0.6;
}

// Environmental effects
switch (environmentalPressure) {
case ‘high_stress’:
if (gene.type === ‘regulatory’) transcriptionRate *= 1.5;
break;
case ‘low_energy’:
transcriptionRate *= 0.7;
break;
case ‘toxic’:
if (gene.type === ‘metabolic’) transcriptionRate *= 0.5;
break;
case ‘optimal’:
transcriptionRate *= 1.2;
break;
}

transcriptionRate = Math.min(1, Math.max(0, transcriptionRate));

if (transcriptionRate > 0.2) {
// Transcribe to mRNA
const mRNA = gene.sequence.replace(/T/g, ‘U’);
currentTranscripts.set(gene.id, {
sequence: mRNA,
gene: gene,
level: transcriptionRate,
spliceVariants: gene.spliceVariants.map(v => ({
…v,
sequence: v.sequence.replace(/T/g, ‘U’)
}))
});
transcribedCount++;
}
});
});

displayGeneExpression();
updateMetabolicPathway();
logMolecularEvent(`Transcribed ${transcribedCount} genes to mRNA`, ‘success’);
hideLoading();
}

function displayGeneExpression() {
const container = document.getElementById(‘geneExpression’);

if (currentTranscripts.size === 0) {
container.innerHTML = ‘

No genes being expressed…

‘;
return;
}

container.innerHTML = ”;

currentTranscripts.forEach((transcript, geneId) => {
const transcriptDiv = document.createElement(‘div’);
transcriptDiv.className = ‘transcription-unit’;
transcriptDiv.innerHTML = `
${transcript.gene.name} – Expression Level: ${(transcript.level * 100).toFixed(0)}%

mRNA: ${displaySequence(transcript.sequence.substring(0, 45))}…

Length: ${transcript.sequence.length} nucleotides
Splice Variants (${transcript.spliceVariants.length}):
${transcript.spliceVariants.map((variant, i) => `

${variant.name}: ${displaySequence(variant.sequence.substring(0, 30))}…

Efficiency: ${(variant.efficiency * 100).toFixed(0)}%

`).join(”)}

`;
container.appendChild(transcriptDiv);
});
}

function processAlternativeSplicing() {
if (currentTranscripts.size === 0) {
logMolecularEvent(“No transcripts to splice”, ‘error’);
return;
}

showLoading();
let splicingEvents = 0;

currentTranscripts.forEach((transcript, geneId) => {
// Choose splice variant based on environmental conditions and efficiency
let chosenVariant;

if (environmentalPressure === ‘high_stress’ && transcript.spliceVariants.length > 1) {
// Under stress, prefer shorter variants
chosenVariant = transcript.spliceVariants.reduce((shortest, current) =>
current.sequence.length sum + v.efficiency, 0);
let random = Math.random() * totalEfficiency;

for (const variant of transcript.spliceVariants) {
random -= variant.efficiency;
if (random {
const sequence = transcript.finalVariant ? transcript.finalVariant.sequence : transcript.sequence;
const elements = translateSequence(sequence);

const protein = {
gene: transcript.gene,
elements: elements,
level: transcript.level,
modifications: generatePostTranslationalMods(),
interactions: []
};

currentOrganism.proteins.set(geneId, protein);

// Weight elements by expression level
const weightedElements = elements.map(el => ({
element: el,
weight: transcript.level,
type: transcript.gene.type
}));

narrativeElements.push(…weightedElements);
});

// Protein-protein interactions
const proteinArray = Array.from(currentOrganism.proteins.values());
for (let i = 0; i < proteinArray.length; i++) {
for (let j = i + 1; j < proteinArray.length; j++) {
if (Math.random() < 0.3) {
proteinArray[i].interactions.push(proteinArray[j].gene.name);
proteinArray[j].interactions.push(proteinArray[i].gene.name);

proteinComplexes.push({
proteins: [proteinArray[i].gene.name, proteinArray[j].gene.name],
type: 'dimer'
});
}
}
}

// Update metabolic state
updateMetabolicState(narrativeElements);

// Generate narrative
const story = assembleNarrative(narrativeElements, proteinComplexes);
document.getElementById('storyOutput').innerHTML = story;

updateMetabolicPathway();
logMolecularEvent(`Translated ${currentTranscripts.size} transcripts to ${narrativeElements.length} narrative elements`, 'success');
hideLoading();
}

function translateSequence(sequence) {
const elements = [];
const processedCodons = new Set();

// Try all three reading frames
for (let frame = 0; frame < 3; frame++) {
for (let i = frame; i < sequence.length – 2; i += 3) {
const codon = sequence.substring(i, i + 3).replace(/U/g, 'T');

if (processedCodons.has(i + ':' + codon)) continue;
processedCodons.add(i + ':' + codon);

if (geneticCode[codon]) {
if (geneticCode[codon].stop) {
if (frame === 0) break; // Only stop on main frame
} else {
const element = geneticCode[codon].element || geneticCode[codon];
if (typeof element === 'string') {
elements.push(element);
}
}
}
}
}

return elements;
}

function generatePostTranslationalMods() {
const mods = [];
if (Math.random() < 0.3) mods.push('phosphorylated');
if (Math.random() < 0.2) mods.push('glycosylated');
if (Math.random() < 0.15) mods.push('ubiquitinated');
if (Math.random() < 0.1) mods.push('sumoylated');
if (Math.random() {
if (!elementCounts[type]) elementCounts[type] = 0;
elementCounts[type]++;
uniqueElements.add(element);
totalWeight += weight;
});

// Calculate more nuanced metabolic scores
const avgWeight = totalWeight / Math.max(1, elements.length);

// Narrative coherence – based on element diversity and weight distribution
const diversityScore = uniqueElements.size / Math.max(1, elements.length);
currentOrganism.metabolicState.narrativeCoherence = Math.min(100,
diversityScore * 80 + avgWeight * 20
);

// Character depth – based on character-related elements
const characterElements = elements.filter(e =>
e.element.includes(‘hero’) || e.element.includes(‘villain’) ||
e.element.includes(‘mentor’) || e.element.includes(‘character’)
).length;
const characterTransformations = elements.filter(e =>
e.element.includes(‘transform’) || e.element.includes(‘realizes’) ||
e.element.includes(‘awakens’)
).length;
currentOrganism.metabolicState.characterDepth = Math.min(100,
characterElements * 8 + characterTransformations * 12
);

// Plot complexity – based on actions, conflicts, and revelations
const plotElements = elements.filter(e =>
e.element.includes(‘betrayal’) || e.element.includes(‘reveals’) ||
e.element.includes(‘mystery’) || e.element.includes(‘conflict’)
).length;
const actionElements = elements.filter(e =>
e.element.includes(‘strikes’) || e.element.includes(‘searches’) ||
e.element.includes(‘discovers’) || e.element.includes(‘threatens’)
).length;
currentOrganism.metabolicState.plotComplexity = Math.min(100,
plotElements * 15 + actionElements * 5
);

// Thematic resonance – based on emotional and environmental elements
const emotionalElements = elements.filter(e =>
e.element.includes(‘love’) || e.element.includes(‘fear’) ||
e.element.includes(‘hope’) || e.element.includes(‘passion’)
).length;
const environmentalElements = elements.filter(e =>
e.element.includes(‘forest’) || e.element.includes(‘temple’) ||
e.element.includes(‘sky’) || e.element.includes(‘realm’)
).length;
currentOrganism.metabolicState.thematicResonance = Math.min(100,
emotionalElements * 12 + environmentalElements * 8
);

// Ensure minimum values
Object.keys(currentOrganism.metabolicState).forEach(key => {
if (key !== ‘energy’ && currentOrganism.metabolicState[key] < 5) {
currentOrganism.metabolicState[key] = 5;
}
});

// Recalculate fitness
currentOrganism.calculateGeneFitness();
}

function assembleNarrative(elements, proteinComplexes) {
if (elements.length === 0) return "

No narrative elements generated.

“;

// Create a narrative context to track story state
const context = {
usedElements: new Set(),
characters: new Set(),
locations: new Set(),
currentMood: null,
plotPoints: [],
lastAction: null
};

// Sort and deduplicate elements
const uniqueElements = [];
const elementMap = new Map();

elements.forEach(({element, weight, type}) => {
if (!elementMap.has(element)) {
elementMap.set(element, {element, weight, type, count: 1});
} else {
elementMap.get(element).count++;
elementMap.get(element).weight += weight;
}
});

// Convert to array and sort by combined weight
uniqueElements.push(…Array.from(elementMap.values()));
uniqueElements.sort((a, b) => (b.weight * b.count) – (a.weight * a.count));

// Classify elements into narrative categories
const classified = classifyNarrativeElements(uniqueElements);

// Determine narrative arc based on available elements
const narrativeArc = determineNarrativeArc(classified);

// Build the story
let story = ”;

// Title
const chapterTitle = generateDynamicTitle(narrativeArc, classified, currentOrganism.generation);
story += `

${chapterTitle}

`;

// Opening paragraph – establish setting and initial state
story += ‘

‘;
story += generateOpening(classified, context);
story += ‘

‘;

// Development paragraphs – build the narrative
const developmentParagraphs = generateDevelopment(classified, context, narrativeArc);
developmentParagraphs.forEach(para => {
story += `

${para}

`;
});

// Climax paragraph
if (classified.conflicts.length > 0 || classified.transformations.length > 0) {
story += ‘

‘;
story += generateClimax(classified, context);
story += ‘

‘;
}

// Resolution
story += ‘

‘;
story += generateResolution(classified, context, proteinComplexes);
story += ‘

‘;

// Apply environmental effects more subtly
story = applyNuancedEnvironmentalEffects(story);

// Calculate proper metabolic scores based on actual narrative quality
updateNarrativeMetabolism(classified, context);

// Add metadata
story += `

Narrative coherence: ${currentOrganism.metabolicState.narrativeCoherence.toFixed(0)}% |
Character depth: ${currentOrganism.metabolicState.characterDepth.toFixed(0)}% |
Plot complexity: ${currentOrganism.metabolicState.plotComplexity.toFixed(0)}% |
Thematic resonance: ${currentOrganism.metabolicState.thematicResonance.toFixed(0)}%

`;

return story;
}

function classifyNarrativeElements(elements) {
const classified = {
characters: [],
actions: [],
locations: [],
emotions: [],
conflicts: [],
transformations: [],
revelations: [],
relationships: []
};

elements.forEach(item => {
const element = item.element;

if (element.includes(‘hero_’) || element.includes(‘villain_’) || element.includes(‘mentor’) ||
element.includes(‘guardian’) || element.includes(‘stranger’) || element.includes(‘child’)) {
if (element.includes(‘_’) && !element.includes(‘appears’) && !element.includes(‘guides’)) {
const parts = element.split(‘_’);
if (parts.length >= 2) {
classified.characters.push({…item, character: parts[0], action: parts.slice(1).join(‘_’)});
}
} else {
classified.relationships.push(item);
}
}

if (element.includes(‘awakens’) || element.includes(‘strikes’) || element.includes(‘searches’) ||
element.includes(‘discovers’) || element.includes(‘threatens’) || element.includes(‘gathers’)) {
classified.actions.push(item);
}

if (element.includes(‘forest’) || element.includes(‘library’) || element.includes(‘temple’) ||
element.includes(‘mountain’) || element.includes(‘desert’) || element.includes(‘city’) ||
element.includes(‘cavern’) || element.includes(‘valley’)) {
classified.locations.push(item);
}

if (element.includes(‘love’) || element.includes(‘fear’) || element.includes(‘hope’) ||
element.includes(‘hatred’) || element.includes(‘desire’) || element.includes(‘passion’)) {
classified.emotions.push(item);
}

if (element.includes(‘betrayal’) || element.includes(‘conflict’) || element.includes(‘threatens’) ||
element.includes(‘darkness’) || element.includes(‘falls’)) {
classified.conflicts.push(item);
}

if (element.includes(‘transform’) || element.includes(‘realizes’) || element.includes(‘becomes’) ||
element.includes(‘awakens’) || element.includes(‘discovers’)) {
classified.transformations.push(item);
}

if (element.includes(‘reveals’) || element.includes(‘truth’) || element.includes(‘mystery’) ||
element.includes(‘secret’)) {
classified.revelations.push(item);
}
});

return classified;
}

function determineNarrativeArc(classified) {
const scores = {
heroic: classified.characters.filter(c => c.character === ‘hero’).length * 2 +
classified.transformations.length,
tragic: classified.conflicts.length * 2 +
classified.emotions.filter(e => e.element.includes(‘fear’) || e.element.includes(‘hatred’)).length,
mystery: classified.revelations.length * 3 +
classified.locations.filter(l => l.element.includes(‘hidden’) || l.element.includes(‘secret’)).length,
romantic: classified.emotions.filter(e => e.element.includes(‘love’) || e.element.includes(‘passion’)).length * 3,
epic: classified.locations.length + classified.characters.length + classified.conflicts.length
};

let maxScore = 0;
let selectedArc = ‘balanced’;

Object.entries(scores).forEach(([arc, score]) => {
if (score > maxScore) {
maxScore = score;
selectedArc = arc;
}
});

return selectedArc;
}

function generateDynamicTitle(arc, classified, generation) {
const arcTitles = {
heroic: [‘The Rising Dawn’, ‘Awakening Power’, ‘The Hero\’s Call’, ‘Courage Unbound’],
tragic: [‘Shadows Fall’, ‘The Price of Pride’, ‘Darkness Ascending’, ‘Fallen Stars’],
mystery: [‘Veiled Truths’, ‘The Hidden Path’, ‘Secrets Unveiled’, ‘Through the Mist’],
romantic: [‘Hearts Entwined’, ‘Love\’s Journey’, ‘Passion\’s Fire’, ‘United Souls’],
epic: [‘The Great Convergence’, ‘Worlds Collide’, ‘The Final Stand’, ‘Destiny\’s March’],
balanced: [‘The Turning’, ‘Crossroads’, ‘The Awakening’, ‘New Horizons’]
};

const titles = arcTitles[arc] || arcTitles.balanced;
const baseTitle = titles[generation % titles.length];

// Add location flavor if available
if (classified.locations.length > 0) {
const location = classified.locations[0].element;
if (location.includes(‘forest’)) return `${baseTitle} in the Woods`;
if (location.includes(‘mountain’)) return `${baseTitle} Beyond the Peaks`;
if (location.includes(‘temple’)) return `${baseTitle} of the Sacred`;
}

return `Chapter ${generation}: ${baseTitle}`;
}

function generateOpening(classified, context) {
let opening = ”;

// Set location first
if (classified.locations.length > 0) {
const location = selectBestElement(classified.locations, context);
opening += formatLocation(location.element) + ‘, ‘;
context.locations.add(location.element);
context.usedElements.add(location.element);
}

// Introduce initial character or situation
if (classified.characters.length > 0) {
const charAction = selectBestElement(classified.characters, context);
opening += formatCharacterAction(charAction) + ‘. ‘;
context.characters.add(charAction.character);
context.usedElements.add(charAction.element);
context.lastAction = charAction.action;
} else if (classified.emotions.length > 0) {
const emotion = selectBestElement(classified.emotions, context);
opening += ‘The air itself seemed to ‘ + formatElement(emotion.element) + ‘. ‘;
context.currentMood = emotion.element;
context.usedElements.add(emotion.element);
}

// Add atmospheric detail
if (classified.revelations.length > 0 && Math.random() < 0.5) {
const revelation = selectBestElement(classified.revelations, context);
opening += formatElement(revelation.element) + ', casting new light on ancient mysteries. ';
context.usedElements.add(revelation.element);
}

return opening || 'In a world between dreams and waking, the story unfolds. ';
}

function generateDevelopment(classified, context, arc) {
const paragraphs = [];
const targetParagraphs = Math.min(3, Math.floor(classified.actions.length / 2) + 1);

for (let i = 0; i !context.usedElements.has(a.element));
if (unusedActions.length > 0) {
const numActions = Math.min(3, unusedActions.length);
const selectedActions = selectMultipleElements(unusedActions, numActions, context);

if (selectedActions.length > 0) {
paragraph += buildActionSequence(selectedActions, context);
}
}

// Add character interactions
const unusedRelationships = classified.relationships.filter(r => !context.usedElements.has(r.element));
if (unusedRelationships.length > 0 && Math.random() !context.usedElements.has(e.element));
if (unusedEmotions.length > 0 && Math.random() !context.usedElements.has(c.element));
if (unusedConflicts.length > 0) {
const conflict = selectBestElement(unusedConflicts, context);
climax += ‘In a moment of desperate clarity, ‘ + formatElement(conflict.element) + ‘. ‘;
context.usedElements.add(conflict.element);
}

// Add transformation
const unusedTransformations = classified.transformations.filter(t => !context.usedElements.has(t.element));
if (unusedTransformations.length > 0) {
const transformation = selectBestElement(unusedTransformations, context);
climax += formatElement(transformation.element) + ‘, forever changing the course of fate. ‘;
context.usedElements.add(transformation.element);
}

// Final revelation
const unusedRevelations = classified.revelations.filter(r => !context.usedElements.has(r.element));
if (unusedRevelations.length > 0) {
const revelation = selectBestElement(unusedRevelations, context);
climax += ‘And in that instant, ‘ + formatElement(revelation.element) + ‘.’;
context.usedElements.add(revelation.element);
}

return climax || ‘The moment of truth arrived with thunderous intensity.’;
}

function generateResolution(classified, context, proteinComplexes) {
let resolution = ”;

// Resolve character arcs
if (context.characters.size > 0) {
const mainCharacter = Array.from(context.characters)[0];
resolution += `As the dust settled, the ${mainCharacter} `;

const unusedTransformations = classified.transformations.filter(t => !context.usedElements.has(t.element));
if (unusedTransformations.length > 0) {
const transformation = selectBestElement(unusedTransformations, context);
resolution += formatElement(transformation.element) + ‘. ‘;
} else {
resolution += ‘stood changed by all that had transpired. ‘;
}
}

// Add protein complex interactions as metaphor
if (proteinComplexes.length > 0) {
const complex = proteinComplexes[0];
resolution += `Like ${complex.proteins[0]} binding with ${complex.proteins[1]}, `;
resolution += ‘disparate elements united into something greater. ‘;
}

// Final mood
const allEmotions = classified.emotions.filter(e => !context.usedElements.has(e.element));
if (allEmotions.length > 0) {
const finalMood = selectBestElement(allEmotions, context);
resolution += ‘The story ends with ‘ + formatElement(finalMood.element) + ‘, ‘;
resolution += ‘echoing through eternity.’;
} else {
resolution += ‘And so the tale reaches its inevitable conclusion, ‘;
resolution += ‘leaving echoes that will resonate through time.’;
}

return resolution;
}

function selectBestElement(elements, context) {
// Avoid repetition by filtering out used elements
const available = elements.filter(e => !context.usedElements.has(e.element));
if (available.length === 0) return elements[0]; // Fallback

// Weight by expression level and novelty
return available.reduce((best, current) =>
current.weight > best.weight ? current : best
);
}

function selectMultipleElements(elements, count, context) {
const selected = [];
const available = […elements];

for (let i = 0; i 0; i++) {
const element = selectBestElement(available, context);
selected.push(element);
context.usedElements.add(element.element);
available.splice(available.indexOf(element), 1);
}

return selected;
}

function buildActionSequence(actions, context) {
if (actions.length === 0) return ”;

let sequence = formatElement(actions[0].element);

if (actions.length === 1) {
return sequence + ‘.’;
} else if (actions.length === 2) {
return sequence + ‘, and then ‘ + formatElement(actions[1].element) + ‘.’;
} else {
for (let i = 1; i c.toLowerCase());
}

function updateNarrativeMetabolism(classified, context) {
if (!currentOrganism) return;

// Reset scores
let coherence = 0;
let depth = 0;
let complexity = 0;
let resonance = 0;

// Narrative coherence – based on logical flow and used elements
const totalElements = Object.values(classified).flat().length;
const usedRatio = context.usedElements.size / Math.max(1, totalElements);
coherence = Math.min(100, usedRatio * 100 * 1.2);

// Character depth – based on character actions and transformations
const characterActions = classified.characters.length;
const transformations = classified.transformations.length;
depth = Math.min(100, (characterActions * 15 + transformations * 20));

// Plot complexity – based on conflicts, revelations, and relationships
const conflicts = classified.conflicts.length;
const revelations = classified.revelations.length;
const relationships = classified.relationships.length;
complexity = Math.min(100, (conflicts * 20 + revelations * 15 + relationships * 10));

// Thematic resonance – based on emotions and locations
const emotions = classified.emotions.length;
const locations = classified.locations.length;
resonance = Math.min(100, (emotions * 20 + locations * 10));

// Update organism’s metabolic state
currentOrganism.metabolicState.narrativeCoherence = coherence;
currentOrganism.metabolicState.characterDepth = depth;
currentOrganism.metabolicState.plotComplexity = complexity;
currentOrganism.metabolicState.thematicResonance = resonance;
}

function applyNuancedEnvironmentalEffects(narrative) {
switch (environmentalPressure) {
case ‘high_stress’:
return narrative
.replace(/stood/g, ‘trembled’)
.replace(/walked/g, ‘rushed’)
.replace(/said/g, ‘shouted’)
.replace(/moment/g, ‘instant’)
.replace(/slowly/g, ‘frantically’);
case ‘low_energy’:
return narrative
.replace(/rushed/g, ‘crawled’)
.replace(/exploded/g, ‘faded’)
.replace(/shouted/g, ‘whispered’)
.replace(/blazing/g, ‘dim’)
.replace(/powerful/g, ‘weak’);
case ‘toxic’:
return narrative
.replace(/pure/g, ‘corrupted’)
.replace(/clear/g, ‘murky’)
.replace(/bright/g, ‘sickly’)
.replace(/healing/g, ‘poisoning’)
.replace(/growth/g, ‘decay’);
case ‘optimal’:
return narrative
.replace(/struggled/g, ‘flourished’)
.replace(/darkness/g, ‘radiance’)
.replace(/fear/g, ‘confidence’)
.replace(/weak/g, ‘strong’)
.replace(/failed/g, ‘succeeded’);
default:
return narrative;
}
}

function updateMetabolicPathway() {
const container = document.getElementById(‘pathwayDiagram’);
container.innerHTML = ”;

const pathwaySteps = [
{ name: ‘Transcription’, active: currentTranscripts.size > 0 },
{ name: ‘Splicing’, active: Array.from(currentTranscripts.values()).some(t => t.finalVariant) },
{ name: ‘Translation’, active: currentOrganism && currentOrganism.proteins.size > 0 },
{ name: ‘Folding’, active: currentOrganism && currentOrganism.proteins.size > 0 },
{ name: ‘Assembly’, active: false }, // Would need protein complex detection
{ name: ‘Expression’, active: document.getElementById(‘storyOutput’).innerHTML.includes(‘Chapter’) }
];

pathwaySteps.forEach((step, index) => {
const stepDiv = document.createElement(‘div’);
stepDiv.className = `pathway-step ${step.active ? ‘active’ : ”}`;

const efficiency = step.active ? 50 + Math.floor(Math.random() * 50) : 0;

stepDiv.innerHTML = `
${step.name}
${efficiency}% efficiency
${step.active ? ‘
✓ Active‘ : ”}
`;
container.appendChild(stepDiv);
});
}

function introduceMutations() {
if (!currentOrganism) {
logMolecularEvent(“No organism to mutate”, ‘error’);
return;
}

showLoading();
let mutationCount = 0;
const mutationTypes = [];

currentOrganism.chromosomes.forEach(chr => {
// Point mutations
const numPointMutations = Math.floor(Math.random() * 5);
for (let i = 0; i < numPointMutations; i++) {
if (Math.random() b !== oldBase)[Math.floor(Math.random() * 3)];

chr.sequence = chr.sequence.substring(0, position) + newBase +
chr.sequence.substring(position + 1);

mutationCount++;
mutationTypes.push(`Point mutation: ${oldBase}→${newBase} at ${chr.id}:${position}`);
}
}

// Insertions/Deletions
if (Math.random() < 0.1) {
const position = Math.floor(Math.random() * chr.sequence.length);
if (Math.random() 100) {
const deletedBase = chr.sequence[position];
chr.sequence = chr.sequence.substring(0, position) +
chr.sequence.substring(position + 1);
mutationTypes.push(`Deletion: -${deletedBase} at ${chr.id}:${position}`);
}
}
mutationCount++;
}

// Re-identify genes after sequence mutations
chr.genes = chr.identifyGenes();

// Expression mutations
chr.genes.forEach(gene => {
if (Math.random() 0.1) {
mutationTypes.push(`Expression change in ${gene.name}: ${(change > 0 ? ‘+’ : ”)}${(change * 100).toFixed(0)}%`);
mutationCount++;
}
}
});

// Regulatory element mutations
chr.regulatoryElements.forEach(element => {
if (Math.random() {
logMolecularEvent(mut, ‘warning’);
});
if (mutationTypes.length > 5) {
logMolecularEvent(`… and ${mutationTypes.length – 5} more mutations`, ‘warning’);
}

logMolecularEvent(`Introduced ${mutationCount} mutations total`, ‘success’);
hideLoading();
}

function modifyEpigenetics() {
if (!currentOrganism) {
logMolecularEvent(“No organism for epigenetic modification”, ‘error’);
return;
}

showLoading();
let modificationsCount = 0;
const modifications = [];

currentOrganism.chromosomes.forEach(chr => {
chr.genes.forEach(gene => {
if (Math.random() < 0.3) {
const marks = ['methylated', 'acetylated', 'deacetylated'];
const mark = marks[Math.floor(Math.random() * marks.length)];
const previousMark = chr.epigeneticMarks.get(gene.name);

chr.epigeneticMarks.set(gene.name, mark);
modificationsCount++;

modifications.push(`${gene.name}: ${previousMark || 'none'} → ${mark}`);

// Add histone modifications
if (Math.random() < 0.5) {
const histoneMods = ['H3K4me3', 'H3K9me3', 'H3K27me3', 'H3K36me3'];
const mod = histoneMods[Math.floor(Math.random() * histoneMods.length)];
chr.addHistoneModification(gene.start, mod);
}
}
});

// DNA methylation patterns
if (Math.random() {
logMolecularEvent(`Epigenetic: ${mod}`, ‘success’);
});

logMolecularEvent(`Applied ${modificationsCount} epigenetic modifications`, ‘success’);
hideLoading();
}

function simulateEnvironment() {
const environments = [‘high_stress’, ‘low_energy’, ‘toxic’, ‘optimal’, ‘neutral’];
const previousEnvironment = environmentalPressure;
environmentalPressure = environments[Math.floor(Math.random() * environments.length)];

logMolecularEvent(`Environmental shift: ${previousEnvironment} → ${environmentalPressure}`, ‘warning’);

// Environmental effects on gene expression
if (currentOrganism) {
currentOrganism.chromosomes.forEach(chr => {
chr.genes.forEach(gene => {
let expressionChange = 0;

switch (environmentalPressure) {
case ‘high_stress’:
if (gene.type === ‘regulatory’) expressionChange = 0.3;
if (gene.type === ‘metabolic’) expressionChange = 0.2;
break;
case ‘low_energy’:
expressionChange = -0.2;
break;
case ‘toxic’:
if (gene.type === ‘structural’) expressionChange = -0.4;
if (gene.type === ‘metabolic’) expressionChange = -0.3;
break;
case ‘optimal’:
expressionChange = 0.2;
break;
}

gene.expression = Math.max(0, Math.min(1, gene.expression + expressionChange));
});
});

currentOrganism.calculateGeneFitness();
displayOrganism();
}

updatePopulationStats();
}

function sexualReproduction() {
if (!currentOrganism) {
logMolecularEvent(“No organism for reproduction”, ‘error’);
return;
}

if (population.length b.fitness – a.fitness);
const parent1 = currentOrganism;
const parent2 = sortedPop.find(org => org.id !== parent1.id) || sortedPop[1];

logMolecularEvent(`Sexual reproduction: ${parent1.id} × ${parent2.id}`, ‘success’);

// Create offspring
const offspring = new Organism(parent1, parent2);

// Apply some mutations to offspring
offspring.mutationRate = (parent1.mutationRate + parent2.mutationRate) / 2 *
(0.8 + Math.random() * 0.4);

// Small chance of beneficial mutation
if (Math.random() {
const luckyGene = chr.genes[Math.floor(Math.random() * chr.genes.length)];
if (luckyGene) {
luckyGene.expression = Math.min(1, luckyGene.expression * 1.5);
logMolecularEvent(`Beneficial mutation in offspring: ${luckyGene.name} enhanced`, ‘success’);
}
});
}

offspring.calculateGeneFitness();

// Update reproductive success
parent1.reproductiveSuccess++;
parent2.reproductiveSuccess++;

// Add to population
population.unshift(offspring);

// Add to evolution history
evolutionHistory.push({
organism: offspring,
timestamp: Date.now(),
event: `Born from ${parent1.id} × ${parent2.id}`
});

currentOrganism = offspring;
displayOrganism();
updateEvolutionTree();

logMolecularEvent(`Offspring ${offspring.id} created (Generation ${offspring.generation}, Fitness: ${offspring.fitness.toFixed(3)})`, ‘success’);
hideLoading();
}

function horizontalGeneTransfer() {
if (!currentOrganism || population.length org.id !== currentOrganism.id);
if (!donor) {
logMolecularEvent(“No suitable donor for horizontal transfer”, ‘error’);
hideLoading();
return;
}

// Select random gene from donor
const donorGenes = donor.getAllGenes();
const transferredGene = donorGenes[Math.floor(Math.random() * donorGenes.length)];

// Select random chromosome in recipient
const targetChromosome = currentOrganism.chromosomes[
Math.floor(Math.random() * currentOrganism.chromosomes.length)
];

// Insert gene sequence
const insertionPoint = Math.floor(Math.random() * targetChromosome.sequence.length);
targetChromosome.sequence =
targetChromosome.sequence.substring(0, insertionPoint) +
transferredGene.sequence +
targetChromosome.sequence.substring(insertionPoint);

// Re-identify genes
targetChromosome.genes = targetChromosome.identifyGenes();

// Recalculate fitness
currentOrganism.calculateGeneFitness();

logMolecularEvent(`Horizontal transfer: ${transferredGene.name} from ${donor.id} → ${currentOrganism.id}`, ‘success’);

displayOrganism();
hideLoading();
}

function runEvolution(generations) {
if (!currentOrganism) {
generateOrganism();
}

showLoading();
logMolecularEvent(`Starting evolution simulation for ${generations} generations…`, ‘success’);

let generationCount = 0;

function evolveGeneration() {
if (generationCount >= generations) {
// Final summary
const fittest = population.reduce((best, current) =>
current.fitness > best.fitness ? current : best
);

logMolecularEvent(`Evolution complete! Fittest organism: ${fittest.id} (Fitness: ${fittest.fitness.toFixed(3)})`, ‘success’);

currentOrganism = fittest;
displayOrganism();
updateEvolutionTree();
hideLoading();
return;
}

// Simulate one generation
simulateEnvironment();

// Reproduction for top organisms
const breedingPop = […population]
.sort((a, b) => b.fitness – a.fitness)
.slice(0, Math.min(population.length, Math.ceil(population.length / 2)));

// Limit breeding pairs for performance
const maxBreedingPairs = Math.min(10, Math.floor(breedingPop.length / 2));

for (let i = 0; i < maxBreedingPairs * 2 && i {
for (let j = 0; j < 3; j++) {
if (Math.random() 100) {
// Only cull if population gets very large to maintain performance
population.sort((a, b) => b.fitness – a.fitness);
population = population.slice(0, Math.floor(population.length * 0.8)); // Keep top 80%
}

// Age all organisms
population.forEach(org => org.ageOrganism());

generationCount++;
logMolecularEvent(`Generation ${generationCount}/${generations} complete. Population fitness: ${
(population.reduce((sum, org) => sum + org.fitness, 0) / population.length).toFixed(3)
}`, ‘success’);

// Continue evolution
setTimeout(evolveGeneration, 100);
}

evolveGeneration();
}

function analyzeGenome() {
if (!currentOrganism) {
logMolecularEvent(“No organism to analyze”, ‘error’);
return;
}

showLoading();

const analysis = {
totalGenes: currentOrganism.getAllGenes().length,
activeGenes: currentOrganism.getActiveGenes().length,
genomeSize: currentOrganism.chromosomes.reduce((sum, chr) => sum + chr.sequence.length, 0),
geneTypes: {},
averageGeneLength: 0,
gcContent: 0,
epigeneticMarks: 0,
regulatoryElements: 0
};

// Gene type distribution
currentOrganism.getAllGenes().forEach(gene => {
if (!analysis.geneTypes[gene.type]) {
analysis.geneTypes[gene.type] = 0;
}
analysis.geneTypes[gene.type]++;
analysis.averageGeneLength += gene.sequence.length;
});

analysis.averageGeneLength /= analysis.totalGenes;

// Calculate genome-wide GC content
let totalGC = 0;
let totalBases = 0;
currentOrganism.chromosomes.forEach(chr => {
const gc = (chr.sequence.match(/[GC]/g) || []).length;
totalGC += gc;
totalBases += chr.sequence.length;

// Count epigenetic marks
analysis.epigeneticMarks += chr.epigeneticMarks.size;

// Count regulatory elements
analysis.regulatoryElements += chr.regulatoryElements.length;
});

analysis.gcContent = (totalGC / totalBases * 100).toFixed(1);

// Generate analysis report
const reportHtml = `

Genome Analysis Report

Organism ID: ${currentOrganism.id}

Generation: ${currentOrganism.generation}

Fitness Score: ${currentOrganism.fitness.toFixed(3)}

Genome Statistics

Genome Size: ${analysis.genomeSize} bp

Total Genes: ${analysis.totalGenes}

Active Genes: ${analysis.activeGenes} (${(analysis.activeGenes/analysis.totalGenes*100).toFixed(1)}%)

Average Gene Length: ${analysis.averageGeneLength.toFixed(0)} bp

GC Content: ${analysis.gcContent}%

Gene Type Distribution

${Object.entries(analysis.geneTypes).map(([type, count]) =>
`

${type}: ${count} genes (${(count/analysis.totalGenes*100).toFixed(1)}%)

`
).join(”)}

Regulatory Features

Regulatory Elements: ${analysis.regulatoryElements}

Epigenetic Marks: ${analysis.epigeneticMarks}

Metabolic State

Narrative Coherence: ${currentOrganism.metabolicState.narrativeCoherence.toFixed(0)}%

Character Depth: ${currentOrganism.metabolicState.characterDepth.toFixed(0)}%

Plot Complexity: ${currentOrganism.metabolicState.plotComplexity.toFixed(0)}%

Thematic Resonance: ${currentOrganism.metabolicState.thematicResonance.toFixed(0)}%

`;

// Show analysis in modal
document.getElementById(‘geneDetails’).innerHTML = reportHtml;
document.getElementById(‘geneModal’).style.display = ‘block’;

logMolecularEvent(“Genome analysis complete”, ‘success’);
hideLoading();
}

function fullLifeCycle() {
if (!currentOrganism) {
generateOrganism();
}

logMolecularEvent(“Initiating complete life cycle…”, ‘success’);

const steps = [
{ fn: transcribeGenes, delay: 300 },
{ fn: processAlternativeSplicing, delay: 600 },
{ fn: expressProteins, delay: 900 },
{ fn: introduceMutations, delay: 1200 },
{ fn: simulateEnvironment, delay: 1500 },
{ fn: () => {
if (population.length >= 2 && Math.random() < 0.7) {
sexualReproduction();
} else if (Math.random() {
setTimeout(step.fn, step.delay);
});

setTimeout(() => {
logMolecularEvent(“Life cycle complete!”, ‘success’);
}, 2100);
}

function saveOrganism() {
if (!currentOrganism) {
logMolecularEvent(“No organism to save”, ‘error’);
return;
}

const saveData = {
organism: {
id: currentOrganism.id,
generation: currentOrganism.generation,
chromosomes: currentOrganism.chromosomes.map(chr => ({
id: chr.id,
sequence: chr.sequence,
epigeneticMarks: Array.from(chr.epigeneticMarks.entries())
})),
fitness: currentOrganism.fitness,
metabolicState: currentOrganism.metabolicState,
mutationRate: currentOrganism.mutationRate,
age: currentOrganism.age
},
environment: environmentalPressure,
timestamp: Date.now()
};

const dataStr = JSON.stringify(saveData);
const dataBlob = new Blob([dataStr], {type: ‘application/json’});
const url = URL.createObjectURL(dataBlob);
const link = document.createElement(‘a’);
link.href = url;
link.download = `organism_${currentOrganism.id}_gen${currentOrganism.generation}.json`;
link.click();

logMolecularEvent(`Organism ${currentOrganism.id} saved to file`, ‘success’);
}

function loadOrganism() {
const input = document.createElement(‘input’);
input.type = ‘file’;
input.accept = ‘.json’;

input.onchange = (e) => {
const file = e.target.files[0];
if (!file) return;

const reader = new FileReader();
reader.onload = (event) => {
try {
const saveData = JSON.parse(event.target.result);

// Reconstruct organism
currentOrganism = new Organism();
currentOrganism.id = saveData.organism.id;
currentOrganism.generation = saveData.organism.generation;
currentOrganism.fitness = saveData.organism.fitness;
currentOrganism.metabolicState = saveData.organism.metabolicState;
currentOrganism.mutationRate = saveData.organism.mutationRate;
currentOrganism.age = saveData.organism.age;

// Reconstruct chromosomes
currentOrganism.chromosomes = saveData.organism.chromosomes.map(chrData => {
const chr = new Chromosome(chrData.id, 0, chrData.sequence);
chrData.epigeneticMarks.forEach(([key, value]) => {
chr.epigeneticMarks.set(key, value);
});
return chr;
});

environmentalPressure = saveData.environment;

// Add to population
population.unshift(currentOrganism);

displayOrganism();
updateEvolutionTree();

logMolecularEvent(`Organism ${currentOrganism.id} loaded successfully`, ‘success’);
} catch (error) {
logMolecularEvent(`Error loading organism: ${error.message}`, ‘error’);
}
};

reader.readAsText(file);
};

input.click();
}

function logMolecularEvent(message, type = ‘info’) {
const log = document.getElementById(‘molecularLog’);
const time = new Date().toLocaleTimeString();
const entry = document.createElement(‘div’);
entry.className = `log-entry ${type}`;
entry.innerHTML = `[${time}] ${message}`;
log.appendChild(entry);
log.scrollTop = log.scrollHeight;

// Keep log size manageable
while (log.children.length > 100) {
log.removeChild(log.firstChild);
}
}

// Event listeners
window.onclick = function(event) {
if (event.target == document.getElementById(‘geneModal’)) {
closeModal();
}
}

// Keyboard shortcuts
document.addEventListener(‘keydown’, (e) => {
if (e.ctrlKey || e.metaKey) {
switch (e.key) {
case ‘g’:
e.preventDefault();
generateOrganism();
break;
case ‘t’:
e.preventDefault();
transcribeGenes();
break;
case ‘e’:
e.preventDefault();
expressProteins();
break;
case ‘m’:
e.preventDefault();
introduceMutations();
break;
case ‘s’:
e.preventDefault();
saveOrganism();
break;
case ‘l’:
e.preventDefault();
loadOrganism();
break;
}
}
});

// Initialize
window.onload = function() {
logMolecularEvent(“Advanced Molecular Narrative Engine v3.0 initialized”, ‘success’);
logMolecularEvent(“Ready for organism generation and genetic processes”, ‘info’);
logMolecularEvent(“Keyboard shortcuts: Ctrl+G (Generate), Ctrl+T (Transcribe), Ctrl+E (Express), Ctrl+M (Mutate)”, ‘info’);
logMolecularEvent(“Population size is unlimited – large populations may impact performance”, ‘warning’);

// Display initial empty state
updatePopulationStats();
updateRegulatoryNetwork();
updateEvolutionTree();
updateMetabolicPathway();
};