patx/afterdarklabs
simplify the hero
Commit c017d19 · patx · 2026-07-08T16:55:32-04:00
Comments
No comments yet.
Diff
diff --git a/docs/index.html b/docs/index.html
index 5f3b720..176268a 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -26,7 +26,7 @@
<meta name="twitter:image:alt" content="After Dark Labs Florida website design and development">
<link rel="stylesheet" href="index.tailwind.css?v=2">
<style>
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Space+Grotesk:wght@500;600;700&family=Syne:wght@500;600;700;800&display=swap');
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Space+Grotesk:wght@500;600;700&family=Syne:wght@500;600;700;800&family=Yellowtail&display=swap');
:root {
--neon: #ccff00;
@@ -54,22 +54,70 @@
}
.neon-text {
+ position: relative;
+ isolation: isolate;
+ display: inline-flex;
+ align-items: baseline;
+ font-family: 'Yellowtail', cursive;
+ font-size: clamp(0.94em, 18vw, 1.22em);
+ font-weight: 400;
+ letter-spacing: 0.01em;
+ line-height: 0.9;
color: var(--neon);
- text-shadow: 0 0 10px var(--neon), 0 0 25px var(--neon), 0 0 50px var(--neon);
+ transform: rotate(-1deg);
+ transform-origin: left center;
+ vertical-align: -0.03em;
+ white-space: nowrap;
+ }
+
+ .neon-letter,
+ .neon-gap {
+ position: relative;
+ display: inline-block;
+ }
+
+ .neon-letter {
+ color: #ccff00;
+ -webkit-text-fill-color: currentColor;
+ -webkit-text-stroke: 0.012em rgba(250,255,205,0.88);
+ filter:
+ drop-shadow(0 0 0.014em rgba(255,255,235,0.72))
+ drop-shadow(0 0 0.045em rgba(204,255,0,0.72))
+ drop-shadow(0 0 0.105em rgba(204,255,0,0.26));
+ text-shadow:
+ 0 0 0.035em rgba(255,255,235,0.55),
+ 0 0 0.095em rgba(204,255,0,0.42);
+ animation: neon-letter-idle 5.2s ease-in-out infinite;
+ animation-delay: var(--idle-delay, 0s);
}
- #hero-canvas {
+ .neon-letter::after {
+ content: attr(data-letter);
position: absolute;
inset: 0;
- width: 100%;
- height: 100%;
- display: block;
- z-index: 0;
+ color: transparent;
+ -webkit-text-fill-color: transparent;
+ -webkit-text-stroke: 0.018em rgba(4,8,10,0.46);
+ transform: translate(0.01em, 0.012em);
+ opacity: 0.45;
+ z-index: -1;
+ }
+
+ .neon-letter--flicker {
+ animation-name: neon-letter-idle, neon-letter-flicker;
+ animation-duration: 5.2s, var(--flicker-duration, 9s);
+ animation-timing-function: ease-in-out, linear;
+ animation-iteration-count: infinite, infinite;
+ animation-delay: var(--idle-delay, 0s), var(--flicker-delay, 0s);
+ }
+
+ .neon-gap {
+ width: 0.22em;
}
.hero-content {
position: relative;
- z-index: 1;
+ z-index: 2;
}
.hero-vignette {
@@ -82,6 +130,48 @@
z-index: 1;
}
+ @keyframes neon-letter-idle {
+ 0%, 100% {
+ filter:
+ drop-shadow(0 0 0.014em rgba(255,255,235,0.72))
+ drop-shadow(0 0 0.045em rgba(204,255,0,0.72))
+ drop-shadow(0 0 0.105em rgba(204,255,0,0.26));
+ }
+ 50% {
+ filter:
+ drop-shadow(0 0 0.018em rgba(255,255,235,0.84))
+ drop-shadow(0 0 0.055em rgba(204,255,0,0.80))
+ drop-shadow(0 0 0.13em rgba(204,255,0,0.32));
+ }
+ }
+
+ @keyframes neon-letter-flicker {
+ 0%, 4%, 6%, 9%, 37%, 39%, 41%, 100% {
+ opacity: 1;
+ -webkit-text-stroke-color: rgba(250,255,205,0.88);
+ }
+ 4.7%, 38% {
+ opacity: 0.22;
+ -webkit-text-stroke-color: rgba(204,255,0,0.28);
+ filter:
+ drop-shadow(0 0 0.006em rgba(204,255,0,0.30))
+ drop-shadow(0 0 0.025em rgba(204,255,0,0.18));
+ }
+ 5.4%, 40% {
+ opacity: 0.64;
+ }
+ 70%, 71.5% {
+ opacity: 0.48;
+ }
+ }
+
+ @media (prefers-reduced-motion: reduce) {
+ .neon-letter,
+ .neon-letter--flicker {
+ animation: none;
+ }
+ }
+
.service-chip:has(input:checked) {
border-color: rgba(204,255,0,0.8);
background: rgba(204,255,0,0.12);
@@ -199,13 +289,12 @@
<main>
<section id="hero" class="hero-bg min-h-screen flex items-center pt-20" style="position:relative; overflow:hidden;">
- <canvas id="hero-canvas"></canvas>
<div class="hero-vignette"></div>
<div class="hero-content mx-auto grid w-full max-w-7xl gap-10 px-6 py-32 text-left lg:grid-cols-[1.3fr_0.7fr] lg:items-end">
<div>
<h1 class="heading text-7xl font-bold leading-none tracking-tighter md:text-8xl lg:text-7xl xl:text-8xl">
- Websites and tools that help businesses<br><span class="neon-text">stand out</span>.
+ Websites and tools that help businesses<br><span class="neon-text" aria-hidden="true"><span class="neon-letter neon-letter--flicker" data-letter="s" style="--idle-delay:-0.4s; --flicker-delay:-1.1s; --flicker-duration:11s;">s</span><span class="neon-letter" data-letter="t" style="--idle-delay:-1.6s;">t</span><span class="neon-letter neon-letter--flicker" data-letter="a" style="--idle-delay:-2.2s; --flicker-delay:-5.6s; --flicker-duration:13s;">a</span><span class="neon-letter" data-letter="n" style="--idle-delay:-0.8s;">n</span><span class="neon-letter neon-letter--flicker" data-letter="d" style="--idle-delay:-3.1s; --flicker-delay:-8.4s; --flicker-duration:15s;">d</span><span class="neon-gap"></span><span class="neon-letter" data-letter="o" style="--idle-delay:-1.2s;">o</span><span class="neon-letter neon-letter--flicker" data-letter="u" style="--idle-delay:-2.7s; --flicker-delay:-3.3s; --flicker-duration:12s;">u</span><span class="neon-letter" data-letter="t" style="--idle-delay:-3.6s;">t</span></span><span class="sr-only">stand out</span>
</h1>
</div>
<div class="mx-auto flex max-w-xl flex-col items-start gap-8 lg:mx-0">
@@ -667,166 +756,6 @@
setStep(0, false);
})();
- /* ─── HERO CANVAS ANIMATION ──────────────────────────────── */
- (function () {
- const canvas = document.getElementById('hero-canvas');
- const section = canvas.closest('section');
- const ctx = canvas.getContext('2d');
-
- const NODE_COUNT = 80;
- const LINK_DIST = 140;
- const PULSE_SPEED = 0.012;
-
- let W, H, nodes = [], mouse = { x: -9999, y: -9999 };
-
- function resize() {
- const rect = section.getBoundingClientRect();
- W = canvas.width = rect.width * devicePixelRatio;
- H = canvas.height = rect.height * devicePixelRatio;
- canvas.style.width = rect.width + 'px';
- canvas.style.height = rect.height + 'px';
- }
-
- function makeNode() {
- return {
- x: Math.random() * W,
- y: Math.random() * H,
- vx: (Math.random() - 0.5) * 0.45,
- vy: (Math.random() - 0.5) * 0.45,
- r: 1.5 + Math.random() * 2,
- phase: Math.random() * Math.PI * 2,
- };
- }
-
- function init() {
- resize();
- nodes = Array.from({ length: NODE_COUNT }, makeNode);
- }
-
- const ORBS = [
- { cx: 0.20, cy: 0.35, r: 0.22, spd: 0.0007, off: 0 },
- { cx: 0.75, cy: 0.60, r: 0.18, spd: 0.0011, off: 2.1 },
- { cx: 0.50, cy: 0.25, r: 0.14, spd: 0.0009, off: 4.5 },
- { cx: 0.85, cy: 0.20, r: 0.12, spd: 0.0013, off: 1.3 },
- ];
-
- function drawOrbs(t) {
- ORBS.forEach(o => {
- const cx = (o.cx + Math.sin(t * o.spd + o.off) * 0.06) * W;
- const cy = (o.cy + Math.cos(t * o.spd * 1.3 + o.off) * 0.06) * H;
- const r = o.r * Math.min(W, H);
- const g = ctx.createRadialGradient(cx, cy, 0, cx, cy, r);
- g.addColorStop(0, 'rgba(204,255,0,0.10)');
- g.addColorStop(0.5, 'rgba(204,255,0,0.04)');
- g.addColorStop(1, 'rgba(204,255,0,0)');
- ctx.beginPath();
- ctx.arc(cx, cy, r, 0, Math.PI * 2);
- ctx.fillStyle = g;
- ctx.fill();
- });
- }
-
- let rings = [];
- section.addEventListener('mousemove', e => {
- const rect = section.getBoundingClientRect();
- mouse.x = (e.clientX - rect.left) * devicePixelRatio;
- mouse.y = (e.clientY - rect.top) * devicePixelRatio;
- if (Math.random() < 0.08) {
- rings.push({ x: mouse.x, y: mouse.y, r: 0, alpha: 0.5 });
- }
- });
- section.addEventListener('mouseleave', () => { mouse.x = mouse.y = -9999; });
-
- function drawRings() {
- rings = rings.filter(rg => rg.alpha > 0.01);
- rings.forEach(rg => {
- rg.r += 1.8;
- rg.alpha *= 0.93;
- ctx.beginPath();
- ctx.arc(rg.x, rg.y, rg.r, 0, Math.PI * 2);
- ctx.strokeStyle = `rgba(204,255,0,${rg.alpha})`;
- ctx.lineWidth = 1;
- ctx.stroke();
- });
- }
-
- let t = 0;
- function frame() {
- t++;
- ctx.clearRect(0, 0, W, H);
- ctx.fillStyle = getComputedStyle(document.documentElement).getPropertyValue('--page-bg').trim() || '#17212b';
- ctx.fillRect(0, 0, W, H);
-
- drawOrbs(t);
-
- nodes.forEach(n => {
- n.phase += PULSE_SPEED;
- n.x += n.vx;
- n.y += n.vy;
- if (n.x < 0 || n.x > W) n.vx *= -1;
- if (n.y < 0 || n.y > H) n.vy *= -1;
-
- const dx = n.x - mouse.x, dy = n.y - mouse.y;
- const d2 = dx * dx + dy * dy;
- if (d2 < 90000) {
- const f = (1 - d2 / 90000) * 0.4;
- n.vx += (dx / Math.sqrt(d2)) * f;
- n.vy += (dy / Math.sqrt(d2)) * f;
- }
-
- const spd = Math.sqrt(n.vx * n.vx + n.vy * n.vy);
- if (spd > 1.2) { n.vx /= spd / 1.2; n.vy /= spd / 1.2; }
- });
-
- ctx.lineWidth = 0.8;
- for (let i = 0; i < nodes.length; i++) {
- for (let j = i + 1; j < nodes.length; j++) {
- const a = nodes[i], b = nodes[j];
- const dx = a.x - b.x, dy = a.y - b.y;
- const d = Math.sqrt(dx * dx + dy * dy);
- if (d < LINK_DIST * devicePixelRatio) {
- const alpha = (1 - d / (LINK_DIST * devicePixelRatio)) * 0.35;
- ctx.strokeStyle = `rgba(204,255,0,${alpha})`;
- ctx.beginPath();
- ctx.moveTo(a.x, a.y);
- ctx.lineTo(b.x, b.y);
- ctx.stroke();
- }
- }
- }
-
- nodes.forEach(n => {
- const pulse = 0.5 + 0.5 * Math.sin(n.phase);
- const alpha = 0.55 + 0.45 * pulse;
- const glow = ctx.createRadialGradient(n.x, n.y, 0, n.x, n.y, n.r * 4);
- glow.addColorStop(0, `rgba(204,255,0,${alpha})`);
- glow.addColorStop(0.4, `rgba(204,255,0,${alpha * 0.3})`);
- glow.addColorStop(1, 'rgba(204,255,0,0)');
- ctx.beginPath();
- ctx.arc(n.x, n.y, n.r * 4 * devicePixelRatio, 0, Math.PI * 2);
- ctx.fillStyle = glow;
- ctx.fill();
-
- ctx.beginPath();
- ctx.arc(n.x, n.y, n.r * devicePixelRatio, 0, Math.PI * 2);
- ctx.fillStyle = `rgba(204,255,0,${alpha})`;
- ctx.fill();
- });
-
- drawRings();
-
- for (let y = 0; y < H; y += 4) {
- ctx.fillStyle = 'rgba(255,255,255,0.018)';
- ctx.fillRect(0, y, W, 1);
- }
-
- requestAnimationFrame(frame);
- }
-
- window.addEventListener('resize', () => { resize(); });
- init();
- frame();
- })();
</script>
</body>
</html>