customer-presentation/CHANGES 4.md
2026-04-23 13:31:11 +02:00

8.9 KiB
Raw Permalink Blame History

Site update v5 — hero centered, real pin-scroll, card illustrations, bifrost headline breathing room

Four changes in this round. v4's wheelMultiplier sticky approach is replaced with a proper ScrollTrigger pin implementation because the previous attempts didn't feel sticky enough.

Files to replace

File What changed
protected/index.html Hero centered vertically (align-items + padding reset); AI + Agents cards get custom mask-image illustrations; Project Bifrost headline padding + looser line-height
protected/bifrost.js wheelMultiplier approach removed; ScrollTrigger pins added on hero, each map stop, and #bifrost-join; map path rebuilds on ScrollTrigger refresh
protected/timeline.js No change from v4 — copy only if you want fresh copy alongside

New files to upload

File Destination on server
ai.png /opt/fenja/protected/fenja/illustrations/ai.png
agents.png /opt/fenja/protected/fenja/illustrations/agents.png

If you're using rsync with --delete, ensure the local protected/fenja/illustrations/ folder contains both PNGs so they end up on the VPS. Otherwise the AI and Agents cards will show blank (the mask-image URL points to 404).

Change-by-change

1. Hero vertically centered

  • #hero is now align-items: center (was start) with padding-top: 0.
  • #page-overview #hero .hero-wrap also has padding-top: 0 — parent centering now handles vertical position.
  • The whole block (eyebrow + title + lede + hero-foot row) reads as centered on viewport load. No block-level math needed — CSS grid does it.

2. Real scroll pinning via GSAP ScrollTrigger

v4's wheelMultiplier trick (reducing Lenis wheel input to 0.35× inside a "sticky zone") didn't produce the tactile "scroll a few times to pass" feel you wanted. Replaced entirely with proper GSAP ScrollTrigger pins.

How it works:

ScrollTrigger.create({
  trigger: el,
  start: 'center center',
  end: '+=300',      // 300px of extra scroll distance held
  pin: true,
  pinSpacing: true,  // document grows by 300px — user MUST scroll through
  anticipatePin: 1,
});

Pinned targets + their hold distances:

Target Hold Why
#hero +300px Gentle hold on entry
#bifrost-meaning .map-stop--intro +260px Short — it's just an intro card
#bifrost-meaning .map-stop[data-stop="1"] (Community) +360px Full artifact card — noticeable hold
#bifrost-meaning .map-stop[data-stop="2"] (Advisory Council) +360px Same
#bifrost-meaning .map-stop[data-stop="3"] (Pilot Projects) +360px Same
#bifrost-join +260px CTA gets a moment before footer

Deliberately NOT pinned (they already have their own pin/scrub mechanics — double-pinning would fight):

  • #stack-scene (S2 architecture — GSAP scrub pin)
  • #words-scene (S3 — position:sticky pin inside tall parent)
  • #bifrost (S4 — position:sticky pin on .bifrost-pin)

Why pinSpacing:true matters: pinSpacing: true injects a spacer div that grows the document by the pin hold distance. Without it, the pin is visually held but the scroll counter advances normally — no "scroll multiple times" feeling. With it, every pin zone adds real scroll distance, so the user genuinely has to keep scrolling.

The map path rebuild: pinSpacing: true pushes each subsequent map stop further down the document. The winding SVG path that connects the dots is computed from live DOM positions via buildMapPath(). To keep the path threading correctly through the shifted dots, buildMapPath now re-runs on every ScrollTrigger.refresh event. No manual intervention needed.

3. Card illustrations — AI + Agents

Two of the four architecture cards now carry bespoke illustrations:

  • The AI (data-layer="0") → /fenja/illustrations/ai.png — the single topographic orb
  • The Agents (data-layer="3") → /fenja/illustrations/agents.png — central orb with six connected smaller orbs

How the rendering works: The PNGs are white line-art on black backgrounds. They're applied via CSS mask-image on the existing .card-brain element. The black background becomes transparent (mask excludes black) and the white lines paint through in the card's paper fill color. Because it's a mask, the lines render as a single flat color on every card background — matches the existing design system.

Per-card overrides (layers 1 and 2 keep the default brain mask):

.layer-card[data-layer="0"] .card-brain {
  mask-image: url('/fenja/illustrations/ai.png');
  aspect-ratio: 1 / 1;
  mask-size: contain;
  mask-position: center;
}
.layer-card[data-layer="3"] .card-brain {
  mask-image: url('/fenja/illustrations/agents.png');
  aspect-ratio: 1 / 1;
  mask-size: contain;
  mask-position: center;
}

The PNGs must be deployed to /opt/fenja/protected/fenja/illustrations/ or the cards will show blank. See "New files to upload" above.

4. Project Bifrost headline — room to breathe

.bifrost-pin has overflow: hidden (it clips the aurora arc's off-screen portions). Combined with .bifrost-name's tight line-height: 0.95 and the italic "Bifrost" token's gradient background-clip: text, the top and bottom edges of the headline were getting clipped.

Fixes, both on .bifrost-name:

  • line-height: 0.951.12 — room for ascenders and descenders
  • Added padding: 0.12em 0.08em — generous vertical buffer absorbed into the headline's own box, so the parent .bifrost-pin overflow:hidden doesn't reach into the glyphs

Parent overflow:hidden stays (it's protecting the arc animation). The headline simply carries its own breathing room now.

Spot-check after deploy

  • Overview → hero text sits vertically centered on viewport load. Visually balanced — not clinging to top or bottom.
  • Scroll past hero → real resistance. After a bit of wheel input, hero unpins and S2 comes in. NOT a smooth flyby.
  • Scroll into treasure map. Each stop visibly holds as it reaches viewport center. You need several wheel flicks to pass through Community, then Advisory Council, then Pilot Projects.
  • The winding SVG path still threads through each dot correctly — the path has rebuilt itself to account for the new document height from pin spacing.
  • AI card shows a single textured orb illustration (white line-art, paper color on the card's color).
  • Agents card shows the network-of-orbs illustration.
  • Knowledge and Tools cards still show the default brain illustration.
  • S4 Bifrost reveal: "Project Bifrost" headline visible top to bottom — no clipping on italic "Bifrost" tall letters.

Tuning knobs

If the pin holds feel too aggressive:

Target In bifrost.js (stickyPinSpecs array) Change
Less hero hold { sel: '#hero', hold: 300 } 150
Less treasure map hold hold: 360 on data-stop entries 200
Stronger hold any hold: N → higher N

If a single pin feels wrong and you want to kill it without breaking others, just delete that entry from stickyPinSpecs.

If the pins break the map path threading (it's rebuilt on refresh but if something's off): open DevTools, scroll through, and verify buildMapPath is firing via the ScrollTrigger.addEventListener('refresh', buildMapPath) hook. The path uses live DOM positions so it should always match.

Things NOT touched

  • public/entrance.html / entrance.js — unchanged.
  • Any of src/ (auth, db, sessions) — unchanged.
  • S2 architecture scene (scrub pin intact), S3 words fly-in (sticky pin intact), S4 aurora arc (sticky pin intact).
  • The topography parallax behind Europe map (from v3) — still present, still working.
  • The Welcome dot, 7-section nav, hero-foot restructure — all still in place.

Deploy steps

# Local — copy the new files in
Copy-Item -Force site-update-v5\protected\index.html  protected\index.html
Copy-Item -Force site-update-v5\protected\timeline.js protected\timeline.js
Copy-Item -Force site-update-v5\protected\bifrost.js  protected\bifrost.js

# Create the illustrations folder if it doesn't exist and copy PNGs
New-Item -ItemType Directory -Force -Path protected\fenja\illustrations
Copy-Item -Force site-update-v5\protected\fenja\illustrations\ai.png     protected\fenja\illustrations\
Copy-Item -Force site-update-v5\protected\fenja\illustrations\agents.png protected\fenja\illustrations\

# Test locally
npm run dev
# Verify all four changes work before pushing

# Commit + deploy
git add protected/
git commit -m "Hero centered, real ScrollTrigger pins, AI+Agents card illustrations, Bifrost headline breathing room"
# rsync + VPS steps same as before — rsync picks up the new PNGs automatically

On the VPS after rsync, verify the PNGs landed:

ls -la /opt/fenja/protected/fenja/illustrations/
# Should show: ai.png, agents.png, and the three existing stop illustrations

Then sudo systemctl restart fenja and spot-check.