Squarely - Puzzle Game Design (iOS app + marketing)
Status: App-side tokens are CONTRACT-GRADE (extracted from
~/Projects/squarely-ios/squarely-ios/TileColors.swift2026-05-23). Marketing-surface extrapolation is DIRECTIONAL - pending founder approval. The single file covers both per founder directive 2026-05-23 19:19 ET ("ONE file covering iOS app + marketing properties").Inherits: RDCO umbrella for layout grid, voice umbrella attributes, asset inventory convention. Overrides palette + typography + shapes + components entirely (puzzle game lives in a different visual register than editorial RDCO).
Section name aliases: uses the longer descriptive names. Stitch-canonical short names are aliased.
Brand & Style
Squarely Puzzle is a daily 5x5 logic puzzle game for iOS - fill each row and column with numbers 1-5, no repeats, clues at the intersections guiding placement. Five difficulty tiers (Flash, Easy, Medium, Hard, Expert). The brand mood is tactile crossword-book on a wooden board: glass-finish numbered tiles on a sunken cream grid set inside a warm wooden frame, with rounded-system type and soft drop shadows that read "physical object you can pick up."
The closest mood references are the printed-puzzle aesthetic of a classic Sudoku booklet, Tobago wooden Scrabble boards, and the editorial restraint of a NYT mini-crossword. Squarely is decidedly NOT in the flat-tech-startup register (no neon gradients, no clean white SaaS look). The warm wood + cream + glass-tile aesthetic is intentional, founder-locked, and load-bearing.
The app uses Apple's SF Pro Rounded throughout (.system(..., design: .rounded)) - there is no custom display font. Marketing surfaces MAY add Source Serif 4 from the RDCO umbrella for editorial-grade headlines (landing page hero, blog posts) - but the in-app and screenshot register stays rounded-sans-only.
Tells the brand must hit on every surface:
- Warm wood + cream pairing visible. Cream is the surface, wood-tones provide framing/depth. No flat backgrounds.
- Glass-tile motif (or its echo on marketing). The colored, beveled, glow-shadowed glass tile is the signature visual.
- Rounded geometry. All radii ≥4px; tile radii are deliberately soft. SF Pro Rounded as type.
- Tactile depth. Drop shadows are USED here (unlike RDCO umbrella) - to sell the "physical object" feel. Sunken cells, raised tiles, shadowed frames.
- Daily-puzzle ritual register in copy. Frame the player as taking 5 minutes of quiet, not "leveling up" or "competing."
Consumer behavior table (Stitch contract)
| Scenario | Behavior |
|---|---|
| Unknown section heading | Preserve, do not error |
| Unknown color/typography token name | Accept if value valid |
| Unknown spacing value | Accept; store as string if not valid Dimension |
| Unknown component property | Accept with warning |
| Duplicate section heading | Error, reject file |
Colors
App-side palette extracted from live Swift code. CSS variable prefix --sq-.
| Token | Hex | Swift source | Role | Notes |
|---|---|---|---|---|
colors.surface |
#F2EBD9 |
cream (0.98, 0.96, 0.92 in some refs; canonical TileColors uses #F2EBD9) |
Body bg, screen surface, cell base lighter | Warm cream - never pure white |
colors.primary |
#CC9E6B |
wood/tan (0.80, 0.62, 0.42) |
Glass tile main color (mapped per-number, see below); accent fills | Warm wood-tan |
colors.tertiary |
#402E1A |
ink (0.25, 0.18, 0.10) |
Primary text, hint text, frame shadow | Deep brown-ink |
colors.on-surface |
#402E1A |
(same as tertiary) | Text on cream surface | 11+ AAA |
colors.on-surface-soft |
#59472E |
iconColor (0.35, 0.28, 0.18) |
Icon fills, hint-tile glyph color | |
colors.neutral |
#8C6640 |
labelColor (0.55, 0.40, 0.25) |
Secondary text, label color | |
colors.accent-highlight |
#FFF28C |
selected-cell color (1.0, 0.95, 0.55) | Active cell highlight (sunken-cell-selected) | The puzzle-game accent |
colors.accent-peer |
#FFFAC7 |
peer-cell color (1.0, 0.98, 0.78) | Same-row/column peer cells | Lighter highlight |
colors.cell-default |
#E0D6C6 |
unselected cell (0.88, 0.84, 0.78) | Default sunken cell | Slightly darker than cream for contrast |
colors.wood-light |
#B88552 |
frameLight (0.72, 0.52, 0.32) |
Wooden frame gradient top-left | |
colors.wood-medium |
#8C6138 |
frameMedium (0.55, 0.38, 0.22) |
Wooden frame mid gradient | |
colors.wood-dark |
#664526 |
frameDark (0.40, 0.28, 0.15) |
Wooden frame gradient bottom-right | |
colors.wood-shadow |
#402E1A |
frameShadow (0.25, 0.18, 0.10) |
Drop shadow under wooden frame |
Per-number tile palette (9 distinct, one per number 1-9 even though core game uses 1-5):
| Number | Light | Main | Dark | Role |
|---|---|---|---|---|
| 1 | #F58585 |
#E64C59 |
#B22E40 |
Rose / red |
| 2 | #FAAD6B |
#F28033 |
#C7591A |
Orange |
| 3 | #FAD966 |
#F2BF26 |
#CC990D |
Amber / yellow |
| 4 | #73D98C |
#33B866 |
#1A8C47 |
Emerald / green |
| 5 | #6BE0E0 |
#26B8C7 |
#148594 |
Cyan / teal |
| 6 | #85ADF2 |
#4D80E0 |
#2E59AD |
Blue |
| 7 | #B88CF2 |
#8C59E0 |
#6638B2 |
Violet |
| 8 | #D17AD1 |
#AD47B8 |
#852E8C |
Purple |
| 9 | #F285B8 |
#E64C8C |
#B82E6B |
Pink / magenta |
The colors.primary token resolves to #CC9E6B (wood-tan) as the umbrella semantic accent for marketing chrome. The 9 tile colors above are an enumerated set used ONLY for tile rendering in the game.
Marketing palette discipline (DIRECTIONAL - pending founder approval): marketing surfaces use surface (cream) + tertiary (ink) + primary (wood-tan) as the 60/30/10 base, then add accent-highlight #FFF28C (the puzzle-yellow) as the single saturated marketing accent. Tile colors appear ONLY in app screenshots; never as marketing chrome (the rainbow palette is in-game-only).
Typography
App-side: SF Pro Rounded throughout (.system(..., design: .rounded)). No custom display font in the app - Apple-native registers as warm-friendly and tested-against-Dynamic-Type.
Marketing-side: MAY add Source Serif 4 (from RDCO umbrella) for landing-page hero only. Rest of marketing copy stays SF Pro Rounded for register continuity with the app.
| Token | Family | Size | Weight | Surface |
|---|---|---|---|---|
typography.headline-display |
SF Pro Rounded | 48px | 700 | App: difficulty selector hero, marketing secondary hero |
typography.headline-lg |
SF Pro Rounded | 34px | 700 | Screen titles, marketing H1 (when not using marketing-headline) |
typography.headline-md |
SF Pro Rounded | 22px | 700 | Section headers, score displays |
typography.body-lg |
SF Pro Rounded | 18px | 400 | Lead instructions, marketing body lead |
typography.body-md |
SF Pro Rounded | 16px | 400 | Default in-app body, settings rows |
typography.body-sm |
SF Pro Rounded | 14px | 400 | Compact metadata, leaderboard rows |
typography.label-lg |
SF Pro Rounded | 17px | 600 | Primary button labels (44pt tap target) |
typography.label-md |
SF Pro Rounded | 14px | 600 | Secondary buttons, tab bar |
typography.label-sm |
SF Pro Rounded | 12px | 500 | Captions, timer chip |
typography.tile-number |
SF Pro Rounded | 22px (scales with tile size at 0.5x) | 700 | The number stamped on each glass tile |
typography.marketing-headline |
Source Serif 4 | 64px | 700 | Marketing landing-page hero ONLY |
Tap targets: all interactive elements ≥44pt (iOS HIG). Tile size in active gameplay = 44pt minimum.
Layout & Spacing
Inherits RDCO 8px scale (xs=4, sm=8, md=16, lg=24, xl=48). Squarely-specific:
| Token | Value | Use case |
|---|---|---|
spacing.tile-gap |
8px | Gap between adjacent tiles in tile bar |
spacing.board-pad |
12px | Inner padding of wooden frame around board |
spacing.md |
12px | Squarely override of umbrella md (was 16) - tighter mobile-game rhythm |
spacing.lg |
16px | Squarely override (was 24) |
spacing.xl |
24px | Squarely override (was 48) - most screens are mobile-portrait |
iOS screen layout: NavigationStack root. Each major screen is a vertical scroll. Wooden frame sits center-screen at gameplay. Hint tile + number palette docked below the grid.
Marketing breakpoints (inherits umbrella): mobile 0+, tablet 640+, desktop 1024+, wide 1440+.
Elevation & Depth
This is where Squarely diverges hardest from RDCO. RDCO umbrella avoids floating UI; Squarely USES drop shadows as a load-bearing motif because the brand sells "physical puzzle object on a table" - depth is core to the read.
| Token | Value | Use case |
|---|---|---|
elevation.none |
none |
Flat areas - none in core gameplay |
elevation.sm |
0 1px 2px rgba(64, 46, 26, 0.18) |
Sunken cell inner shadow simulation |
elevation.md |
0 4px 8px rgba(64, 46, 26, 0.25) |
Glass tile drop shadow |
elevation.lg |
0 8px 16px rgba(64, 46, 26, 0.35) |
Wooden frame shadow on cream surface |
elevation.tile-glow |
0 6px 12px rgba(204, 158, 107, 0.5) |
Active-tile colored glow (uses tile color at 0.4 opacity) |
Hard rule: drop shadows in Squarely are physical-object simulation, not decorative. Wooden frame casts shadow on the screen; tiles cast shadow into cells; cells cast inner shadow to feel "sunken." Never use shadow for emphasis on text - use weight + color.
Shapes
| Token | Value | Use case |
|---|---|---|
rounded.none |
0 | Never used - Squarely is all-rounded |
rounded.sm |
4px | Sunken cells, inset matte |
rounded.md |
8px | Default - most controls, hint tile, modal sheets |
rounded.lg |
12px | Wooden frame, cards, primary buttons |
rounded.xl |
18px | Tile radius (calculated size * 0.18 at canonical 44pt tile = 8px; on larger marketing tiles it grows) |
rounded.full |
999px | Stat chips, badge pills |
Motif primitives (Squarely-specific):
- Glass tile - rounded-square (radius
size * 0.18), linear-gradient fill (light → dark per number color), white-bevel inner stroke (top-left highlight + bottom-right shadow simulating glass refraction), 75%-width × 40%-height white-shine overlay top-half, colored glow shadow (tile-main at 40% opacity) offset y+3 blur 6. Per-number color set baked in. - Wooden frame - rounded outer container, linear-gradient fill (wood-light → wood-dark top-left → bottom-right), 6px or 8px border in lighter-wood gradient, drop shadow
frameShadow @ 50% opacityradius 4 offset 2,4. - Sunken cell - rounded-4, fill = cream/highlight/peer based on state, inner-shadow simulated via stroked overlay at 60% opacity, top-left gradient overlay for sunken effect, bottom-right white-30% gradient for "lit from above."
- Marketing tile-mosaic (DIRECTIONAL): on landing-page hero, a 3x3 or 5x5 tile mosaic using the 9-color palette to telegraph the game at a glance - without showing UI chrome.
Components
Stitch convention: separate keyed entries per variant.
glass-tile
// SwiftUI canonical render (see GameView.swift, TileColors.swift)
struct GlassTile: View {
let number: Int
let size: CGFloat // default 44, scales for hint-tile
let isDisabled: Bool
// Renders: glow shadow, gradient fill (per-number light→dark),
// bevel stroke (white→clear→black), white shine overlay (top half),
// number text in white with 0.35-opacity shadow
}
<!-- Web/marketing equivalent -->
<div class="sq-tile sq-tile--3"><span>3</span></div>
.sq-tile {
width: 44px; height: 44px;
border-radius: 8px;
position: relative;
display: inline-flex; align-items: center; justify-content: center;
font: 700 22px/1 -apple-system, "SF Pro Rounded", system-ui, sans-serif;
color: #fff;
text-shadow: 1px 1px 1px rgba(0,0,0,0.35);
}
.sq-tile::before { /* glow */
content: ""; position: absolute; inset: 0; border-radius: 8px;
box-shadow: 0 6px 12px var(--sq-tile-main, #CC9E6B);
opacity: 0.4; z-index: -1;
}
.sq-tile--3 { background: linear-gradient(135deg, #FAD966, #CC990D); }
/* repeat per-number 1-9 */
When to use: primary game tile (in tile bar, on board). Number determines color from the per-number palette.
hint-tile
.sq-hint-tile {
width: 44px; height: 44px; border-radius: 8px;
background: linear-gradient(135deg, #F2EBD9, #8C6640);
/* same bevel/shine as glass-tile but in cream/wood-cream gradient */
color: #59472E; /* iconColor */
}
Same shape and structure as glass-tile, but cream/wood monochrome instead of saturated number color. Shows lightbulb glyph + remaining-count.
sunken-cell-default / sunken-cell-selected / sunken-cell-peer
Stitch convention requires separate keyed entries per state.
.sq-cell {
width: 50px; height: 50px; border-radius: 4px;
background: var(--sq-cell-default, #E0D6C6);
position: relative; box-shadow: inset 0 1px 2px rgba(64,46,26,0.18);
}
.sq-cell--selected { background: var(--sq-accent-highlight, #FFF28C); }
.sq-cell--peer { background: var(--sq-accent-peer, #FFFAC7); }
wooden-frame
.sq-wooden-frame {
background: linear-gradient(135deg, #B88552, #664526);
border: 6px solid;
border-image: linear-gradient(135deg, #B88552, #402E1A) 1;
border-radius: 12px;
padding: 12px;
box-shadow: 0 8px 16px rgba(64,46,26,0.35);
}
When to use: wraps the play grid; also the home-menu primary card.
button-primary / button-primary-hover (marketing surfaces)
<a class="sq-btn">Play today's puzzle</a>
.sq-btn {
display: inline-flex; align-items: center; gap: 8px;
height: 44px; padding: 12px 24px; border-radius: 12px;
background: #402E1A; color: #F2EBD9;
font: 600 17px/1 -apple-system, "SF Pro Rounded", sans-serif;
border: none; cursor: pointer; transition: background 120ms;
}
.sq-btn:hover { background: #59472E; }
marketing-hero-card (DIRECTIONAL)
.sq-hero-card {
background: #F2EBD9; color: #402E1A;
border-radius: 18px; padding: 48px;
font: 700 64px/1.05 "Source Serif 4", serif;
}
When to use: landing-page hero. The ONE surface where Squarely uses RDCO umbrella's Source Serif for editorial-grade pull.
Do's and Don'ts
(In addition to RDCO umbrella rules not overridden.)
Always:
- Use the cream + wood-tone + glass-tile aesthetic on every surface
- Render numbered tiles in their canonical per-number color (1=rose, 3=amber, etc.)
- Use SF Pro Rounded in-app; SF Pro Rounded or Source Serif 4 on marketing
- Use drop shadows to simulate physical depth (wooden frame, glass tiles, sunken cells)
- Hit 44pt minimum tap targets
- Use puzzle-yellow
#FFF28Cas the active-cell highlight (it IS the in-game accent) - Frame copy in "daily ritual / 5 minutes of quiet" register, not "compete / level up"
Never:
- Use neon gradients or aurora-mesh backgrounds (puzzle game, not crypto product)
- Use pure white as the page surface - always cream
#F2EBD9 - Use shadows for text emphasis (use weight + color)
- Use the per-number tile palette in marketing chrome (rainbow stays in-game-only)
- Use ALL CAPS marketing headlines (sentence case, like the RDCO umbrella)
- Use clickbait subject lines or "limited time" panic in app store copy
- Use Inter on marketing surfaces (SF Pro Rounded continuity with the app; Source Serif 4 for hero is the only exception)
- Show flat 2D vector illustrations of a "puzzle game" - Squarely is depth-forward
- Use the umbrella terracotta
#a64f3a(it doesn't live in the Squarely palette; wood-tan is the equivalent accent) - Use question-mark headlines (declarative)
RDCO extension beyond Stitch core: Voice & Copy
DIRECTIONAL - pending founder voice corpus capture for Squarely. Working assumptions:
Five attributes (DIRECTIONAL):
- Quiet ritual, not gamified compete. "Five minutes of quiet" beats "level up your IQ."
- Puzzle-respect register. Talk to the player as someone who'll appreciate a well-built grid, not someone who needs the rules dumbed down.
- No streak-bait. Streaks exist mechanically (the calendar tracks them) but copy does NOT lean on FOMO ("don't lose your 47-day streak!").
- Plain words, no game-jargon. "Difficulty" not "tier 4 unlock." "Today's puzzle" not "daily challenge dungeon."
- Founder-as-puzzle-author voice in About/Help. Ben built this; the About page should sound like a craftsman, not a faceless studio.
Mechanics (hard rules):
- Sentence case for all headlines and button labels.
- Numbers: digits ("Day 47", "5x5 grid") - game is number-forward.
- Length: app copy ≤8 words per line. Marketing body 30-60 words per paragraph.
- No emoji in-app. Marketing may use sparingly for tone (one per page max).
- Tool/brand names plain text.
Banned phrases / patterns:
- "Train your brain!" / "Boost your IQ!" - over-promised game-puzzle clichés
- "Limited time!" / "Last chance!" - panic CTAs
- "Hardest puzzle ever?" - clickbait question headlines
- "Streak in danger" notifications (founder declines the dark-pattern; verify in app)
- Em-dash overuse (more than ~2 per paragraph) - single em-dash is fine per softened
feedback_no_em_dashes2026-05-23
RDCO extension beyond Stitch core: Format-specific templates
| Surface | Dimensions | Notes |
|---|---|---|
| iPhone 15 Pro (gameplay) | 393 x 852 | Wooden frame centered, tile bar docked bottom, hint tile inline with bar |
| iPhone SE (gameplay) | 375 x 667 | Wooden frame scales; tile size 36pt minimum |
| iPad Pro 11 (gameplay) | 1194 x 834 (landscape) | Wooden frame centered; tile size up to 60pt; right rail for stats |
| App Store screenshot 6.5" | 1290 x 2796 | Hero shot of in-progress puzzle on wooden frame; cream BG |
| App Store screenshot 12.9" iPad | 2048 x 2732 | Landscape gameplay + leaderboard composite |
| Landing-page hero (desktop) | 1440 x 900 | Source Serif marketing-headline + tile mosaic visual |
| Landing-page hero (mobile) | 393 x 852 | SF Pro Rounded headline clamps to 34px; tile mosaic stacks |
| Open Graph image | 1200 x 630 | Tile mosaic + "Daily 5x5 logic puzzle" tagline |
| Social card (square) | 1200 x 1200 | Single hero tile + day-number callout |
| Email body (TestFlight invite, marketing) | max-width 600px | SF Pro Rounded body; tile-mosaic header |
RDCO extension beyond Stitch core: Asset inventory
App source: /Users/ray/Projects/squarely-ios/squarely-ios/
| File | Description |
|---|---|
TileColors.swift |
CANONICAL palette source - 9 per-number tile colors, hint colors, wood frame colors |
GameView.swift |
Main game UI (~2970 lines) - glass tile rendering, wooden frame, sunken cell |
ContentView.swift |
Root NavigationStack, home menu using wooden frame as primary card |
DailyPuzzleView.swift |
Daily puzzle hub: difficulty selection, progress display |
LeaderboardView.swift |
Leaderboard with rank pills |
CalendarView.swift |
Monthly calendar showing completion history |
Assets.xcassets |
App icon + accent color asset |
Skill home: /Users/ray/.claude/skills/squarely-deploy/ (deploy rails, not design - design currently lives in this DESIGN.md + the Swift source)
Project memory:
| Path | Description |
|---|---|
/Users/ray/Projects/squarely-ios/CLAUDE.md |
Project-level Claude config: state mgmt rules, color palette refs, Firebase SDK caveats |
/Users/ray/rdco-vault/09-bet-stacks/squarely.yaml |
(if present) bet-stack ledger |
Pending / future:
- DIRECTIONAL: marketing landing page does not yet exist. When built, lives at
squarely.app(or similar) - register a~/rdco-vault/01-projects/squarely-puzzles/subdirectory for marketing assets. - DIRECTIONAL: no logo wordmark currently exists; the App Store icon serves as the brand mark. When a marketing wordmark is needed, propose 2-3 variants for founder approval.
Cross-references
- Parent:
/Users/ray/rdco-vault/02-sops/DESIGN-rdco.md - App source (canonical palette):
/Users/ray/Projects/squarely-ios/squarely-ios/TileColors.swift - Project Claude config:
/Users/ray/Projects/squarely-ios/CLAUDE.md - Deploy skill:
/Users/ray/.claude/skills/squarely-deploy/SKILL.md - Reference sample:
/Users/ray/rdco-vault/02-sops/design-samples/squarely-sample.html+.pdf