Gallery Guide · For the Curious Visitor
How This Museum
Was Built
Concept, craft, and pipeline notes from the builder. The museum upstairs plays its joke completely straight; this document is where the machinery is allowed to show.
Concept and direction
The premise: a museum exhibiting artifacts from civilizations that never existed — AI archaeology, honestly labeled. The entire design bet is deadpan. Nothing on the main floor winks. The catalog numbers are plausible, the conservation notes are procedurally dry, and the honest provenance (“Unearthed: latent space, layer 34”) is set in the same reverent italic a real museum would use for “Thebes, West Bank.” The comedy is structural, not decorative: it only works if every other detail is played as straight as the Metropolitan Museum's wall text.
Six civilizations were invented with real texture — the Veshari Concordance, who believed the stars descend; the Qenat-Hur, who wrote prayers legible only to rain; the Thal-Vessora, who numbered the mind's attentions; the Ombric Court, crowned facing inward; the Ashkarat League, who sealed contracts in silence; the Pellucid Marches, who filed the actual sky as an erratum. Each needed a cosmology strong enough to justify one object, and no more — the plaque format enforces brevity the way real vitrines do.
The visual grammar is a night gallery: obsidian walls, bone text, oxblood feature-walls (museums genuinely paint them close to this), and gold leaf reserved for numerals and rules. Cinzel carries the engraved Roman-capital wall text; EB Garamond carries every plaque, dossier and paragraph, because it is what four centuries of catalogs have trained the eye to trust.
Palette and type specimen
- Bone
#ECE5D8text, plaques, the About room - Obsidian
#16130Fthe walls of the hall - Oxblood
#6E1B1Bsection banners, feature walls - Gold leaf
#A5893Cnumerals, rules, catalog numbers
Cinzel — wall text, engraved capitals
Synthetic Antiquities
ABCDEFGHIJKLMNOPQRSTUVWXYZ · MSA 10.041
EB Garamond — plaques, catalog prose
The collection does not ask whether its civilizations were real. It asks what it means that they are so easy to believe — Unearthed: latent space, layer 34.
Signature technique: the horizontal hall
The centerpiece is a pinned gallery: vertical scroll is translated into an eastward walk past six plinths. GSAP's ScrollTrigger pins the hall for the duration and scrubs the track's x transform across the full overflow width. Two decisions matter more than the pin itself:
One number per bay. Every frame, each bay computes its distance from the viewport center and smooth-steps it into a single value --s (0 = in the dark, 1 = dead center), written as a CSS custom property. Everything downstream — image brightness, the volumetric cone, plaque opacity, the gold numeral, the typing trigger — is plain CSS reading that one variable. The JS stays tiny and the choreography stays declarative.
Scroll ratio. The pin consumes only 0.7× the horizontal distance, which keeps the whole route under the screenshot-tooling ceiling (~8,000px) while the hall still travels its full width. The scrub's 1.15s smoothing is what makes the traversal feel like walking rather than dragging.
// vertical scroll becomes an eastward walk
gsap.to(track, {
x: () => -(track.scrollWidth - innerWidth),
ease: 'none',
onUpdate: updateBloom,
scrollTrigger: {
trigger: hall, start: 'top top',
end: () => '+=' + (track.scrollWidth - innerWidth) * 0.7,
pin: true, scrub: 1.15, invalidateOnRefresh: true,
},
})
// each bay carries one number: its share of the light
function updateBloom() {
const mid = innerWidth / 2, span = innerWidth * 0.42
bays.forEach((bay, i) => {
const r = stages[i].getBoundingClientRect()
const d = Math.min(Math.abs(r.left + r.width/2 - mid) / span, 1)
const s = smooth(1 - d) // smoothstep: 0 dark … 1 centred
bay.style.setProperty('--s', s.toFixed(3))
if (s > 0.55) typePlaque(bay) // plaques type once, when lit
})
}
/* CSS does the rest — the whole spotlight rig reads --s */
.bay-figure img {
filter: brightness(calc(0.3 + 0.78 * var(--s)))
saturate(calc(0.72 + 0.32 * var(--s)));
}
.cone { opacity: var(--s); } /* volumetric beam */
.plaque { opacity: calc(0.42 + 0.58 * var(--s)); }
The dust is a single 2D canvas over the pinned viewport: ~80 motes, each with a slow fall and a sinusoidal sway. A mote's alpha is weighted by the glow of the nearest lit cone — a Gaussian around each bay's screen-x, scaled by that bay's --s — so dust only sparkles where light actually falls, and the beams appear to carry it. With prefers-reduced-motion, the hall lays out vertically, unpinned, fully lit, plaques pre-typed.
Asset pipeline
All eight photographs were generated with Higgsfield's nano_banana_pro model for 16 credits total. The trick that makes them read as one collection photographed in one studio: the first generation (the bronze orrery) became the anchor, and every subsequent prompt passed that job as reference media while restating the same style contract — pitch-black backdrop, a single overhead cone of warm light, dust in the beam, dark museum glass with a faint mirror reflection, “no text, no labels, no people.” Only the subject clause changed.
| Asset | Subject clause (abridged) | Credits |
|---|---|---|
| I · Orrery | bronze orrery disc, planets mounted on the inside of the rings — the style anchor | 2 |
| II · Vessel | terracotta votive vessel, looping script that spirals and never repeats | 2 |
| III · Mask | jade mask, halves not quite mirrored, a third eye on the brow | 2 |
| IV · Diadem | gilded diadem, flame rays curving inward toward the absent head | 2 |
| V · Bell | bronze bell cast without a clapper, mouth sealed at the foundry | 2 |
| VI · Bowl | astronomer's bowl, gold star map matching no recorded sky | 2 |
| Featured | corroded computational mechanism, non-integer tooth counts (2K) | 2 |
| Entrance / OG | the hall itself — five lit vitrines receding into blackness | 2 |
Masters stayed in assets-src/; the site ships only optimized WebP pairs (800/1600) via the repo's optimg tool — the whole collection weighs about 900KB. The impossible details were requested outright (inverse orbits, unmirrored faces, sealed bells): the model obliges precisely because such objects are what a museum photograph of a nonexistent civilization should look like.
Iteration diary
Three formal passes were run against the screenshot harness (scroll-step captures at 375, 768 and 1440px), each logged in the repo's ITERATION-LOG.md.
Pass 1 — Structure
The most instructive bug of the build: the 375px hero capture came back as a solid black frame, twice, for two different wrong reasons. The real culprit was one CSS line — html { scroll-behavior: smooth } — which turned the harness's instant programmatic scrolls into slow animated ones; captures fired while the page was still gliding, hundreds of pixels from where the tooling believed it was. Removing it (Lenis smooths for humans anyway) fixed the black hero, the offset desktop hero and the mid-flight scroll steps at once. Also this pass: the route was 8,651px tall at 1440 and crashed full-page capture, so the hall track was slimmed and the pin's scroll ratio dropped to 0.7×; and the mobile bay overflowed 812px until its figure and plaque were compacted.
Pass 2 — Craft
Fixes found by reading stills like a curator: the rotating accession seal's circular inscription was longer than its circle and collided with itself at the seam (shortened and re-measured against the circumference); reduced-motion visitors got a permanently dim hall because the inline --s:0 beat the stylesheet override (now set from JS); the guide's own reveal observer never fired for content the harness jumped past, leaving whole sections invisible in full-page captures (auto-reveal under automation, generous top margin for humans). Dust gained a little more presence; plaques now begin typing earlier in the approach; artifact stages lift 6px on hover.
Pass 3 — Refinement
A hostile read of every screen at three widths found the weakest room: Visit, a bare list at the end of an ornate building. It received the museum's seal (its inscription ring turning alone — the plinth glyph inside holds still), a final entry (“Getting here — You are already here”), and a closing line set in gold italic. The diary you are reading pushed this page past the capture ceiling on phones, so the mobile guide was re-set tighter. Final state: clean QA report at all three widths, both routes, reduced-motion verified, zero console output.
Colophon
Vite · GSAP ScrollTrigger · Lenis · hand-written CSS. Fonts: Cinzel and EB Garamond, self-hosted. No frameworks, no trackers, no cookies. Images generated, curated and art-directed as described above.
Designed & built autonomously by Claude Fable 5 (Anthropic)