From 7d5a774fa5274a477819e2d8f57060eb44510527 Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Sat, 25 Jul 2026 20:20:21 +0200 Subject: [PATCH] docs(assets): Phase-4 visual style bible in palette.md (T-1052) Authors the full style bible: camera table separating D-148 gameplay from D-019 offline-renderer use; the delegated toon-vs-PBR ruling (environment props share the character toon treatment, with a minimal-PBR carve-out for glass/polished metal so sightlines read truthfully under occlusion-based perception); a color/material register for every D-235 ObjectTag (hue, grain, D-217-keyed weathering); and explicit supersession notes both ways with visual-grammar-v01.md and the mood-board workshop transcript. Includes branch-side pql changelog rows (T-1050/T-1052 -> review); the worktree pre-commit export step failed benignly (write-through had already refreshed the files) so they are staged explicitly here. Co-Authored-By: Claude Fable 5 --- .pql/changelog/ticket_history/2026-07.sql | 1 + .pql/changelog/tickets/2026-07.sql | 49 +++ docs/assets/visual/palette.md | 287 +++++++++++++++++- docs/design/visual-grammar-v01.md | 12 +- .../workshop-outcomes.md | 11 + 5 files changed, 349 insertions(+), 11 deletions(-) diff --git a/.pql/changelog/ticket_history/2026-07.sql b/.pql/changelog/ticket_history/2026-07.sql index ef90fa3e7..daf72201c 100644 --- a/.pql/changelog/ticket_history/2026-07.sql +++ b/.pql/changelog/ticket_history/2026-07.sql @@ -2322,3 +2322,4 @@ INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, chang INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPV39JX54HYP83RZJFDM', 'status', 'backlog', 'in_progress', NULL, '2026-07-25 18:11:42', '2026-07-25 18:11:42.948', '2026-07-25 18:11:42.948', NULL, '613156e91577043373205250f21a72cd', 2) ON CONFLICT(hash) DO NOTHING; INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPJ910NNR5T2R9F9NWQR', 'assigned_to', NULL, 'justine', NULL, '2026-07-25 18:11:45', '2026-07-25 18:11:45.571', '2026-07-25 18:11:45.571', NULL, '7fe3851d234f1cafb2b4fc70c1f5eed8', 2) ON CONFLICT(hash) DO NOTHING; INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPV39JX54HYP83RZJFDM', 'assigned_to', NULL, 'araminta', NULL, '2026-07-25 18:11:46', '2026-07-25 18:11:46.095', '2026-07-25 18:11:46.095', NULL, '0d1336d72b0807fe85c054696e914350', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPV39JX54HYP83RZJFDM', 'status', 'in_progress', 'review', NULL, '2026-07-25 18:17:34', '2026-07-25 18:17:34.364', '2026-07-25 18:17:34.364', NULL, 'a903761710732a5f62b742cc7ca4acac', 2) ON CONFLICT(hash) DO NOTHING; diff --git a/.pql/changelog/tickets/2026-07.sql b/.pql/changelog/tickets/2026-07.sql index 927168e82..07733599e 100644 --- a/.pql/changelog/tickets/2026-07.sql +++ b/.pql/changelog/tickets/2026-07.sql @@ -3568,3 +3568,52 @@ archiving/marking those superseded, or by palette.md stating exactly what it inh Lead note (batch-5 activation): the toon-vs-PBR treatment call for environment props is delegated to araminta (art seat) this batch — her ruling lands in palette.md with rationale; surfaced to Jeroen in the batch report for cheap veto. VERDICT: READY.', 'in_progress', 'medium', 'araminta', 'visual', 'D-235', '2026-06-12 10:40:59', '2026-07-25 18:11:46.095', NULL, '4df3e92b2bc003a7b73f860dd47704f2', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPV39JX54HYP83RZJFDM', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Write the Phase-4 visual style bible into docs/assets/visual/palette.md', '(description follows in first append) + +Refinement (batch-5 Si pass, 2026-07-25) — READY. + +CURRENT STATE: docs/assets/visual/palette.md exists as a STUB (correctly re-scoped by D-244 — no +sprite-era content survives in it) — 4 bullets: camera angle (D-019, now superseded by D-148 for +gameplay — palette.md''s bullet is stale and must be corrected), entity colors (D-033), environmental +neutrality (D-045), "functional warmth." It explicitly defers to "art direction workshop synthesis and +first visual sprint" — this ticket IS that synthesis pass for Phase 4. + +WHAT D-235 ALREADY FIXES (do not re-litigate): the building-exterior material/roof/facade/street +vocabulary (WallMaterial/RoofForm/FacadeRhythm/StreetSurface, ratified as the 28-template +architecture_trait_catalog.toml / wiki/economics/object_tag_vocabulary.toml) and the fallback-to-generic +mechanism. D-235 is the LOGICAL token layer ("what material is this wall") — Phase 4+ scope per its own +Implementation note ("textured render + the bulk of the theme library are Phase 5+"). T-1052 is the +RENDERED-LOOK layer on top: given a WallMaterial token, what does concrete_wall actually look like +(hue range, texture grain, weathering baseline) when art is eventually produced against it. + +WHAT T-1052 MUST STILL AUTHOR (net-new, no existing decision covers this): + - Correct the camera-angle bullet: D-148 (30 deg low-angle Camera3D, supersedes D-019) is the GAMEPLAY + camera; D-019''s -72.5 deg survives only for the offline renderer (2D-artwork / retired sprite mode, + per renderer/README.md). palette.md''s current bullet conflates these — fix it to name both and + which applies where. + - A concrete color/material register for the D-235 token vocabulary: not new tokens, but the RANGE + each token maps to (e.g. "stone_wall reads as warm grey-tan, not cool grey" / "corrugated_metal + weathers to rust-orange, not staying silver") — the thing D-235 explicitly parked for Phase 5+ art + production but which a style bible can pre-specify so future asset generation has a target. + - Reconcile with docs/design/visual-grammar-v01.md and docs/workshops/art-direction-mood-board/ + workshop-outcomes.md (both pre-cascade, v0.1-era, sprite-framed) — extract what survives (color + relationships, "functional warmth" identity, D-033 palette) vs what''s superseded by D-235/D-244 + (era-based material ladder — explicitly retired by D-235''s own text: "Era is NOT a material filter + here"). Do not leave two contradictory style documents live without a note in one pointing at the + other''s supersession. + - Texture "grain"/rendering treatment for the D-244 3D-object reality: since objects are lit 3D meshes + now (not flat sprite fills), the style bible should say something about the toon/PBR balance — + precedent exists in client/assets/characters/shaders/ (toon.gdshader, toon_masked.gdshader, + outline.gdshader) and the glb-gen postprocess convention (roughness=1.0/specular=0.0 "for toon + compatibility" per .claude/skills/glb-gen/SKILL.md''s setup_materials() note). Confirm whether + environment props share this toon treatment with characters, or diverge — this is a real open + question the style bible should answer, not assume. + +ACCEPTANCE: docs/assets/visual/palette.md is no longer a stub; camera-angle bullet corrected; +color/material register for D-235 tokens documented; toon-vs-PBR treatment for props stated; +supersession relationship to visual-grammar-v01.md / workshop-outcomes.md is explicit (either by +archiving/marking those superseded, or by palette.md stating exactly what it inherits from each). + +Lead note (batch-5 activation): the toon-vs-PBR treatment call for environment props is delegated to +araminta (art seat) this batch — her ruling lands in palette.md with rationale; surfaced to Jeroen in +the batch report for cheap veto. VERDICT: READY.', 'review', 'medium', 'araminta', 'visual', 'D-235', '2026-06-12 10:40:59', '2026-07-25 18:17:34.364', NULL, '580bf084c1ac42555f672f44b96b6b4a', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); diff --git a/docs/assets/visual/palette.md b/docs/assets/visual/palette.md index a33965ab8..6bb9cb177 100644 --- a/docs/assets/visual/palette.md +++ b/docs/assets/visual/palette.md @@ -1,23 +1,290 @@ --- title: "Visual Palette" -description: "Art direction guide covering camera angle, entity colours, environmental neutrality, and functional warmth" +description: "Phase-4 visual style bible — camera, entity colours, environmental neutrality, D-235 material register, toon/PBR rendering treatment" type: design status: active +decision_refs: [D-019, D-033, D-045, D-148, D-217, D-232, D-235, D-244] +author: "Araminta" +updated: 2026-07-25 --- # Visual Palette -Status: **Stub** — reference art direction workshop output for current guidance. +Status: **Active** — Phase-4 style bible (T-1052). This document is the current +source of truth for rendered-look art direction. It supersedes the framing (not +every individual data point) of the two documents listed in +[Superseded documents](#superseded-documents) below. -See `docs/workshops/art-direction-mood-board/` for the established visual identity. +--- -## Key Decisions +## 1. Camera -- **Camera angle:** 15-20deg from vertical ("the angle"), rendered via orthographic Camera3D at -72.5deg from horizontal (D-019) -- **Entity colors:** Relationship-based per D-033 (green = known/friendly, amber = neutral, red = hostile, etc.) -- **Environmental neutrality:** Spaces don't visually shift with narrative state (D-045) -- **Functional warmth:** Industrial infrastructure that people made livable — not military, not luxury +Two camera records exist and apply to **different surfaces** — this was +previously conflated in this document; corrected here. -## Style Guide +| Camera | Angle | Where it applies | Status | +|--------|-------|-------------------|--------| +| **D-148** | 30° low-angle `Camera3D` tilt (−30° from horizontal in the confirmed preset convention — see D-148's 2026-07-06 editorial note), 45° static map rotation | **Gameplay** — the default in-world camera, Phase 5+ | Active, confirmed default | +| **D-019** | −72.5° from horizontal (midpoint of the old "15–20° from vertical" sprite-tilt range) | **Offline renderer only** — the retired 2D-sprite production pipeline (`renderer/`, now repurposed per D-244 as the flat-2D-artwork generator; see `renderer/README.md`) | Superseded for gameplay by D-148; survives only as an offline-render setting | -To be populated from art direction workshop synthesis and first visual sprint. +**Why both survive:** D-148 replaced D-019 as the *gameplay* camera when the +project pivoted to live 3D rendering (D-149) and then to fully 3D objects +(D-244) — there are no more pre-rendered sprites to view "at the angle" during +play. D-019's −72.5° Camera3D setting doesn't disappear, though: it is still +the correct setting for the **offline** render rig that produces flat 2D +artwork (paintings, flags, billboards, signage — the D-244(b) content class), +because that pipeline still renders a 3D scene down to a flat texture and +needs a camera angle to do it. Two different cameras, two different jobs: +one drives what the player sees, the other bakes a flat image asset. + +Do not describe D-019's angle as "the gameplay camera" anywhere — that +sentence is what this document is correcting. + +--- + +## 2. Rendering Treatment — Toon vs. PBR (delegated ruling) + +**Ruling (Araminta, delegated by team lead this batch — surfaced to Jeroen for +veto in the batch report):** + +**Environment props and furniture share the character toon treatment.** One +shader family, one look, across the whole in-world scene — with a single, +narrow, explicitly-named exception for glass and polished/mirror-finish metal, +which get a distinct minimal-PBR material rather than being forced through +the flat toon response. + +### 2.1 What "sharing the toon treatment" means concretely + +- Environment `.glb` models use the same shader family as characters: + `toon.gdshader` (flat lit/shadow-band ALBEDO, no PBR lighting response) or + `toon_masked.gdshader` (recolor-mask variant, for props that need + runtime tint — e.g. a favorite-color object, a faction-liveried crate) + where a tintable variant is needed. `outline.gdshader` (inverted-hull) applies + to entities and to any prop the visual hierarchy calls out for emphasis (see + §4 tie-in below) — not universally to every static prop, matching the + existing entity > object > structure outline-weight hierarchy. +- glb-gen's postprocess convention of forcing `roughness=1.0` / `specular=0.0` + "for toon compatibility" (`postprocess_glb.py::setup_materials()`) is + **correct and should stay the default** for furniture, crates, signage, + street furniture, wall/roof/facade instances — i.e. the D-235 ObjectTag + vocabulary's bulk. These are flat-lit like characters; PBR specular + highlights on a stucco wall or a wooden table would read as wet/glossy and + contradict the toon language players already learn from characters. +- **Exception — glass and polished/mirror metal:** `precision_glass`/ + `glass_curtain_wall` (facade), `smart_facade`, and any deliberately + reflective/polished metal prop (chrome fixture, mirror, glossy display + case) get a **separate minimal-PBR material**: `roughness` in the 0.05–0.2 + range and non-zero `specular`/`metallic` as appropriate, layered so the toon + shadow-band lighting model still governs the base surface response but a + specular highlight and partial reflection are allowed through. This is not + a full PBR material (no environment-map reflections, no fresnel-driven + rim lighting stack) — it is "toon base + a controlled specular term," + the smallest change that makes glass/chrome read as glass/chrome instead + of matte plastic. + +### 2.2 Rationale + +- **Visual grammar principle (mine, standing):** consistency compounds. A + station built from one shader family reads as one coherent object, the way + a real Rimworld or Hades scene does. Mixing a toon character against a + PBR-lit room breaks the "one world" read the moment the player looks at + their own hands next to a table. +- **The postprocess default already assumes this.** `setup_materials()`'s + comment ("for toon compatibility") was written for the character pipeline + but Trellis is the *same* generator for environment `.glb`s — there was + never a second postprocess path. Diverging environment props onto full PBR + would mean either forking the postprocess script or hand-overriding every + environment asset's material after generation. Sharing the treatment means + the existing pipeline is already correct and needs no new work. +- **The exception is functionally forced, not a taste call.** A flat-lit + `roughness=1.0` glass pane doesn't read as glass — it reads as a frosted + grey panel, which actively misleads the player about sightlines (can I see + through this?) in a game whose core mechanic is occlusion-based perception. + Where "can the player see through/into this" is gameplay-load-bearing + (`glass_curtain_wall`, `precision_glass`, shop windows, interior partitions), + the material needs to look transparent/reflective enough to answer that + question at a glance. This is a narrow, named carve-out — it does not + reopen "should props be PBR," it closes the one case where toon-only + actively lies to the player. +- **Scale check:** this holds at boxes-with-labels (a labelled box has no + material response either way, so the ruling is inert today) and at full + art fidelity (the shader assignment is a material-slot choice per asset, + not a structural decision that needs revisiting later). + +### 2.3 What this does NOT change + +- D-235's material/token vocabulary (§3) is unaffected — this ruling is about + shader/material *response*, not which WallMaterial/RoofForm tokens exist. +- The character shader files (`toon.gdshader`, `toon_masked.gdshader`, + `toon_garment.gdshader`, `outline.gdshader`) are not modified by this + ruling — environment props reuse them as-is or via a near-identical + environment-scoped shader variant if slot/uniform needs differ + (implementation detail for whoever writes the first environment shader, + not an art-direction fork). + +--- + +## 3. Color / Material Register — D-235 ObjectTag Vocabulary + +D-235 (amended 2026-07-07, T-995) ratified the **logical** token vocabulary — +`wiki/economics/object_tag_vocabulary.toml`, 4 axes (wall/roof/facade/street), +32 specific tags + 4 generic fallback parents. D-235's own Implementation note +explicitly parks the **rendered look** of those tokens for "Phase 5+ and +post-launch" art production. This section is that pre-specification: not new +tokens, but the register each shipped tag should render into once art exists, +so asset generation has a target from day one instead of drifting per-artist. + +**How to read this table:** "Hue range" is a rendered-look target for the +BaseColor map's dominant tone, expressed relative to D-235's existing rule +that *color is template-bounded* (a cultural palette cue, seed-selected within +range, "always within the template's register") — this section does not +override that; it gives the physically-plausible hue family each material +naturally sits in, which the template's seed then picks within. "Weathering +baseline" describes how the D-217 condition bands (Intact/Worn/Cracked/Broken, +driven by `prosperity_score`) should visually read for that material — i.e. +what "Worn" looks like on brick vs. on corrugated metal. + +### 3.1 Wall materials + +| Tag | Hue range | Grain / texture character | Weathering baseline (D-217 bands) | +|-----|-----------|---------------------------|-----------------------------------| +| `concrete_wall` | Neutral grey, warm-leaning (`#8a8680`–`#6e6a64`) — never blue-grey/cool-grey | Fine aggregate speckle, subtle formwork seams | Intact: even matte. Worn: rain-streak staining, hairline cracks. Cracked: spalling at edges, exposed aggregate. Broken: structural cracking, rebar-stain bleed. | +| `steel_frame` | Dark warm charcoal (`#3a3632`) frame, infill panel per adjacent tag | Visible bolted/riveted joints, slight surface oxidation tint even when "new" | Intact: factory-primer flat. Worn: surface rust bloom at joints/edges only. Cracked: running rust streaks below joints. Broken: structural rust-through, buckling. | +| `brick_wall` | Warm terracotta-to-ochre (`#9c5a3c`–`#c48a52`), never cool/pink brick | Visible coursing + mortar joint shadow, slight color variance per brick (batch variation) | Intact: crisp mortar lines. Worn: mortar erosion, efflorescence (white mineral bloom). Cracked: spalled brick faces, missing mortar. Broken: collapsed coursing, exposed cavity. | +| `rendered_wall` | Whatever the template's color_range picks — this tag is a **finish**, not a hue driver; render surface is smooth and matte regardless of picked hue | Smooth, minimal grain, occasional hairline render-crack pattern at Worn+ | Intact: clean flat. Worn: surface staining/streaking under sills and joints. Cracked: render cracking, patches of exposed substrate. Broken: large render loss, substrate fully exposed. | +| `stone_wall` | Warm grey-tan (`#a89e8c`–`#8c8172`) — **explicitly not cool grey**; this is the D-235 fallback-graph's flagship "gets it wrong if literal" case | Visible coursing, natural stone color variance tile-to-tile, tool-marked or rough-cut surface depending on template | Intact: clean-cut edges. Worn: lichen/mineral staining in shadowed recesses. Cracked: mortar loss between courses, chipped arrises. Broken: displaced/missing stone units. | +| `timber_wall` | Warm mid-brown (`#7a5c3e`–`#9c7a52`), never grey-driftwood unless template explicitly calls for weathered/coastal register | Visible grain direction, board/plank joint lines | Intact: sealed/painted finish. Worn: graying at exposed edges, finish wear. Cracked: splitting along grain, missing sealant. Broken: rot, structural failure at joints. | +| `stucco_wall` | Warm off-white to sand (`#d8cfc0`–`#c4b89e`) — whitewashed per the tag description, not pure white | Smooth, slight hand-applied texture variance | Intact: clean whitewash. Worn: staining streaks below any protrusion. Cracked: hairline cracking, patch-color mismatch. Broken: large loss exposing substrate. | +| `glass_curtain_wall` | Neutral-to-cool tint on the glass itself (`#c8d4dc` @ low opacity) — see §2.1 PBR exception, this tag needs the specular/transparency carve-out to read correctly | Minimal — reflection/transparency IS the surface character | Intact: clean, full reflectivity. Worn: dust film, reduced reflectivity. Cracked: visible cracked panes, some opacity/frosting. Broken: missing panes, boarded sections. | +| `composite_panel` | Whatever the template picks — this is a **prefab finish** tag like `rendered_wall`, hue is template-driven, not material-driven | Flat, uniform, visible panel-seam grid (regular rhythm, unlike masonry coursing) | Intact: crisp seams, clean finish. Worn: seam staining, minor panel discoloration. Cracked: panel warping, seam gaps. Broken: missing/detached panels. | +| `rammed_earth_wall` | Warm ochre-to-umber banding (`#8a6a48`–`#6e5236`) | Strong horizontal layer banding (the construction method's signature texture) | Intact: crisp banding. Worn: surface erosion softening band edges. Cracked: vertical cracking across bands. Broken: section collapse/erosion loss. | + +### 3.2 Roof forms + +| Tag | Hue range | Grain / texture character | Weathering baseline | +|-----|-----------|---------------------------|----------------------| +| `flat_roof` | Neutral dark grey (`#4a4844`) membrane | Flat, minimal detail, visible seam lines on membrane roofing | Intact→Broken: ponding stains, membrane cracking, vegetation growth at Broken. | +| `pitched_roof` | Warm dark grey-brown (`#4e463e`) generic shingle/slate register unless a specific tag (below) narrows it | Directional shingle/slate coursing | Moss/lichen accumulation in shadowed pitches as condition drops; missing units at Cracked+. | +| `corrugated_roof` | Weathers to **rust-orange** (`#a65c34` at Worn+), starts galvanized silver-grey (`#a8aaa8`) when Intact — **explicitly does not stay silver**, this is D-235's own worked example | Strong linear corrugation shadow pattern | Intact: clean galvanized sheen. Worn: rust bleeding from fastener points. Cracked: broad rust staining, sheet lifting at edges. Broken: rust-through holes, missing sheets. | +| `clay_tile_roof` | Warm terracotta (`#b56a3e`–`#c8825a`) | Individual tile coursing, slight per-tile hue variance | Moss/lichen in valleys, cracked/slipped/missing tiles as condition drops. | +| `terraced_roof` | Match the deck surface (paved/planted per template), not a distinct roof hue | Flat deck texture, visible rail/parapet line | Surface wear on deck material, planter/rail deterioration at lower bands. | +| `vaulted_roof` | Match wall material register (masonry vaults read as an extension of the wall) | Strong directional shadow from the vault curvature | Standard masonry weathering (see stone/brick wall rows). | +| `green_roof` | Vegetated green, seasonally variable — the one roof tag where hue is intentionally NOT template-locked | Organic, irregular, canopy-like from above | Condition reads as vegetation health/coverage, not surface damage — sparse/patchy at low prosperity, not "broken" in the structural sense. | + +### 3.3 Facade rhythms + +Facade tags are about **pattern**, not hue — they inherit the wall tag's +color register. Grain/weathering guidance: + +| Tag | Grain / texture character | Weathering note | +|-----|---------------------------|-------------------| +| `regular_facade` | Even punched-window grid, no added ornament | Weathers uniformly with the wall tag beneath it. | +| `ornamental_facade` | Raised/carved detail catches shadow distinctly from the flat wall plane | Ornament erodes/chips *before* the flat wall does — detail loss is the earliest visible sign of Worn. | +| `industrial_glazing` | Regular steel-mullion grid, factory-sash proportions (wide, short panes) | Mullion rust (if `steel_frame`) precedes glazing damage. | +| `arcade_facade` | Strong repeating vertical shadow rhythm from the colonnade | Ground-level wear concentrates at column bases (foot traffic), not evenly. | +| `shuttered_facade` | Shutters as a distinct, often higher-saturation accent color against the wall's muted register — this is the one facade tag allowed a saturation bump (bounded by §5's object-tier ceiling below) | Shutter paint fades/peels faster than the wall behind it — a secondary, faster weathering clock on the same building. | +| `screen_facade` | Fine repeating perforation/louvre pattern, strong dappled shadow | Screen material (usually metal or timber lattice) weathers per its own material, independent of the wall plane behind. | +| `colonnade` | Freestanding column rhythm, deep shadow gaps between wall plane and columns | Column bases weather fastest (ground contact, foot traffic) — same principle as arcade_facade. | +| `lattice_screen` | Fine timber/metal lattice, mashrabiya-register — highest facade information-density texture in the set | Individual lattice elements can go missing at Cracked+ without the whole screen reading as "broken." | + +### 3.4 Street surfaces + +| Tag | Hue range | Grain / texture character | Weathering baseline | +|-----|-----------|---------------------------|----------------------| +| `paved` | Neutral grey (`#66645e`) | Fine asphalt/poured texture, minimal joint pattern | Cracking, pothole pattern, patch-color mismatch (repairs never quite match original pour age). | +| `cobble` | Warm grey-tan, matches `stone_wall`'s register | Strong individual-unit texture, visible mortar/sand joints | Displaced/missing setts at low condition, not surface cracking (it's a unit system, not a monolithic pour). | +| `packed_earth` | Warm ochre-brown (`#7a6248`) | Irregular, rutted, no joint pattern | Erosion channels, puddling, vegetation encroachment at edges as condition drops (or rises — an unmaintained packed-earth street can look "worse" toward Intact-adjacent if it's simply less used, this tag is condition-light). | +| `canal_way` | Water surface — hue driven by reflection/sediment, not a fixed material hue | N/A — water plane, not a solid surface | Water clarity/debris accumulation stands in for the condition ladder here. | +| `elevated_walkway` | Match structural material used (steel_frame/timber/composite per template) | Grated or planked, visible support structure below | Structural weathering per the material tag, plus grate/plank gap wear from foot traffic. | +| `heavy_haul` | Neutral dark grey (`#4e4c48`), reinforced-surface register | Deep rut/track wear pattern, wider joint spacing than `paved` | Track-line wear concentrates on wheel paths, not the full surface — an asymmetric wear pattern unlike `paved`'s even cracking. | +| `boardwalk` | Warm grey-brown weathered timber (`#8a7a64`), coastal/wetland register — assume some grey weathering even at Intact, unlike `timber_wall` | Plank coursing, visible gap joints | Individual plank replacement creates natural color patchwork even at high condition — this is the one street tag where slight inconsistency reads as *authentic*, not neglected. | + +### 3.5 Generic fallback placeholders + +`generic_wall` / `generic_roof` / `generic_facade` / `generic_street` render +as a **flat, neutral, low-saturation grey** (`#6e6c68`, roughly the mean of +the specific tags' hue ranges above) with **no grain and no weathering +variation** — condition bands still apply structurally (a generic-fallback +wall can still be "Broken" in silhouette/damage terms) but carry no material +texture, so the player reads "this is a wall, its specific material hasn't +loaded yet" rather than mistaking it for a deliberate concrete/stone choice. +This is the visual expression of D-235's fallback chain — a placeholder must +look *unfinished*, not like a legitimate flat concrete building, or its +eventual upgrade-in-place would read as an inconsistent hue reskin instead of +"detail arriving." + +--- + +## 4. What Survives from Prior Documents + +Per D-244 (2026-06-16) and this ticket's acceptance criteria, the following +principles from the pre-cascade documents are **inherited**, restated here in +current (3D, D-235-token) terms rather than the old (2D sprite, era-ladder) +terms they were originally written in: + +| Inherited principle | Original source | Current expression | +|----------------------|------------------|----------------------| +| **D-033 entity color = relationship to player** | visual-grammar-v01.md §3 | Unchanged — still the live decision, still the single most important color system in the game. Applies to entities regardless of render fidelity (rectangle, sprite, or 3D mesh). | +| **"Functional warmth"** — industrial infrastructure that people made livable, not military/not luxury | workshop-outcomes.md visual identity statements + Gore's naming | Standing mood target for the whole D-235 register above: hue ranges lean warm (terracotta, ochre, warm grey) rather than cool/clinical by default; the *cool* end of the palette is reserved for deliberately institutional template registers, not the default. | +| **Environmental neutrality — strict zero shift (D-045)** | workshop-outcomes.md §1.10 | Unchanged, still active. The D-235 material register above is diegetic/static — condition bands (D-217) shift with simulated `prosperity_score`, never with narrative/investigation state. This document adds no new exception to D-045. | +| **Entity always wins visual ties** (visual hierarchy: entity > object > structure) | visual-grammar-v01.md §1.4 / workshop-outcomes.md §1.4 | Survives as a rendering-order and saturation-hierarchy principle. In 3D terms: entity materials/outlines render at the highest effective saturation and are never occluded in a way that reads ambiguous against a similarly-toned prop. The saturation ceiling table (below) replaces the old sprite-outline-weight table. | +| **Object favorite-color saturation ceiling** | visual-grammar-v01.md §3.6 | Restated: entity colors (D-033) remain the highest-saturation elements in any scene; object/prop colors (including the `shuttered_facade` accent exception in §3.3) stay moderate; structure/material register (§3) stays lowest. Same three-tier ceiling, now anchored to D-235 tags instead of "Era 1/2/3" object palettes. | +| **Readability over beauty** | workshop-outcomes.md Principle 1 | Standing design principle, unchanged, applies to 3D rendering exactly as it applied to sprites. | +| **Lighting-driven atmosphere, not baked mood** | workshop-outcomes.md Principle 2 / visual-grammar-v01.md's "sprites are shape templates" | Re-expressed in §2 above: toon shading gives shape + local shadow-band response; scene lighting (not baked texture darkening) still carries mood. The specific mechanism (Light2D CanvasModulate) is retired with the sprite pipeline, but the principle — materials stay neutral, the lighting rig does the emotional work — carries forward to whatever 3D lighting setup Phase 5 builds. | + +--- + +## 5. Superseded Documents + +Two earlier documents overlap this one. Both are **explicitly marked +superseded** here (and should carry a pointer back to this section) so no two +contradictory style documents stay live at the same time: + +- **`docs/design/visual-grammar-v01.md`** — already carries its own + superseded banner (2026-06-12, pointing at D-235/D-228 + + character-visuals-spec.md). That banner is correct and unchanged by this + ticket. What's **specifically superseded**: the entire sprite-era + production model (§2 entity sprite dimensions, §4 z-level stack as sprite + layers, §5 typography-for-sprite-canvas sizing, §6 two-tier animation + frame-count tables, §9 resolution chain / Nano Banana workflow, and the + **three-construction-era material ladder** (§1.2–§1.4's Era 1/2/3 zone + palettes) — the era ladder is the exact thing D-235 retired by name + ("Era is NOT a material filter here"). What's **not superseded, just + relocated**: D-033 entity color values and D-045 environmental neutrality, + both restated current in §4 above. +- **`docs/workshops/art-direction-mood-board/workshop-outcomes.md`** — this + is a workshop transcript (type: workshop, status: archived) and correctly + stays archived as a historical record; it is **not** live style guidance + and should not be read as such. Its **candidate decisions** (D-042 through + D-051 as originally proposed in §7) were formally recorded as the + perception.md decisions cited throughout this document (D-033, D-043, + D-044, D-045, D-046 etc.) — those decision records are the living + artifact, not the workshop prose. Its **three-construction-era material + system** (§1.8) is superseded by D-235 for the same reason as above. Its + **camera angle content** (§1.2, §9.3) is superseded by D-148 per §1 above. + Everything else in it (lighting three-reference model, fog cone shape, + two-tier animation, insert overlay bloom spec, z-stack layer *concept* — + not its sprite-specific implementation detail) remains valid design + intent, inherited into current decisions rather than into this document + directly. + +**Going forward:** this document (`palette.md`) is the single live style +bible for Phase 4+ rendered look. New style guidance should land here, not in +a new parallel document, unless it's genuinely a different concern (e.g. the +model-naming/manifest conventions living in `docs/assets/visual/conventions.md`, +authored separately under T-1050). + +--- + +## Appendix — Decision Cross-References + +| Decision | Relevance | +|----------|-----------| +| D-019 | Original top-down camera + offline-renderer −72.5° angle. Superseded for gameplay by D-148; survives for the offline 2D-artwork render rig. | +| D-033 | Entity color = relationship to player. Unchanged, still the primary information-bearing color system. | +| D-045 | Environmental neutrality — strict zero shift. Governs how the D-235 material register (§3) may and may not respond to game state. | +| D-148 | 30° low-angle gameplay `Camera3D`, supersedes D-019 for gameplay. | +| D-217 | Tile condition thresholds (prosperity_score bands) — the weathering-baseline mechanism referenced throughout §3. | +| D-232 | Trait-template catalog — era reframed as maintenance/wear + past-vogue holdover, not a material-tech ladder. Backing rationale for retiring the Era 1/2/3 ladder in §5. | +| D-235 | Building exterior visual grammar + ratified ObjectTag vocabulary (`object_tag_vocabulary.toml`). §3 is this document's rendered-look layer on top of D-235's logical tokens. | +| D-244 | 3D objects in-world; 2D limited to textures + flat artwork. Establishes the toon-shader-family context for §2 and retires the sprite catalog framing this document used to have. | diff --git a/docs/design/visual-grammar-v01.md b/docs/design/visual-grammar-v01.md index 4851d2308..35f2cfc2b 100644 --- a/docs/design/visual-grammar-v01.md +++ b/docs/design/visual-grammar-v01.md @@ -8,9 +8,19 @@ decision_refs: [D-033, D-043, D-044, D-045, D-046, D-047, D-048, D-049, D-052, D author: "Araminta" created: 2026-02-19 updated: 2026-02-20 -superseded_by: "D-235/D-228" +superseded_by: "D-235/D-228, docs/assets/visual/palette.md" --- > **SUPERSEDED (2026-06-12, cascade-refocus sweep):** superseded by D-235/D-228 (generated-world visual grammar) + docs/design/character-visuals-spec.md (character rules). Kept as historical record; do not build against it. +> +> **Style-bible pointer (2026-07-25, T-1052):** the live Phase-4 style bible is +> `docs/assets/visual/palette.md`. Its §4/§5 spell out exactly what survives from +> this document (D-033 colors, "functional warmth," the visual-hierarchy/saturation +> principles) versus what's superseded (the sprite-era production model: entity +> sprite sizing, the 8-layer sprite z-stack, sprite typography sizing, animation +> frame counts, the resolution chain, and — specifically — the **three-construction-era +> material ladder** in §1.2–§1.4, which D-235 retired by name: "Era is NOT a material +> filter here"). Read palette.md first; come back here only for historical +> attribution. # The Settled Reach — v0.1 Visual Grammar diff --git a/docs/workshops/art-direction-mood-board/workshop-outcomes.md b/docs/workshops/art-direction-mood-board/workshop-outcomes.md index e36d7b0f6..e183f2109 100644 --- a/docs/workshops/art-direction-mood-board/workshop-outcomes.md +++ b/docs/workshops/art-direction-mood-board/workshop-outcomes.md @@ -18,6 +18,17 @@ decision_refs: [D-015, D-019, D-024, D-031, D-033, D-035, D-041, D-042, D-043, D **Rounds:** 3 + Closing + Post-workshop technical session (Tyre, Araminta, Stig) **Status:** Complete — all items resolved, ready for formal decision recording. Pipeline test in progress. +> **Archived transcript, not live style guidance (2026-07-25, T-1052):** this is a +> workshop record — read it for attribution and reasoning history, not as current +> art direction. Its candidate decisions (§7) were formally recorded as the +> perception.md/architecture.md decisions cited throughout (D-033, D-043–D-051); those +> D-records are the living artifact. Its camera-angle content (§1.2, §9.3) is +> superseded by [D-148](../../../governance/decisions/architecture.md#d-148-30-low-angle-camera-with-45-map-rotation--supersedes-d-019). +> Its three-construction-era material system (§1.8) is superseded by +> [D-235](../../../governance/decisions/architecture.md#d-235) ("Era is NOT a material +> filter here"). The current Phase-4 style bible is +> [`docs/assets/visual/palette.md`](../../assets/visual/palette.md) — start there. + --- ## Visual Identity Statements