File size: 10,863 Bytes
2abfd2c
d57a1a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2abfd2c
d57a1a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2abfd2c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
<!doctype html>
<html lang="en">
<head>
	<meta charset="utf-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
	<meta name="theme-color" content="#071b45" />
	<meta name="description" content="A free static classroom Sunk Cost game for COMSCI/ECON 206." />
	<title>Sunk Cost Game · COMSCI/ECON 206</title>
	<link rel="stylesheet" href="style.css" />
</head>
<body>
	<!-- ============ TOP BAR ============ -->
	<header class="topbar">
		<div class="brand">
			<span class="brand-emoji" aria-hidden="true">🪙</span>
			<span class="brand-name">COMSCI/ECON 206</span>
			<span class="brand-sub">Computational Microeconomics</span>
		</div>
		<nav class="steps" aria-label="Game steps">
			<button class="step is-active" data-step="1">1&nbsp;Inquiry</button>
			<button class="step" data-step="2">2&nbsp;Decision</button>
			<button class="step" data-step="3">3&nbsp;Reveal</button>
			<button class="step" data-step="4">4&nbsp;Reflect</button>
		</nav>
	</header>

	<main class="shell">
		<!-- ============ STEP 1 · INQUIRY / LANDING ============ -->
		<section class="view" id="view-inquiry" data-view="1">
			<div class="week-badge">Week 3 · Practice Laboratory</div>

			<h1 class="hero-title">A wasted cost. <em>Two rational choices.</em></h1>
			<p class="hero-sub">
				If money is already gone and unrecoverable, what does a self-interest benchmark
				predict — and what will people actually choose?
			</p>

			<div class="tag-row">
				<span class="tag">Private by design · no server, login, or tracking</span>
			</div>

			<div class="scenario card">
				<h2>The half-finished project</h2>
				<p>
					Your company has already spent <strong>$100,000</strong> on Project&nbsp;X, and it is now clearly
					underperforming. Finishing it would cost another <strong>$50,000</strong>. The same $50,000 could instead
					launch Project&nbsp;Y, whose expected returns are much higher.
				</p>
				<p class="muted">
					You must allocate the remaining <strong>10 points</strong> (each = $5,000) between
					“keep funding X” and “switch to Y.”
				</p>
			</div>

			<div class="roles">
				<article class="role-card" data-role="manager">
					<div class="role-kicker">Role A</div>
					<h3>Play the Manager</h3>
					<p>You already paid the $100,000. You decide how to spend the next $50,000.</p>
					<button class="btn" data-begin="manager">Begin decision →</button>
				</article>

				<article class="role-card" data-role="advisor">
					<div class="role-kicker">Role B</div>
					<h3>Play the Advisor</h3>
					<p>Fresh eyes, no sunk cost. You see the same numbers and decide.</p>
					<button class="btn" data-begin="advisor">Begin decision →</button>
				</article>
			</div>

			<div class="benchmark card">
				<h2>The self-interest benchmark</h2>
				<p>
					Because the $100,000 is gone either way, a strictly rational decider ignores it and
					puts <strong>all 10 points into Project Y</strong> — <strong>0 into X</strong>. Sunk costs must not drive
					tomorrow’s choices. Emotional attachment or loss aversion may produce a different observation.
				</p>
			</div>
		</section>

		<!-- ============ STEP 2 · DECISION ============ -->
		<section class="view" id="view-decision" data-view="2" hidden>
			<div class="week-badge">Step 2 · Decision</div>
			<h1 class="hero-title small">Where does the next <em>$50,000</em> go?</h1>

			<div class="card decision-card">
				<div class="role-kicker" id="decision-role-kicker">Role A · Manager</div>
				<h2 id="decision-role-title">Allocate the next $50,000</h2>
				<p class="muted" id="decision-role-copy">
					Drag the slider to split 10 points between continuing Project X and switching to Project Y.
				</p>

				<div class="slider-block">
					<div class="slider-scale">
						<span>Project X (continue)</span>
						<span id="slider-x">5</span> · <span id="slider-y">5</span>
						<span>Project Y (switch)</span>
					</div>
					<input type="range" id="sunk-slider" min="0" max="10" value="5" step="1" aria-label="Allocate points" />
					<div class="slider-bars">
						<div class="bar-x" id="bar-x"><span>X</span></div>
						<div class="bar-y" id="bar-y"><span>Y</span></div>
					</div>
					<div class="money-readout">
						<span id="money-x">$25,000 → X</span>
						<span id="money-y">$25,000 → Y</span>
					</div>
				</div>

				<div class="btn-row">
					<button class="btn ghost" data-reset="reset">Reset</button>
					<button class="btn" id="lock-decision">Lock decision →</button>
				</div>
			</div>
		</section>

		<!-- ============ STEP 3 · REVEAL ============ -->
		<section class="view" id="view-reveal" data-view="3" hidden>
			<div class="week-badge">Step 3 · Reveal</div>
			<h1 class="hero-title small">What the benchmark <em>predicts</em></h1>

			<div class="card reveal-card">
				<div class="reveal-verdict" id="reveal-verdict"></div>
				<p class="muted" id="reveal-text"></p>
				<div class="reveal-compare">
					<div>
						<span class="role-kicker">Rational benchmark</span>
						<p><strong>0 points → X</strong> · all 10 → Y</p>
						<p class="muted">Sunk cost is ignored.</p>
					</div>
					<div>
						<span class="role-kicker">Your choice</span>
						<p><strong id="reveal-your-x">0 → X</strong> · <span id="reveal-your-y">10 → Y</span></p>
						<p class="muted" id="reveal-your-verdict"></p>
					</div>
				</div>
			</div>

			<div class="btn-row">
				<button class="btn" id="to-reflect">See the lesson →</button>
			</div>
		</section>

		<!-- ============ STEP 4 · REFLECT ============ -->
		<section class="view" id="view-reflect" data-view="4" hidden>
			<div class="week-badge">Step 4 · Reflect</div>
			<h1 class="hero-title small">The sunk cost <em>fallacy</em></h1>

			<ol class="lessons card">
				<li>
					<strong>Only future costs and benefits matter.</strong> Money already spent is gone
					whether you continue or stop — it should never tip the scale.
				</li>
				<li>
					<strong>Decision-makers with sunk costs behave differently.</strong> The Manager (who paid)
					is systematically more likely to keep funding X than the Advisor (who didn’t), even with
					identical numbers.
				</li>
				<li>
					<strong>Good decisions are made from the outside.</strong> Ask: “If I hadn’t already spent
					the $100,000, would I still choose X?” If not, cut losses now.
				</li>
			</ol>

			<div class="btn-row">
				<button class="btn" id="restart">Play again ↺</button>
			</div>
		</section>
	</main>

	<footer class="foot">
		COMSCI/ECON 206 · Autumn 2026 · Browser-only classroom demonstration · No centralized data collection
	</footer>

	<script>
		(function () {
			"use strict";

			const ROLES = {
				manager: {
					kicker: "Role A · Manager",
					title: "You already paid the $100,000",
					copy: "You are emotionally invested. Drag the slider to split 10 points between continuing Project X and switching to Project Y."
				},
				advisor: {
					kicker: "Role B · Advisor",
					title: "Fresh eyes, no sunk cost",
					copy: "You never paid the $100,000. You see the exact same numbers. Drag the slider to split 10 points between X and Y."
				}
			};

			const slider = document.getElementById("sunk-slider");
			const barX = document.getElementById("bar-x");
			const barY = document.getElementById("bar-y");
			const moneyX = document.getElementById("money-x");
			const moneyY = document.getElementById("money-y");
			let role = null;
			let x = 5;

			function showStep(n) {
				document.querySelectorAll(".view").forEach(function (v) {
					v.hidden = Number(v.dataset.view) !== n;
				});
				document.querySelectorAll(".step").forEach(function (s) {
					s.classList.toggle("is-active", Number(s.dataset.step) === n);
				});
				window.scrollTo({ top: 0, behavior: "smooth" });
			}

			function renderSlider() {
				x = Number(slider.value);
				barX.style.width = (x * 10) + "%";
				barY.style.width = ((10 - x) * 10) + "%";
				moneyX.textContent = "$" + (x * 5000).toLocaleString() + " → X";
				moneyY.textContent = "$" + ((10 - x) * 5000).toLocaleString() + " → Y";
			}

			function startDecision(which) {
				role = which;
				document.getElementById("decision-role-kicker").textContent = ROLES[which].kicker;
				document.getElementById("decision-role-title").textContent = ROLES[which].title;
				document.getElementById("decision-role-copy").textContent = ROLES[which].copy;
				slider.value = 5;
				renderSlider();
				showStep(2);
			}

			function lockDecision() {
				renderSlider();
				const verdict =
					x === 0
						? "Perfectly rational — you ignored the sunk cost."
						: x <= 3
							? "Mostly rational — a little sunk-cost pull, but you switched."
							: x <= 7
								? "Strong sunk-cost pull — the spent $100,000 is dragging your decision."
								: "Classic sunk-cost fallacy — the unrecoverable $100,000 decided for you.";
				document.getElementById("reveal-verdict").textContent = verdict;
				document.getElementById("reveal-text").innerHTML =
					role === "manager"
						? "You were the <strong>Manager</strong> who paid. Losing $100,000 already, people systematically throw good money after bad. Your choice shows exactly how the sunk cost bends the decision."
						: "You were the <strong>Advisor</strong> with fresh eyes. With no sunk cost, the rational benchmark is far easier to reach — exactly why outsiders see it so clearly.";
				document.getElementById("reveal-your-x").textContent = x + " → X";
				document.getElementById("reveal-your-y").textContent = (10 - x) + " → Y";
				document.getElementById("reveal-your-verdict").textContent =
					x === 0 ? "Textbook rational." : "The sunk cost pulled you.";
				showStep(3);
			}

			document.querySelectorAll("[data-begin]").forEach(function (b) {
				b.addEventListener("click", function () {
					startDecision(b.getAttribute("data-begin"));
				});
			});

			document.querySelectorAll("[data-reset]").forEach(function (b) {
				b.addEventListener("click", function () {
					slider.value = 5;
					renderSlider();
				});
			});

			slider.addEventListener("input", renderSlider);
			document.getElementById("lock-decision").addEventListener("click", lockDecision);
			document.getElementById("to-reflect").addEventListener("click", function () {
				showStep(4);
			});
			document.getElementById("restart").addEventListener("click", function () {
				role = null;
				slider.value = 5;
				renderSlider();
				showStep(1);
			});

			// Keyboard/Enter also works on the step buttons.
			document.querySelectorAll(".step").forEach(function (s) {
				s.addEventListener("click", function () {
					// Free navigation between already-visited steps is allowed.
					showStep(Number(s.dataset.step));
				});
			});

			renderSlider();
		})();
	</script>
</body>
</html>