# Site update v3 — Welcome dot, smaller cards, parallax topography, sticky scroll, hero polish

Six changes land together. All in `protected/`. Server-side untouched.

## Files to replace

| File | What changed |
|---|---|
| `protected/index.html` | Welcome dot added; card sizes reduced 15%; topography layer added (markup + CSS); hero padding reduced; hero-foot restructured (moved into left column, arrow points down) |
| `protected/timeline.js` | Dot-nav click handler now supports `external-*` targets (Welcome routes back to `/`); `setActiveDot` skips external dots |
| `protected/bifrost.js` | `cellSize` and `targetW` adjusted for the shrunk grid; topography SVG generator + parallax driver added; sticky-scroll velocity damping added for non-pinned scenes |

## Change-by-change

### 1. Welcome dot (nav position 1)

- 8th dot, placed FIRST in the dot-nav (before Timeline).
- On click, navigates to `/` — the entrance page. Since the user's session is still valid, they land on the welcome step with the "Learn more" button.
- **Never shows as active** — even when scrolling `/timeline`, the Welcome dot stays in the default outlined state. It's a navigation link, not a section marker.
- HTML: `<button class="dot-btn" data-target="external-welcome" data-href="/">`
- JS: `timeline.js`'s click handler recognises `external-*` prefixes and uses `window.location.href` instead of the page-switching flow.

### 2. Cards shrunk 15%

Applies to both animation phases:

**Drop phase (`.layer-card` + `.card-box`):**
- Cards previously spanned `left: 0 / right: 0`. Now have `7.5%` margin on each side (= 15% total width reduction).
- `.card-box` padding reduced from `clamp(1.75rem, 3.2vw, 2.8rem)` → `clamp(1.5rem, 2.7vw, 2.4rem)`.
- `min-height` reduced from 240px → 204px.
- Content gap slightly tightened.

**Grid phase (`.in-grid .card-box`):**
- `width: 20vw` → `width: 17vw`. Matching `max-width` and inner padding also reduced.

**bifrost.js (the two places that compute grid geometry):**
- `cellSize = vw * 0.20` → `vw * 0.17` (line ~298)
- `targetW = vw * 0.20` → `vw * 0.17` (line ~423)

### 3. Parallax topography layer

- New `<div id="overview-topography">` sits inside `#page-overview`, at `z-index: 0` — behind the Europe map (z-index 1) and all content (z-index 2+).
- At init, `bifrost.js` draws 34 concentric rings (each with multi-harmonic sinusoidal distortion) into the SVG. Path coordinates match the entrance page's "currents" generator — intentionally a visual sibling — but with altered parameters:
  - **34 rings** (vs 26 on entrance), tighter **28px step**, larger **32px amplitude**
  - Positioned with **bottom-left anchor** (entrance uses top-right)
  - **Rotated 40°** via CSS so the harmonic pattern reads as distinct from the entrance
  - **Lower opacity** (0.04 / 0.07) — it sits behind the map, shouldn't compete
- Parallax: driven from `lenis.on('scroll')`, translating the SVG by `scrollTop * -0.15` pixels (very slow — the layer barely moves, feels like atmospheric depth).
- The CSS `rotate(40deg)` is composed WITH the JS `translateY()` in a single transform string so neither clobbers the other.

### 4. Sticky scroll (non-pinned scenes only)

- Velocity-damping hook on `lenis.on('scroll')`. When a non-pinned scene's vertical midpoint is within ±20% of viewport height from the viewport center, damping engages.
- While engaged: multiplies Lenis's `velocity` by 0.82 per frame. The scene appears to "hold" the scroll briefly.
- **Hard cap: 300ms per scene entry.** No scene can hold the user for longer than that — even if they stop scrolling in the zone, the damping window expires.
- Re-armed when scene leaves the zone. Each entry gets a fresh 300ms window.
- **Excluded scenes:** `stack-scene` (S2) is already pinned + scrubbed by GSAP ScrollTrigger; damping on top would make its card-fall feel sluggish. Included: `hero`, `words-scene`, `bifrost`, `bifrost-meaning`, `bifrost-join`.
- Implementation is in `bifrost.js` init, as part of the Lenis scroll subscribers.

### 5. Hero text moved up

- `#hero` padding-top: `clamp(7rem, 14vh, 11rem)` → `clamp(3.5rem, 7vh, 5.5rem)`.
- `#page-overview #hero .hero-wrap` padding-top: `clamp(6rem, 16vh, 12rem)` → `clamp(3rem, 8vh, 6rem)`.
- The overview-specific rule is the more-specific selector — it's the one that actually wins on the Overview page. Both updated so a future refactor doesn't accidentally reintroduce the low position.
- Text size, weights, kerning: untouched.

### 6. Hero footer restructured

**Before:** `<div class="hero-foot">` was `position: absolute; bottom: 0` — a separate row spanning the full viewport width. "Supported by" on the left, "Scroll →" (with horizontal right-arrow) on the right.

**After:** Moved INSIDE the left column, placed immediately after the lede paragraph:

```
[eyebrow]
[headline]
[lede paragraph]
                                ← margin-top: clamp(2rem, 5vh, 3.5rem)
[Supported by [Innov]]           [↓ Scroll]
  ↑ same baseline                  ↑ aligned to right edge of left column
```

- `.hero-foot` is now `display: flex; justify-content: space-between; align-items: baseline`. Both items share the baseline of "Supported by".
- `.scroll-hint .arrow` rotated to vertical: `width: 1px; height: 28px`. The `::after` chevron cap moved from top-right (pointing right) to bottom-left corner, rotated 45° to point down.
- `@keyframes hint`: `translateX(6px)` → `translateY(6px)`. The arrow now bounces downward, matching its new meaning.
- Mobile fallback override simplified (no longer needs `position: static` since the element is no longer absolutely positioned).

## Spot-check after deploy

### Nav + Welcome dot
- [ ] 8 dots visible at bottom center.
- [ ] Leftmost dot, hover → tooltip reads **"Welcome"**. Click → browser navigates to `/`, entrance welcome step renders.
- [ ] Second dot, hover → **"Timeline"**. Click → Timeline page (P1) becomes active, Welcome dot stays in default state.
- [ ] Scroll through Overview. Watch the active dot cycle: Hero → Architecture → Words → Bifrost → Participate → Join. Welcome dot never lights up.

### Cards
- [ ] S2 drop phase: cards appear visibly narrower than before (15% reduction — should be noticeable).
- [ ] S2 grid phase (scroll through the pin): the 2x2 grid is slightly smaller; text in copy panels doesn't overflow into the grid area.

### Topography
- [ ] Open Overview page. Behind the Europe map, faint ring patterns visible in the paper — rotated, offset to bottom-left.
- [ ] Scroll slowly. The rings shift vertically at a much slower rate than the scene content — barely perceptible but present (parallax).
- [ ] The rings are visibly **different from the entrance page's currents** — rotated, denser, lower opacity.

### Sticky scroll
- [ ] Scroll with a trackpad or mouse wheel through Overview. When a scene's middle is close to viewport-center, feel a brief slowdown (about 300ms).
- [ ] The effect is subtle — you can still scroll quickly through scenes with determined effort.
- [ ] **Scene 2 (architecture, pinned) is NOT affected.** Its scrubbed scroll speed is unchanged.
- [ ] No "hostile" feel. If it's too much, reduce `DAMP_FACTOR` from 0.82 → 0.88 in bifrost.js.

### Hero
- [ ] Hero text (eyebrow, headline, lede) sits in the upper half of the viewport, closer to the site-mark.
- [ ] Below the lede, a row: "Supported by Innovationsfonden" on the LEFT, vertical-down "↓ Scroll" arrow on the RIGHT, same baseline.
- [ ] The arrow bounces DOWNWARD (translateY animation), not rightward.
- [ ] No absolutely-positioned element at the bottom of the hero viewport.

## Tuning knobs

If any feel wrong after deploy:

| Tuning | File | Default | Change to |
|---|---|---|---|
| Parallax speed | `bifrost.js` | `PARALLAX_SPEED = 0.15` | higher (faster) or lower (slower) |
| Topography density | `bifrost.js` | `RINGS = 34, STEP = 28` | reduce rings or increase step for sparser pattern |
| Topography opacity | `bifrost.js` | `0.04 / 0.07` | lower to fade further |
| Sticky damping strength | `bifrost.js` | `DAMP_FACTOR = 0.82` | `0.88` for weaker, `0.75` for stronger |
| Sticky zone size | `bifrost.js` | `DAMP_ZONE_VH = 0.20` | `0.15` narrower, `0.25` wider |
| Sticky hold duration | `bifrost.js` | `DAMP_MAX_MS = 300` | `200`–`500` |
| Hero text position | `index.html` | `clamp(3rem, 8vh, 6rem)` | increase for lower text |

## Things NOT touched

- `public/entrance.html` / `entrance.js` — unchanged. The currents pattern there remains the original.
- S2 card content, S3 sentence, S5/S6 content — unchanged.
- Auth flow, session, invite system — unchanged.
- Nav labels (Welcome, Timeline, Hero, Architecture, Words, Bifrost, Participate, Join) — unchanged.

## Race condition to watch

There's a race window between `timeline.js`'s `/auth/me` fetch and `bifrost.js`'s init. If the user clicks the Overview dot before the fetch resolves, S3 may render with the no-name fallback even for a named invite. On refresh, the name appears correctly. Not critical — flagged in previous CHANGES.md. If this bites in practice, the fix is to `await` the fetch in the Overview activation path.
