Files
Sanctification/spikes/card-harness
2026-09-11 21:19:08 -07:00
..
2026-09-08 14:00:27 -07:00
2026-09-11 21:19:08 -07:00
2026-09-11 21:19:08 -07:00
2026-09-11 21:19:08 -07:00
2026-09-08 14:00:27 -07:00
2026-09-08 14:00:27 -07:00
2026-09-08 14:00:27 -07:00
2026-09-11 21:19:08 -07:00
2026-09-08 14:00:27 -07:00
2026-09-11 21:19:08 -07:00
2026-09-08 14:00:27 -07:00
2026-09-11 21:19:08 -07:00

Sanctification Card Lab

Bounded Three.js proof for the card-rendering harness plan.

The approved visual baseline is recorded in CURRENT-DEFAULTS.md.

Included proof scope

  • David printed-ink, foil, and holographic presets
  • Independently selectable paper, linen, metal, and wood substrates
  • Timothy as the second-artwork fixture
  • David color-based coverage and title-panel protection; automatic saturation/value coverage for Timothy
  • Procedural rounded-card geometry generated from shared physical dimensions
  • Deterministic linen normal map
  • Card manipulation, camera inspection, zoom, frame-rate-independent flip/reset, interruption-safe sweep, and movable lighting
  • Repeatable front, grazing-angle, edge, and back inspection poses
  • Point, directional, and spot lighting with repeatable studio, gallery, window, dramatic, and flat-review presets
  • Live light color, position, intensity, environment contribution, and exposure controls
  • Lab-mode loading of local artwork and finish-mask images without rebuilding
  • Named browser experiment saves, versioned JSON import/export, and PNG capture
  • Experimental condition wear with substrate-aware edges, scratches, scuffs, and imperfection seeds; wear and imperfections are deferred product features
  • Bare Inspect mode and small Lab-mode parameter panel
  • Pack mode: a touch-responsive foil pouch with a draggable tear strip, reveal-safe ordered stack, and one-at-a-time inspection
  • Drawing-buffer resolution plus median, p95, and worst frame-time display

Transform gizmos and a general timeline are intentionally deferred. The separate Flutter Scene comparison project is unchanged; Three.js remains the authoritative runtime.

Tear-open foil pack prototype

Choose Pack in the Mode selector (expand Controls first on mobile). Use Pack style in the same toolbar to compare three wrapper-only design studies:

  • Cathedral glass: deep blue, geometric stained-glass window artwork, and restrained gold.
  • Illuminated manuscript: warm ivory, burgundy, and botanical manuscript linework.
  • Quiet modern (initial selection): dark green, generous space, and a small sacred emblem.

All three use the same wording, foil material, pouch geometry, lighting, card contents, and opening animation. These are alternative visual studies, not different pack tiers or reward odds. Switching styles changes the front, back, and matching tear strip in place, preserving the current tear/inspection state. Use Restart to compare sealed packs; the chosen style is retained across Restart and mode switches, but not a page reload. On mobile, reopen Controls after entering Pack to access the selector. The six front/back textures are generated once and uploaded during pack preparation, then reused for instant switching. No illustration service or external asset is needed.

Drag the gold top seam to the right, or use Tear open for the same authored opening without dragging:

Sealed → progressive tear → strip curls away → mouth spreads → staggered card extraction → face-down stack → lifting → lifted → revealing → inspecting → advancing → next stack / complete.

Lifting and flipping are separate actions so the universal back can be reviewed before revealing. The authored order is always David / Printed ink / Linen, Timothy / Foil / Paper, then David / Holographic / Metal. This is not a randomized reward system.

  • The seam has a mouse/touch hit area at least 44 px tall. Drag distance drives tear progress monotonically: pulling back does not reseal it. A full pull completes the opening on release; a short pull holds its exact tear and Finish opening continues from there. The progress bar and percentage also expose the state without relying on the animation.
  • Cancellation or lost pointer capture holds a partial tear; another seam pull, Finish opening, or Skip can continue it. A second finger relinquishes the tear gesture to pinch zoom. Restart and mode changes release all captured pointers.
  • Pressing the pouch makes a small local dent that settles on release. Creases and seam crimps are deterministic, not continuously moving noise.
  • Drag to rotate and pinch or wheel to zoom during inspection. Pinch/wheel zoom also works before revealing; hidden cards cannot be manually tilted. User zoom may intentionally crop the composition.
  • Touching or zooming during a scripted transition pauses at the current pose. Continue resumes from that elapsed point, without snapping. A tap that interrupts motion does not also advance it.
  • Skip finishes only the current transition, or performs one step immediately from a resting state. It never skips an unseen card's reveal. Restart restores the sealed wrapper and first card.
  • Reduced-motion preference shortens each transition to 70 ms with the same state and reveal/completion ordering.
  • Switching away pauses Pack and preserves the Inspect/Lab card, camera, materials, local images and experiment settings. Returning to Pack resumes its retained state via Continue.

The foil wrapper is two subdivided, joined pouch surfaces and a separate subdivided top ribbon. Controlled vertex deformation creates shallow creases, a travelling tear front, a curled detached strip, and spreading lips. Typography is printed directly on the sheet materials, not on an almost-coplanar label layer. There is no rigid-panel split, transparent cross-fade, cloth engine, or extra asset dependency. The pouch stays above the floor while the three cards slide upward with a small stagger. Only after all cards clear the mouth does the empty pouch move aside; the cards then settle into the existing face-down stack. Opening-only camera framing widens and recenters during extraction, then returns to the established stack framing.

Cards use the existing procedural geometry and approved runtime shader. Before revealing, fronts are hidden, backs share the fixed universal material, and edges use a neutral paper recipe. Authored substrate edges are enabled only after the flip finishes. The active card lifts to a dedicated inspection plane before flipping or free rotation. The reserve stack stays visible, offset to the lower right and safely behind the active card's full corner-sweep volume. The exit animation also stays on that safe plane while the reserve stack recenters. Camera framing eases with the lift/exit so the deeper separation does not unexpectedly enlarge the card. The edge mesh draws only extrusion side walls, not end caps beneath the dedicated artwork faces, preventing depth-fighting bands at farther zoom distances. Pack assets are loaded separately on first entry, with retry on failure. Before enabling pack interaction, textures are uploaded and shaders are compiled for the pouch, hidden card fronts, universal backs, and both neutral/revealed edge materials using the scene's lighting and environment. This preparation does not draw or reveal cards. The loading state lasts until it finishes; failures release the new pack resources and keep retry available. Returning to an already prepared pack retains its state without repeating this preparation.

Wrapper deformation is coalesced to once per rendered frame, including touch dents and tear input. Fixed crease/crimp calculations are cached; unchanged pouch surfaces and ribbons do not recalculate normals/bounds or upload vertex buffers. Hidden wrappers do not deform. Pack UI updates are also coalesced and only write changed values. These optimizations retain the same mesh resolution, deformation formulas, materials, lighting, pixel ratio, and antialiasing. Mint cards (condition = 1) bypass procedural wear calculations whose contribution is zero. Worn cards use the original wear equations, and all finish/substrate shading remains unchanged.

There is no sound, haptics, particles, cloth simulation, backend, rewards persistence, pack progress persistence, or timeline/editor. This is a choreography proof, not an final pack-design or mobile performance sign-off. The approved rigid prototype and artifact-free card inspection are the preserved foundation; this foil treatment is the next review iteration. The canvas emits packreveal (one-based index and variant) and packcomplete (count), once per card/pack per restart.

Finish and substrate are separate:

  • Finish controls printed ink, foil, or holographic coating.
  • Substrate controls surface roughness/microtexture, underprint response, and edge/core appearance.

Paper uses fine, irregular fibers and a broad, weak highlight. Linen uses raised-looking interlaced threads with analytic slope lighting, a bounded two-sample procedural parallax offset, and broad ridge highlights that remain visible in Printed ink at oblique angles. Only the weave shifts with the view: artwork and lettering stay anchored. Surface detail scales the effect; unresolved threads fade to avoid shimmer. This is shader relief with no added geometry or change to the card's silhouette, back, or thickness. This linen look was visually approved September 10, 2026 as linen-relief-v1-2026-09-10; its exact defaults are recorded in CURRENT-DEFAULTS.md. No extra toggle or configuration is required: selecting Linen applies it in Inspect, Lab, and the authored pack. The legacy Plastic shader recipe remains readable by older saved experiments but is not offered in the UI or randomized packs. Wood uses raised longitudinal grain with bounded procedural parallax, stronger relief, and a restrained warm tint. The artwork stays anchored while grain shading and tint shift together. Metal retains its reflective underprint and uses luminance-driven recesses: bounded parallax shifts the artwork and finish mask together, with directional groove shading to emphasize depth. The effect fades at the card edges. Metal and wood depth were visually approved September 10, 2026 as metal-wood-relief-v1-2026-09-10. Surface detail scales the relief; neither material adds geometry or changes the card silhouette. Procedural detail fades below pixel resolution to limit shimmer. The universal card back uses fixed neutral material properties so front finish and substrate choices do not spoil a pack reveal. The holo spectrum and coverage rules are independent of these substrate changes. Metal combined with Foil preserves the printed colors while adding restrained, slightly raised champagne-metal polishing over the etched steel base.

Reference

npm run assets creates public/reference/manifest.json, copies the source artwork and approved reference renders, and generates the two masks and normal map. Card geometry is generated directly in Three.js from the dimensions recorded in the manifest; Blender is not required to build or run the harness. The current runtime reference revision is runtime-look-v4-2026-09-07, visually informed by:

  • blender_prototype/premium_finishes.py
  • blender_prototype/card_finish_material.py
  • blender_prototype/render_premium_review.py

The approved linen, metal, and wood depth follow-ups change runtime shader behavior, not the source artwork, generated normal map, or Blender reference renders. The asset manifest therefore retains its v4 reference revision; the scoped material approvals and parameters are tracked in CURRENT-DEFAULTS.md.

The runtime shader and geometry are runtime implementations, not a claim of pixel-identical Blender output. David uses color-based coverage and title-panel protection. Holographic color and angle response are preserved; reduced sheen applies only to foil.

Run

npm install
npm run dev

Production build:

npm run build

Pack regression checks (Node 22.15+):

npm test

These check exact pre-optimization wrapper geometry snapshots, surface update counts, per-frame input batching, pause/resume, pinch handoff, restart, reduced motion, ordered reveals, GPU preparation, and failure cleanup. They are CPU/state checks, not a real-device GPU or touch-latency benchmark; mobile performance still needs on-device validation.

WebGL pixel parity and pack shader-preparation checks require a local headless Chromium browser with WebGL2 support, installed project dependencies, and generated reference assets (npm run assets):

SHADER_BROWSER=/absolute/path/to/chromium \
SHADER_BROWSER_KIND=chromium \
node scripts/shader-pixel-regression.mjs

The Chromium runner uses SwiftShader software WebGL. Browsers are not installed automatically; a missing browser, missing WebGL support, timeout, pixel mismatch, or unexpected shader program causes a nonzero exit rather than a skipped check.

The pixel check compares 360 combinations of substrate, finish, condition, angle, and lighting against the current shader with unconditional wear evaluation, verifying that the mint fast path remains equivalent. A separately hash-verified v4 reference checks that Paper and Plastic remain unchanged and that the approved Linen, Metal, and Wood iterations produce a visual difference. The pack check exercises opening, all three reveals, and restart under point, directional, and spot lighting, checking for new shader programs after preparation. Software WebGL can validate pixel parity and program reuse, but its timings are not mobile GPU benchmarks.

The asset-generation script uses cross-platform Node APIs and works on Windows and Linux. The retained export:blender script is an optional reference utility and is not part of the application pipeline.

Baseline

Initial development machine:

  • Windows
  • Intel Arc Graphics, driver 32.0.101.6737
  • Node 24.14.1
  • Three.js version pinned by package-lock.json

The browser/version, viewport, drawing-buffer resolution, texture settings, and observation duration must be recorded during material approval. The on-screen frame-time display is diagnostic rather than a complete benchmark.