Maze Tower Defense
Design system of the native iOS / iPadOS / macOS game — semantic theme roles, five biome palettes, Cute Mode, and the accents that never change.
Theme Model
Every SwiftUI view reads eleven semantic color roles from a single Theme struct via
@Environment(\.theme) — no view carries raw color literals. ThemeManager resolves
the active theme in priority order: the Classic black-and-white override
(td-use-classic-theme) → the biome of the run in progress → the last-played biome
(td-last-biome) → Plains as the fallback. Swatch colors on this page are the app's
real values and don't follow this site's light/dark toggle.
| Role | Purpose | Classic value |
|---|---|---|
| background | Full-screen background | #000 |
| surface | Panel fill | white @ 5% |
| surfaceElevated | Raised panel | white @ 15% |
| primaryText | Primary text | #fff |
| secondaryText | Muted text | white @ 70% |
| accent | Biome signature color | #fff |
| buttonFill | Primary CTA background | #fff |
| buttonText | Text on primary CTA | #000 |
| buttonSecondaryFill | Secondary button background | white @ 15% |
| border | Strokes and borders | white @ 25% |
| overlayScrim | Modal scrim | black @ 85% |
Classic Theme
The launch look, and still available as a player toggle: pure black and white, the same monochrome voice as this site. Surfaces and borders are white at low opacity over black, so nothing in Classic carries a hue.
Biome Palettes
Five biomes rotate every five waves — Plains, Desert, Tundra, Forest, Mountains — and each brings a full palette: an accent plus tinted background, surface, and text values. Each palette defines five base colors; the other six theme roles derive from them by rule.
| Derived role | Rule (standard biomes) |
|---|---|
| secondaryText | primaryText @ 70% |
| buttonFill | accent |
| buttonText | background — dark text on the bright accent |
| buttonSecondaryFill | accent @ 18% |
| border | accent @ 45% |
| overlayScrim | background @ 88% |
Cute Mode
A full second theme axis, not a reskin: every biome has a pastel "kawaii" palette with light backgrounds and softer accents that flip the tactical/dark feel. Cute Mode also swaps the entire type ramp from monospaced to rounded and adds sticker-style chrome.
| Derived role | Rule (Cute Mode) |
|---|---|
| secondaryText | primaryText @ 65% |
| buttonText | white — "buttonText = background" would vanish on a saturated accent over a pastel page, so filled buttons get white text plus a strong dark border |
| buttonSecondaryFill | surfaceElevated |
| border | primaryText @ 55% |
| overlayScrim | background @ 92% |
Sticker Chrome Modifiers
| Modifier | Effect (Cute Mode only — no-op otherwise) |
|---|---|
| cuteSoftShadow | Soft drop shadow — black @ 12%, radius 4, offset y 2. For stat pills and small floating elements. |
| cutePrimaryButtonChrome | 2px stroke black @ 35%, corner radius 10, shadow black @ 15% — primary CTAs stand off the pastel background like stickers. |
| cuteStickerStyle | 1.5px white @ 85% ring, corner radius 8, −2° rotation, shadow black @ 12% — badge flourish. |
Preserved Accents
A handful of colors deliberately sit outside the theme and never change with biome or
Cute Mode — gold means gold in every biome, damage is always red. Documented in
Theme.swift so call sites don't carry raw literals.
| Name | Value | Used for |
|---|---|---|
| hudGold | #ffc714 (rgb 1.0, 0.78, 0.08) | Live gold counter in the game HUD |
| legendaryGold | #d4a117 (rgb 0.83, 0.63, 0.09) | "Achievement" gold — Victory, Game Over, Leaderboard |
| fireballExplosion | #ff4d1a (rgb 1.0, 0.3, 0.1) | Fireball explosion badge in the guide |
| NPS red / green | system red / green @ 70–80% | Feedback score anchors |
| damage red | system red | Damage flashes |
| repair orange | system orange (bg @ 20%) | TowerBar repair action |
SpriteKit Grid Colors
The 11×18 board is rendered by SpriteKit, outside the SwiftUI theme — each biome defines
its own cell colors directly (BiomeTheme.swift). Cute Mode swaps in pastel
cell palettes so the board harmonises with the pastel chrome instead of showing dark
cells in a light frame.
| Biome | Cell Empty | Entrance | Exit | Buffer | Enemy Tint |
|---|---|---|---|---|---|
| Plains | #1e2a1e | #1a1a3a | #1a3a1a | #243525 | — |
| Desert | #2e2510 | #3a2e18 | #2e3a1a | #3a3018 | #d4a017 |
| Tundra | #182030 | #1e2840 | #1e3828 | #222c40 | #80deea |
| Forest | #162a16 | #1e3a1e | #1e4a1e | #1f3820 | #66bb6a |
| Mountains | #221e30 | #2e2840 | #28382e | #2d2840 | #b39ddb |
| Biome | Cell Empty | Entrance | Exit | Buffer | Enemy Tint |
|---|---|---|---|---|---|
| Plains | #d4ebd6 | #bedfc1 | #cae6cd | #c2e2c5 | #4ca85f |
| Desert | #fce4a0 | #f6d27a | #f0e09a | #f5d88a | #c98a1f |
| Tundra | #d6ecf2 | #bcdce6 | #c6e6dc | #cce4ec | #5fa6b3 |
| Forest | #cce4d2 | #b6d6bc | #c2dcc8 | #bfd9c4 | #5b9d68 |
| Mountains | #dcd0ea | #cabae0 | #cfc2e3 | #d4c7e6 | #9376b8 |
Typography
One font helper, Font.cute(…), gates the entire type system: the system font
in .monospaced design by default (the tactical voice), switching to
.rounded when Cute Mode is on. Weights pass through unchanged, and sizes use
semantic text styles (Dynamic Type) with explicit sizes only where layout demands it.
Web specimens below approximate SF Mono and SF Rounded.