From a2cbf57ce298546a900309db454a54ddc786b229 Mon Sep 17 00:00:00 2001 From: Arlind Ukshini Date: Fri, 24 Apr 2026 10:46:08 +0200 Subject: [PATCH] stack-scene: centered title, per-card counters, earlier anchor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Stack title bar moves from top-left next to the site-mark to centered at ~14vh so the title anchors visually to the cards below. Font size bumped to clamp(2rem, 3.6vw, 3rem). - Counter ("1 / 4 … 4 / 4") relocates from the title bar into each .layer-card as a .card-counter element in the top-right of each card-box. No longer driven by ScrollTrigger onUpdate — each card carries its own number, so stacked + grid phases both read correctly without JS. Grid phase shrinks the counter so it doesn't compete with the per-cell label. - SCENE_ANCHOR_OFFSET for stack-scene drops from 1800 back to 0, so clicking the "Capabilities" dot lands at the top of the pin — the title and first card come in together instead of starting mid-stack. Welcome step: the "desktop experience" aside and its CSS are removed. Users now see only the two definitions before the CTA. Co-Authored-By: Claude Opus 4.7 (1M context) --- protected/bifrost.js | 32 +++-------------- protected/index.html | 82 ++++++++++++++++++++++++-------------------- public/entrance.html | 41 ---------------------- 3 files changed, 49 insertions(+), 106 deletions(-) diff --git a/protected/bifrost.js b/protected/bifrost.js index a5f6a29..e55b543 100644 --- a/protected/bifrost.js +++ b/protected/bifrost.js @@ -463,11 +463,6 @@ // to yPercent, so centering is preserved). copyLayers.forEach(el => gsap.set(el, { yPercent: -50, opacity: 0, y: 20 })); - // Counter element in the stack-scene title bar. Updated on scroll to - // tick 1/4 → 4/4 as each card lands. Read inside the ScrollTrigger - // onUpdate below. Null-safe so missing markup doesn't break the scene. - const stackCounterEl = document.querySelector('#stack-counter .sc-current'); - const stackTl = gsap.timeline({ scrollTrigger: { trigger: '#stack-scene', @@ -478,22 +473,6 @@ pinSpacing: true, anticipatePin: 1, invalidateOnRefresh: true, - // Drive the "N/4" counter in the title bar. Each card in Phase A - // occupies ~0.105 of the timeline (see cards.forEach below), so - // the Nth card is fully landed at roughly N * 0.105. We show the - // *current* card — i.e. the highest-index card that has started - // its fall. After Phase A completes (~0.42) we hold on 4/4. - onUpdate(self) { - if (!stackCounterEl) return; - const p = self.progress; - // Landing midpoints: card i (0-indexed) finishes at roughly - // i * 0.105 + 0.1. Use floor((p - 0.01) / 0.105) + 1 so the - // tick advances slightly after each card starts, then clamp. - const n = Math.min(4, Math.max(1, Math.floor(p / 0.105) + 1)); - if (stackCounterEl.textContent !== String(n)) { - stackCounterEl.textContent = String(n); - } - }, } }); @@ -1236,9 +1215,9 @@ // dot-nav button anchors to it, so the reader lands AFTER the scene's // initial reveal rather than at an empty pre-scrub frame. // - // stack-scene — pin is 5000px long; Phase A (cards falling in) is - // complete at ~0.42 of that (~2100px). 1800 lands just before the - // 4th card fully settles, so the reveal still has one tick to go. + // stack-scene — offset 0 (top of the pin) so the reader lands right + // when the title appears and the first card starts its fall, and + // sees the full progression through all 4 landings. // // bifrost — section is 200vh with a scrubbed reveal that runs from // top-top to bottom-bottom (100vh scroll range). The sub-headline @@ -1251,9 +1230,8 @@ function getSceneAnchorOffset(sceneId) { const vh = window.innerHeight; switch (sceneId) { - case 'stack-scene': return 1800; - case 'bifrost': return Math.round(vh * 0.85); - default: return 0; + case 'bifrost': return Math.round(vh * 0.85); + default: return 0; } } diff --git a/protected/index.html b/protected/index.html index 042617a..10b7f72 100644 --- a/protected/index.html +++ b/protected/index.html @@ -1072,52 +1072,30 @@ html { /* ───────── Stack scene title bar ───────── Sits above the card theatre and rides with the pin so it remains - visible through all four card landings and the grid rearrange. The - .sc-current token is updated from bifrost.js's ScrollTrigger onUpdate - — 1/4 → 4/4 — one tick per landing card. - - Vertical top is aligned with the fixed .site-mark (top:28px) so - the title rides beside the wordmark at the very top of the scene, - floating horizontally at the same baseline. Horizontal padding on - the left is sized to clear the wordmark's right edge (~146px). */ + visible through all four card landings and the grid rearrange. + Centered horizontally; positioned lower so the title anchors + visually to the cards below rather than floating at the top of + the viewport. Per-card counter (1/4, 2/4, …) now lives inside + each .layer-card rather than being slaved to scroll progress. */ .stack-title-bar { position: absolute; - top: clamp(1.25rem, 2.8vh, 1.85rem); + top: clamp(5.5rem, 14vh, 10rem); left: 0; right: 0; z-index: 20; - display: flex; - justify-content: space-between; - align-items: baseline; - gap: 1.5rem; - padding-left: clamp(10rem, 12vw, 12rem); - padding-right: clamp(0.75rem, 2vw, 2.25rem); + text-align: center; + padding-inline: clamp(1rem, 4vw, 3rem); pointer-events: none; } .stack-title { margin: 0; font-family: "Newsreader", Georgia, serif; font-weight: 400; - font-size: clamp(1.4rem, 2.6vw, 2.2rem); - letter-spacing: -0.01em; - line-height: 1.2; + font-size: clamp(2rem, 3.6vw, 3rem); + letter-spacing: -0.015em; + line-height: 1.12; color: var(--ink); } - .stack-counter { - font-family: "Newsreader", Georgia, serif; - font-weight: 500; - font-size: clamp(1.1rem, 2vw, 1.6rem); - color: var(--ink-soft); - font-variant-numeric: tabular-nums; - white-space: nowrap; - } - .stack-counter .sc-current { - color: var(--accent); - font-weight: 600; - transition: color 180ms var(--ease); - } - .stack-counter .sc-sep, - .stack-counter .sc-total { color: var(--ink-soft); } /* LEFT COPY (visible only during grid phase) */ .copy-stage { @@ -1302,6 +1280,32 @@ html { z-index: 2; } + /* Per-card counter — lives in the top-right of each card-box and + reads "1 / 4" through "4 / 4". Paper-toned to contrast against + the sage/slate/clay/plum card backgrounds. */ + .card-counter { + position: absolute; + top: clamp(1rem, 1.4vw, 1.4rem); + right: clamp(1rem, 1.4vw, 1.4rem); + font-family: "Newsreader", Georgia, serif; + font-weight: 500; + font-size: clamp(0.85rem, 1.05vw, 1.05rem); + letter-spacing: 0.04em; + color: rgba(255, 252, 247, 0.85); + font-variant-numeric: tabular-nums; + line-height: 1; + pointer-events: none; + z-index: 2; + } + .in-grid .card-counter { + /* Keep the counter visible in the grid phase but smaller so it + doesn't compete with the grid-label. */ + top: clamp(0.5rem, 0.7vw, 0.8rem); + right: clamp(0.5rem, 0.7vw, 0.8rem); + font-size: clamp(0.6rem, 0.7vw, 0.75rem); + opacity: 0.7; + } + .in-grid .card-box { /* 15% reduction from the original 20vw — matches the drop-phase shrink. Also matches cellSize and targetW in bifrost.js (both are vw * 0.17). */ @@ -2485,13 +2489,11 @@ html {
+ the reader scrolls through all 4 capability cards. The per-card + counter now lives inside each .layer-card (see .card-counter + below), so the title here is a standalone centered lockup. -->
@@ -2518,6 +2520,7 @@ html {
The AI
+

An open-source model, running on your own hardware.

@@ -2530,6 +2533,7 @@ html {
The Knowledge
+

The business context that makes AI understand your world.

@@ -2542,6 +2546,7 @@ html {
The Tools
+

How AI acts — not just what it knows.

@@ -2554,6 +2559,7 @@ html {
The Agents
+

Specialized AI agents working together around real tasks.

diff --git a/public/entrance.html b/public/entrance.html index 2068670..c94efae 100644 --- a/public/entrance.html +++ b/public/entrance.html @@ -211,39 +211,6 @@ color: var(--ink); } - /* Practical viewing-experience note. Lives between the definitions - and the CTA so readers see it before committing to "Learn more". - Left-bordered callout in the editorial voice — same Newsreader as - the surrounding copy, tempered colour so it reads as guidance not - body text. */ - .welcome-note { - max-width: 620px; - margin: 22px 0 8px 0; - padding: 14px 18px; - border-left: 3px solid var(--crimson); - background: rgba(138, 58, 47, 0.04); - font-family: "Newsreader", Georgia, "Times New Roman", serif; - font-weight: 400; - font-size: 17px; - line-height: 1.5; - color: var(--ink); - } - .welcome-note strong { - font-weight: 600; - color: var(--ink); - } - .welcome-note em { - font-style: italic; - font-weight: 700; - color: var(--crimson); - } - .welcome-note p { - margin: 0; - } - .welcome-note p + p { - margin-top: 8px; - } - .welcome-cta { all: unset; display: inline-flex; @@ -378,14 +345,6 @@

Project Bifrost

The initiative created to ensure that Fenja AI is built not just for organisations like yours, but with you.

-