diff --git a/src/pages/mystery.astro b/src/pages/mystery.astro
new file mode 100644
index 0000000..3af1f10
--- /dev/null
+++ b/src/pages/mystery.astro
@@ -0,0 +1,48 @@
+---
+import '../mystery/ui/crt.css'
+---
+
+
+
+
+
+ Halfstreet — Ethan J Lewis
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ui/crt.css b/src/ui/crt.css
new file mode 100644
index 0000000..d6c5159
--- /dev/null
+++ b/src/ui/crt.css
@@ -0,0 +1,171 @@
+:root[data-mystery-theme='amber'] {
+ --m-bg: #1a0d00;
+ --m-fg: #ffb000;
+ --m-accent-1: #ffb000;
+ --m-accent-2: #ffb000;
+ --m-dim: rgba(255, 176, 0, 0.55);
+ --m-bezel: #0a0500;
+ --m-divider-style: dashed;
+}
+
+:root[data-mystery-theme='ansi'] {
+ --m-bg: #000080;
+ --m-fg: #ffffff;
+ --m-accent-1: #ffff55;
+ --m-accent-2: #55ffff;
+ --m-dim: #aaaaaa;
+ --m-bezel: #000040;
+ --m-divider-style: double;
+}
+
+.mystery-root {
+ position: fixed;
+ inset: 0;
+ background: var(--m-bezel);
+ color: var(--m-fg);
+ font-family: 'Courier New', 'Cascadia Mono', 'Consolas', monospace;
+ font-size: 14px;
+ line-height: 1.45;
+ letter-spacing: 0.02em;
+ display: flex;
+ flex-direction: column;
+ padding: 16px;
+ box-sizing: border-box;
+ text-shadow: 0 0 1.5px currentColor;
+}
+
+.mystery-bezel {
+ flex: 1;
+ background: var(--m-bg);
+ border-radius: 6px;
+ padding: 22px 26px 14px;
+ position: relative;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ box-shadow: inset 0 0 60px rgba(0, 0, 0, 0.55);
+}
+
+.mystery-bezel::before {
+ /* scanlines overlay */
+ content: '';
+ position: absolute;
+ inset: 0;
+ pointer-events: none;
+ background: repeating-linear-gradient(
+ to bottom,
+ transparent 0,
+ transparent 2px,
+ rgba(0, 0, 0, 0.18) 2px,
+ rgba(0, 0, 0, 0.18) 3px
+ );
+ opacity: 0.6;
+ z-index: 1;
+}
+
+.mystery-theme-toggle {
+ position: absolute;
+ top: 8px;
+ right: 12px;
+ z-index: 3;
+ display: flex;
+ gap: 6px;
+ font-size: 11px;
+}
+
+.mystery-theme-toggle button {
+ background: transparent;
+ color: var(--m-dim);
+ border: 1px solid var(--m-dim);
+ border-radius: 2px;
+ padding: 2px 6px;
+ font: inherit;
+ cursor: pointer;
+}
+
+.mystery-theme-toggle button[aria-pressed='true'] {
+ color: var(--m-fg);
+ border-color: var(--m-fg);
+}
+
+.mystery-transcript {
+ flex: 1;
+ overflow-y: auto;
+ white-space: pre-wrap;
+ word-break: break-word;
+ position: relative;
+ z-index: 2;
+ padding-right: 6px;
+}
+
+.mystery-transcript .system {
+ color: var(--m-accent-1);
+ font-weight: bold;
+ margin-top: 0.6em;
+}
+
+.mystery-transcript .player {
+ color: var(--m-accent-2);
+}
+
+.mystery-transcript .player::before { content: '> '; }
+
+.mystery-transcript .narration {
+ margin: 0.25em 0;
+}
+
+.mystery-input-row {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ margin-top: 10px;
+ position: relative;
+ z-index: 2;
+}
+
+.mystery-input-row::before {
+ content: '>';
+ color: var(--m-accent-2);
+}
+
+.mystery-input {
+ flex: 1;
+ background: transparent;
+ color: var(--m-fg);
+ border: none;
+ outline: none;
+ font: inherit;
+ text-shadow: inherit;
+ caret-color: var(--m-fg);
+}
+
+.mystery-chips {
+ display: none;
+ flex-wrap: wrap;
+ gap: 4px;
+ padding: 6px 0 4px;
+ position: relative;
+ z-index: 2;
+ border-top: 1px var(--m-divider-style) var(--m-dim);
+ margin-top: 8px;
+}
+
+.mystery-chip {
+ background: transparent;
+ color: var(--m-fg);
+ border: 1px solid var(--m-fg);
+ border-radius: 2px;
+ padding: 3px 7px;
+ font: inherit;
+ cursor: pointer;
+ font-size: 11px;
+}
+
+.mystery-chip[disabled] {
+ opacity: 0.35;
+ cursor: not-allowed;
+}
+
+@media (pointer: coarse) {
+ .mystery-chips { display: flex; }
+}
diff --git a/src/ui/terminal.ts b/src/ui/terminal.ts
new file mode 100644
index 0000000..2cc0209
--- /dev/null
+++ b/src/ui/terminal.ts
@@ -0,0 +1,10 @@
+// Stub. Replaced in Task 10 with the full terminal implementation.
+console.info('[halfstreet] terminal placeholder loaded')
+
+const transcript = document.querySelector('[data-mystery-transcript]')
+if (transcript) {
+ const line = document.createElement('div')
+ line.className = 'narration'
+ line.textContent = 'Terminal scaffold loaded. Type wiring lands in the next task.'
+ transcript.appendChild(line)
+}