pre-mortem 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
@@ -0,0 +1,382 @@
1
+ (function(g,n){typeof exports=="object"&&typeof module<"u"?n(exports,require("matter-js")):typeof define=="function"&&define.amd?define(["exports","matter-js"],n):(g=typeof globalThis<"u"?globalThis:g||self,n(g.PreMortem={},g.Matter))})(this,function(g,n){"use strict";var E=Object.defineProperty;var C=(g,n,d)=>n in g?E(g,n,{enumerable:!0,configurable:!0,writable:!0,value:d}):g[n]=d;var l=(g,n,d)=>C(g,typeof n!="symbol"?n+"":n,d);var d=(c=>(c.BOOTSTRAP="bootstrap",c.VC="vc",c.SLACKER="slacker",c.CONTROL_FREAK="control_freak",c.PRIMA_DONNA="prima_donna",c.QUIET_QUITTER="quiet_quitter",c.SLACK_SPAMMER="slack_spammer",c))(d||{});const f={bootstrap:{w:132,h:44,color:"#555555",density:.005,friction:.8,restitution:0,label:"Refactoring",possibleLabels:["Refactoring","Unit Tests","Bug Fixes","User Support","Documentation","Security Audit","Compliance","Cleanup","Optimization","CI/CD Pipeline","Code Review","DB Tuning","API Design","Accessibility","Localization","Error Logs","Backups","Legacy Code","Hiring","Customer Love","Bossware","YAML Hell","DNS Propagation","Regex","npm audit","GDPR / SOC2","Migration","Certificate Expiry","On-Call","Technical Debt","Works on my machine","Yak Shaving"]},vc:{w:120,h:40,color:"#FF00FF",density:5e-4,friction:.3,restitution:.6,label:"AI Blockchain",possibleLabels:["GenAI","Blockchain","Web3","Metaverse","NFTs","Viral Growth","Pivot","Synergy","Disruption","Thought Leader","Influencers","Hyper-Scale","Quantum","Big Data","Growth Hack","Paradigm Shift","10x Engineer","Visionary","Series B Pitch","Exit Strategy","Vibe Coding","Founder Mode","Prompt Engineering","AGI","AI Wrapper","Unlimited PTO","Radical Candor","Community Led","Pre-Revenue","Fractional CxO"]},slacker:{w:64,h:64,color:"#FFFFFF",density:.01,friction:1,restitution:.1,label:"The Slacker",possibleLabels:["The Slacker"]},control_freak:{w:64,h:64,color:"#FF0000",density:.012,friction:.5,restitution:.2,label:"Control Freak",possibleLabels:["Control Freak"]},prima_donna:{w:56,h:56,color:"#FFFF00",density:.008,friction:.1,restitution:1.2,label:"Prima Donna",possibleLabels:["Prima Donna"]},quiet_quitter:{w:48,h:48,color:"#00FFFF",density:.005,friction:.01,restitution:.9,label:"Quiet Quitter",possibleLabels:["Quiet Quitter"]},slack_spammer:{w:60,h:60,color:"#00FF00",density:.01,friction:.4,restitution:.4,label:"Slack Spammer",possibleLabels:["Slack Spammer"]}},y=c=>{const t=f[c].possibleLabels||[];return t[Math.floor(Math.random()*t.length)]},v=(c,t,e)=>{const i=f[e],s=y(e),a={density:i.density,friction:i.friction,restitution:i.restitution,render:{fillStyle:i.color,strokeStyle:"#000",lineWidth:2},label:s};if(e==="vc"){const o=i.w,h=i.h,p=Math.random()*15,u=Math.random()*15,r=(Math.random()-.5)*20,m=[{x:0+r,y:p},{x:o+r,y:u},{x:o,y:h},{x:0,y:h}];return n.Bodies.fromVertices(c,t,[m],a)}else if(e==="slacker"||e==="control_freak"||e==="prima_donna"||e==="quiet_quitter"||e==="slack_spammer"){const h={...a,render:{sprite:{texture:{slacker:"./slacker.png",control_freak:"./control-freak.png",prima_donna:"./prima-donna.png",quiet_quitter:"./quet-quitter.png",slack_spammer:"./slack-spammer.png"}[e],xScale:i.w/512*2,yScale:i.h/512*2},lineWidth:3,strokeStyle:"#ffffff"}};return e==="quiet_quitter"?n.Bodies.circle(c,t,i.w/2,h):e==="control_freak"?n.Bodies.trapezoid(c,t,i.w,i.h,.5,h):e==="prima_donna"?n.Bodies.polygon(c,t,5,i.w/2,h):e==="slack_spammer"?n.Bodies.polygon(c,t,6,i.w/2,h):n.Bodies.rectangle(c,t,i.w,i.h,h)}else return n.Bodies.rectangle(c,t,i.w,i.h,a)};class w{constructor(t){l(this,"runway");l(this,"valuation",0);l(this,"stage");l(this,"status","playing");l(this,"lastPenaltyReason","");l(this,"config");l(this,"currentStageIndex",0);l(this,"listeners",[]);if(this.config=t,this.runway=t.initialRunway,!this.config.stages||this.config.stages.length===0)throw new Error("Game must have at least one stage defined.");this.config.stages.sort((e,i)=>e.threshold-i.threshold),this.currentStageIndex=0,this.stage=this.config.stages[0].name,this.checkStage()}setPaused(t){t?this.status==="playing"&&(this.status="paused"):this.status==="paused"&&(this.status="playing"),this.notify()}togglePause(){this.setPaused(this.status==="playing")}tick(t){if(this.status!=="playing")return;const e=Math.min(t,.1),i=this.getDynamicBurnRate();this.runway-=i*e,this.runway<=0&&(this.runway=0,this.status="bankrupt");const s=this.config.stages[this.config.stages.length-1];this.valuation>=s.threshold&&this.status==="playing"&&(this.status="exited"),this.checkStage(),this.notify()}getDynamicBurnRate(){return this.config.stages[this.currentStageIndex].burnRate}addValuation(t){this.valuation+=t,this.checkStage(),this.notify()}spendMoney(t){this.runway-=t,this.notify()}addMoney(t){this.runway+=t,this.notify()}setCollapsed(){this.status==="playing"&&(this.status="collapsed",this.notify())}getNextStageThreshold(){return this.currentStageIndex<this.config.stages.length-1?this.config.stages[this.currentStageIndex+1].threshold:this.config.stages[this.config.stages.length-1].threshold}penalty(t,e){this.runway-=t,this.lastPenaltyReason=e,this.runway<0&&(this.runway=0,this.status="bankrupt"),this.notify("penalty")}checkStage(){let t=0;for(let e=0;e<this.config.stages.length&&this.valuation>=this.config.stages[e].threshold;e++)t=e;if(t!==this.currentStageIndex){if(t>this.currentStageIndex){const e=this.config.stages[t].fundingBonus||0;e>0&&(this.addMoney(e),this.notify("funding:"+e))}this.currentStageIndex=t,this.stage=this.config.stages[t].name}}subscribe(t){this.listeners.push(t)}notify(t){this.listeners.forEach(e=>e(t))}isPlaying(){return this.status==="playing"}isBankrupt(){return this.status==="bankrupt"}}class b{constructor(t,e={}){l(this,"engine");l(this,"render");l(this,"runner");l(this,"container");l(this,"width");l(this,"height");l(this,"mouseConstraint");l(this,"currentQuote",null);l(this,"chaosTimer",1e4);l(this,"chaosInterval",9e4);l(this,"onCrisis");l(this,"gameState");l(this,"spawnVertical",!1);this.container=t,this.width=e.width||t.clientWidth||800,this.height=e.height||t.clientHeight||600,this.onCrisis=e.onCrisis,this.chaosInterval=e.chaosInterval||9e4,this.chaosTimer=e.chaosInterval?e.chaosInterval:1e4;const i=[{name:"Seed Round",threshold:0,burnRate:2e3},{name:"Series A",threshold:1e8,burnRate:1e4,fundingBonus:25e4},{name:"Series B",threshold:25e7,burnRate:25e3,fundingBonus:5e5},{name:"Series C",threshold:5e8,burnRate:5e4,fundingBonus:1e6},{name:"Series D",threshold:7e8,burnRate:75e3,fundingBonus:2e6},{name:"Series E",threshold:85e7,burnRate:1e5,fundingBonus:5e6},{name:"Unicorn Status",threshold:1e9,burnRate:15e4,fundingBonus:1e7}];this.gameState=new w({initialRunway:e.initialRunway||2e5,stages:e.stages||i}),this.engine=n.Engine.create(),this.render=n.Render.create({element:this.container,engine:this.engine,options:{width:this.width,height:this.height,wireframes:!1,background:"#1a1a1a"}}),this.runner=n.Runner.create(),this.initWorld(),this.initMouse(),this.initRenderLoop(),this.initGameLoop(),this.initControls(),this.gameState.subscribe(()=>{this.gameState.status==="paused"?this.runner.enabled=!1:this.gameState.status==="playing"&&(this.runner.enabled=!0)})}initControls(){window.addEventListener("keydown",t=>{(t.key==="r"||t.key==="R")&&this.gameState.isPlaying()&&this.rotateHeldBody()})}rotateHeldBody(){const t=this.mouseConstraint.body;t&&n.Body.rotate(t,45*(Math.PI/180))}initWorld(){const{width:t,height:e}=this,i=60,s=n.Bodies.rectangle(t/2,e-i/2,t,i,{isStatic:!0,render:{fillStyle:"#333"}});n.Composite.add(this.engine.world,[s])}initMouse(){const t=n.Mouse.create(this.render.canvas);this.mouseConstraint=n.MouseConstraint.create(this.engine,{mouse:t,constraint:{stiffness:.2,render:{visible:!1}}}),n.Composite.add(this.engine.world,this.mouseConstraint),this.render.mouse=t}start(){n.Render.run(this.render),n.Runner.run(this.runner,this.engine)}stop(){n.Render.stop(this.render),n.Runner.stop(this.runner)}initRenderLoop(){n.Events.on(this.render,"afterRender",()=>{const t=this.render.context,e=this.width/2,i=400,s=700,a=100,o={x:e-i/2,y:a,w:i,h:this.height-a},h={x:e-s/2,y:a-50,w:s,h:this.height-a+100};if(t.beginPath(),t.setLineDash([10,10]),t.lineWidth=2,t.strokeStyle="rgba(255, 255, 255, 0.3)",t.strokeRect(o.x,o.y,o.w,o.h),t.font='10px "Inter", sans-serif',t.fillStyle="rgba(255, 255, 255, 0.3)",t.textAlign="center",t.fillText("ACCURATE VALUATION ZONE",e,o.y-15),!this.currentQuote){const u=[{text:`WE ARE A
2
+ FAMILY`,author:"- CEO"},{text:`CHANGE THE
3
+ WORLD`,author:"- Founder"},{text:`DISRUPT
4
+ EVERYTHING`,author:"- VC"},{text:`MOVE FAST
5
+ BREAK THINGS`,author:"- Tech Lead"},{text:`RADICAL
6
+ CANDOR`,author:"- HR"},{text:`UNLIMITED
7
+ PTO`,author:"- Recruiter"},{text:`VISIONARY
8
+ LEADER`,author:"- LinkedIn"},{text:`10X
9
+ GROWTH`,author:"- Investor"},{text:`PIVOT
10
+ TO AI`,author:"- Board"}];this.currentQuote=u[Math.floor(Math.random()*u.length)]}t.save(),t.translate(e,o.y+o.h/3),t.rotate(-Math.PI/12),t.textAlign="center",t.textBaseline="middle",t.font='900 48px "Inter", sans-serif',t.fillStyle="rgba(255, 255, 255, 0.05)";const p=this.currentQuote.text.split(`
11
+ `);p.forEach((u,r)=>t.fillText(u,0,r*50)),t.font='italic 700 24px "Inter", sans-serif',t.fillStyle="rgba(255, 255, 255, 0.04)",t.fillText(this.currentQuote.author,0,p.length*50+10),t.restore(),t.beginPath(),t.setLineDash([]),t.lineWidth=1,t.strokeStyle="rgba(255, 50, 50, 0.2)",t.strokeRect(h.x,h.y,h.w,h.h),t.font='bold 13px "Inter", sans-serif',t.textAlign="center",t.textBaseline="middle",t.fillStyle="#FFFFFF",this.engine.world.bodies.forEach(u=>{if(!u.label||u.label.includes("Body")||u.isStatic)return;const r=u.gameData,m=r&&r.vested;t.save(),t.translate(u.position.x,u.position.y),t.rotate(u.angle),m?(t.shadowColor="#00ff7f",t.shadowBlur=10,t.fillStyle="#00ff7f",t.fillText(u.label+" ✓",0,0)):(t.shadowColor="black",t.shadowBlur=4,t.fillStyle="#FFFFFF",t.fillText(u.label,0,0)),t.restore()})})}initGameLoop(){n.Events.on(this.runner,"afterUpdate",()=>{if(!this.gameState.isPlaying())return;const t=this.runner.delta;this.gameState.tick(t/1e3),this.gameState.valuation>=1e6&&(this.chaosTimer-=t,this.chaosTimer<=0&&(this.triggerChaosEvent(),this.chaosTimer=this.chaosInterval));const e=this.width/2,i=400,s=700;this.engine.world.bodies.forEach(a=>{if(a.isStatic)return;const o=a.gameData;if(Math.abs(a.position.x-e)>s/2||a.position.y>this.height+50){n.Composite.remove(this.engine.world,a);const p=["VC Scolding!","Server Outage!","GDPR Violation!","TechCrunch Hit Piece!","IP Lawsuit!"];this.gameState.penalty(5e4,p[Math.floor(Math.random()*p.length)]);return}if(o&&!o.vested){const p=a.speed<.15&&Math.abs(a.angularVelocity)<.05,u=Math.abs(a.position.x-e)<i/2;p&&u?(o.vestTimer+=this.runner.delta,o.vestTimer>1e3&&(o.vested=!0,this.gameState.addValuation(o.value))):o.vestTimer=0}})})}triggerChaosEvent(){var e,i,s,a,o;switch(Math.floor(Math.random()*5)){case 0:(e=this.onCrisis)==null||e.call(this,"STRATEGIC PIVOT","CEO: 'We are pivoting to AI!' (Gravity Shift)"),this.engine.world.gravity.x=.2,setTimeout(()=>{this.engine.world.gravity.x=0},5e3);break;case 1:(i=this.onCrisis)==null||i.call(this,"THE BIG REORG","HR: 'New Org Chart Announced!' (No Friction)"),this.engine.world.bodies.forEach(r=>{r.isStatic||(r.oldFriction=r.friction,r.friction=0,r.frictionStatic=0)}),setTimeout(()=>{this.engine.world.bodies.forEach(r=>{r.isStatic||(r.friction=r.oldFriction||.1,r.frictionStatic=.5)})},5e3);break;case 2:(s=this.onCrisis)==null||s.call(this,"LEGACY DEPRECATION","CTO: 'Deprecating v1 API!' (Ghost Blocks)");const h=this.engine.world.bodies.filter(r=>!r.isStatic);if(h.length>3){const r=h[Math.floor(Math.random()*h.length)];r.isSensor=!0,setTimeout(()=>{r.isSensor=!1},4e3)}break;case 3:(a=this.onCrisis)==null||a.call(this,"FEATURE CREEP","PM: 'Just one more feature...' (1.2x Scaling)"),this.engine.world.bodies.forEach(r=>{r.isStatic||n.Body.scale(r,1.2,1.2)});break;case 4:(o=this.onCrisis)==null||o.call(this,"VIRAL SPIKE","DevOps: 'Traffic Spike!' (Earthquake)");let p=0;const u=setInterval(()=>{this.engine.world.bodies.forEach(r=>{r.isStatic||n.Body.applyForce(r,r.position,{x:(Math.random()-.5)*.05,y:(Math.random()-.5)*.05})}),++p>20&&clearInterval(u)},100);break}}toggleRotation(){this.spawnVertical=!this.spawnVertical}spawnBlock(t){if(!this.gameState.isPlaying())return;if(Math.random()<1/15){const a=[d.SLACKER,d.CONTROL_FREAK,d.PRIMA_DONNA,d.QUIET_QUITTER,d.SLACK_SPAMMER];t=a[Math.floor(Math.random()*a.length)]}t===d.BOOTSTRAP?this.gameState.spendMoney(5e3):t===d.VC&&this.gameState.addMoney(75e3);const e=this.width/2+(Math.random()-.5)*40,i=v(e,S,t);let s=this.spawnVertical?90*(Math.PI/180):0;t===d.VC&&(s+=(Math.random()-.5)*(30*(Math.PI/180))),n.Body.setAngle(i,s),i.gameData={type:t,value:t===d.VC?5e7:t===d.BOOTSTRAP?5e6:0,vested:!1,vestTimer:0},n.Composite.add(this.engine.world,i)}}const S=100;class x{constructor(t,e){l(this,"container");l(this,"options");l(this,"hudElement");this.container=t,this.options=e,this.initStyles(),this.createHUD(),this.createControls(),this.createLegend(),this.createSystemButtons(),this.options.gameState.subscribe(i=>{if(this.updateHUD(),i==="penalty")this.showToast(`-${this.options.gameState.lastPenaltyReason}`,"danger");else if(i!=null&&i.startsWith("funding:")){const s=i.split(":")[1];this.showToast(`+$${parseInt(s).toLocaleString()} Series Funding!`,"info")}}),this.updateHUD()}initStyles(){const t=document.createElement("style");t.textContent=`
12
+ .uj-hud {
13
+ position: absolute;
14
+ top: 20px; /* Restored to top */
15
+ right: 20px;
16
+ color: #fff;
17
+ font-family: 'Inter', sans-serif;
18
+ text-align: right;
19
+ pointer-events: none;
20
+ z-index: 100;
21
+ }
22
+ /* ... existing styles ... */
23
+ .uj-sys-btn {
24
+ background: rgba(255,255,255,0.1);
25
+ border: 1px solid rgba(255,255,255,0.3);
26
+ color: #fff;
27
+ padding: 6px 10px;
28
+ border-radius: 4px;
29
+ cursor: pointer;
30
+ font-size: 11px; /* Slightly smaller to be discreet */
31
+ font-family: 'Inter', sans-serif;
32
+ transition: background 0.2s;
33
+ pointer-events: auto;
34
+ }
35
+ .uj-sys-btn:hover { background: rgba(255,255,255,0.2); }
36
+ .uj-sys-container {
37
+ position: absolute;
38
+ bottom: 20px; /* Moved to bottom */
39
+ left: 20px; /* Moved to left */
40
+ display: flex;
41
+ gap: 10px;
42
+ z-index: 200;
43
+ opacity: 0.6; /* Make them even less conspicuous */
44
+ transition: opacity 0.2s;
45
+ }
46
+ .uj-sys-container:hover { opacity: 1; }
47
+ .uj-stat-label {
48
+ font-size: 12px;
49
+ color: #888;
50
+ text-transform: uppercase;
51
+ }
52
+ .uj-stat-value {
53
+ font-size: 20px;
54
+ font-weight: bold;
55
+ margin-bottom: 10px;
56
+ }
57
+ .uj-stat-value.danger {
58
+ color: #ff4444;
59
+ }
60
+ .uj-controls {
61
+ position: absolute;
62
+ bottom: 20px;
63
+ right: 20px; /* Aligned with HUD */
64
+ display: flex;
65
+ flex-direction: column; /* Stack vertically for cleaner look on right side? Or Keep horizontal? */
66
+ /* User said "move right". Sidebar layout might be better. */
67
+ gap: 20px;
68
+ z-index: 100;
69
+ align-items: flex-end; /* Align right */
70
+ }
71
+ .uj-btn {
72
+ padding: 16px 0; /* Changed padding to vertical only, width handles horizontal */
73
+ width: 220px; /* Fixed width for equality */
74
+ font-family: 'Inter', sans-serif;
75
+ font-weight: bold;
76
+ border: none;
77
+ border-radius: 8px;
78
+ cursor: pointer;
79
+ text-transform: uppercase;
80
+ font-size: 16px;
81
+ box-shadow: 0 4px 6px rgba(0,0,0,0.3);
82
+ transition: transform 0.1s;
83
+ text-align: center; /* Ensure centered text */
84
+ }
85
+ .uj-btn:active {
86
+ transform: scale(0.95);
87
+ }
88
+ .uj-btn-solid {
89
+ background: #555;
90
+ color: #fff;
91
+ border-bottom: 4px solid #333;
92
+ }
93
+ .uj-btn-hype {
94
+ background: #FF00FF;
95
+ color: #fff;
96
+ border-bottom: 4px solid #cc00cc;
97
+ animation: pulse 2s infinite;
98
+ }
99
+ .uj-btn-rotate {
100
+ background: #0077ff;
101
+ color: #fff;
102
+ border-bottom: 4px solid #0055aa;
103
+ padding: 16px 20px;
104
+ }
105
+ .uj-btn-rotate.vertical {
106
+ background: #00AAFF;
107
+ transform: translateY(-2px);
108
+ }
109
+ @keyframes pulse {
110
+ 0% { box-shadow: 0 0 0 0 rgba(255, 0, 255, 0.7); }
111
+ 70% { box-shadow: 0 0 0 10px rgba(255, 0, 255, 0); }
112
+ 100% { box-shadow: 0 0 0 0 rgba(255, 0, 255, 0); }
113
+ }
114
+ .uj-overlay-logo {
115
+ position: absolute;
116
+ top: 20px;
117
+ left: 20px;
118
+ max-width: 150px;
119
+ z-index: 100;
120
+ pointer-events: none;
121
+ }
122
+ .uj-legend {
123
+ position: absolute;
124
+ top: 80px;
125
+ left: 20px;
126
+ width: 240px;
127
+ z-index: 90;
128
+ font-family: 'Inter', sans-serif;
129
+ color: white;
130
+ background: rgba(0,0,0,0.6);
131
+ padding: 12px;
132
+ border-radius: 8px;
133
+ backdrop-filter: blur(6px);
134
+ border: 1px solid rgba(255,255,255,0.1);
135
+ }
136
+ .uj-legend-item {
137
+ display: flex;
138
+ align-items: center;
139
+ margin-bottom: 12px;
140
+ }
141
+ .uj-swatch {
142
+ width: 20px;
143
+ height: 20px;
144
+ margin-right: 10px;
145
+ border: 1px solid white;
146
+ }
147
+ .uj-swatch.solid { background: #555; }
148
+ .uj-swatch.hype { background: #FF00FF; }
149
+ .uj-legend-text { font-size: 12px; line-height: 1.4; }
150
+ .uj-legend-note { margin-top: 10px; opacity: 0.7; font-size: 11px; }
151
+ .uj-legend-mini {
152
+ display: flex;
153
+ align-items: center;
154
+ gap: 6px;
155
+ font-size: 10px;
156
+ color: #ddd;
157
+ }
158
+ .uj-crisis-overlay {
159
+ position: absolute;
160
+ top: 0; left: 0; width: 100%; height: 100%;
161
+ pointer-events: none;
162
+ display: flex;
163
+ flex-direction: column;
164
+ align-items: center;
165
+ justify-content: center;
166
+ z-index: 400;
167
+ font-family: 'Inter', sans-serif;
168
+ background: rgba(255, 0, 0, 0);
169
+ transition: background 0.3s;
170
+ }
171
+ .uj-crisis-overlay.active {
172
+ background: rgba(255, 0, 0, 0.2);
173
+ animation: flash-red 1s infinite;
174
+ }
175
+ @keyframes flash-red {
176
+ 0%, 100% { background: rgba(255,0,0,0.1); }
177
+ 50% { background: rgba(255,0,0,0.3); }
178
+ }
179
+ .uj-crisis-box {
180
+ background: #ff4444;
181
+ color: white;
182
+ padding: 20px 40px;
183
+ border-radius: 12px;
184
+ box-shadow: 0 0 20px rgba(0,0,0,0.5);
185
+ text-align: center;
186
+ transform: scale(0.8);
187
+ opacity: 0;
188
+ transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
189
+ }
190
+ .uj-crisis-box.visible {
191
+ transform: scale(1);
192
+ opacity: 1;
193
+ }
194
+ .uj-crisis-shout {
195
+ font-size: 32px;
196
+ font-weight: 900;
197
+ margin-bottom: 5px;
198
+ text-transform: uppercase;
199
+ }
200
+ .uj-crisis-desc {
201
+ font-size: 18px;
202
+ opacity: 0.9;
203
+ }
204
+ `,document.head.appendChild(t)}createControls(){const t=document.createElement("div");t.className="uj-controls";const e=document.createElement("button");e.className="uj-btn uj-btn-solid",e.innerText=`Build Solid
205
+ (Costs $5k)`,e.onclick=()=>this.options.onSpawn(d.BOOTSTRAP);const i=document.createElement("button");i.className="uj-btn uj-btn-hype",i.innerText=`Hype Up
206
+ (Grants $75k)`,i.onclick=()=>this.options.onSpawn(d.VC),t.appendChild(e),t.appendChild(i),this.container.appendChild(t)}createSystemButtons(){const t=document.createElement("div");t.className="uj-sys-container";const e=document.createElement("button");e.className="uj-sys-btn",e.innerText="⏸ PAUSE",e.id="uj-btn-pause",e.onclick=()=>{const s=this.options.gameState.isPlaying();this.options.gameState.togglePause(),e.innerText=s?"▶ RESUME":"⏸ PAUSE"};const i=document.createElement("button");i.className="uj-sys-btn",i.innerText="↻ RESET",i.onclick=()=>window.location.reload(),t.appendChild(e),t.appendChild(i),this.container.appendChild(t)}createLegend(){var e;const t=document.createElement("div");t.className="uj-legend",t.innerHTML=`
207
+ <div style="margin-bottom: 8px; border-bottom: 1px solid rgba(255,255,255,0.1); padding-bottom: 6px;">
208
+ <strong style="color: #00ff7f; font-size: 14px;">MISSION</strong>
209
+ <div class="uj-legend-text">
210
+ 1. Reach <strong>$1 Billion</strong> Valuation.<br>
211
+ 2. Don't run out of <strong>Runway</strong>.<br>
212
+ <small style="opacity:0.7">Burn Rate increases with Stage!</small>
213
+ </div>
214
+ </div>
215
+
216
+ <div style="margin-bottom: 12px;">
217
+ <div class="uj-legend-item">
218
+ <div class="uj-swatch solid"></div>
219
+ <div class="uj-legend-text">
220
+ <strong>Build Solid</strong><br>
221
+ High Friction. Good Foundation.<br>
222
+ <span style="color:#ffaaaa">Costs $5k. Low Value.</span>
223
+ </div>
224
+ </div>
225
+ <div class="uj-legend-item">
226
+ <div class="uj-swatch hype"></div>
227
+ <div class="uj-legend-text">
228
+ <strong>Hype Up</strong><br>
229
+ Distorted Shape. Unstable.<br>
230
+ <span style="color:#aaffaa">Grants $75k. High Value.</span>
231
+ </div>
232
+ </div>
233
+ </div>
234
+
235
+ <!-- Toxic Employees Section -->
236
+ <div style="margin-bottom: 8px; border-top: 1px solid rgba(255,255,255,0.1); padding-top: 6px;">
237
+ <strong style="color: #ff4444; font-size: 13px;">TOXIC (Risk: 1/15)</strong>
238
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 5px;">
239
+ <div class="uj-legend-mini">
240
+ <img src="./slacker.png" style="width: 30px; height: auto;">
241
+ <span>Slacker</span>
242
+ </div>
243
+ <div class="uj-legend-mini">
244
+ <img src="./control-freak.png" style="width: 30px; height: auto;">
245
+ <span>Control Freak</span>
246
+ </div>
247
+ <div class="uj-legend-mini">
248
+ <img src="./prima-donna.png" style="width: 30px; height: auto;">
249
+ <span>Prima Donna</span>
250
+ </div>
251
+ <div class="uj-legend-mini">
252
+ <img src="./quet-quitter.png" style="width: 30px; height: auto;">
253
+ <span>Quiet Quitter</span>
254
+ </div>
255
+ <div class="uj-legend-mini">
256
+ <img src="./slack-spammer.png" style="width: 30px; height: auto;">
257
+ <span>Spammer</span>
258
+ </div>
259
+ </div>
260
+ <div class="uj-legend-note" style="color: #ffaaaa; margin-top: 5px;">
261
+ $0 Val. Heavy. Annoying.
262
+ </div>
263
+ </div>
264
+ <div class="uj-legend-note" style="font-size: 10px; line-height: 1.3;">
265
+ <strong style="font-size: 11px;">STRATEGY:</strong><br>
266
+ • <strong>Hype-Hole</strong>: High Hype = Zero stability. Organization & code collapse.<br>
267
+ • <strong>Solid-Sink</strong>: Pure solid = Runway burn. No growth velocity.<br>
268
+ <span style="color: #00ff7f; opacity: 0.9;"><em>Balance foundation with noise.</em></span>
269
+ </div>
270
+
271
+ <div class="uj-legend-note" style="margin-top: 8px;">
272
+ <strong>RULES:</strong><br>
273
+ - Blocks only vest inside <strong>Dashed Zone</strong>.<br>
274
+ - Crossing <strong>Red Line</strong> = Penalty.<br>
275
+ - Press <strong>'R'</strong> to rotate.
276
+ </div>
277
+
278
+ <!-- Chaos Events Description -->
279
+ <div style="margin-top: 8px; border-top: 1px solid rgba(255,255,255,0.1); padding-top: 6px;">
280
+ <strong style="color: #ffaa00; font-size: 13px;">CHAOS EVENTS</strong>
281
+ <div style="font-size: 11px; color: #ccc; line-height: 1.4; margin-top: 4px;">
282
+ • <strong>Strategic Pivot</strong>: Gravity shifts.<br>
283
+ • <strong>The Big Reorg</strong>: Zero friction.<br>
284
+ • <strong>Legacy Deprecation</strong>: Ghost API.<br>
285
+ • <strong>Feature Creep</strong>: Codescale 1.2x.<br>
286
+ • <strong>Viral Spike</strong>: Trafficequake.
287
+ </div>
288
+ </div>
289
+
290
+ <button id="uj-view-labels" style="
291
+ margin-top: 15px;
292
+ width: 100%;
293
+ background: rgba(255,255,255,0.1);
294
+ border: 1px solid rgba(255,255,255,0.3);
295
+ color: #ccc;
296
+ border-radius: 4px;
297
+ padding: 6px 8px;
298
+ cursor: pointer;
299
+ font-size: 11px;
300
+ transition: background 0.2s;">
301
+ View Label Dictionary
302
+ </button>
303
+ `,this.container.appendChild(t),(e=document.getElementById("uj-view-labels"))==null||e.addEventListener("click",()=>{this.showGlossary()})}showGlossary(){if(document.getElementById("uj-glossary"))return;const t=this.options.gameState.isPlaying();if(t){this.options.gameState.setPaused(!0);const s=document.getElementById("uj-btn-pause");s&&(s.innerText="▶ RESUME")}const e=document.createElement("div");e.id="uj-glossary",e.style.cssText=`
304
+ position: absolute;
305
+ top: 0; left: 0; width: 100%; height: 100%;
306
+ background: rgba(0,0,0,0.9);
307
+ color: white;
308
+ display: flex;
309
+ flex-direction: column;
310
+ align-items: center;
311
+ justify-content: center;
312
+ z-index: 300;
313
+ font-family: 'Inter', sans-serif;
314
+ `,e.innerHTML=`
315
+ <div style="background: #222; padding: 40px; border-radius: 12px; max-width: 800px; width: 90%; max-height: 80vh; overflow-y: auto; position: relative;">
316
+ <button id="uj-glossary-close" style="position: absolute; top: 10px; right: 10px; background: none; border: none; color: white; font-size: 24px; cursor: pointer;">&times;</button>
317
+ <h2 style="text-align: center; margin-bottom: 30px;">Startup Lingo Dictionary</h2>
318
+ <div style="display: flex; gap: 40px;">
319
+ <div style="flex: 1;">
320
+ <h3 style="color: #aaa; border-bottom: 2px solid #555; padding-bottom: 10px;">Build Solid (The Work)</h3>
321
+ <ul id="uj-solid-list" style="list-style: none; padding: 0; color: #ccc; line-height: 1.6;"></ul>
322
+ </div>
323
+ <div style="flex: 1;">
324
+ <h3 style="color: #FF00FF; border-bottom: 2px solid #cc00cc; padding-bottom: 10px;">Hype Up (The Noise)</h3>
325
+ <ul id="uj-hype-list" style="list-style: none; padding: 0; color: #ffccff; line-height: 1.6;"></ul>
326
+ </div>
327
+ </div>
328
+ </div>
329
+ `,this.container.appendChild(e),this.populateGlossaryLists();const i=()=>{if(e.remove(),t){this.options.gameState.setPaused(!1);const s=document.getElementById("uj-btn-pause");s&&(s.innerText="⏸ PAUSE")}};document.getElementById("uj-glossary-close").onclick=i,e.onclick=s=>{s.target===e&&i()}}populateGlossaryLists(){var i,s;const t=document.getElementById("uj-solid-list"),e=document.getElementById("uj-hype-list");t&&e&&((i=f[d.BOOTSTRAP].possibleLabels)==null||i.forEach(a=>{const o=document.createElement("li");o.textContent=a,t.appendChild(o)}),(s=f[d.VC].possibleLabels)==null||s.forEach(a=>{const o=document.createElement("li");o.textContent=a,e.appendChild(o)}))}createHUD(){this.hudElement=document.createElement("div"),this.hudElement.className="uj-hud",this.container.appendChild(this.hudElement)}updateHUD(){const t=this.options.gameState,e=new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",maximumFractionDigits:0}),i=new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",notation:"compact",maximumFractionDigits:1}),a=t.isBankrupt()?"uj-stat-value danger":"uj-stat-value",o=t.getNextStageThreshold(),h=o>0?`<small style="font-size:12px; opacity:0.7">Next: ${i.format(o)}</small>`:"";this.hudElement.innerHTML=`
330
+ <div class="uj-stat-label">Stage</div>
331
+ <div class="uj-stat-value">${t.stage}</div>
332
+
333
+ <div class="uj-stat-label">Valuation</div>
334
+ <div class="uj-stat-value" style="color: #00ff7f">
335
+ ${e.format(t.valuation)}<br>
336
+ ${h}
337
+ </div>
338
+
339
+ <div class="uj-stat-label">Runway</div>
340
+ <div class="${a}">${e.format(t.runway)}</div>
341
+ `,t.status!=="playing"&&this.showGameOver(t.status,t.valuation)}showToast(t,e="info"){const i=document.createElement("div");i.innerText=t,i.style.cssText=`
342
+ position: absolute;
343
+ top: 100px;
344
+ left: 50%;
345
+ transform: translateX(-50%);
346
+ background: ${e==="danger"?"rgba(255, 68, 68, 0.9)":"rgba(0, 0, 0, 0.8)"};
347
+ color: white;
348
+ padding: 10px 20px;
349
+ border-radius: 20px;
350
+ font-family: 'Inter', sans-serif;
351
+ font-weight: bold;
352
+ z-index: 500;
353
+ animation: fadeUp 2s forwards;
354
+ white-space: nowrap;
355
+ `,this.container.appendChild(i),setTimeout(()=>{i.style.transition="opacity 0.5s",i.style.opacity="0",setTimeout(()=>i.remove(),500)},2e3)}showGameOver(t,e){if(document.getElementById("uj-gameover"))return;const i=document.createElement("div");i.id="uj-gameover",i.style.cssText=`
356
+ position: absolute;
357
+ top: 0; left: 0; width: 100%; height: 100%;
358
+ background: rgba(0,0,0,0.85);
359
+ color: white;
360
+ display: flex;
361
+ flex-direction: column;
362
+ align-items: center;
363
+ justify-content: center;
364
+ z-index: 200;
365
+ font-family: 'Inter', sans-serif;
366
+ `;let s="",a="",o="#fff";switch(t){case"bankrupt":s="HONEST POOR",a="You ran out of runway. The market did not love you.",o="#ff4444";break;case"collapsed":s="SCANDAL!",a="Your tower of lies has collapsed. TechCrunch is mocking you.",o="#ffaa00";break;case"exited":s="VISIONARY FRAUD",a=`You exited with $${(e/1e6).toFixed(1)}M! You are a genius.`,o="#00ff7f";break}i.innerHTML=`
367
+ <h1 style="font-size: 48px; color: ${o}; margin-bottom: 10px;">${s}</h1>
368
+ <p style="font-size: 18px; color #ccc; max-width: 400px; text-align: center;">${a}</p>
369
+ <button onclick="window.location.reload()" style="
370
+ margin-top: 30px;
371
+ padding: 15px 30px;
372
+ font-size: 20px;
373
+ background: white;
374
+ border: none;
375
+ cursor: pointer;
376
+ border-radius: 8px;
377
+ font-weight: bold;
378
+ ">TRY AGAIN</button>
379
+ `,this.container.appendChild(i)}showLogo(t){if(!t)return;const e=document.createElement("img");e.src=t,e.className="uj-overlay-logo",this.container.appendChild(e)}showCrisisAlert(t,e){const i=document.createElement("div");i.className="uj-crisis-overlay active";const s=document.createElement("div");s.className="uj-crisis-box",s.innerHTML=`
380
+ <div class="uj-crisis-shout">${t}</div>
381
+ <div class="uj-crisis-desc">${e}</div>
382
+ `,i.appendChild(s),this.container.appendChild(i),setTimeout(()=>s.classList.add("visible"),100),setTimeout(()=>{s.classList.remove("visible"),i.classList.remove("active"),setTimeout(()=>{i.remove()},500)},4e3)}}class k{constructor(t,e={}){l(this,"game");l(this,"ui");this.game=new b(t,{...e,onCrisis:(i,s)=>this.ui.showCrisisAlert(i,s)}),this.ui=new x(t,{onSpawn:i=>this.game.spawnBlock(i),onRotate:()=>this.game.toggleRotation(),gameState:this.game.gameState}),e.logoUrl&&this.ui.showLogo(e.logoUrl)}start(){this.game.start()}}g.PreMortem=k,g.PreMortemGame=b,g.UIManager=x,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"})});
Binary file
Binary file
Binary file
Binary file
package/index.html ADDED
@@ -0,0 +1,39 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Pre-Mortem - The Exit Simulator</title>
7
+ <style>
8
+ body {
9
+ margin: 0;
10
+ padding: 0;
11
+ background: #000;
12
+ color: #fff;
13
+ font-family: sans-serif;
14
+ overflow: hidden;
15
+ }
16
+ #app {
17
+ width: 100vw;
18
+ height: 100vh;
19
+ position: relative;
20
+ }
21
+ </style>
22
+ </head>
23
+ <body>
24
+ <div id="app"></div>
25
+ <script type="module">
26
+ import { PreMortem } from './src/index.ts';
27
+
28
+ const app = document.getElementById('app');
29
+ // Example Logo: using a placeholder or local asset
30
+ // For demo, we leave it empty or use a placeholder
31
+ const game = new PreMortem(app, {
32
+ logoUrl: './logo.png', // Local logo
33
+ width: window.innerWidth,
34
+ height: window.innerHeight
35
+ });
36
+ game.start();
37
+ </script>
38
+ </body>
39
+ </html>
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "pre-mortem",
3
+ "version": "0.1.0",
4
+ "description": "The Exit Simulator: A satirical startup physics game",
5
+ "main": "dist/pre-mortem.umd.js",
6
+ "module": "dist/pre-mortem.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "scripts": {
9
+ "dev": "vite",
10
+ "build": "vite build && tsc --emitDeclarationOnly --outDir dist",
11
+ "preview": "vite preview"
12
+ },
13
+ "keywords": [
14
+ "game",
15
+ "satire",
16
+ "physics",
17
+ "matter-js"
18
+ ],
19
+ "author": "Boobs",
20
+ "license": "ISC",
21
+ "dependencies": {
22
+ "matter-js": "^0.20.0"
23
+ },
24
+ "devDependencies": {
25
+ "@types/matter-js": "^0.19.0",
26
+ "@types/node": "^25.0.3",
27
+ "typescript": "^5.0.0",
28
+ "vite": "^5.0.0"
29
+ }
30
+ }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file