feat(hero): single H1, annotation pins, microline, anchor CTA
- Drop the rotating headline and its <script> block - Replace with single category-defining H1: 'Ship Camel integrations. Sleep through the night.' - Add price microline under the CTAs (14-day trial · from €20/mo) - Replace 'Sign in' secondary CTA with 'See it in action ↓' anchor to #walkthrough - Add three numbered annotation pins overlaid on the screenshot, with a 3-up legend below the image (correlation ID, failure context, error pinned) The eyebrow pill is retained — the only surviving camel pun on the homepage per the pun-budget decision in the spec. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,19 @@
|
|||||||
import CTAButtons from '../CTAButtons.astro';
|
import CTAButtons from '../CTAButtons.astro';
|
||||||
import TopographicBg from '../TopographicBg.astro';
|
import TopographicBg from '../TopographicBg.astro';
|
||||||
import Lightbox from '../Lightbox.astro';
|
import Lightbox from '../Lightbox.astro';
|
||||||
|
|
||||||
|
interface Pin {
|
||||||
|
label: string;
|
||||||
|
body: string;
|
||||||
|
top: string;
|
||||||
|
left: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pins: Pin[] = [
|
||||||
|
{ label: '01', body: 'Correlation ID — click to follow one exchange across services.', top: '14%', left: '12%' },
|
||||||
|
{ label: '02', body: 'Failure in context — circuit breaker tripped, fallback ran, tried backend:80.', top: '46%', left: '52%' },
|
||||||
|
{ label: '03', body: 'Full error pinned — exception, stack trace, headers, payload.', top: '78%', left: '78%' },
|
||||||
|
];
|
||||||
---
|
---
|
||||||
<section class="relative overflow-hidden border-b border-border">
|
<section class="relative overflow-hidden border-b border-border">
|
||||||
<TopographicBg opacity={0.22} lines={11} />
|
<TopographicBg opacity={0.22} lines={11} />
|
||||||
@@ -22,19 +35,20 @@ import Lightbox from '../Lightbox.astro';
|
|||||||
<span aria-hidden="true" class="text-base">✦</span>
|
<span aria-hidden="true" class="text-base">✦</span>
|
||||||
Your camels called. They want a GPS.
|
Your camels called. They want a GPS.
|
||||||
</p>
|
</p>
|
||||||
<h1
|
<h1 class="font-bold text-text mb-6 hero-h1">
|
||||||
class="font-bold text-text mb-6 hero-rotator"
|
Ship Camel integrations. Sleep through the night.
|
||||||
aria-live="off"
|
|
||||||
data-hero-rotator
|
|
||||||
>
|
|
||||||
<span class="hero-line" data-active aria-hidden="false">Run Apache Camel without running Apache Camel.</span>
|
|
||||||
<span class="hero-line" aria-hidden="true">Camel integrations, minus the baggage.</span>
|
|
||||||
<span class="hero-line" aria-hidden="true">Your camels, our caravan. You just ride.</span>
|
|
||||||
</h1>
|
</h1>
|
||||||
<p class="text-lg md:text-xl text-text-muted max-w-prose leading-relaxed mb-10">
|
<p class="text-lg md:text-xl text-text-muted max-w-prose leading-relaxed mb-8">
|
||||||
The hosted home for your Camel integrations — with deep tracing, replay, and live control built in. Because you chose Camel to stay free, not to stay up all night.
|
Cameleer is the hosted runtime and observability platform for Apache Camel — auto-traced, replay-ready, cross-service correlated. The 3 AM page becomes a 30-second answer.
|
||||||
|
</p>
|
||||||
|
<CTAButtons
|
||||||
|
size="lg"
|
||||||
|
secondaryLabel="See it in action ↓"
|
||||||
|
secondaryHref="#walkthrough"
|
||||||
|
/>
|
||||||
|
<p class="mt-4 font-mono text-xs text-text-faint">
|
||||||
|
14-day trial · from €20/mo · no credit card
|
||||||
</p>
|
</p>
|
||||||
<CTAButtons size="lg" />
|
|
||||||
</div>
|
</div>
|
||||||
<div class="lg:col-span-7 relative">
|
<div class="lg:col-span-7 relative">
|
||||||
<div class="hero-shot relative rounded-lg border border-border-strong bg-bg-elevated overflow-hidden">
|
<div class="hero-shot relative rounded-lg border border-border-strong bg-bg-elevated overflow-hidden">
|
||||||
@@ -46,7 +60,24 @@ import Lightbox from '../Lightbox.astro';
|
|||||||
loading="eager"
|
loading="eager"
|
||||||
/>
|
/>
|
||||||
<div class="absolute inset-0 ring-1 ring-inset ring-accent/10 pointer-events-none rounded-lg"></div>
|
<div class="absolute inset-0 ring-1 ring-inset ring-accent/10 pointer-events-none rounded-lg"></div>
|
||||||
|
{pins.map((pin) => (
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="hero-pin absolute inline-flex items-center justify-center w-7 h-7 rounded-full bg-accent text-bg font-mono text-xs font-bold pointer-events-none"
|
||||||
|
style={`top:${pin.top};left:${pin.left}`}
|
||||||
|
>
|
||||||
|
{pin.label}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
<ul class="hero-pin-legend mt-5 grid sm:grid-cols-3 gap-3 text-text-muted">
|
||||||
|
{pins.map((pin) => (
|
||||||
|
<li class="flex items-start gap-2 text-sm leading-snug">
|
||||||
|
<span class="font-mono text-accent text-xs mt-0.5">{pin.label}</span>
|
||||||
|
<span>{pin.body}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
<div aria-hidden="true" class="hero-shot-glow"></div>
|
<div aria-hidden="true" class="hero-shot-glow"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -54,36 +85,21 @@ import Lightbox from '../Lightbox.astro';
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* Rotating H1 — fluid size + fade transition */
|
.hero-h1 {
|
||||||
.hero-rotator {
|
|
||||||
font-size: clamp(2.25rem, 4.5vw, 4rem);
|
font-size: clamp(2.25rem, 4.5vw, 4rem);
|
||||||
line-height: 1.05;
|
line-height: 1.05;
|
||||||
letter-spacing: -0.02em;
|
letter-spacing: -0.02em;
|
||||||
position: relative;
|
|
||||||
display: block;
|
|
||||||
/* Reserve enough vertical space that a 2-line wrap of the longest line
|
|
||||||
does not push the page on swap (mobile wraps line 1 to 2 lines). */
|
|
||||||
min-height: 2.5em;
|
|
||||||
}
|
}
|
||||||
.hero-line {
|
|
||||||
display: block;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 700ms ease-in-out;
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
}
|
|
||||||
.hero-line[data-active] {
|
|
||||||
opacity: 1;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Product screenshot frame — subtle dropshadow + amber glow behind */
|
|
||||||
.hero-shot {
|
.hero-shot {
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 1px 0 rgba(240, 180, 41, 0.08) inset,
|
0 1px 0 rgba(240, 180, 41, 0.08) inset,
|
||||||
0 30px 60px -20px rgba(0, 0, 0, 0.6),
|
0 30px 60px -20px rgba(0, 0, 0, 0.6),
|
||||||
0 10px 25px -10px rgba(0, 0, 0, 0.5);
|
0 10px 25px -10px rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
|
.hero-pin {
|
||||||
|
box-shadow: 0 0 0 4px rgba(240, 180, 41, 0.22), 0 4px 10px -2px rgba(0, 0, 0, 0.5);
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
.hero-shot-glow {
|
.hero-shot-glow {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 10% -5% 10% -5%;
|
inset: 10% -5% 10% -5%;
|
||||||
@@ -96,7 +112,6 @@ import Lightbox from '../Lightbox.astro';
|
|||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Slow sway on the mark — tasteful, not distracting */
|
|
||||||
@keyframes hero-mark-sway {
|
@keyframes hero-mark-sway {
|
||||||
0%, 100% { transform: translateY(0) rotate(0deg); }
|
0%, 100% { transform: translateY(0) rotate(0deg); }
|
||||||
50% { transform: translateY(-2px) rotate(-1.5deg); }
|
50% { transform: translateY(-2px) rotate(-1.5deg); }
|
||||||
@@ -107,34 +122,6 @@ import Lightbox from '../Lightbox.astro';
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.hero-line { transition: none; }
|
|
||||||
.hero-mark { animation: none; }
|
.hero-mark { animation: none; }
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
|
||||||
// Hero rotating headline. Bundled by Astro (CSP: script-src 'self').
|
|
||||||
const rotator = document.querySelector<HTMLElement>('[data-hero-rotator]');
|
|
||||||
if (rotator) {
|
|
||||||
const lines = Array.from(rotator.querySelectorAll<HTMLElement>('.hero-line'));
|
|
||||||
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
||||||
if (!reduced && lines.length > 1) {
|
|
||||||
let index = 0;
|
|
||||||
let paused = false;
|
|
||||||
const pause = () => { paused = true; };
|
|
||||||
const resume = () => { paused = false; };
|
|
||||||
rotator.addEventListener('mouseenter', pause);
|
|
||||||
rotator.addEventListener('mouseleave', resume);
|
|
||||||
rotator.addEventListener('focusin', pause);
|
|
||||||
rotator.addEventListener('focusout', resume);
|
|
||||||
setInterval(() => {
|
|
||||||
if (paused) return;
|
|
||||||
lines[index].removeAttribute('data-active');
|
|
||||||
lines[index].setAttribute('aria-hidden', 'true');
|
|
||||||
index = (index + 1) % lines.length;
|
|
||||||
lines[index].setAttribute('data-active', '');
|
|
||||||
lines[index].setAttribute('aria-hidden', 'false');
|
|
||||||
}, 10000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user