I want to make a hero section for my website. Is there any protocol or technique to achieve the best?
best practices hero section website design 2025 techniques
hero section CSS HTML design patterns conversion optimization
| Element | Purpose | Tips |
|---|---|---|
| Headline | State your core value in one sentence | Short, bold, specific - not clever, be clear |
| Subheading | Expand on the headline | 1-2 sentences max, answer "why should I care?" |
| CTA Button | Drive the primary action | One CTA only, high contrast, action verb ("Get Started", "Try Free") |
| Hero Visual | Reinforce the message visually | Image, illustration, or video - must support the message, not distract |
| Navigation | Context and trust | Keep it minimal so the hero gets full attention |
<link rel="preload"> for the hero image) to hit a fast LCP scoresrcset for responsive images so mobile gets a smaller file<!-- Hero image preloading example -->
<link rel="preload" as="image" href="hero.webp" fetchpriority="high">
<!-- Responsive hero image -->
<img
src="hero-800.webp"
srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1600.webp 1600w"
sizes="100vw"
alt="Descriptive alt text"
width="1600" height="900"
fetchpriority="high"
>
So, I want to... design the hero visual of my hero section and my... Product is an application used by... Medical students, doctors, and it is basically an evidence synthesis tool where they can, they could search about... different topics and get answers from strong evidence. Like research paper guidelines. And much more.
mkdir -p /home/daytona/workspace/hero-section && echo "dir ready"
~/hero-section/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>EvidenceAI — Hero Section</title>
<style>
/* ── Reset & Base ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #050d1a;
--surface: #0a1628;
--border: rgba(56, 189, 248, 0.18);
--accent: #38bdf8; /* sky-400 */
--accent2: #818cf8; /* indigo-400 */
--accent3: #34d399; /* emerald-400 */
--text: #e2e8f0;
--muted: #64748b;
--glow: rgba(56, 189, 248, 0.35);
}
body {
background: var(--bg);
color: var(--text);
font-family: 'Inter', 'Segoe UI', system-ui, sans-serif;
min-height: 100vh;
overflow-x: hidden;
}
/* ── NAV ── */
nav {
position: fixed;
top: 0; left: 0; right: 0;
z-index: 100;
padding: 18px 48px;
display: flex;
align-items: center;
justify-content: space-between;
background: rgba(5, 13, 26, 0.75);
backdrop-filter: blur(14px);
border-bottom: 1px solid var(--border);
}
.logo {
font-size: 1.25rem;
font-weight: 700;
letter-spacing: -0.02em;
color: var(--accent);
display: flex;
align-items: center;
gap: 8px;
}
.logo svg { width: 22px; height: 22px; }
.nav-links {
display: flex;
gap: 32px;
list-style: none;
font-size: 0.875rem;
color: var(--muted);
}
.nav-links a { color: inherit; text-decoration: none; transition: color .2s; }
.nav-links a:hover { color: var(--text); }
.nav-cta {
font-size: 0.875rem;
font-weight: 600;
padding: 9px 20px;
border-radius: 8px;
background: var(--accent);
color: #050d1a;
border: none;
cursor: pointer;
transition: opacity .2s, transform .15s;
}
.nav-cta:hover { opacity: .88; transform: translateY(-1px); }
/* ── HERO WRAPPER ── */
.hero {
min-height: 100vh;
padding-top: 80px;
display: grid;
grid-template-columns: 1fr 1fr;
align-items: center;
gap: 0;
position: relative;
overflow: hidden;
}
/* Ambient background glow blobs */
.hero::before {
content: '';
position: absolute;
top: -120px; left: -180px;
width: 600px; height: 600px;
border-radius: 50%;
background: radial-gradient(circle, rgba(56,189,248,.12) 0%, transparent 70%);
pointer-events: none;
}
.hero::after {
content: '';
position: absolute;
bottom: -150px; right: -100px;
width: 700px; height: 700px;
border-radius: 50%;
background: radial-gradient(circle, rgba(129,140,248,.1) 0%, transparent 70%);
pointer-events: none;
}
/* ── LEFT COLUMN: Copy ── */
.hero-copy {
padding: 0 48px 0 80px;
z-index: 2;
position: relative;
}
.badge {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 0.75rem;
font-weight: 600;
letter-spacing: .06em;
text-transform: uppercase;
color: var(--accent);
background: rgba(56,189,248,.1);
border: 1px solid rgba(56,189,248,.25);
border-radius: 100px;
padding: 5px 14px;
margin-bottom: 24px;
}
.badge::before {
content: '';
width: 6px; height: 6px;
background: var(--accent);
border-radius: 50%;
animation: pulse-dot 2s infinite;
}
@keyframes pulse-dot {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: .4; transform: scale(.7); }
}
.hero-headline {
font-size: clamp(2.2rem, 4vw, 3.4rem);
font-weight: 800;
line-height: 1.12;
letter-spacing: -0.03em;
margin-bottom: 20px;
}
.headline-gradient {
background: linear-gradient(135deg, var(--accent) 0%, var(--accent2) 60%, var(--accent3) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-sub {
font-size: 1.05rem;
color: #94a3b8;
line-height: 1.7;
max-width: 460px;
margin-bottom: 36px;
}
.hero-actions {
display: flex;
align-items: center;
gap: 16px;
flex-wrap: wrap;
}
.btn-primary {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 14px 28px;
border-radius: 10px;
background: linear-gradient(135deg, var(--accent), var(--accent2));
color: #fff;
font-weight: 700;
font-size: .95rem;
border: none;
cursor: pointer;
transition: transform .2s, box-shadow .2s;
box-shadow: 0 0 24px rgba(56,189,248,.35);
text-decoration: none;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 0 40px rgba(56,189,248,.55);
}
.btn-secondary {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 13px 24px;
border-radius: 10px;
background: transparent;
color: var(--text);
font-weight: 600;
font-size: .95rem;
border: 1px solid var(--border);
cursor: pointer;
transition: border-color .2s, background .2s;
text-decoration: none;
}
.btn-secondary:hover {
border-color: var(--accent);
background: rgba(56,189,248,.06);
}
.social-proof {
margin-top: 40px;
display: flex;
align-items: center;
gap: 16px;
}
.avatars {
display: flex;
}
.avatars span {
width: 32px; height: 32px;
border-radius: 50%;
border: 2px solid var(--bg);
background: linear-gradient(135deg, #475569, #64748b);
margin-left: -8px;
display: flex;
align-items: center;
justify-content: center;
font-size: .65rem;
font-weight: 700;
color: #cbd5e1;
}
.avatars span:first-child { margin-left: 0; }
.social-proof-text {
font-size: .8rem;
color: var(--muted);
}
.social-proof-text strong { color: var(--text); }
/* ── RIGHT COLUMN: Visual ── */
.hero-visual {
position: relative;
height: 580px;
z-index: 2;
padding-right: 60px;
}
/* ── CANVAS: Node graph background ── */
#node-canvas {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
/* ── CENTRAL QUERY CARD ── */
.query-card {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 320px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 16px;
padding: 20px 20px 16px;
box-shadow: 0 0 60px rgba(56,189,248,.15), 0 24px 60px rgba(0,0,0,.6);
animation: float-card 6s ease-in-out infinite;
z-index: 10;
}
@keyframes float-card {
0%, 100% { transform: translate(-50%, -50%) translateY(0px); }
50% { transform: translate(-50%, -50%) translateY(-12px); }
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 14px;
}
.card-title {
font-size: .7rem;
font-weight: 600;
letter-spacing: .08em;
text-transform: uppercase;
color: var(--accent);
}
.card-status {
display: flex;
align-items: center;
gap: 5px;
font-size: .65rem;
color: var(--accent3);
font-weight: 600;
}
.status-dot {
width: 6px; height: 6px;
background: var(--accent3);
border-radius: 50%;
animation: pulse-dot 1.6s infinite;
}
.search-bar {
background: rgba(255,255,255,.04);
border: 1px solid var(--border);
border-radius: 8px;
padding: 10px 14px;
font-size: .8rem;
color: var(--text);
margin-bottom: 14px;
display: flex;
align-items: center;
gap: 8px;
}
.search-bar svg { opacity: .5; flex-shrink: 0; }
.search-query { color: var(--accent); font-weight: 500; }
.evidence-items { display: flex; flex-direction: column; gap: 7px; }
.ev-item {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 9px 12px;
border-radius: 8px;
background: rgba(255,255,255,.03);
border: 1px solid rgba(255,255,255,.06);
transition: border-color .3s;
}
.ev-item:hover { border-color: rgba(56,189,248,.3); }
.ev-badge {
font-size: .58rem;
font-weight: 700;
letter-spacing: .04em;
padding: 2px 7px;
border-radius: 4px;
flex-shrink: 0;
margin-top: 1px;
}
.ev-badge.sr { background: rgba(56,189,248,.15); color: var(--accent); }
.ev-badge.rct { background: rgba(129,140,248,.15); color: var(--accent2); }
.ev-badge.gl { background: rgba(52,211,153,.15); color: var(--accent3); }
.ev-text { font-size: .72rem; color: #94a3b8; line-height: 1.4; }
.ev-text strong { color: var(--text); font-weight: 600; }
.confidence-bar {
margin-top: 14px;
padding-top: 12px;
border-top: 1px solid rgba(255,255,255,.06);
}
.conf-label {
display: flex;
justify-content: space-between;
font-size: .65rem;
color: var(--muted);
margin-bottom: 6px;
}
.conf-label span:last-child { color: var(--accent3); font-weight: 700; }
.conf-track {
height: 4px;
background: rgba(255,255,255,.08);
border-radius: 2px;
overflow: hidden;
}
.conf-fill {
height: 100%;
border-radius: 2px;
background: linear-gradient(90deg, var(--accent2), var(--accent3));
width: 0%;
animation: fill-bar 2.5s 1s cubic-bezier(.4,0,.2,1) forwards;
}
@keyframes fill-bar {
to { width: 91%; }
}
/* ── FLOATING SATELLITE CARDS ── */
.sat-card {
position: absolute;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 12px 14px;
z-index: 8;
backdrop-filter: blur(8px);
}
/* Paper card - top right */
.sat-paper {
top: 48px;
right: 20px;
width: 170px;
animation: float-card 7s 1s ease-in-out infinite;
}
.sat-paper .sp-tag {
font-size: .6rem;
font-weight: 700;
letter-spacing: .06em;
text-transform: uppercase;
color: var(--accent2);
margin-bottom: 6px;
}
.sat-paper .sp-title {
font-size: .7rem;
color: var(--text);
line-height: 1.4;
font-weight: 600;
margin-bottom: 6px;
}
.sp-meta {
display: flex;
gap: 8px;
font-size: .6rem;
color: var(--muted);
}
.sp-cite {
display: flex;
align-items: center;
gap: 3px;
}
/* Stats card - bottom left */
.sat-stats {
bottom: 60px;
left: 10px;
width: 150px;
animation: float-card 5.5s 0.5s ease-in-out infinite;
}
.stat-row {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
}
.stat-row:last-child { margin-bottom: 0; }
.stat-label { font-size: .62rem; color: var(--muted); }
.stat-val {
font-size: .75rem;
font-weight: 700;
}
.stat-val.blue { color: var(--accent); }
.stat-val.purple { color: var(--accent2); }
.stat-val.green { color: var(--accent3); }
.stat-mini-bar {
height: 3px;
border-radius: 2px;
margin-top: 3px;
background: rgba(255,255,255,.06);
overflow: hidden;
}
.stat-mini-fill {
height: 100%;
border-radius: 2px;
animation: fill-mini 2s ease forwards;
}
@keyframes fill-mini { from { width: 0; } }
.fill-b { background: var(--accent); animation-delay: .8s; }
.fill-p { background: var(--accent2); animation-delay: 1.2s; }
.fill-g { background: var(--accent3); animation-delay: 1.6s; }
/* Guideline chip - top left */
.sat-chip {
top: 80px;
left: 20px;
padding: 8px 14px;
display: flex;
align-items: center;
gap: 8px;
animation: float-card 6.5s 2s ease-in-out infinite;
}
.chip-icon {
width: 28px; height: 28px;
border-radius: 8px;
background: rgba(52,211,153,.15);
display: flex;
align-items: center;
justify-content: center;
}
.chip-text .ct-label { font-size: .6rem; color: var(--muted); }
.chip-text .ct-val { font-size: .75rem; font-weight: 700; color: var(--accent3); }
/* ── SCAN LINE ANIMATION ── */
.scan-line {
position: absolute;
left: 0; right: 0;
height: 1px;
background: linear-gradient(90deg, transparent 0%, var(--accent) 50%, transparent 100%);
opacity: .4;
animation: scan 4s linear infinite;
pointer-events: none;
z-index: 15;
}
@keyframes scan {
0% { top: 0%; opacity: 0; }
5% { opacity: .4; }
95% { opacity: .4; }
100% { top: 100%; opacity: 0; }
}
/* ── GRID OVERLAY ── */
.hero-visual::before {
content: '';
position: absolute;
inset: 0;
background-image:
linear-gradient(rgba(56,189,248,.04) 1px, transparent 1px),
linear-gradient(90deg, rgba(56,189,248,.04) 1px, transparent 1px);
background-size: 40px 40px;
pointer-events: none;
mask-image: radial-gradient(ellipse 80% 80% at 50% 50%, black 40%, transparent 100%);
z-index: 1;
}
/* ── GLOW RING around central card ── */
.glow-ring {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: 360px; height: 360px;
border-radius: 50%;
border: 1px solid rgba(56,189,248,.12);
animation: ring-pulse 3s ease-in-out infinite;
pointer-events: none;
z-index: 3;
}
.glow-ring-2 {
width: 480px; height: 480px;
animation-delay: 1s;
border-color: rgba(129,140,248,.08);
}
@keyframes ring-pulse {
0%, 100% { transform: translate(-50%,-50%) scale(1); opacity: 1; }
50% { transform: translate(-50%,-50%) scale(1.04); opacity: .5; }
}
/* ── RESPONSIVE ── */
@media (max-width: 900px) {
.hero {
grid-template-columns: 1fr;
padding-top: 100px;
}
.hero-copy { padding: 40px 24px 0; }
.hero-visual {
height: 420px;
padding: 0 20px;
margin: 20px auto;
width: 100%;
max-width: 460px;
}
nav { padding: 16px 24px; }
.nav-links { display: none; }
}
</style>
</head>
<body>
<!-- NAV -->
<nav>
<div class="logo">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="3"/>
<path d="M12 2v3M12 19v3M4.22 4.22l2.12 2.12M17.66 17.66l2.12 2.12M2 12h3M19 12h3M4.22 19.78l2.12-2.12M17.66 6.34l2.12-2.12"/>
</svg>
EvidenceAI
</div>
<ul class="nav-links">
<li><a href="#">Features</a></li>
<li><a href="#">Evidence Base</a></li>
<li><a href="#">Pricing</a></li>
<li><a href="#">For Teams</a></li>
</ul>
<button class="nav-cta">Get Early Access</button>
</nav>
<!-- HERO -->
<section class="hero">
<!-- LEFT: Copy -->
<div class="hero-copy">
<div class="badge">AI-Powered Evidence Synthesis</div>
<h1 class="hero-headline">
Medical decisions<br>
backed by<br>
<span class="headline-gradient">the strongest evidence</span>
</h1>
<p class="hero-sub">
Search any clinical question and get synthesized answers from systematic reviews, RCTs, and international guidelines - in seconds, not hours.
</p>
<div class="hero-actions">
<a href="#" class="btn-primary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
Search Evidence
</a>
<a href="#" class="btn-secondary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 3"/></svg>
Watch Demo
</a>
</div>
<div class="social-proof">
<div class="avatars">
<span>JR</span><span>AL</span><span>MB</span><span>SK</span><span>+</span>
</div>
<div class="social-proof-text">
Trusted by <strong>12,000+ clinicians</strong> & medical students
</div>
</div>
</div>
<!-- RIGHT: Visual -->
<div class="hero-visual">
<!-- Animated node graph -->
<canvas id="node-canvas"></canvas>
<!-- Grid overlay is ::before pseudo -->
<!-- Glow rings -->
<div class="glow-ring"></div>
<div class="glow-ring glow-ring-2"></div>
<!-- Scan line -->
<div class="scan-line"></div>
<!-- Floating satellite: guideline chip top-left -->
<div class="sat-card sat-chip">
<div class="chip-icon">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
</div>
<div class="chip-text">
<div class="ct-label">Guideline match</div>
<div class="ct-val">WHO · AHA · ESC</div>
</div>
</div>
<!-- Floating satellite: paper card top-right -->
<div class="sat-card sat-paper">
<div class="sp-tag">Systematic Review</div>
<div class="sp-title">Efficacy of dual antiplatelet therapy in ACS management</div>
<div class="sp-meta">
<span class="sp-cite">
<svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>
2,140 citations
</span>
<span>NEJM 2024</span>
</div>
</div>
<!-- CENTRAL: Query card -->
<div class="query-card">
<div class="card-header">
<div class="card-title">Evidence Synthesis</div>
<div class="card-status"><div class="status-dot"></div> Analyzing</div>
</div>
<div class="search-bar">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
<span>Best treatment for <span class="search-query">Type 2 Diabetes</span></span>
</div>
<div class="evidence-items">
<div class="ev-item">
<span class="ev-badge sr">SR</span>
<div class="ev-text"><strong>Metformin first-line therapy</strong> — 94% of SRs agree. GRADE: High</div>
</div>
<div class="ev-item">
<span class="ev-badge rct">RCT</span>
<div class="ev-text"><strong>SGLT2 inhibitors</strong> reduce CV mortality by 14% (NNT 38)</div>
</div>
<div class="ev-item">
<span class="ev-badge gl">GL</span>
<div class="ev-text"><strong>ADA 2025 Guideline</strong> recommends individualized HbA1c targets</div>
</div>
</div>
<div class="confidence-bar">
<div class="conf-label">
<span>Synthesis confidence</span>
<span>91%</span>
</div>
<div class="conf-track">
<div class="conf-fill"></div>
</div>
</div>
</div>
<!-- Floating satellite: stats card bottom-left -->
<div class="sat-card sat-stats">
<div class="stat-row">
<div>
<div class="stat-label">Sources scanned</div>
<div class="stat-val blue">48,200+</div>
<div class="stat-mini-bar"><div class="stat-mini-fill fill-b" style="width:88%"></div></div>
</div>
</div>
<div class="stat-row">
<div>
<div class="stat-label">Avg. answer time</div>
<div class="stat-val purple">< 3 sec</div>
<div class="stat-mini-bar"><div class="stat-mini-fill fill-p" style="width:70%"></div></div>
</div>
</div>
<div class="stat-row">
<div>
<div class="stat-label">GRADE accuracy</div>
<div class="stat-val green">96.4%</div>
<div class="stat-mini-bar"><div class="stat-mini-fill fill-g" style="width:96%"></div></div>
</div>
</div>
</div>
</div><!-- /hero-visual -->
</section>
<!-- NODE GRAPH ANIMATION -->
<script>
const canvas = document.getElementById('node-canvas');
const ctx = canvas.getContext('2d');
const COLORS = {
accent: '#38bdf8',
accent2: '#818cf8',
accent3: '#34d399',
};
let W, H, nodes, edges;
function resize() {
const parent = canvas.parentElement;
W = canvas.width = parent.offsetWidth;
H = canvas.height = parent.offsetHeight;
}
// Node types representing different evidence sources
const NODE_TYPES = [
{ color: COLORS.accent, label: 'SR', r: 5 },
{ color: COLORS.accent2, label: 'RCT', r: 4 },
{ color: COLORS.accent3, label: 'GL', r: 4 },
{ color: '#f472b6', label: 'MA', r: 3.5 },
{ color: '#fb923c', label: 'CS', r: 3 },
];
function randomBetween(a, b) { return a + Math.random() * (b - a); }
function initNodes() {
nodes = [];
const count = 28;
for (let i = 0; i < count; i++) {
const type = NODE_TYPES[Math.floor(Math.random() * NODE_TYPES.length)];
nodes.push({
x: randomBetween(0.05, 0.95) * W,
y: randomBetween(0.05, 0.95) * H,
vx: randomBetween(-.3, .3),
vy: randomBetween(-.3, .3),
r: type.r,
color: type.color,
alpha: randomBetween(0.3, 0.85),
pulsePhase: Math.random() * Math.PI * 2,
});
}
// Build edges: connect nodes that are close
edges = [];
for (let i = 0; i < nodes.length; i++) {
for (let j = i + 1; j < nodes.length; j++) {
const dx = nodes[i].x - nodes[j].x;
const dy = nodes[i].y - nodes[j].y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 160) {
edges.push({ a: i, b: j, dist });
}
}
}
}
function draw(t) {
ctx.clearRect(0, 0, W, H);
// Update node positions
nodes.forEach(n => {
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;
});
// Recompute edges dynamically
edges = [];
for (let i = 0; i < nodes.length; i++) {
for (let j = i + 1; j < nodes.length; j++) {
const dx = nodes[i].x - nodes[j].x;
const dy = nodes[i].y - nodes[j].y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 160) {
edges.push({ a: i, b: j, dist });
}
}
}
// Draw edges
edges.forEach(e => {
const na = nodes[e.a], nb = nodes[e.b];
const dx = na.x - nb.x, dy = na.y - nb.y;
const dist = Math.sqrt(dx * dx + dy * dy);
const alpha = (1 - dist / 160) * 0.25;
const grad = ctx.createLinearGradient(na.x, na.y, nb.x, nb.y);
grad.addColorStop(0, na.color + Math.round(alpha * 255).toString(16).padStart(2,'0'));
grad.addColorStop(1, nb.color + Math.round(alpha * 255).toString(16).padStart(2,'0'));
ctx.beginPath();
ctx.moveTo(na.x, na.y);
ctx.lineTo(nb.x, nb.y);
ctx.strokeStyle = grad;
ctx.lineWidth = 0.8;
ctx.stroke();
});
// Draw nodes
nodes.forEach((n, i) => {
const pulse = 0.7 + 0.3 * Math.sin(t * 0.001 + n.pulsePhase);
const r = n.r * pulse;
// Outer glow
const glow = ctx.createRadialGradient(n.x, n.y, 0, n.x, n.y, r * 4);
glow.addColorStop(0, n.color + '55');
glow.addColorStop(1, n.color + '00');
ctx.beginPath();
ctx.arc(n.x, n.y, r * 4, 0, Math.PI * 2);
ctx.fillStyle = glow;
ctx.fill();
// Core dot
ctx.beginPath();
ctx.arc(n.x, n.y, r, 0, Math.PI * 2);
ctx.fillStyle = n.color;
ctx.globalAlpha = n.alpha * pulse;
ctx.fill();
ctx.globalAlpha = 1;
});
requestAnimationFrame(draw);
}
window.addEventListener('resize', () => { resize(); initNodes(); });
resize();
initNodes();
requestAnimationFrame(draw);
</script>
</body>
</html>
wc -l /home/daytona/workspace/hero-section/index.html && echo "---" && grep -c "…
index
HTML File · HTML
index.html in any browser. Customize the headline, stats, and color variables at the top of the <style> block under :root {}.