# The game interface — first brush

## overview.md
```yaml
id: game-interface
title: The game interface — first brush
area: client
summary: The UI layer over the 3D world — title screen, HUD, the Ingredients collection view and the element-card visual language — plus the card editor Kris authors the 64 with, wrapped as an HTML shell over the live multiplayer world.
repo: land-of-lor
depends_on: []
```

## What this is

The first visual brush of the actual game. The live multiplayer POC already gives us a 3D
browser world with touch-to-move (`server-architecture`, deliverable 8); this epic puts the
*game* around it: a title screen, an in-game HUD, and the player's collection — the 64
elements rendered as collectable cards. It also builds the authoring tool Kris uses to
create and edit those 64 cards, which is the vehicle for `element-table`'s task 001
(this epic builds the tool and the card look; `element-table` stays the owner of the
*content* — names, properties, rarities).

The goal state for this pass: title screen → walk around the world → open your
Ingredients and look at your cards. Placeholder visuals are fine; the real visual design
comes from a Claude Design session driven by [`design-brief.md`](design-brief.md) in this
folder. Once account creation lands (the immediate next epic after this one), this is a
functioning MVP that real beta testers — Kris's kids, nephews and nieces, and interested
friends — can be invited into.

## What's decided (2026-08-11, planning session with Kris)

- **HUD structure:** a health bar plus three buttons — **Ingredients**, **Spells**
  (cauldron icon — eventually a view of the actual cauldron object), **Gear** — and all
  three open **one full-screen panel on different tabs**. This is the hybrid of the two
  options Kris was weighing, and it matches the earlier inventory thinking in
  `land-of-lor/docs/thought-specs/inventory-interface.md` (one inventory, major tabs);
  Blueprints/Recipes can join as a tab later without touching the HUD.
- **The element card** (from Kris's pencil sketches + the physical table session):
  card background is the element's colour · art panel · hexagram glyph + King Wen number
  in the corner · trigram pair ("Wind over Mountain") · name bar · a lower box for
  *where it comes from + what you need to hold/collect it* (the `origin` column made
  visible) · rarity: common / rare / legendary. The machinery (hexagram, number) is never
  hidden; only flavour is.
- **The Ingredients grid shows all 64, always** — laid out logically (upper-trigram rows ×
  lower-trigram columns, same as Kris's physical table). Cards you haven't collected are
  greyed-out templates with a big "?" — the full set is memorisable and the gaps invite
  collection.
- **Shell architecture:** an HTML/CSS/JS layer that boots the untouched Godot web export
  from its own page (`GODOT_CONFIG` lives in the page, so no re-export is needed) and
  overlays DOM UI above the canvas. Claude Design produces HTML/CSS, so its output slots
  straight in. Lives at `land-of-lor/pocs/game-shell/`.

## Notes toward later decisions

- The collectible-card framing opens a real-money acquisition channel **outside the
  game**: purchasable element packs (dozen-based bundles, at least one rare per dozen;
  maybe premium rare-heavy dozens; maybe player-created packs offered on the web version
  of the trading post). In-game remains currency-free — trading stays item-for-item, per
  the settled no-in-game-currency principle. Direction Kris likes, not yet a decision.
- **Hold the 64 lightly.** The hexagram set is the guiding structure and its boundedness
  is genuinely useful (any player can memorise the whole table) — but Kris can imagine
  wanting more than 64 someday. Everything here keys elements by King Wen number without
  hard-capping the set.

## Sequencing (named, not decomposed here)

After this epic: **account creation and remembering accounts** (so testers keep their
collections), then a marketing pass — inviting the beta family/friends circle in, website
engagement work, and the Kickstarter pre-launch (`kickstarter-prelaunch`) — engagement
more than money. A step soon after MVP: **collecting ingredients in the world**.

## Non-goals

- Not the spell-crafting interaction itself (`spell-crafting-interface`) — the Spells tab
  is a placeholder until the cauldron exists.
- Not account creation or persistence — next epic, deliberately excluded here.
- Not the element *content* — names, properties and rarities belong to `element-table`.
- Not the recipe engine, trading, or any server change (`server-architecture`,
  `barter-marketplace`).

## Open design questions (prose for now — formalise only if they block tasks)

- How much of an un-collected card is revealed — name? some properties? Currently: glyph
  and number only, everything else hidden. Kris was explicitly unsure ("maybe you see the
  name, and maybe even some properties").
- What the Spells tab shows before spell-crafting lands (currently a cauldron placeholder).
- Whether the grid's un-collected treatment should tease rarity (a legendary-shaped hole
  invites questing) or stay uniform.

## Relevant docs

- [`design-brief.md`](design-brief.md) — the self-contained brief for the Claude Design session.
- `land-of-lor/pocs/game-shell/README.md` — the shell, the shared card renderer/data
  contract, run and deploy instructions.
- `land-of-lor/docs/thought-specs/inventory-interface.md` — Kris's earlier inventory-tabs
  thinking (with Ben) that the HUD decision matches.
- `epics/element-table/overview.md` — the keystone table this UI renders; the settled
  machinery/flavour, rarity and origin principles.
- `brand/design.md` — the storybook-cover direction, palette and typography the brief
  inlines.

## status.md
```yaml
updated: 2026-08-12
parked: false
tasks: {"backlog":0,"needs-input":0,"ready":0,"doing":0,"review":0,"done":4}
open_questions: []
tag: done
next: Nothing outstanding. Promoting the card editor onto the public site is a later, separate call once more elements are defined; element authoring itself is tracked as element-table/003.
```

## Task summary

All four tasks done, signed off by Kris on 2026-08-12.

- **001 — Claude Design brief** — `done`. The brief was written, taken to a Claude Design
  session, and the resulting design came through into the actual game.
- **002 — Card renderer, seeded table data, and the card editor** — `done`. Shared
  renderer, 64 seeded records, editor runs from disk. Kris: "we have the card editor now,
  I'm really happy with that."
- **003 — Game shell** — `done`. The Claude Design pass integrated, the shell graduated to
  `land-of-lor/game/`, the site's `/play` page is the public home, and the lor2026-signed
  APK is on the droplet. Deliverable 9 delivered same-day (gate satisfied before close).
- **004 — Android interface parity** — `done`. The interface is native Godot Control-node
  scenes (`game/world/client/ui/`) — one implementation on web and Android. Title, HUD,
  stuff panel, element cards in-engine; the DOM shell is now a thin tap-to-play loader;
  `player_state.gd` is the seam for future server-backed accounts. Phone play confirmed,
  with follow-up fixes landed (crash fix, pressed-state feedback, hold-to-move).

## Open questions

None tracked — open design threads are prose in `overview.md`.

## Next

Nothing is waiting on an agent or on Kris here. Two threads deliberately left outside this
epic:

- **Promote the card editor to the public site** — Kris expects to want this once more
  elements exist. Not decided, not scheduled; it would be a new task when it is.
- **Author the elements** — Kris's own work, tracked as `element-table/003`.

## tasks/ (4)

### game-interface/001 — Claude Design brief for the first interface pass
```yaml
id: game-interface/001
title: Claude Design brief for the first interface pass
epic: game-interface
state: done
priority: 1
blocked_by: []
estimate: S
created: 2026-08-11
updated: 2026-08-12
claimed_by: null
claimed_at: null
delivers: []
review_artifact: epics/game-interface/design-brief.md
```

## What

Write a self-contained brief Kris can paste into a Claude Design session to get the first
real pass of the game's screens: title screen, HUD, the tabbed stuff-panel with the
Ingredients grid, and the element card at all three rarities. Self-contained means the
brief inlines everything Claude Design can't reach — palette hex values, typography rules,
card anatomy, screen inventory, output constraints (DOM over a WASM canvas, portrait
phone first, no external font links).

## Done

Brief written to `epics/game-interface/design-brief.md` (2026-08-11). Decisions baked in:
three HUD buttons opening one tabbed panel; card anatomy from Kris's sketches; sample
elements drawn from the real seeded table; full-title treatment "Lor: The Ten Thousand
Things".

## Review

Kris reads the brief, takes it to Claude Design, and brings the HTML/CSS output back to
task 003 for integration. Anything the brief got wrong is cheaper to fix here than after
the design session.

### game-interface/002 — Element-card renderer, seeded table data, and the card editor
```yaml
id: game-interface/002
title: Element-card renderer, seeded table data, and the card editor
epic: game-interface
state: done
priority: 1
blocked_by: []
estimate: M
created: 2026-08-11
updated: 2026-08-12
claimed_by: null
claimed_at: null
delivers: []
review_artifact: land-of-lor/pocs/game-shell/card-editor.html
```

## What

The shared card layer both the game and the authoring tool sit on:

- `elements.js` — the working element table as structured data, seeded from the historic
  periodic-table doc (64 records: provisional name, trigram pair, King Wen number, a
  colour blended from the trigram colours, rarity, origin, collect-text, value, art slot).
  This starts the authoring `element-table/001` was waiting on; that epic still owns the
  content itself.
- `card-renderer.js` + `card-styles.css` — one renderer for the card (full and grid-tile
  sizes, owned and un-collected treatments, rarity styling) used by BOTH the game shell
  and the editor, so preview and in-game can never drift.
- `card-editor.html` — Kris's tool: open from disk, pick any of the 64, edit
  name/colour/rarity/origin/collect-text/value/art, live card preview, "Download
  elements.js" to save (localStorage autosave as crash protection only).

## Done

All four files live in `land-of-lor/pocs/game-shell/` (2026-08-11). #53 seeded as
"Leather" (Rah's documented name for Wind over Mountain); all other names are provisional
seeds from the historic table — Kris's sticky-note renames from the physical table
session (Fire Crystal, Mushrooms, Wood, Gold, Silver, Dirt, …) still need applying in the
editor. Verified: editor renders and edits from a plain local serve; grid and card
variants render correctly.

## Review

Kris opens `land-of-lor/pocs/game-shell/card-editor.html` in a browser (straight from
disk works), pokes at an element or two, downloads `elements.js`, and confirms the tool
fits how he wants to author the table. Then: apply the sticky-note renames from the
physical table.

## Outcome — done (2026-08-12)

Signed off by Kris: "we have the card editor now, I'm really happy with that."

Two follow-ons deliberately **not** folded into this task:

- **Promoting the card editor to the public site** is a later, separate call —
  Kris expects to want it once more elements are defined, but it isn't decided
  and isn't scheduled.
- **Authoring the actual elements** is Kris's own work, now tracked as
  `element-table/003`.

### game-interface/003 — Game shell — title screen, HUD, Ingredients view over the live world, deployed
```yaml
id: game-interface/003
title: Game shell — title screen, HUD, Ingredients view over the live world, deployed
epic: game-interface
state: done
priority: 1
blocked_by: []
estimate: M
created: 2026-08-11
updated: 2026-08-12
claimed_by: laptop-claude-session-2026-08-11
claimed_at: 2026-08-11T10:30:00.000Z
delivers: [9]
review_artifact: land-of-lor/game/README.md
```

## What

The playable shell: `land-of-lor/pocs/game-shell/index.html` boots the untouched
multiplayer-poc web export from its own page (custom `GODOT_CONFIG`, adaptive canvas,
engine load deferred until Start Game) and layers the DOM UI above it — title screen,
HUD (health bar + three buttons), the tabbed stuff-panel with the Ingredients grid and
large-card view.

**Scope change (Kris-approved, 2026-08-11 planning session):** the shell graduates out of
`pocs/` into the real game folder — `land-of-lor/game/` (fresh copy; POCs stay as reference,
marked adopted). Deployment is **site-only**: the web build is committed into the workspace
repo at `site/public/embeds/lor-game/` and served from a new public "Play the Game" page at
`https://lor.kris.ai-task-runner.com/play` — the originally planned droplet `/app/` deploy is
dropped. The APK (new package id, signed with lor2026) goes to the droplet `/download/` and is
linked from the play page.

## Notes

Skeleton built 2026-08-11 with placeholder brand-palette styling; the Claude Design
output came back the same evening and was integrated in full. **Built and live
2026-08-11:** the shell graduated to `land-of-lor/game/shell/` restyled to the design
pass (title / HUD / stuff panel / element cards, landscape 844×390), the world project
to `game/world/` (identity-only edits, 64/64 pure-logic tests pass), and the public
home is the site's `/play` page — committed web build at `site/public/embeds/lor-game/`
plus the lor2026-signed `land-of-lor-v0.apk` on the droplet's `/download/`. Verified
headless end-to-end: engine boots from the shell, connects to the live droplet
director, remote entities stream in; HUD press-hold labels, grid, card modal, and
portrait fallback all screenshot-checked. `/play/` on the droplet untouched.
Delivers deliverable 9 — in review for Kris's sign-off (read
`land-of-lor/game/README.md`, then play the live page).

### game-interface/004 — Android build is missing the whole interface — shell is DOM-only, APK ships the bare 3D world
```yaml
id: game-interface/004
title: Android build is missing the whole interface — shell is DOM-only, APK ships the bare 3D world
epic: game-interface
state: done
priority: 1
blocked_by: []
estimate: L
created: 2026-08-11
updated: 2026-08-12
claimed_by: laptop-claude-session-2026-08-12
claimed_at: 2026-08-11T21:30:00.000Z
delivers: []
review_artifact: land-of-lor/game/README.md
```

## What

Kris played the live `/play` page (works — title screen, HUD, Ingredients panel all
present) and then installed the APK on his phone: the 3D world runs, but none of the
interface layer is there — no title screen, no HUD buttons, no Ingredients/Spells/Gear
panel, not even the help bar. He suspected the UI had only ever been built as an HTML
overlay rather than into the Godot project itself. That's exactly right, confirmed by
reading the actual architecture:

- `game/README.md` and `game/shell/README.md` both say plainly: the shell is "the DOM
  layer... floated over the untouched Godot web export." It boots `./engine/index.js`
  and draws HTML/CSS on top of the `<canvas>` from the *page*, not from anything inside
  the `.godot` project.
- `game/export-android.sh` exports `$HERE/world` only — the raw Godot project
  (`game/world/`, `run/main_scene = client_main.tscn`). There is no Control-node UI
  anywhere in `world/`; grepped for it, nothing exists.
- So the APK is, correctly, exactly the Godot project on its own: touch-to-move in the
  3D world, and nothing else. This was never a bug in the export script — the shell
  genuinely has no path into a native Android build. It's a real, undocumented gap:
  `game/README.md`'s "Known limits (deliberate, v0.0)" section lists several intentional
  v0.0 shortcuts (static health bar, hardcoded owned-set, Spells/Gear placeholders) but
  never says "Android has no interface at all" — this wasn't a decision anyone signed
  off on, it fell out of the shell being built web-first and nobody checked the APK
  against deliverable 9's acceptance criteria before shipping it.

Deliverable 9's own acceptance criteria ("title screen... HUD... Ingredients tab") make
no browser/mobile distinction — the APK not meeting them is a real gap against what was
promised, not a scope question.

## The fork this needs

Two genuinely different ways to close this gap:

1. **Wrap the existing web build in a WebView shell for Android**, instead of exporting
   the raw Godot project. Reuses the shell, the Claude Design pass, and the card
   renderer/editor contract completely untouched — zero redesign. Downsides: WASM inside
   a mobile WebView is materially slower than Godot's native Android renderer; touch
   input, fullscreen/back-button behaviour, and Android WebView quirks (version
   fragmentation) all need real verification, not assumption; app size grows (bundling
   the web build into the APK).
2. **Build the interface natively in Godot** (Control nodes: title screen, HUD, tabbed
   stuff panel, card grid/modal) so one implementation ships identically on web and
   Android. Better native performance and input handling, no WebView involved at all.
   Downsides: the whole Claude Design handoff (`docs/design/HANDOFF.md`, the two
   `.dc.html` references) is HTML/CSS — none of it transfers directly to Godot's UI
   system, so the visual pass has to be rebuilt by hand in-engine and now has two
   places that can drift (DOM shell for web, Control-node UI for Android) unless the web
   shell is later retired in favour of the same native UI running inside the Web export
   too.

**RESOLVED by Kris (2026-08-12, planning session):** option 2 — native Godot UI — is the
direction, explicitly confirmed ("we want this correctly implemented in Godot — and well
architected too"). The WebView wrap is rejected. The DOM shell's UI layers get retired to a
thin tap-to-play loader (Kris chose the gate over auto-loading the ~40MB engine on page
open); the Godot Control-node scenes become the visual source of truth for the interface.
The original assumption text follows for provenance:

**Assumption (flagging, not blocking):** defaulting to option 2 — native Godot UI — as
the direction to prototype first, because "one implementation, both platforms" matches
this project's existing bias (`world/`'s whole reason for being one shared project is
"movement code can never diverge between client and server by reimplementation drift" —
the same argument applies to the interface). But this is a real architectural fork with
a real cost (redoing the Claude Design visual pass by hand), not a mechanical fix, so
whoever picks this up should read both options above before starting rather than take
the assumption on faith — and Kris should get a chance to weigh in during review, since
it resets which surface (`shell/` DOM vs. Godot Control nodes) is the visual source of
truth going forward.

## Done

Both platforms show the same interface: title screen, HUD (health bar + Ingredients /
Spells / Gear), tabbed stuff panel with the Ingredients grid and card modal, working
identically on the live `/play` page and on a fresh install of the APK on an Android
phone. Update `game/README.md`'s "Known limits" section either way — this stops being an
undocumented gap once someone's made the call.

## Review

Kris installs the rebuilt APK on his phone and confirms the interface is there and
usable one-handed in landscape, same as the browser version.

## Built (2026-08-12)

The interface was rebuilt as native Godot Control-node scenes in
`land-of-lor/game/world/client/ui/` — title screen, HUD (press-hold labels, tap-to-move
passthrough), stuff panel with the always-8-across grid, and the element card with all
three rarity frames (legendary = animated foil shader) and the un-collected template.
Architecture notes in `land-of-lor/game/README.md`: `app.tscn` root flow;
`player_state.gd` is the deliberate MMOG seam (demo owned-set, placeholder health,
signals) that server-backed accounts later replace; `element_db.gd` reads
`data/elements.json`, synced from the canonical `shell/elements.js` by
`sync-elements.sh` inside both export scripts. `client_main.gd`, the six shared `.gd`
files, and the protocol are byte-identical; 64/64 pure-logic tests pass. The web shell
is now a thin tap-to-play loader (Kris chose the gate over auto-download); the card
editor + its HTML renderer stay as authoring tools (documented drift tradeoff: editor
preview vs Godot render — data cannot drift). Verified end-to-end in a CDP-driven
browser: loader → engine boot → native title → Start → live-droplet world with HUD,
1600+ remote entity updates streaming. New APK (27.7 MB, package
`au.com.cocreations.lor.game` v0.0.1, lor2026-signed) uploaded to the droplet.

Pre-existing quirk noticed while verifying (NOT introduced here, present in the old poc
web build too when connected): the client logs occasional "Parse JSON failed" console
errors during live traffic — protocol-side, frozen code, harmless to gameplay; worth a
look whenever the protocol next opens for changes.

## questions/ (0)

## deliverables (1)

- #9 — The start of the game — title screen, HUD, and your card collection (2026-08-11) — /deliverables/9