Timeline page: - .page-sub: final sentence wrapped in .page-sub-accent and styled crimson so the rhetorical beat lifts off the block. - Scroll-to-begin hint is now toggled from applyScroll() against state.target, so it dismisses on first commit AND re-appears when the reader scrolls all the way back to the start. onWheel no longer hard-adds .hint-dismissed; the applyScroll toggle drives both ways. Overview page: - Hero scroll icon: size and presence bumped (2px line, 44px tall, 11px chevron, weight 600, color:var(--ink)) so it reads as a confident cue, not a whisper at the bottom of the hero. - Architecture scene gains a title bar pinned with the scene: "The Fenja AI platform in four steps" with a 1/4 → 4/4 counter driven by the scroll-trigger onUpdate. Bar is placed below the site-mark's fixed position so the two don't collide. - Dot-nav: dot size 5px → 10px (1.5px ring) for better click target + visual weight. Buttons for "Words" and "Participate" removed — the corresponding intermediate sections now map to their nearest surviving dot in bifrost.js's scroll-spy (words-scene → stack-scene, bifrost-meaning → bifrost). - Renames: "Hero" → "Fenja introduction", "Architecture" → "Capabilities", "Bifrost" → "Project Bifrost". - scrollTo() adds a per-scene SCENE_ANCHOR_OFFSET — stack-scene lands +2100px into its 5000px pin so the reader arrives on the fully stacked state instead of an empty pre-animation frame. Welcome step (public/entrance.html): - New .welcome-note callout between definitions and CTA advising desktop viewing and gentle scrolling so readers don't fly past animated sections before they've resolved. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
407 lines
12 KiB
HTML
407 lines
12 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
<title>Fenja AI</title>
|
|
<style>
|
|
@view-transition { navigation: auto; }
|
|
|
|
:root {
|
|
--paper: #faf6ee;
|
|
--paper-sink: #e7e1d0;
|
|
--paper-sink-deep: #ddd6c3;
|
|
--ink: #383831;
|
|
--ink-soft: #5f5e5e;
|
|
--ink-dim: #8a887f;
|
|
--walnut: #785f53;
|
|
--walnut-dim: #6b5348;
|
|
--crimson: #8a3a2f;
|
|
--ease: cubic-bezier(0.2, 0, 0, 1);
|
|
--dur: 240ms;
|
|
}
|
|
|
|
*, *::before, *::after { box-sizing: border-box; }
|
|
|
|
html, body {
|
|
margin: 0; padding: 0;
|
|
min-height: 100%;
|
|
background: var(--paper);
|
|
color: var(--ink);
|
|
font-family: "Manrope", system-ui, -apple-system, sans-serif;
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
body {
|
|
min-height: 100vh;
|
|
background: radial-gradient(1100px 760px at 22% 42%, #fffcf7 0%, var(--paper) 58%, #f2ecdd 100%);
|
|
display: flex;
|
|
align-items: center;
|
|
view-transition-name: paper;
|
|
}
|
|
|
|
/* ───── Topographic currents ───── */
|
|
.currents {
|
|
position: fixed;
|
|
top: -22vh; right: -18vw;
|
|
width: 90vw; height: 130vh;
|
|
max-width: 1600px;
|
|
pointer-events: none;
|
|
z-index: 1;
|
|
-webkit-mask-image: radial-gradient(60% 60% at 50% 50%, #000 40%, transparent 82%);
|
|
mask-image: radial-gradient(60% 60% at 50% 50%, #000 40%, transparent 82%);
|
|
opacity: 0;
|
|
transition: opacity 900ms var(--ease);
|
|
}
|
|
.currents.is-ready { opacity: 1; }
|
|
.currents svg { width: 100%; height: 100%; display: block; }
|
|
|
|
.entrance {
|
|
position: relative;
|
|
z-index: 10;
|
|
width: 100%;
|
|
min-height: 100vh;
|
|
padding: 0 112px;
|
|
/* Vertically center the active step (email or welcome). Body-level
|
|
flex also centers, but an extra flex layer here ensures the
|
|
welcome step — which is taller than the email step — stays
|
|
anchored to the viewport centre rather than drifting down. */
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
.entrance-inner {
|
|
max-width: 620px;
|
|
width: 100%;
|
|
}
|
|
|
|
/* ───── Steps ───── */
|
|
.step { display: none; }
|
|
.step.is-active {
|
|
display: block;
|
|
animation: enter 640ms var(--ease) forwards;
|
|
}
|
|
/* Suppress every step until entrance.js has checked /auth/me and picked
|
|
the right starting step. Prevents a flash of the email form when an
|
|
authed user lands on /. */
|
|
body.is-pending .step { display: none !important; }
|
|
@keyframes enter {
|
|
from { opacity: 0; transform: translateY(6px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
/* ───── Tagline ───── */
|
|
.tagline {
|
|
font-family: "Newsreader", Georgia, "Times New Roman", serif;
|
|
font-style: italic;
|
|
font-weight: 400;
|
|
font-size: 34px;
|
|
line-height: 1.28;
|
|
letter-spacing: -0.012em;
|
|
color: var(--ink);
|
|
margin: 0 0 40px 0;
|
|
text-wrap: pretty;
|
|
}
|
|
|
|
/* ───── Field ───── */
|
|
.field { display: block; width: 100%; }
|
|
.field-input {
|
|
display: block; width: 100%;
|
|
height: 56px; padding: 0 18px;
|
|
background: var(--paper-sink);
|
|
color: var(--ink);
|
|
font-family: "Manrope", system-ui, sans-serif;
|
|
font-size: 17px; font-weight: 400;
|
|
border: 0;
|
|
border-radius: 12px 12px 0 0;
|
|
outline: 0;
|
|
box-shadow: inset 0 -1px 0 0 rgba(56, 56, 49, 0.25);
|
|
transition: box-shadow var(--dur) var(--ease), background var(--dur) var(--ease);
|
|
}
|
|
.field-input::placeholder {
|
|
color: var(--ink-dim);
|
|
font-family: "Newsreader", Georgia, serif;
|
|
font-style: italic;
|
|
font-size: 17px;
|
|
}
|
|
.field-input:focus {
|
|
background: #eae3d0;
|
|
box-shadow: inset 0 -2px 0 0 var(--walnut);
|
|
}
|
|
.field-input.is-error {
|
|
box-shadow: inset 0 -2px 0 0 var(--crimson);
|
|
}
|
|
.field-input:disabled { opacity: 0.55; cursor: default; }
|
|
|
|
/* ───── Welcome-step wordmark (centered in the right half) ───── */
|
|
.welcome-logo {
|
|
position: fixed;
|
|
top: 50%;
|
|
left: 75%;
|
|
transform: translate(-50%, -50%);
|
|
width: 280px;
|
|
height: auto;
|
|
opacity: 0;
|
|
pointer-events: none;
|
|
z-index: 5;
|
|
transition: opacity 640ms var(--ease) 120ms;
|
|
}
|
|
body:has(#step-welcome.is-active) .welcome-logo {
|
|
opacity: 0.92;
|
|
}
|
|
|
|
/* ───── Welcome ───── */
|
|
.welcome-title {
|
|
font-family: "Newsreader", Georgia, "Times New Roman", serif;
|
|
font-weight: 400;
|
|
font-size: 54px;
|
|
line-height: 1.05;
|
|
letter-spacing: -0.022em;
|
|
color: var(--ink);
|
|
margin: 0 0 28px 0;
|
|
text-wrap: pretty;
|
|
}
|
|
/* The terminal keyword — per the Definitive Emphasis rule:
|
|
Newsreader Bold Italic on the last word, followed by the
|
|
absolute period. Applies to both "Thanks for your interest,
|
|
Erik." (name) and "Thank you for your interest." (no name). */
|
|
.welcome-title em {
|
|
font-style: italic;
|
|
font-weight: 700;
|
|
}
|
|
.welcome-body {
|
|
font-family: "Newsreader", Georgia, "Times New Roman", serif;
|
|
font-weight: 400;
|
|
font-size: 20px;
|
|
line-height: 1.55;
|
|
color: var(--ink);
|
|
max-width: 620px;
|
|
margin: 0 0 20px 0;
|
|
text-wrap: pretty;
|
|
}
|
|
.welcome-body em { font-style: italic; font-weight: 700; }
|
|
|
|
/* Two-line definition block: bold-italic term + short definition. */
|
|
.welcome-define {
|
|
max-width: 620px;
|
|
margin: 0 0 18px 0;
|
|
}
|
|
.welcome-term {
|
|
font-family: "Newsreader", Georgia, "Times New Roman", serif;
|
|
font-weight: 500;
|
|
font-size: 22px;
|
|
line-height: 1.2;
|
|
color: var(--ink);
|
|
margin: 0 0 2px 0;
|
|
}
|
|
.welcome-term em {
|
|
font-style: italic;
|
|
font-weight: 700;
|
|
}
|
|
.welcome-def {
|
|
font-family: "Newsreader", Georgia, "Times New Roman", serif;
|
|
font-weight: 400;
|
|
font-size: 19px;
|
|
line-height: 1.5;
|
|
color: var(--ink-soft);
|
|
margin: 0;
|
|
text-wrap: pretty;
|
|
}
|
|
.welcome-def em {
|
|
font-style: italic;
|
|
font-weight: 700;
|
|
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;
|
|
align-items: center;
|
|
gap: 14px;
|
|
margin-top: 20px;
|
|
padding: 16px 24px;
|
|
background: #fffcf7;
|
|
color: var(--ink);
|
|
cursor: pointer;
|
|
box-shadow:
|
|
0 0 0 0.5px rgba(56,56,49,0.06),
|
|
0 18px 32px -18px rgba(56,56,49,0.22),
|
|
0 2px 6px -3px rgba(56,56,49,0.08);
|
|
transition:
|
|
background var(--dur) var(--ease),
|
|
box-shadow var(--dur) var(--ease);
|
|
animation: welcome-breath 2800ms var(--ease) infinite;
|
|
}
|
|
.welcome-cta:hover {
|
|
background: #fffbf2;
|
|
box-shadow:
|
|
0 0 0 0.5px rgba(56,56,49,0.10),
|
|
0 24px 40px -20px rgba(56,56,49,0.28),
|
|
0 3px 8px -4px rgba(56,56,49,0.10);
|
|
}
|
|
.welcome-cta .c-label {
|
|
font-family: "Newsreader", Georgia, serif;
|
|
font-size: 19px;
|
|
font-weight: 400;
|
|
letter-spacing: -0.01em;
|
|
color: var(--ink);
|
|
line-height: 1;
|
|
}
|
|
.welcome-cta .c-icon {
|
|
flex-shrink: 0;
|
|
color: var(--ink-soft);
|
|
display: block;
|
|
}
|
|
.welcome-cta .c-arrow {
|
|
font-family: "Newsreader", Georgia, serif;
|
|
font-style: italic;
|
|
font-size: 21px;
|
|
color: var(--crimson);
|
|
line-height: 1;
|
|
transition: transform var(--dur) var(--ease);
|
|
}
|
|
.welcome-cta:hover .c-arrow {
|
|
transform: translateX(4px);
|
|
}
|
|
@keyframes welcome-breath {
|
|
0%, 100% { transform: translateX(0); }
|
|
50% { transform: translateX(5px); }
|
|
}
|
|
|
|
/* ───── Post-submit acknowledgement ───── */
|
|
.ack {
|
|
margin-top: 16px;
|
|
font-family: "Newsreader", Georgia, serif;
|
|
font-style: italic;
|
|
font-size: 15px;
|
|
color: var(--ink-soft);
|
|
min-height: 22px;
|
|
opacity: 0;
|
|
transform: translateY(-4px);
|
|
transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
|
|
}
|
|
.ack.is-visible { opacity: 1; transform: translateY(0); }
|
|
.ack.is-error { color: var(--crimson); }
|
|
|
|
@media (max-width: 720px) {
|
|
.entrance { padding: 0 28px; }
|
|
.tagline { font-size: 26px; margin-bottom: 32px; }
|
|
.currents { opacity: 0.5; }
|
|
.welcome-title { font-size: 38px; }
|
|
.welcome-body { font-size: 18px; }
|
|
.welcome-logo { display: none; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="is-pending">
|
|
|
|
<div class="currents" id="currents" aria-hidden="true"></div>
|
|
|
|
<img class="welcome-logo" src="/fenja/fenja-wordmark-black.svg" alt="Fenja" aria-hidden="true" />
|
|
|
|
<main class="entrance">
|
|
<div class="entrance-inner">
|
|
|
|
<!-- STEP 1 — EMAIL -->
|
|
<section class="step is-active" id="step-email">
|
|
<p class="tagline">
|
|
Thank you for your commitment and willingness to contribute.
|
|
</p>
|
|
<form class="field" id="email-form" novalidate>
|
|
<input
|
|
type="email"
|
|
class="field-input"
|
|
id="email-input"
|
|
name="email"
|
|
autocomplete="email"
|
|
spellcheck="false"
|
|
placeholder="your email"
|
|
aria-label="Email address"
|
|
required
|
|
/>
|
|
<div class="ack" id="email-ack" aria-live="polite"></div>
|
|
</form>
|
|
</section>
|
|
|
|
<!-- STEP 2 — WELCOME -->
|
|
<!-- The title is set dynamically by entrance.js:
|
|
with first name: "Thanks for your interest, <em>Erik.</em>"
|
|
without first name: "Thank you for your <em>interest.</em>"
|
|
Static fallback text (for no-JS) renders the anonymous variant. -->
|
|
<section class="step" id="step-welcome">
|
|
<h1 class="welcome-title" id="welcome-title">
|
|
Thank you for your <em>interest.</em>
|
|
</h1>
|
|
<p class="welcome-body">
|
|
This is a personal invitation because we believe your perspective
|
|
can make a meaningful contribution to an important mission: building
|
|
trusted, sovereign AI for Denmark and Europe. In this short web
|
|
experience, we will explain why this matters, what Fenja AI is, and
|
|
how you, through Project Bifrost, can help shape its future.
|
|
</p>
|
|
<div class="welcome-define">
|
|
<h3 class="welcome-term"><em>Fenja AI</em></h3>
|
|
<p class="welcome-def">The company and platform for sovereign and safe AI.</p>
|
|
</div>
|
|
<div class="welcome-define">
|
|
<h3 class="welcome-term"><em>Project Bifrost</em></h3>
|
|
<p class="welcome-def">The initiative created to ensure that Fenja AI is built not just for organisations like yours, but <em>with</em> you.</p>
|
|
</div>
|
|
<aside class="welcome-note" aria-label="Viewing recommendation">
|
|
<p>
|
|
This site is a <strong>desktop experience</strong>. It showcases many of the capabilities of our products, and is therefore not optimised for mobile — we recommend viewing it on a <em>desktop screen</em>.
|
|
</p>
|
|
<p>
|
|
Be mindful of the scrolling experience: <em>scroll gently</em> so you don’t accidentally pass over a section before it finishes animating.
|
|
</p>
|
|
</aside>
|
|
<button type="button" class="welcome-cta" id="welcome-continue">
|
|
<svg class="c-icon" width="20" height="20" viewBox="0 0 24 24" fill="none"
|
|
stroke="currentColor" stroke-width="1.3"
|
|
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
<path d="M4 4.5c2.5-.7 5-.7 8 .5C15 4 17.5 3.8 20 4.5v14c-2.5-.7-5-.5-8 .5-3-1-5.5-1.2-8-.5v-14Z"/>
|
|
<path d="M12 5v14"/>
|
|
</svg>
|
|
<span class="c-label">Learn more about Project Bifrost</span>
|
|
<span class="c-arrow" aria-hidden="true">→</span>
|
|
</button>
|
|
</section>
|
|
|
|
</div>
|
|
</main>
|
|
|
|
<script src="/entrance.js" defer></script>
|
|
|
|
</body>
|
|
</html>
|