fix hero placement, add iamges
This commit is contained in:
parent
8790b6629b
commit
8bd0fda910
6 changed files with 196 additions and 23 deletions
170
CHANGES 4.md
Normal file
170
CHANGES 4.md
Normal file
|
|
@ -0,0 +1,170 @@
|
||||||
|
# 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:**
|
||||||
|
```js
|
||||||
|
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):
|
||||||
|
|
||||||
|
```css
|
||||||
|
.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.95` → `1.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
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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.
|
||||||
BIN
protected/fenja/illustrations/agents.png
Normal file
BIN
protected/fenja/illustrations/agents.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 340 KiB |
BIN
protected/fenja/illustrations/ai.png
Normal file
BIN
protected/fenja/illustrations/ai.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 270 KiB |
BIN
protected/fenja/illustrations/blocs tools.png
Normal file
BIN
protected/fenja/illustrations/blocs tools.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 352 KiB |
BIN
protected/fenja/illustrations/lightbulb - knowledge.png
Normal file
BIN
protected/fenja/illustrations/lightbulb - knowledge.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 431 KiB |
|
|
@ -691,14 +691,19 @@
|
||||||
display: grid;
|
display: grid;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
/* Asymmetric block padding — the larger padding-bottom shifts the
|
||||||
|
centered hero content upward, leaving breathing room between the
|
||||||
|
hero-foot row and the dot-nav at the bottom of the viewport. */
|
||||||
|
padding-top: clamp(1.5rem, 3vh, 2.5rem);
|
||||||
|
padding-bottom: clamp(6rem, 16vh, 11rem);
|
||||||
}
|
}
|
||||||
#page-overview #hero .hero-wrap {
|
#page-overview #hero .hero-wrap {
|
||||||
/* Constrain to the left column so Europe is visible to its right. */
|
/* Constrain to the left column so Europe is visible to its right. */
|
||||||
max-width: 62ch;
|
max-width: 62ch;
|
||||||
/* Reduced from clamp(6rem, 16vh, 12rem) to move hero text up into
|
/* Zeroed: wrap padding-top was adding down-drift inside the centered
|
||||||
the upper half of the viewport. Same intent as the #hero padding
|
container, pushing the hero-foot toward the dot-nav. Vertical
|
||||||
reduction above — the more-specific selector takes precedence. */
|
position is now controlled entirely by #hero's asymmetric padding. */
|
||||||
padding-top: clamp(3rem, 8vh, 6rem);
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure scenes don't accidentally inherit `main { position: relative }` */
|
/* Make sure scenes don't accidentally inherit `main { position: relative }` */
|
||||||
|
|
@ -1032,32 +1037,32 @@ html {
|
||||||
will-change: opacity;
|
will-change: opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Brain icon — CSS mask filled with cream color; looks good on any card tint */
|
/* Card illustration — per-layer PNG set via --card-illust custom property. */
|
||||||
.card-brain {
|
.card-brain {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
aspect-ratio: 20 / 17;
|
aspect-ratio: 20 / 17;
|
||||||
background-color: var(--paper);
|
background-image: var(--card-illust);
|
||||||
-webkit-mask-image: var(--brain-mask);
|
background-size: contain;
|
||||||
mask-image: var(--brain-mask);
|
background-position: center right;
|
||||||
-webkit-mask-size: contain;
|
background-repeat: no-repeat;
|
||||||
mask-size: contain;
|
opacity: 0.95;
|
||||||
-webkit-mask-position: center right;
|
|
||||||
mask-position: center right;
|
|
||||||
-webkit-mask-repeat: no-repeat;
|
|
||||||
mask-repeat: no-repeat;
|
|
||||||
opacity: 0.9;
|
|
||||||
margin-right: clamp(-3.5rem, -3vw, -1.5rem); /* bleed off right edge */
|
margin-right: clamp(-3.5rem, -3vw, -1.5rem); /* bleed off right edge */
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Per-layer colours — muted Nordic mid-tones.
|
/* Per-layer colours — muted Nordic mid-tones. */
|
||||||
Dark ink text + cream brain both read well on each. */
|
|
||||||
.layer-card[data-layer="0"] .card-box { background: #7a8c70; } /* sage — AI Model */
|
.layer-card[data-layer="0"] .card-box { background: #7a8c70; } /* sage — AI Model */
|
||||||
.layer-card[data-layer="1"] .card-box { background: #7b9399; } /* slate — Knowledge */
|
.layer-card[data-layer="1"] .card-box { background: #7b9399; } /* slate — Knowledge */
|
||||||
.layer-card[data-layer="2"] .card-box { background: #b07556; } /* clay — Tools */
|
.layer-card[data-layer="2"] .card-box { background: #b07556; } /* clay — Tools */
|
||||||
.layer-card[data-layer="3"] .card-box { background: #8a7a92; } /* plum — Agents */
|
.layer-card[data-layer="3"] .card-box { background: #8a7a92; } /* plum — Agents */
|
||||||
|
|
||||||
|
/* Per-layer illustrations — URL-encode spaces in filenames. */
|
||||||
|
.layer-card[data-layer="0"] .card-brain { --card-illust: url('/fenja/illustrations/ai.png'); }
|
||||||
|
.layer-card[data-layer="1"] .card-brain { --card-illust: url('/fenja/illustrations/lightbulb%20-%20knowledge.png'); }
|
||||||
|
.layer-card[data-layer="2"] .card-brain { --card-illust: url('/fenja/illustrations/blocs%20tools.png'); }
|
||||||
|
.layer-card[data-layer="3"] .card-brain { --card-illust: url('/fenja/illustrations/agents.png'); }
|
||||||
|
|
||||||
/* z-stacking — later layers appear on top */
|
/* z-stacking — later layers appear on top */
|
||||||
.layer-card[data-layer="0"] { z-index: 1; }
|
.layer-card[data-layer="0"] { z-index: 1; }
|
||||||
.layer-card[data-layer="1"] { z-index: 2; }
|
.layer-card[data-layer="1"] { z-index: 2; }
|
||||||
|
|
@ -1124,17 +1129,15 @@ html {
|
||||||
/* Hide long title + body in grid phase */
|
/* Hide long title + body in grid phase */
|
||||||
.in-grid .card-content { display: none; }
|
.in-grid .card-content { display: none; }
|
||||||
|
|
||||||
/* Brain fills remaining space, centered. */
|
/* Illustration fills remaining space, centered. */
|
||||||
.in-grid .card-brain {
|
.in-grid .card-brain {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
aspect-ratio: auto;
|
aspect-ratio: auto;
|
||||||
-webkit-mask-position: center;
|
background-position: center;
|
||||||
mask-position: center;
|
background-size: 90% auto;
|
||||||
-webkit-mask-size: 90% auto;
|
opacity: 0.9;
|
||||||
mask-size: 90% auto;
|
|
||||||
opacity: 0.85;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hide the outside-box eyebrow during grid phase */
|
/* Hide the outside-box eyebrow during grid phase */
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue