The ledger claimed the map scene renders per-location Suedtor/Aschestrasse artwork, but world-page.component.scss hardcodes a single static world-map background image; per-location artwork is only used in the context-panel thumbnail. Corrected the description to match the shipped behavior.
188 lines
11 KiB
Markdown
188 lines
11 KiB
Markdown
# First Visible Vertical Slice — Fidelity Ledger
|
||
|
||
Reference: `docs/references/world-travel-screen.png` (concept mock, Graufurt hub with
|
||
full RPG chrome: currencies, mail/friends/settings icons, "Shop" nav item, region
|
||
detail panel with encounters/rewards, "Gebiet erkunden" action).
|
||
|
||
Renders (this task, post-fix): `docs/verification/first-visible-slice-1920x1080.png`,
|
||
`docs/verification/first-visible-slice-1440x900.png`,
|
||
`docs/verification/first-visible-slice-1366x768.png`. All three captured with
|
||
Playwright/Chromium at `http://localhost:4200/world`, live API + seeded Postgres,
|
||
with Verbrannte Straße selected as the travel target (matches the reference's
|
||
state: travel panel populated).
|
||
|
||
Scope reminder: the reference is a full-game concept mock. This slice implements
|
||
only the demo character, two locations, and travel — currencies, mail/social,
|
||
settings, Shop, encounters/rewards, and "Gebiet erkunden" exploration are
|
||
out of scope by design (see Task 1–10 rulings) and are recorded below as
|
||
deliberate deviations, not defects.
|
||
|
||
## Comparison points
|
||
|
||
### 1. Shell proportions and persistent regions
|
||
|
||
- Reference: top bar (portrait, name/level, HP bar, currencies, icon row) +
|
||
left icon nav (Karte/Jagd/Quests/Inventar/Charakter/Shop) + center map +
|
||
right context panel + footer (chat/system line, world/online/time).
|
||
- Render: top bar (portrait, name/level, HP bar, brand wordmark) + left nav
|
||
(Karte enabled; Jagd/Quests/Inventar/Charakter present but disabled,
|
||
`aria-label="… ist noch nicht verfügbar"`) + center map + right
|
||
"Gebietsinfo" panel + footer (status dot + text, ornament, region name).
|
||
- Result: structural grid matches (top bar / nav+main+context / footer).
|
||
Currency row, mail/friends/settings/logout icons, and "Shop" nav item are
|
||
absent — deliberate, no such systems exist yet. No fix needed.
|
||
|
||
### 2. Artwork dominance and crop
|
||
|
||
- Reference: large painterly Graufurt gate artwork fills the map region,
|
||
`background-size: cover`-style dominant visual, quiet areas reserved for
|
||
path/nodes/panel.
|
||
- Render: `.world-page__scene` uses a single static, project-generated world
|
||
map background (`/images/backgrounds/map_ashen_realm.png`, upgraded to
|
||
`/images/backgrounds/runtime/map_ashen_realm-1440.jpg` via `image-set()`
|
||
where supported) for the whole map region, `background-size: cover`, same
|
||
compositional role as the reference's gate artwork. Per-location artwork
|
||
(`Suedtor.png` / `Aschestrasse.png`) is generated per the style guide too,
|
||
but is only used as the small thumbnail in the right "Gebietsinfo" panel
|
||
(`context-panel.component.html`), not as the map background.
|
||
- Result: matches intent for dominance/crop/compositional role. The map
|
||
region itself does not switch per-location artwork the way the reference's
|
||
single-gate mock implies — a static world map plus a per-location panel
|
||
thumbnail is an established, deliberate choice from earlier tasks, not a
|
||
regression introduced here — left as a recorded deviation, not fixed.
|
||
|
||
### 3. Typography hierarchy and control typography
|
||
|
||
- Reference: large serif location title overlaid top-left of the map, green
|
||
safety subtitle, short descriptive paragraph in the same overlay; serif
|
||
headers in the side panel.
|
||
- Render: serif (`Georgia`) location title top-left of the map
|
||
(`.world-page__location-title`); description/safety/level facts live in
|
||
the right "Gebietsinfo" panel instead of a second overlay block on the
|
||
map. Control typography (buttons, dl labels) uses the app's sans body
|
||
font with small-caps-style eyebrows ("REISEN", "GEBIETSINFO").
|
||
- Result: title hierarchy matches (serif, large, top-left). The map-overlay
|
||
vs. side-panel placement of description text is an established
|
||
information-architecture choice from earlier tasks (Task 8/9), not a
|
||
regression introduced here — left as a recorded deviation, not fixed,
|
||
since re-architecting panel content is outside this task's evidenced-defect
|
||
scope.
|
||
|
||
### 4. Dark palette, bronze borders, and blue/current state
|
||
|
||
- Reference: anthracite/black panels, bronze/gold hairline borders, blue ring
|
||
on the current-location node, gold ring + gold path on selected/target.
|
||
- Render: `--ar-bg`/`--ar-panel` dark palette, `--ar-border`/
|
||
`--ar-border-highlight` bronze/gold borders on top bar, panels, and travel
|
||
box; `.location-node--current` renders a blue marker ring (confirmed in all
|
||
three captures, "Aktueller Ort" label green), selected/target node renders
|
||
gold ring + gold dashed path (confirmed, "Ausgewähltes Ziel" label gold).
|
||
- Result: matches the style guide's colour semantics (blue = current/active
|
||
navigation, gold = selection/important action). No fix needed.
|
||
|
||
### 5. Node/path legibility
|
||
|
||
- Reference: node names + short state label beneath each node, dashed gold
|
||
connecting path.
|
||
- Render: same pattern — `location-node__name` + `location-node__state`
|
||
("Aktueller Ort" / "Ausgewähltes Ziel" / "Erreichbar"), dashed gold SVG
|
||
path between the two nodes. Legible with sufficient text-shadow contrast
|
||
against the background artwork at all three captured sizes.
|
||
- Result: matches. No fix needed.
|
||
|
||
### 6. Travel panel placement and action prominence
|
||
|
||
- Reference: travel panel overlays the bottom edge of the map itself, as a
|
||
floating box, with a full-width primary blue button.
|
||
- Render: `.world-page__travel-panel` is a separate block directly beneath
|
||
the map (not overlaid on top of it), centered, `min(29rem, 100%)` wide,
|
||
with a full-width primary button (`Reise beginnen` / `Zur Verbrannte
|
||
Straße reisen?`) using the gold-bordered, blue-tinted button style.
|
||
- Result: placement differs (below vs. overlaid on the map) — an established
|
||
layout choice from earlier tasks, not introduced or regressed by this
|
||
task. Action prominence (full-width primary button, clear label, disabled
|
||
state while travelling) matches reference intent. Not treated as a
|
||
material mismatch requiring a redesign in this verification-only task.
|
||
|
||
### 7. Context-panel information density
|
||
|
||
- Reference: region title, recommended level, "Mögliche Begegnungen" icon
|
||
row, description, "Mögliche Belohnungen" icon row, "Gebiet erkunden"
|
||
button.
|
||
- Render: "GEBIETSINFO" eyebrow, location name, selected-target note,
|
||
artwork thumbnail, description paragraph, facts list (recommended level /
|
||
safety / hunting availability).
|
||
- Result: reduced density is intentional — encounters, rewards, and area
|
||
exploration are later-gameplay systems explicitly out of scope for this
|
||
slice (per the plan's deliberate limitations). Not a defect.
|
||
|
||
### 8. Responsive behaviour at all three sizes
|
||
|
||
- Evidence (pre-fix): measured via a Playwright DOM probe —
|
||
`document.documentElement.scrollHeight` vs. `window.innerHeight`:
|
||
- 1920×1080: docHeight 1098 vs. viewport 1080 (18px overflow; footer's
|
||
bottom 18px clipped below the fold).
|
||
- 1440×900: docHeight 997 vs. viewport 900 (97px overflow; travel button
|
||
and footer entirely below the fold).
|
||
- 1366×768: docHeight 909 vs. viewport 768 (141px overflow; travel button
|
||
and footer entirely below the fold, ~half the travel panel cut off).
|
||
- Root cause: `.world-page__scene { min-block-size: clamp(30rem, 67vh,
|
||
44rem); }` sized the map purely off viewport height without accounting
|
||
for the fixed chrome around it (top bar + paddings + travel panel +
|
||
footer ≈ 395px), so the three required desktop sizes all overflowed the
|
||
viewport and pushed the footer (and, at the two smaller sizes, the
|
||
travel button) out of view without scrolling.
|
||
- **Fixed** in `apps/web/src/app/features/world/world-page.component.scss`:
|
||
changed to `min-block-size: clamp(20rem, calc(100dvh - 25rem), 44rem)`,
|
||
which sizes the map to the remaining space after the known chrome height
|
||
(with a small safety margin), while keeping the existing 20–44rem floor
|
||
and ceiling.
|
||
- Evidence (post-fix), same probe: 1920×1080 → 1080 vs. 1080 (0 overflow);
|
||
1440×900 → 900 vs. 900 (0 overflow); 1366×768 → 768 vs. 768 (0
|
||
overflow). Re-captured screenshots (see paths above) show the top bar,
|
||
nav, map with both nodes, full travel panel including the primary
|
||
button, context panel, and footer all fully visible with no clipping at
|
||
all three sizes.
|
||
- Result: **material mismatch found and fixed.**
|
||
|
||
## Above-the-fold copy diff
|
||
|
||
Every visible string across all three renders was checked against the
|
||
brief's allowed-copy categories (API content, requested navigation labels,
|
||
travel labels, restrained system/footer text):
|
||
|
||
| Text | Source | Category |
|
||
|---|---|---|
|
||
| "Aric Duskwalker", "Stufe 1", "100 / 100" | API (`/api/characters/me`) | API content |
|
||
| "Südtor von Graufurt", "Verbrannte Straße", description paragraph, "1–1", "Sicherer Ort", "Keine Jagd" | API (`/api/world/current-location`) | API content |
|
||
| "Verbrannte Straße", "00:00:10", "Niedrig" | API (`/api/world/current-location` connections) | API content |
|
||
| "Karte", "Jagd", "Quests", "Inventar", "Charakter" | side nav | requested navigation labels |
|
||
| "REISEN", "Zur … reisen?", "Ziel", "Reisezeit", "Gefahr", "Reise beginnen", "Ankunft in", "REISE LÄUFT", "Reise läuft", "Wähle einen erreichbaren Ort auf der Karte." | travel panel | travel labels |
|
||
| "GEBIETSINFO", "Ausgewähltes Ziel: …", "Empfohlene Stufe", "Sicherheit", "Jagd", "Aktueller Ort", "Ausgewähltes Ziel", "Erreichbar" | context panel / node labels | restrained system text |
|
||
| "Verbindung bereit", "Aschenfelder", "Ashen Realms" | footer / top bar | restrained system/footer text |
|
||
| "Weltzustand wird geladen…", "Weltkarte wird vorbereitet.", "Erneut versuchen" | loading/empty states | restrained system text |
|
||
| "Unable to load world state." | error fallback (`world.store.ts`) | **violation — English string in an otherwise fully German UI** |
|
||
|
||
**Fixed:** `apps/web/src/app/features/world/world.store.ts`,
|
||
`toErrorMessage()` fallback changed from `'Unable to load world state.'` to
|
||
`'Weltzustand konnte nicht geladen werden.'`, matching the German tone/case
|
||
used everywhere else in the app (e.g. `"Weltzustand wird geladen…"`).
|
||
Verified live: killed the API process, reloaded `/world`, confirmed the
|
||
in-shell error box now reads "Weltzustand konnte nicht geladen werden." with
|
||
no `window.alert()` dialog fired (Playwright `page.on('dialog', …)` listener
|
||
recorded zero dialogs across every step of the verification pass).
|
||
|
||
No invented, promotional, or placeholder copy was found anywhere in the
|
||
above-the-fold content.
|
||
|
||
## Summary
|
||
|
||
One functional/visual defect found and fixed (responsive overflow/clipping
|
||
at all three required desktop sizes — item 8). One copy defect found and
|
||
fixed (English fallback error string — copy diff table above). All other
|
||
comparison points either matched the reference's visual language directly,
|
||
or reflect deliberate, already-ruled-on scope reductions from earlier tasks
|
||
(no currencies/social/settings/Shop, reduced context-panel density, no
|
||
map-overlay description block, travel panel placed below rather than over
|
||
the map) that this verification-only task did not redesign.
|