Mushroom Alien Games — Website Devlog
Append-only. New entries at the bottom.
2026-08-26 — Phase 1 session
Branch: redesign Changed:
assets/css/main.cssrewritten as Layer 1 perDESIGN_SYSTEM.md: cream/panel/teal/orange/rule tokens, Archivo/IBM Plex Serif/IBM Plex Mono, 8/16/24/32/48/64/96 spacing scale as custom properties.- Old navy/gold system preserved verbatim in new
assets/css/legacy-game.css, every rule scoped under a.legacy-navy-goldclass (mirrors the Layer 2 mechanism inSITE_ARCHITECTURE.mdrather than relying on stylesheet load order)._layouts/default.htmlputs that class on<body>, and loadslegacy-game.cssplus the old Fraunces/Public Sans font stack, only whenpage.layout == 'game'. Result: Salt & Stone’s page body renders exactly as before; header and footer on that page now use the new Layer 1 system (confirmed with Willem this session — see Decisions flagged). _includes/header.html: wiredmag_colour.svgin as the wordmark (copied toassets/img/brand/mag_colour.svg); added a fixed minimal CTA bar (“Get in touch” →/#contact) that appears once the full header scrolls out of view, viaIntersectionObserver(no scroll listener)._includes/footer.html: version stamp motif (page title · vGG.YYMM.rrrr (Stable|WIP) · © year Willem van Wyk), sourced from new_config.ymlkeysversion/version_status; small wordmark added.- Field-guide component set built in
main.cssand actually applied on Home/Games/Updates:.fig-label(Fig. 01/02/03 on the three homepage sections),.caption(meta lines, version stamp),hr.hairline(full-width section dividers, replacing the old automaticsection{border-top}),.panel(game cards, update items). - Fixed the old system’s mobile nav dead-end (
nav.site-links{display:none}under 560px, no replacement) — nav now wraps and stays reachable. - Moved every orange usage the old file had at body/small-meta text size (post links, “See the game →”, update tags) to teal-faded with an underline — orange is now only on
.fig-label, the CTA button, the nav’s current-page state, and one large emphasised word in the homepage<h1>, all UI/large-text per the contrast table. - Added
.gitignore(_site/,.bundle/,vendor/, jekyll cache) and excludedvendorfrom Jekyll’s own build in_config.yml— needed once Bundler was installed locally this session, otherwise Jekyll tried to build the gem source tree invendor/bundleas site content. _layouts/post.htmlgiven the.captionclass on its meta line for consistency (page itself unchanged otherwise, not in Phase 1’s required scope but shares the same layout chain).
Decisions flagged:
- Salt & Stone header/footer, this phase: brief said the page was “untouched” this phase; asked Willem directly whether that meant the whole page including header/footer, or just the page body. Confirmed: new Layer 1 header/footer render on Salt & Stone now too, only the hero/pillars/flip-cards/illustration stay on the old system until Phase 2’s proper Layer 2 accent replaces
legacy-game.cssoutright. - Site version stamp value: no
versionkey existed in_config.ymlbefore this session. Addedversion: "01.2608.0001",version_status: "WIP"(first stamp, odd revision = WIP per the versioning convention). Flag back to Willem — pick your own value if0001isn’t where you want to start. - Local environment had no Ruby/Bundler at session start. Willem installed Ruby system-wide mid-session at my request; I then did
gem install --user-install bundlerandbundle config set --local path 'vendor/bundle'(no sudo available) to getjekyll serverunning for verification.
DoD check (Phase 1, per BUILD_BRIEF.md):
- Home, Games index, Updates index render in the new system with consistent header/footer/typography — Pass (verified via
jekyll build/jekyll serve+curl, HTML inspected directly; see gotcha below on what wasn’t checked). jekyll servebuilds clean, no console errors — Partial pass. Build is clean (bundle exec jekyll buildexits with no errors or warnings beyond a Faraday retry-middleware notice, unrelated to this work). Console errors could not be checked: no browser automation tool (claude-in-chromenot connected, nochromium-cli/Playwright/node in this environment) was available this session, so nothing was visually rendered or screenshotted. The sticky-header script and CSS were verified by reading the served HTML/CSS output only, not by rendering it. This needs a real preview pass from Willem before the phase is fully signed off, particularly the mobile viewport check and the sticky-CTA scroll behaviour.
Gotchas:
- This container has no Ruby/Bundler/browser-automation tooling by default — future sessions needing
jekyll serveor a visual/console check should expect to ask Willem to install Ruby (no passwordless sudo) and should flag if visual verification isn’t possible rather than assuming it happened. - Bundling with the default gem path tries to
jekyll buildits ownvendor/bundlegem source as site content unlessvendoris in_config.yml’sexcludelist — add it up front next time bundler is set up locally in-repo. - First pass through the verification checklist, the contrast re-check was done by eye against DESIGN_SYSTEM.md’s existing table rather than actually computed for the new pairs this session introduced (text on
.panel). Willem asked to see the numbers — always actually run the WCAG maths for any new colour/background pairing, don’t just reason from the existing table.
2026-08-26 — Phase 1 follow-up: badge-only crop
Branch: redesign Changed:
mag_colour.svg’s two compound paths (path9teal#06373c,path10orange#c85915) each contain both the badge illustration and the wordmark as separate subpaths within onedstring — there’s no existing “badge path” to isolate. Parsed all 90 subpaths withsvgelements, clustered by y-extent, and found a clean ~30-47px gap separating one contiguous block from the rest: badge subpaths span y 114.12–910.87, wordmark subpaths (3 lines) span y 957.97–1258.12. Badge height as a fraction of the 1402-tall canvas: 56.83% (y0 = 8.14%, y1 = 64.97%) — confirms DESIGN_SYSTEM.md’s “~55-60% by eye” note against actual geometry rather than just trusting the estimate.- Badge-only x/y bbox across those subpaths: x 291.204–822.890, y 114.121–910.867 (width 531.686, height 796.746). Rounded outward to whole pixels (floor min, ceil max, so nothing clips): viewBox
291 114 532 797. - New
assets/img/brand/mag_badge.svg: copy ofmag_colour.svgwith only the outer<svg>width/height/viewBox changed to that crop and the editor-onlysodipodi:namedviewblock dropped. Both<path d="...">strings are byte-identical to the source (diffed to confirm) — genuinely a viewBox crop, no path data touched. - No padding added around the tight bbox — flagging that as still open rather than silently picking a padding amount (per CLAUDE.md’s “don’t silently decide asset crops”). If it reads as cramped in the header, tell me a padding percentage/px and I’ll adjust the viewBox.
_includes/header.html: both logo instances (full header on load, sticky-CTA mini bar) repointed frommag_colour.svgtomag_badge.svg— these are the two spots that were squeezing the full badge+wordmark lockup into a ~40px/~26px-tall header strip, shrinking the badge itself to near-illegible size._includes/footer.htmlleft unchanged (stillmag_colour.svg, full lockup) — confirmed via grep this was the only other usage site, and it’s an explicit exception per this session’s direction (full mark reads fine at footer’s more generous, less height-constrained placement).
Decisions flagged:
- The exact crop is
viewBox="291 114 532 797"(badge aspect ratio 0.667, ~2:3 portrait) — this is the reference to use for a future favicon export too, per the asset inventory in DESIGN_SYSTEM.md. Didn’t edit that doc’s asset-inventory table myself since it’s a locked/versioned reference doc — flagging the numbers here for whoever updates it next. - Padding around the badge crop is a live open question (see above) — zero padding shipped, deliberately not eyeballed.
2026-08-26 — Phase 1 follow-up: header wordmark restored beside badge
Branch: redesign Changed:
- The badge-only crop fixed legibility but dropped the studio name entirely, since the original lockup paired it below the badge (now cropped off). Rather than re-embedding the full stacked lockup at header scale, typeset “Mushroom Alien Games” as real text next to the badge — Archivo 700, uppercase,
var(--teal)only (no orange), matching the “wordmark companion” pairing DESIGN_SYSTEM.md already specifies for Archivo, and avoiding a second orange element in the same viewport as the nav’s orange.currentindicator. _includes/header.html: main header’s.brandlink now holds the badge image (alt="", now decorative) plus a<span class="brand-wordmark">Mushroom Alien Games</span>that carries the link’s accessible name. Sticky-CTA mini bar left badge-only (kept itsalt="Mushroom Alien Games") — it’s the “sticky minimal bar” per BUILD_BRIEF’s own phrasing, and adding the full wordmark there would compete with the CTA button for very little horizontal space.assets/css/main.css:.brandgetsgap: var(--sp-16)for the badge/text pairing;.brand-markreduced from 80px back to 60px now that it doesn’t have to carry identity alone; new.brand-wordmark(Archivo 700, 1.05rem, uppercase, teal); new@media (max-width:420px)rule stacks badge above text (flex-direction:column) instead of letting the wordmark wrap awkwardly beside the badge — separate, narrower breakpoint from the existing 560px nav-stacking rule since it’s a distinct concern (brand-row wrapping vs. nav reachability).- No screenshot produced — no headless browser in this container (chromium-browser here is a snap package, more setup than the earlier Ruby install) and Willem opted to skip installing one for this change. Verified via rebuilt HTML output and by reading the CSS/cascade directly instead.
Decisions flagged:
- Went with Willem’s stated mild preference: all-teal wordmark, no second colour, rather than matching the original lockup’s two-tone treatment.
- The 420px stacking breakpoint is a reasoned estimate (badge + nowrap uppercase Archivo text at that size), not something rendered and measured — flagging it as the one number in this change that would benefit most from an actual preview.
2026-08-27 — Fix: .wrap/.hero padding-shorthand collision (zero horizontal margin on real devices)
Branch: redesign
Changed: root cause confirmed by Willem — .wrap{ padding: 0 var(--sp-24); }’s 2-value shorthand explicitly zeroes padding-top/padding-bottom, not just the intended horizontal gutter. Combined with .hero{ padding: var(--sp-64) 0 var(--sp-48); } on the same element (<section class="hero wrap">), both are single-class selectors at tied specificity, so source order decides — .hero is declared later in the file and wins outright, zeroing left/right in the process. Result: hero content had no horizontal margin on real devices.
.hero: shorthand replaced withpadding-top/padding-bottomonly, exactly as specified — no declaration touches left/right at all now.- Grepped every
padding:/margin:shorthand inmain.cssand cross-referenced against everyclass="...wrap..."combination across_includes/,_layouts/, and the three index pages. Found the identical shape in two more places, both confirmed combined with.wrapin markup:.post-header(post.html:<section class="post-header wrap">) — same tied-specificity/source-order mechanism as.hero. Fixed the same way.section(bare type selector, base rule + the 640px media query) — combined with.wrapon every plain<section class="wrap" id="...">(the three homepage sections, games/updates index bodies). This one is a different mechanism, not source-order:sectionis a type selector, permanently lower specificity than.wrap’s class selector, so convertingsection’s shorthand to longhand alone doesn’t fix anything —.wrap’s own shorthand still explicitly zeroes padding-top/bottom at higher specificity regardless of order. The actual root cause is.wrapitself declaring vertical padding it was never meant to own. Fixed.wrapto longhandpadding-left/padding-rightonly (dropped the top/bottom:0 it never needed), which is what actually restoressection’s 64px/32px vertical padding on every page — convertedsection’s shorthand to longhand too, for consistency/hygiene, though after the.wrapfix it’s no longer strictly load-bearing.- Practical effect of the
section/.wrapbug: every plain homepage/index section (not.hero, not.post-header) had been rendering with zero vertical padding site-wide until this fix — a real, previously-undetected regression, not just the one spot flagged.
- Checked
header.siteandfooter’s identical-shaped shorthands (padding: var(--sp-24) 0/padding: var(--sp-32) 0 var(--sp-48)) against markup — confirmed not a bug: in bothheader.htmlandfooter.html,.wrapsits on an inner child<div>, never the same element asheader.site/footeritself, so there’s no collision. Left both as intentional full-bleed-background-plus-inset-content shorthands. .sticky-cta-inner(also combined with.wrapviaclass="wrap sticky-cta-inner") was already longhand top/bottom-only from when it was written — no fix needed there.- Not touched:
legacy-game.css’s.legacy-navy-gold .hero{ padding: 90px 0 70px; }has the identical collision with.wrapon the Salt & Stone page (<section class="hero wrap">ingame.html) — and it’s a pre-existing bug that predates this redesign (the original site had the same two-tied-class/source-order shape). Left alone deliberately: Salt & Stone’s page body is still out of scope until Phase 2, and Phase 1’s own rule is not to touch it. Flagging it so it doesn’t get lost — Phase 2 should either fix it while rebuilding the page’s CSS, or carry it over if Willem wants to confirm it’s actually a problem in practice first.
Verification: rebuild is clean. Padding math confirmed by hand-tracing CSS cascade/specificity rules for every affected selector pair (not guessed) — no browser available in this container to render and confirm at an actual 375px viewport, so Willem is checking that directly against the running jekyll serve instance rather than me claiming a render I can’t produce.
Contrast re-check, computed (WCAG 2.1 relative luminance, same method as DESIGN_SYSTEM.md’s table):
teal on substrate 11.01 (AA-body pass, UI pass)
teal-faded on substrate 4.99 (AA-body pass, UI pass)
orange on substrate 3.64 (AA-body fail, UI pass) — orange only ever used at UI/large-text size, confirmed
teal on panel 10.05 (AA-body pass, UI pass)
teal-faded on panel 4.55 (AA-body pass, UI pass) — tightest margin introduced this session (.caption/.game-card p/.update-excerpt/.game-more inside .panel); worth a visual gut-check on preview
orange on panel 3.32 (AA-body fail, UI pass) — not actually used anywhere
substrate on orange 3.64 (AA-body fail, UI pass) — .cta-button text, UI-component sized, consistent with the locked exception
2026-08-27 — Phase 1 Amendment: dark background revision (DESIGN_SYSTEM.md v0003)
Branch: redesign Changed:
assets/css/main.css::roottoken--tealrenamed to--ink(same hex#06373C, DESIGN_SYSTEM.md v0003 drops--tealentirely with no alias — confirmed against the doc’s ownbody{}before/after example, which never references--tealin the “becomes” block). Added new token--cream-faded: #B7AE94.--teal-fadedkept unchanged but is now valid only inside.panel(fails outright directly on--ink, 2.21:1 per DESIGN_SYSTEM.md’s recomputed table).- Individually reclassified every existing
var(--teal)/var(--teal-faded)usage inmain.cssrather than blind-renaming — full selector-by-selector table below. Two selectors turned out to be shared between page-background and panel contexts and needed splitting:.caption(used directly on the page for.hero-meta/post-header meta/footer.version-stamp, and inside.panelfor.game-status/.update-meta) and.update-tag(panel instances in.update-item, page-bg instance in post.html’s post-header). Both got their base rule repointed tovar(--cream-faded)plus a new.panel .caption/.panel .update-tagoverride restoringvar(--teal-faded)for the panel case. header.site’s explicitbackground: var(--substrate)override confirmed to be the real inconsistency flagged going in — repointed tovar(--ink)so the header no longer stays a light bar over the new dark page..sticky-ctabackground repointed the same way (explicit ask, same hex, token rename only)..brand-wordmarkfont-size increased1.05rem → 1.4remdesktop,0.85rem → 1.1remat the existing≤420pxbreakpoint. Flagging these exact numbers per DESIGN_SYSTEM.md’s explicit ask rather than picking silently. Confirmed the sticky-bar mini-mark can’t scale as a side effect — the sticky bar’s markup carries no.brand-wordmarktext at all, only the badge image at its existing fixed26pxheight.- Found and fixed a real problem while auditing, not hypothetical: the header/sticky/footer logo assets (
mag_badge.svg,mag_colour.svg) fill their primary shape with#06373C— byte-identical to the new--inkbackground hex, so that shape would have gone fully invisible (0:1 contrast) in all three placements. Raised with Willem before acting; his direction was to build light-fill duplicates rather than a CSS workaround. Inspected the SVG source first (not assumed): both files share one compound path (path9, no explicitfill-rule, so default nonzero winding) whose internal detail lines are negative-space cutouts within that single path, not separate light paths drawn on top — so a single fill-attribute swap (#06373c → #F2ECDE,--substrate’s hex) was sufficient; the holes correctly reveal the dark--inkpage behind them as dark detail lines with no path restructuring needed. New files:assets/img/brand/mag_badge-light.svg,assets/img/brand/mag_colour-light.svg(orange accent path#C85915left untouched in both). Wired into_includes/header.html(both.brand-markand.brand-mark-miniin the main header/sticky bar) and_includes/footer.html(.brand-mark-mini, full lockup). Originals (mag_badge.svg,mag_colour.svg) left untouched — still used nowhere now, since all three logo placements moved to the light variant, but not deleted. - Updated DESIGN_SYSTEM.md’s asset inventory table: marked the “Single-colour variants” row done with the new filenames, and reworded the badge-legibility row to record the negative-space finding and resolution rather than leaving it as an open “not yet re-checked” flag.
_config.yml:version: "01.2608.0001" → "01.2608.0003", stillWIP. Bumped forward one WIP revision — the odd/even convention means the very next value (0002) would be a Stable slot, so the next WIP revision skips it, matching the_0003document filenames already in use this session.- Confirmed Salt & Stone (
/games/salt-and-stone/,body.legacy-navy-gold) is unaffected beyond header/footer:legacy-game.cssuses its own separate--cream/--navy/--goldtoken namespace with zero overlap with the renamed tokens, and its.hero/.tagline/.hook/.game-bodyselectors are all overridden under the.legacy-navy-goldprefix regardless of whatmain.css’s base rules do.
Selector-by-selector reclassification (assets/css/main.css unless noted):
| Selector | Context | New value |
|---|---|---|
body background |
page | var(--ink) |
body color |
page-bg text | var(--substrate) |
a (global fallback — live via the homepage’s “All updates →” link) |
page-bg | var(--cream-faded) |
header.site background |
header bar | var(--ink) |
.brand-wordmark |
header, dark bar | var(--substrate) |
nav.site-links a |
header, dark bar | var(--cream-faded) |
nav.site-links a:hover/:focus-visible |
header, dark bar | var(--substrate) |
.sticky-cta background |
explicit ask | var(--ink) |
.cta-button:hover/:focus-visible background |
self-contained button fill, not a page/panel text role | unchanged, var(--teal-faded) |
.caption (base) |
shared — split | base var(--cream-faded); new .panel .caption{ color: var(--teal-faded); } |
.eyebrow |
hero, page-bg | var(--cream-faded) |
h1.tagline |
hero, page-bg | var(--substrate) |
.hook |
hero, page-bg | var(--cream-faded) |
h2.section-title |
page-bg | var(--substrate) |
.lede |
page-bg | var(--cream-faded) |
.label-facts dt |
page-bg | var(--cream-faded) |
.label-facts dd |
page-bg | var(--substrate) |
.game-card:hover/:focus-visible border-color |
panel border | unchanged, var(--teal-faded) |
.game-card h3 |
panel | var(--ink) |
.game-card p |
panel | unchanged, var(--teal-faded) |
.game-card .game-more |
panel | unchanged, var(--teal-faded) |
.update-tag (base) |
shared — split | base var(--cream-faded); new .panel .update-tag{ color: var(--teal-faded); } |
.update-item h3 a |
panel | var(--ink) |
.update-item h3 a:hover/:focus-visible |
panel | unchanged, var(--teal-faded) |
.update-item .update-excerpt |
panel | unchanged, var(--teal-faded) |
.post-header h1 |
page-bg | var(--substrate) |
.post-body (+ h2/h3) |
page-bg | var(--substrate) |
.post-body a |
page-bg | var(--cream-faded) |
.footer-contact (+ a) |
footer inherits body bg (--ink) |
var(--cream-faded) |
.fig-label and h1.tagline em (orange) untouched — no --teal/--teal-faded involved, already vetted per DESIGN_SYSTEM.md.
Decisions flagged:
- Wordmark size:
1.4remdesktop /1.1remat≤420px— a proposal, not a locked-in final number; adjust if it doesn’t read right on preview. .cta-button:hoverbackground stayingvar(--teal-faded)unchanged — it’s a self-contained button surface (own bg +var(--substrate)text), not a text-directly-on-page or text-in-panel case, so the role table doesn’t map onto it cleanly. Left as-is since the hex is unchanged from the already-shipped 0002/Phase-1 build.- Asset-inventory “single-colour variants” row marked done against the light-fill badge/lockup work — flagging that what was built is a two-tone dark-context variant (substrate shape + orange accent kept), not a literal single-hue monochrome, in case that distinction matters for a future favicon/mono use.
DoD check (this session’s Acceptance criteria):
- Every pre-existing
var(--teal)/var(--teal-faded)usage individually reclassified, not blind-renamed — Pass, table above; confirmed viagrepthat novar(--teal)references remain and every survivingvar(--teal-faded)use is panel-scoped or the one flagged self-contained-button exception. - Home, Games index, Updates index, header/footer render on
--inkwith correct contrast throughout — Pass on cascade-tracing: rebuilt via the already-runningbundle exec jekyll serve --host 0.0.0.0(auto-regenerated cleanly, confirmed viacurl), then cross-referenced everyclass="..."attribute actually emitted on/,/games/,/updates/, a post page, and the Salt & Stone game page against the selector table above — no class present in the rendered HTML was left unclassified. Not a rendered/visual check — no browser automation available in this container, so nothing was screenshotted; this needs Willem’s real preview pass, particularly the.field-texturestar-chart read, the tightest-margin.teal-faded on .panelpairing (4.55:1, already flagged pre-existing), and the new light-fill badge in situ. - Wordmark visibly larger, exact size flagged — Pass, see above.
- Salt & Stone’s page body unchanged, header/footer only — Pass, confirmed
legacy-game.css’s token namespace has zero overlap with the renamed tokens, and its selectors are all scoped under.legacy-navy-gold, verified against the rendered/games/salt-and-stone/output (body.legacy-navy-gold,legacy-game.cssstill linked, header/footer using the new light badge).
Gotchas:
- Confirmed again this session: a previous session’s
bundle exec jekyll serve --host 0.0.0.0was already running (PID persisted across sessions) with auto-regeneration on, so no second server was started — starting a duplicate would have hitEADDRINUSEon port 4000 anyway. Verified the existing process actually picked up every change viacurlbefore treating it as confirmed.
2026-08-27 — Phase 1 session: field-texture SVG replacement
Branch: redesign
Changed: Replaced .field-texture’s diagonal crosshatch (repeating-linear-gradient ×2, main.css:50-60) with a new SVG asset assets/img/brand/field-texture-tile.svg (512×512 viewBox). Composition: Cluster A (spore-burst/star-cluster, center 120,150) — 5 irregular-angle rays (20-30px, #C9BFA6 stroke, opacity 0.35) each ending in a tiny dot (r1.8, opacity 0.4), plus a centre dot (r1.5, #B7AE94, opacity 0.3). Cluster B — same idea, center 380,340, 4 rays. One orbital arc: quadratic curve M 24,486 Q 320,170 488,26, #B7AE94 stroke, opacity 0.3. 11 individually-placed scattered dots (r1.1-2.2, opacity 0.18-0.3), alternating the two colours, not grid-aligned. No orange, no gradients, no <defs>. Colours are the literal hex of --rule (#C9BFA6) and --cream-faded (#B7AE94) rather than var(...) — a standalone SVG loaded via background-image: url() has no access to the host page’s CSS custom properties. Wired in via background-image: url("/assets/img/brand/field-texture-tile.svg") + background-repeat: repeat, replacing the old gradient declarations. Also changed .field-texture from position: fixed to position: absolute (now scrolls with the page rather than staying pinned — keeps clear of the “no parallax” rule) and moved the fade control from container-level opacity (was 0.5) into per-element SVG opacities (container opacity now 1, single dial instead of two multiplying). Documented in DESIGN_SYSTEM.md: new asset-inventory row for field-texture-tile.svg, new .field-texture entry in the Components section.
Decisions flagged: SVG hardcodes literal --rule/--cream-faded hex rather than var() — needs a manual re-point if either token’s hex value ever changes (noted in DESIGN_SYSTEM.md’s asset row). Per-element opacities (0.18-0.4 range) are a starting point per the brief, not locked — flag back after a real visual look if it reads too busy or too faint. Did not touch legacy-game.css’s .legacy-navy-gold .field-texture override (still its own independent gradient/opacity, out of scope) or Salt & Stone’s page body.
DoD check: .field-texture no longer uses the crosshatch gradient — confirmed via curl against the already-running bundle exec jekyll serve --host 0.0.0.0 (auto-regenerated cleanly): served main.css shows the new rule, field-texture-tile.svg returns 200, and class="field-texture" is present in the rendered HTML of /, /games/, and /updates/ (sitewide via _layouts/default.html, not page-specific). Not a visual/rendered check — no browser tooling in this container, so whether the pattern actually reads as sparse organic marks (vs. too busy/too faint) at real tile size hasn’t been seen. Needs Willem’s preview pass over Tailscale, specifically: does the pattern read as organic rather than a repeating technical grid, are the two clusters/arc/scattered dots legible at normal viewport size, and do the opacity values (0.18-0.4) feel right or need tuning.
2026-08-28 — Phase 1 fix: field-texture full-page height
Branch: redesign
Changed: Willem’s preview caught that .field-texture (position: absolute, inset: 0) was sizing to viewport height only, not full document height — with no positioned ancestor, an absolutely-positioned element’s containing block is the initial containing block (viewport), not the document. Fixed by adding position: relative to body (main.css, body{} rule), making body the containing block so inset:0 now stretches .field-texture to body’s actual rendered (full-page) height.
Decisions flagged: Checked every other position: declaration in main.css and legacy-game.css before making the change, to confirm nothing relied on body staying unpositioned — header.site/.hero/section/footer are each position: relative purely for their own z-index stacking above .field-texture, self-contained regardless of body; .sticky-cta is position: fixed (viewport-relative, unaffected since body gets no transform/filter/perspective); legacy-game.css’s .face{position:absolute; inset:0;} is scoped inside its own position: relative ancestor (.flip-card button), independent of body. No side effects found. No other changes — composition, colours, opacity, tile size unchanged from the prior entry.
DoD check: Confirmed via curl against the running server that main.css serves the updated body{} rule (position: relative present) with no syntax breakage and .field-texture’s rule is unchanged. Per Willem’s instruction, server-side inspection was sufficient for this fix — visual confirmation of full-page coverage is his to do.
2026-08-28 — Phase 1 fix: field-texture-tile.svg orbital arc seam
Branch: redesign
Changed: Willem’s preview caught visible breaks at tile boundaries where the orbital arc repeated — the old arc (M 24,486 Q 320,170 488,26) started/ended near but not exactly at the tile edges with no wraparound continuity authored, so each repeated tile drew a disconnected copy at the seam. Fixed by redrawing the arc fully inside the tile interior instead of attempting edge-to-edge wraparound geometry: new path is M 60,450 Q 170,240 300,320 (assets/img/brand/field-texture-tile.svg). Same stroke/colour/opacity as before (#B7AE94, stroke-width 1.2, opacity 0.3, round linecap) — only the coordinates changed.
Decisions flagged: New arc’s three control points (start/control/end) all sit within x:[60,300], y:[240,450] — since a quadratic Bezier’s x(t)/y(t) are convex combinations of its control points, the curve never leaves that bounding box, giving a guaranteed minimum margin of 60px from the left/bottom edges (512px tile) and well over 200px from top/right — comfortably past the requested ~40-50px minimum. Positioned in the open lower-left area so it doesn’t overlap either spore cluster (Cluster A’s rays stay above y=180; Cluster B sits at x≥354) — some overlap with a few scattered dots in that area is fine, reads as organic layering rather than a seam artifact. Both clusters, all scattered dots, colours, opacity, and tile size are unchanged from the prior entries — this was a contained, single-element fix.
DoD check: Confirmed via curl against the running server that the SVG serves (200) with the new <path> element present and well-formed. Per Willem’s instruction, server-side inspection was sufficient — visual confirmation that the seam is actually gone at tile boundaries is his to do.
2026-08-28 — Phase 1 rework: field-texture switched to two-layer parallax-free tiling
Branch: redesign
Changed: Willem flagged that the single-tile field-texture-tile.svg (three rounds in) still read as an obvious repeating stamp — same motifs, same spacing, easy to pattern-match. Switched construction entirely: deleted field-texture-tile.svg (untracked, never committed — safe to remove) and replaced it with two independently-sized SVGs layered via CSS multiple backgrounds so their repeat periods don’t align:
assets/img/brand/field-texture-mycelium.svg(640×640,--rulehex#C9BFA6): three spore-burst clusters of deliberately varied scale — Cluster A (140,160) 5 rays lengths 22-32px/angles -20°/45°/110°/175°/240°, Cluster B (480,420) 4 rays lengths 16-26px/angles 15°/95°/190°/260°, Cluster C (300,540) 3 rays only, lengths 12-18px/angles 30°/150°/260° — a visibly smaller “specimen” than A/B. All three verified ≥50px clear of every tile edge (computed each ray endpoint’s bounding box against the 640px tile; closest approach was Cluster A at x=118.1, still 68px clear of the left edge).assets/img/brand/field-texture-constellation.svg(460×460 — deliberately different size/aspect from the mycelium tile so the two repeat periods share no small common alignment —--cream-fadedhex#B7AE94): one contained arc (M 90,370 Q 190,150 330,230, all three Bezier control points within the 50-410 safe zone on both axes) plus 10 scattered dots, irregular placement, varying r (1.0-1.9) and opacity.- Wired into
.field-texturevia CSS multiple backgrounds on the same rule (not a second div):background-imagewith bothurl(...),background-repeat: repeat, repeat,background-size: 640px 640px, 460px 460px,background-position: 0 0, 90px 140px— the 90/140 offset is deliberate misalignment (not a round multiple of either 640 or 460). Decisions flagged: Layering two independent patterns roughly doubles apparent element density in any given screen area, which risked swinging back toward “too busy” — the original complaint that started this whole thread. Reduced per-element opacity from the single-tile version’s values to compensate rather than reusing them: mycelium rays 0.35→0.2, ray-end dots 0.4→0.24, centre dots →0.18; constellation arc 0.3→0.18, scattered dots 0.18-0.3→0.13-0.2. These are the actual landed values, not final-locked — flag back after real visual review if the combined layering still reads too dense or now too faint. DoD check: Confirmed viacurlagainst the running server — both new SVGs return 200, the oldfield-texture-tile.svgnow 404s (fully removed), and servedmain.cssshows the multi-background.field-texturerule with no syntax errors. Per Willem’s instruction, server-side inspection was sufficient this round — the actual visual result (whether the two layers genuinely break the pattern-matching read, and whether opacity landed in the right place) is his to check.
2026-08-28 — Phase 1 fix: constellation tile enlarged + multi-curve, mycelium/constellation brightness bumped
Branch: redesign
Changed: Willem flagged the constellation tile’s single repeating arc as still pattern-matchable (same line reappearing). Enlarged field-texture-constellation.svg from 460×460 to 727×727 and replaced the one arc with 4 distinct curves — different curvature direction, scale, and quadrant, all ≥50px clear of every edge (verified: minimum observed margin ~60px on curve 1, others 77-327px):
- Curve 1 (top-left):
M 80,120 Q 220,60 340,180— medium scale (~272px span), bows upward, stroke-width 1.0, opacity 0.19. - Curve 2 (top-right/mid):
M 400,140 Q 620,260 480,400— largest scale, bows sideways (opposite orientation from curve 1), stroke-width 1.2, opacity 0.22. - Curve 3 (bottom-left):
M 120,500 Q 160,620 280,560— smallest scale (~171px span), bows downward, stroke-width 0.9, opacity 0.18. - Curve 4 (bottom-right):
M 420,550 Q 580,480 650,650— large scale, bows upward-right, stroke-width 1.1, opacity 0.2. Scattered dots scaled from 10 to 24 (≈2.5x, matching the tile’s ~2.5x larger area), same irregular non-grid placement. 727 was chosen deliberately coprime with the mycelium tile’s 640 (727 is odd and not a multiple of 5, sogcd(640,727)=1, givingLCM=465,280px— a combined repeat period far beyond any realistic page height, not just “different,” per the original size-mismatch principle). Recomputedmain.css’s.field-texturebackground-size/background-positionfor the new tile:727px 727px/ offset137px 205px(non-round, not a multiple of either tile size). Per the addendum in this session’s instructions (“bump the brightness… the previous change to lower brightness was too much”), also bumped per-element opacity on both files — this touchesfield-texture-mycelium.svg’s opacity values only (geometry/composition/colours untouched, as instructed): rays 0.2→0.26, ray-end dots 0.24→0.3, centre dots 0.18→0.22. Constellation dots bumped from the prior 0.13-0.2 range to 0.14-0.22; new curves set at 0.18-0.22 (curve count roughly quadrupled vs. the old single arc, so per-curve opacity was kept closer to the old single-arc value of 0.18 rather than also compounding upward, to avoid the total curve-ink swinging back toward “busy” even as per-element brightness increased). Decisions flagged: Willem’s message said “do not touch field-texture-mycelium.svg” for the main task, then separately asked to bump brightness on “stars, spores, mycelia” — read as an explicit override for opacity only (not composition/ray counts/positions, which are unchanged). Flagging this reconciliation explicitly in case that reading was wrong. Also flagging the curve-count-vs-opacity tradeoff above (curves quadrupled, per-curve brightness only nudged, not fully matching the dot/mycelium bump) as a judgement call, not a locked number — real visual check needed to confirm total density hasn’t crept back up now that there are 4 curves instead of 1. DoD check: Confirmed viacurlagainst the running server — both SVGs return 200, constellation’sviewBox="0 0 727 727"confirmed, 4<path>elements and 24<circle>elements counted, mycelium’s opacity values confirmed at 0.22/0.26/0.3, servedmain.cssshows the updatedbackground-size/background-position, andclass="field-texture"still renders on/,/games/,/updates/. Server-side inspection only, per instruction — the actual visual result (curve variety breaking the pattern-match read, and whether the brightness bump landed right without tipping busy) is Willem’s to check before this merges. Remained onredesignbranch throughout, no merge/push to main.