Files
home/docs/superpowers/plans/2026-05-18-minecraft-theme.md
2026-05-18 05:01:36 -06:00

541 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Minecraft Theme Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Add a "minecraft" design theme — zero border-radius, Minecraft GUI bevel shadows, 16px pixel grid background, monospace font, dark (Stone & Cave) + light (Overworld Day) modes.
**Architecture:** Four small file edits following the established theme pattern. Dark mode uses `html[data-theme="dark"][data-design-theme="minecraft"]` selectors (same specificity as the generic dark override rules, but placed later in the file so they win). Light mode uses `html[data-theme="light"][data-design-theme="minecraft"]`. No font imports — system monospace only.
**Tech Stack:** Vanilla JS, Vite, CSS custom properties. No test suite — verification is manual via `npm start`.
---
## Files Modified
| File | Change |
|---|---|
| `theme.js:1` | Add `"minecraft"` to `DESIGN_THEMES` |
| `index.html:48` | Add `<li role="option" data-value="minecraft">` after animal-crossing |
| `i18n.js:136226` | Add `minecraft` key in all 11 language objects of `DESIGN_THEME_LABELS` |
| `style.css` | Append dark vars + light vars + body/grid/control/card overrides + reduced-motion |
---
## Task 1: Register the theme slug
**Files:**
- Modify: `theme.js:1`
- Modify: `index.html:48`
- [ ] **Step 1: Add slug to DESIGN_THEMES in theme.js**
Change line 1 from:
```js
const DESIGN_THEMES = ["fluent", "material-you", "terminal", "cyberpunk", "nord", "animal-crossing"]
```
to:
```js
const DESIGN_THEMES = ["fluent", "material-you", "terminal", "cyberpunk", "nord", "animal-crossing", "minecraft"]
```
- [ ] **Step 2: Add dropdown option in index.html**
After the animal-crossing `<li>` (currently lines 4648):
```html
<li role="option" data-value="animal-crossing" aria-selected="false">
Animal Crossing
</li>
```
add immediately after:
```html
<li role="option" data-value="minecraft" aria-selected="false">
Minecraft
</li>
```
- [ ] **Step 3: Commit**
```bash
git add theme.js index.html
git commit -m "feat: register minecraft theme slug"
```
---
## Task 2: Add i18n labels
**Files:**
- Modify: `i18n.js:136226`
- [ ] **Step 1: Add `minecraft` key to every language object in DESIGN_THEME_LABELS**
Replace the entire `DESIGN_THEME_LABELS` constant with:
```js
export const DESIGN_THEME_LABELS = {
"zh-Hans": {
fluent: "Fluent",
"material-you": "Material You",
terminal: "终端",
cyberpunk: "赛博朋克",
nord: "Nord",
"animal-crossing": "动森",
minecraft: "我的世界",
},
"zh-Hant": {
fluent: "Fluent",
"material-you": "Material You",
terminal: "終端",
cyberpunk: "賽博龐克",
nord: "Nord",
"animal-crossing": "動森",
minecraft: "我的世界",
},
en: {
fluent: "Fluent",
"material-you": "Material You",
terminal: "Terminal",
cyberpunk: "Cyberpunk",
nord: "Nord",
"animal-crossing": "Animal Crossing",
minecraft: "Minecraft",
},
ja: {
fluent: "Fluent",
"material-you": "Material You",
terminal: "ターミナル",
cyberpunk: "サイバーパンク",
nord: "Nord",
"animal-crossing": "どうぶつの森",
minecraft: "マインクラフト",
},
ko: {
fluent: "Fluent",
"material-you": "Material You",
terminal: "터미널",
cyberpunk: "사이버펑크",
nord: "Nord",
"animal-crossing": "동물의 숲",
minecraft: "마인크래프트",
},
wenyan: {
fluent: "流光",
"material-you": "物材",
terminal: "终端",
cyberpunk: "赛博",
nord: "清寒",
"animal-crossing": "森友",
minecraft: "方块世界",
},
mars: {
fluent: "流↗光",
"material-you": "材↘質",
terminal: "終↗★端",
cyberpunk: "賽↘!博",
nord: "清↗寒★",
"animal-crossing": "动↗森★",
minecraft: "我↗的★世界",
},
garbled: {
fluent: "◼è▦",
"material-you": "拷▤屯ä锟◽",
terminal: "¥¬▤▨¿¿",
cyberpunk: "◼çæ¥烫¥",
nord: "æ◽屯¿",
"animal-crossing": "ä◼▤è",
minecraft: "▤◼▦è屯",
},
bin: {
fluent: "0101",
"material-you": "010101",
terminal: "01010101",
cyberpunk: "0101010101",
nord: "0101010",
"animal-crossing": "01010101",
minecraft: "0101010",
},
meow: {
fluent: "喵喵",
"material-you": "喵喵喵",
terminal: "喵喵",
cyberpunk: "喵喵喵喵",
nord: "喵喵喵",
"animal-crossing": "喵喵喵喵",
minecraft: "喵喵喵",
},
emoji: {
fluent: "💧",
"material-you": "🧱",
terminal: "⌨️",
cyberpunk: "⚡",
nord: "❄️",
"animal-crossing": "🌿",
minecraft: "⛏️",
},
}
```
- [ ] **Step 2: Commit**
```bash
git add i18n.js
git commit -m "feat: add minecraft labels for all 11 languages"
```
---
## Task 3: Add CSS — dark mode (Stone & Cave)
**Files:**
- Modify: `style.css` (append after the `prefers-reduced-motion` block at end of file)
- [ ] **Step 1: Append dark mode CSS block at end of style.css**
```css
/* ─── Minecraft — Stone & Cave / Overworld Day ──────────────── */
html[data-design-theme="minecraft"] {
color-scheme: dark;
--accent: #5aaa3a;
--accent-rgb: 90, 170, 58;
--accent-2: #3d8a2a;
--accent-3: #2a6e1a;
--accent-secondary-rgb: 91, 191, 232;
--page-gradient: #1a1a1a;
--page-texture: none;
--title-gradient: linear-gradient(135deg, #5bbfe8 0%, #5aaa3a 100%);
--control-bg: rgba(62, 62, 62, 0.92);
--control-border: #1a1a1a;
--control-inset: rgba(255, 255, 255, 0.2);
--control-fg: #f0f0f0;
}
html[data-theme="dark"][data-design-theme="minecraft"] {
color-scheme: dark;
--accent: #5aaa3a;
--accent-rgb: 90, 170, 58;
--accent-2: #3d8a2a;
--accent-3: #2a6e1a;
--accent-secondary-rgb: 91, 191, 232;
--page-gradient: #1a1a1a;
--page-texture: none;
--title-gradient: linear-gradient(135deg, #5bbfe8 0%, #5aaa3a 100%);
--control-bg: rgba(62, 62, 62, 0.92);
--control-border: #1a1a1a;
--control-inset: rgba(255, 255, 255, 0.2);
--control-fg: #f0f0f0;
}
html[data-design-theme="minecraft"] body {
font-family: ui-monospace, "Courier New", Courier, monospace;
letter-spacing: 0.04em;
color: #f0f0f0;
}
html[data-theme="dark"][data-design-theme="minecraft"] body {
color: #f0f0f0;
}
html[data-design-theme="minecraft"] body::before {
background-image:
linear-gradient(rgba(255, 255, 255, 0.025) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.025) 1px, transparent 1px);
background-size: 16px 16px;
}
html[data-design-theme="minecraft"] .design-theme-button,
html[data-design-theme="minecraft"] .theme-toggle {
border-radius: 0;
backdrop-filter: none;
-webkit-backdrop-filter: none;
box-shadow:
inset 2px 2px 0 rgba(255, 255, 255, 0.25),
inset -2px -2px 0 rgba(0, 0, 0, 0.5);
transition: all 0.1s steps(2, end);
}
html[data-design-theme="minecraft"] .design-theme-button:hover,
html[data-design-theme="minecraft"] .theme-toggle:hover {
background: rgba(82, 82, 82, 0.95);
box-shadow:
inset 2px 2px 0 rgba(255, 255, 255, 0.35),
inset -2px -2px 0 rgba(0, 0, 0, 0.4);
transform: none;
border-color: rgba(var(--accent-rgb), 0.7);
}
html[data-design-theme="minecraft"] .design-theme-button:active,
html[data-design-theme="minecraft"] .theme-toggle:active {
box-shadow:
inset 2px 2px 0 rgba(0, 0, 0, 0.4),
inset -2px -2px 0 rgba(255, 255, 255, 0.12);
}
html[data-design-theme="minecraft"] .design-theme-list {
border-radius: 0;
backdrop-filter: none;
-webkit-backdrop-filter: none;
background: rgba(30, 30, 30, 0.96);
border: 2px solid #111111;
box-shadow:
inset 2px 2px 0 rgba(255, 255, 255, 0.1),
inset -2px -2px 0 rgba(0, 0, 0, 0.6);
}
html[data-design-theme="minecraft"] .design-theme-list [role="option"] {
border-radius: 0;
}
html[data-design-theme="minecraft"]
.design-theme-list
[role="option"]:hover,
html[data-design-theme="minecraft"]
.design-theme-list
[role="option"][aria-selected="true"] {
background: rgba(var(--accent-rgb), 0.25);
color: var(--control-fg);
}
html[data-theme="dark"][data-design-theme="minecraft"] .card {
background: #3c3c3c;
border: 2px solid #111111;
border-radius: 0;
backdrop-filter: none;
-webkit-backdrop-filter: none;
box-shadow:
inset 2px 2px 0 rgba(255, 255, 255, 0.2),
inset -2px -2px 0 rgba(0, 0, 0, 0.5);
transition: all 0.1s steps(2, end);
transform: none;
}
html[data-theme="dark"][data-design-theme="minecraft"] .card::before {
display: none;
}
html[data-theme="dark"][data-design-theme="minecraft"] .card.pin {
background: #454545;
}
html[data-theme="dark"][data-design-theme="minecraft"] .card h2 {
color: #f0f0f0;
}
html[data-theme="dark"][data-design-theme="minecraft"] .card p {
color: #c8c8c8;
}
html[data-theme="dark"][data-design-theme="minecraft"] .card:hover,
html[data-theme="dark"][data-design-theme="minecraft"] .card:focus {
background: #484848;
transform: none;
border-color: #5aaa3a;
box-shadow:
inset 2px 2px 0 rgba(0, 0, 0, 0.35),
inset -2px -2px 0 rgba(255, 255, 255, 0.12);
}
html[data-theme="dark"][data-design-theme="minecraft"] .card:hover h2,
html[data-theme="dark"][data-design-theme="minecraft"] .card:focus h2 {
color: #5aaa3a;
}
html[data-theme="dark"][data-design-theme="minecraft"] .card:hover p,
html[data-theme="dark"][data-design-theme="minecraft"] .card:focus p {
color: #e0e0e0;
}
html[data-theme="dark"][data-design-theme="minecraft"] .beian a {
color: #c8c8c8;
}
html[data-theme="dark"][data-design-theme="minecraft"] .beian a:hover {
color: #5aaa3a;
}
```
- [ ] **Step 2: Verify dark mode in browser**
Start dev server (`npm start`). Select "我的世界" in dark mode. Verify:
- Background is `#1a1a1a` dark stone (not generic dark gray)
- Title has blue-to-green gradient
- Cards are `#3c3c3c` with visible bevel (lighter top-left, darker bottom-right inset)
- Cards have NO rounded corners (sharp square edges)
- Card hover inverts the bevel and border turns green
- Controls have zero border-radius and bevel effect
- [ ] **Step 3: Commit**
```bash
git add style.css
git commit -m "feat: add minecraft dark mode CSS"
```
---
## Task 4: Add CSS — light mode (Overworld Day)
**Files:**
- Modify: `style.css` (append after dark mode block from Task 3)
- [ ] **Step 1: Append light mode CSS block**
```css
html[data-theme="light"][data-design-theme="minecraft"] {
color-scheme: light;
--accent: #5c9e40;
--accent-rgb: 92, 158, 64;
--accent-2: #4a8a30;
--accent-3: #8b6914;
--accent-secondary-rgb: 135, 206, 235;
--page-gradient: linear-gradient(180deg, #87ceeb 0%, #c9e8f7 50%, #f0f8ff 100%);
--page-texture: none;
--title-gradient: linear-gradient(135deg, #5c9e40 0%, #8b6914 100%);
--control-bg: rgba(198, 198, 198, 0.92);
--control-border: #555555;
--control-inset: rgba(255, 255, 255, 0.5);
--control-fg: #2a2a2a;
}
html[data-theme="light"][data-design-theme="minecraft"] body {
color: #2a2a2a;
}
html[data-theme="light"][data-design-theme="minecraft"] body::before {
background-image:
linear-gradient(rgba(0, 0, 0, 0.04) 1px, transparent 1px),
linear-gradient(90deg, rgba(0, 0, 0, 0.04) 1px, transparent 1px);
background-size: 16px 16px;
}
html[data-theme="light"][data-design-theme="minecraft"] .design-theme-list {
background: rgba(210, 210, 210, 0.96);
border: 2px solid #555555;
box-shadow:
inset 2px 2px 0 rgba(255, 255, 255, 0.7),
inset -2px -2px 0 rgba(0, 0, 0, 0.2);
}
html[data-theme="light"][data-design-theme="minecraft"] .card {
background: rgba(198, 198, 198, 0.85);
border: 2px solid #555555;
border-radius: 0;
backdrop-filter: none;
-webkit-backdrop-filter: none;
box-shadow:
inset 2px 2px 0 rgba(255, 255, 255, 0.6),
inset -2px -2px 0 rgba(0, 0, 0, 0.25);
transition: all 0.1s steps(2, end);
transform: none;
}
html[data-theme="light"][data-design-theme="minecraft"] .card::before {
display: none;
}
html[data-theme="light"][data-design-theme="minecraft"] .card.pin {
background: rgba(210, 210, 210, 0.88);
}
html[data-theme="light"][data-design-theme="minecraft"] .card h2 {
color: #2a2a2a;
}
html[data-theme="light"][data-design-theme="minecraft"] .card p {
color: #4a4a4a;
}
html[data-theme="light"][data-design-theme="minecraft"] .card:hover,
html[data-theme="light"][data-design-theme="minecraft"] .card:focus {
background: rgba(212, 224, 198, 0.92);
transform: none;
border-color: #5c9e40;
box-shadow:
inset 2px 2px 0 rgba(0, 0, 0, 0.15),
inset -2px -2px 0 rgba(255, 255, 255, 0.5);
}
html[data-theme="light"][data-design-theme="minecraft"] .card:hover h2,
html[data-theme="light"][data-design-theme="minecraft"] .card:focus h2 {
color: #5c9e40;
}
html[data-theme="light"][data-design-theme="minecraft"] .card:hover p,
html[data-theme="light"][data-design-theme="minecraft"] .card:focus p {
color: #2a2a2a;
}
html[data-theme="light"][data-design-theme="minecraft"] .beian a {
color: #4a4a4a;
}
html[data-theme="light"][data-design-theme="minecraft"] .beian a:hover {
color: #5c9e40;
}
@media (prefers-reduced-motion: reduce) {
html[data-design-theme="minecraft"] .card,
html[data-design-theme="minecraft"] .design-theme-button,
html[data-design-theme="minecraft"] .theme-toggle {
transition-duration: 0.01ms !important;
transform: none !important;
}
}
```
- [ ] **Step 2: Verify light mode in browser**
Toggle to light mode with "我的世界" theme active. Verify:
- Background is sky blue gradient (top `#87ceeb` to near-white at bottom)
- Cards are stone gray `rgba(198,198,198)` with bevel (light top-left, darker bottom-right)
- Cards have NO rounded corners
- Card hover turns slightly green-tinted and border goes grass green
- 16px grid is faintly visible on the sky background
- [ ] **Step 3: Commit**
```bash
git add style.css
git commit -m "feat: add minecraft light mode CSS"
```
---
## Task 5: Final verification
- [ ] **Step 1: Check `minecraft` is not in FORCED_DARK_DESIGN_THEMES**
Read `theme.js` line 2. It must remain:
```js
const FORCED_DARK_DESIGN_THEMES = new Set(["terminal", "cyberpunk"])
```
"minecraft" must NOT appear here.
- [ ] **Step 2: Verify theme cycles cleanly**
Cycle through all 7 themes in the dropdown. No broken styles at any step.
- [ ] **Step 3: Verify forced-dark restore**
While on Minecraft (light mode), switch to Terminal (forces dark), then back to Minecraft — should restore light mode.
- [ ] **Step 4: Run formatter**
```bash
npm run fmt
```
If files changed, commit:
```bash
git add style.css index.html i18n.js theme.js
git commit -m "style: run prettier after minecraft theme"
```