ELF-457: add slot 3 rotating tagline above hero sub on hatch.surf
Some checks failed
CI / go (push) Has been cancelled
CI / docker (push) Has been cancelled
CI / lint-go (push) Has been cancelled
CI / lint-docs (push) Has been cancelled
CI / check-paperclip (push) Has been cancelled
Deploy static site / Deploy to GitHub Pages (push) Has been cancelled
Deploy static site / Deploy via Docker to hatch.surf (push) Has been cancelled
Some checks failed
CI / go (push) Has been cancelled
CI / docker (push) Has been cancelled
CI / lint-go (push) Has been cancelled
CI / lint-docs (push) Has been cancelled
CI / check-paperclip (push) Has been cancelled
Deploy static site / Deploy to GitHub Pages (push) Has been cancelled
Deploy static site / Deploy via Docker to hatch.surf (push) Has been cancelled
Three taglines rotate every 3.5s with a subtle 700ms opacity crossfade between the H1 and the hero sub on the hatch.surf landing page: 1. Inspect any request. Mock any response. (default, in initial HTML) 2. Your HTTP bin, on your machine. 3. Send. Capture. Mock. No signup. Implementation: - site/index.html: <div class='hero-tagline' aria-live=polite> with three <p class='hero-tagline-item'> children stacked; default #1 has is-active class and no aria-hidden (for SEO + no-JS users) - site/style.css: .hero-tagline uses position:relative with fixed height: 1.7em (no CLS during rotation); absolute children crossfade via transition: opacity 700ms var(--ease-out); font: JetBrains Mono weight 500 in var(--text-secondary); clamp(0.85rem, 2.2vw, 1rem) so mobile (375px+) fits the longest tagline on one line - site/main.js: initRotatingTagline() in the existing IIFE; setInterval every 3500ms swaps is-active and aria-hidden between siblings; early-returns if prefers-reduced-motion is set, so the default tagline stays visible without animation - Spacing: H1 mb-sp-6, tagline mb-sp-6, sub mb-sp-8 keeps the existing 24px/24px/32px rhythm unchanged below the headline Note: site/index.html (not the Next.js app under app/ + components/) is what hatch.surf/nginx actually serves. The Next.js work from the earlier failed run was reverted.
This commit is contained in:
parent
bcb4f1688e
commit
478e2818b9
@ -67,6 +67,13 @@
|
||||
<h1 data-animate="fade-up" data-delay="80">
|
||||
Self-hostable HTTP request<br>inspector + mocker
|
||||
</h1>
|
||||
<!-- Slot 3 rotating tagline (ELF-457, brief ELF-456). Default #1 is in the
|
||||
initial HTML for no-JS / SEO. JS in main.js cycles opacity every 3.5s. -->
|
||||
<div class="hero-tagline" aria-live="polite" aria-atomic="true">
|
||||
<p class="hero-tagline-item is-active">Inspect any request. Mock any response.</p>
|
||||
<p class="hero-tagline-item" aria-hidden="true">Your HTTP bin, on your machine.</p>
|
||||
<p class="hero-tagline-item" aria-hidden="true">Send. Capture. Mock. No signup.</p>
|
||||
</div>
|
||||
<p class="hero-sub" data-animate="fade-up" data-delay="160">
|
||||
One Go binary. SQLite under the hood.<br>
|
||||
<code>docker compose up</code>, and you have an inspection endpoint and a live feed in under 30 seconds.
|
||||
|
||||
26
site/main.js
26
site/main.js
@ -420,6 +420,32 @@
|
||||
|
||||
initEntranceAnimations(animate, stagger);
|
||||
initTerminalGlow(animate);
|
||||
initRotatingTagline();
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Slot 3 rotating tagline (ELF-457)
|
||||
// Cycles 3 tagline <p>s every 3.5s with a 700ms opacity crossfade
|
||||
// (handled in CSS via .hero-tagline-item transition). Honors
|
||||
// prefers-reduced-motion: skips the timer entirely so the default
|
||||
// #1 stays visible without any animation.
|
||||
// ============================================================
|
||||
|
||||
function initRotatingTagline() {
|
||||
var container = document.querySelector('.hero-tagline');
|
||||
if (!container) return;
|
||||
var items = container.querySelectorAll('.hero-tagline-item');
|
||||
if (items.length < 2) return;
|
||||
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||||
|
||||
var idx = 0;
|
||||
window.setInterval(function () {
|
||||
items[idx].classList.remove('is-active');
|
||||
items[idx].setAttribute('aria-hidden', 'true');
|
||||
idx = (idx + 1) % items.length;
|
||||
items[idx].classList.add('is-active');
|
||||
items[idx].removeAttribute('aria-hidden');
|
||||
}, 3500);
|
||||
}
|
||||
|
||||
// Defer boot by one frame so anime.js engine is ready
|
||||
|
||||
@ -363,6 +363,43 @@ nav {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* Slot 3: rotating tagline (ELF-457). Sits between H1 and hero-sub.
|
||||
Fixed height prevents CLS during rotation; absolute children crossfade. */
|
||||
.hero-tagline {
|
||||
position: relative;
|
||||
max-width: 560px;
|
||||
height: 1.7em;
|
||||
margin: 0 auto var(--sp-6);
|
||||
overflow: hidden;
|
||||
font-family: var(--font-mono);
|
||||
font-size: clamp(0.85rem, 2.2vw, 1rem);
|
||||
font-weight: 500;
|
||||
line-height: 1.7;
|
||||
color: var(--text-secondary);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero-tagline-item {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
margin: 0;
|
||||
opacity: 0;
|
||||
transition: opacity 700ms var(--ease-out);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.hero-tagline-item.is-active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.hero-tagline-item {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
.hero-sub {
|
||||
font-size: clamp(1rem, 2vw, 1.2rem);
|
||||
color: var(--text-secondary);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user