DIY — Maker Workshop Hero
Full-viewport maker workshop hero on a navy blueprint-grid background with a bold stencil-style BUILD IT YOURSELF headline, a safety-orange primary CTA and a ghost secondary CTA. Animated SVG line-art of a wrench, screwdriver and soldering iron draws itself in with stroke-dashoffset, mono-badge stats count up on scroll, and the grid drifts with subtle mouse parallax. Below the fold, three build-path cards for Electronics, Woodworking and 3D Printing lift on hover with corner rivet dots and dashed kraft dividers.
MCP
Code
:root {
--blueprint: #0f2a4a;
--blueprint-d: #0a1e36;
--blueprint-l: #16385f;
--grid: rgba(140, 180, 220, 0.14);
--grid-major: rgba(140, 180, 220, 0.26);
--orange: #ff6b35;
--orange-d: #e0521f;
--orange-soft: #ffe3d6;
--kraft: #d9c7a7;
--kraft-l: #efe6d4;
--ink: #1c2733;
--ink-2: #3d4a57;
--muted: #6b7885;
--bg: #f4f1ea;
--white: #ffffff;
--line: rgba(28, 39, 51, 0.12);
--line-2: rgba(28, 39, 51, 0.2);
--ok: #2f9e6f;
--warn: #d98a2b;
--danger: #d4503e;
--r-sm: 6px;
--r-md: 12px;
--r-lg: 18px;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
font-family: "Inter", system-ui, -apple-system, sans-serif;
-webkit-font-smoothing: antialiased;
line-height: 1.5;
background: var(--bg);
color: var(--ink);
}
.mono { font-family: "JetBrains Mono", ui-monospace, monospace; }
/* ============ HERO ============ */
.hero {
position: relative;
min-height: 100vh;
display: flex;
flex-direction: column;
background: var(--blueprint);
color: var(--kraft-l);
overflow: hidden;
}
.hero-grid {
position: absolute;
inset: -80px;
background-image:
linear-gradient(var(--grid) 1px, transparent 1px),
linear-gradient(90deg, var(--grid) 1px, transparent 1px),
linear-gradient(var(--grid-major) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-major) 1px, transparent 1px);
background-size: 8px 8px, 8px 8px, 80px 80px, 80px 80px;
will-change: transform;
transition: transform 0.25s ease-out;
pointer-events: none;
}
/* ---- topbar ---- */
.topbar {
position: relative;
z-index: 3;
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
padding: 20px clamp(20px, 5vw, 56px);
border-bottom: 1px solid rgba(140, 180, 220, 0.16);
}
.brand {
display: inline-flex;
align-items: center;
gap: 10px;
text-decoration: none;
color: var(--white);
}
.brand-mark {
display: grid;
place-items: center;
width: 36px;
height: 36px;
border-radius: var(--r-sm);
background: var(--orange);
color: var(--blueprint-d);
box-shadow: 0 4px 14px rgba(255, 107, 53, 0.35);
}
.brand-name {
font-weight: 800;
letter-spacing: 0.14em;
font-size: 15px;
}
.brand-amp { color: var(--orange); }
.brand-tag {
font-size: 10px;
letter-spacing: 0.12em;
color: var(--kraft);
border: 1px solid rgba(217, 199, 167, 0.4);
border-radius: 999px;
padding: 2px 8px;
}
.topbar-links {
display: flex;
align-items: center;
gap: clamp(12px, 2.5vw, 28px);
}
.topbar-links a {
color: var(--kraft-l);
text-decoration: none;
font-size: 14px;
font-weight: 600;
opacity: 0.85;
transition: opacity 0.15s, color 0.15s;
}
.topbar-links a:hover,
.topbar-links a:focus-visible { opacity: 1; color: var(--orange); }
/* ---- hero body ---- */
.hero-inner {
position: relative;
z-index: 2;
flex: 1;
display: grid;
grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
align-items: center;
gap: clamp(24px, 4vw, 64px);
padding: clamp(32px, 6vh, 72px) clamp(20px, 5vw, 56px);
max-width: 1240px;
width: 100%;
margin: 0 auto;
}
.hero-kicker {
display: inline-flex;
align-items: center;
gap: 8px;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.22em;
color: var(--kraft);
margin-bottom: 18px;
}
.kicker-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--orange);
box-shadow: 0 0 0 4px rgba(255, 107, 53, 0.22);
animation: pulse 2.4s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { box-shadow: 0 0 0 3px rgba(255, 107, 53, 0.22); }
50% { box-shadow: 0 0 0 7px rgba(255, 107, 53, 0.08); }
}
.hero-title {
font-size: clamp(44px, 7.4vw, 92px);
line-height: 0.98;
font-weight: 800;
letter-spacing: 0.045em;
text-transform: uppercase;
color: var(--white);
text-shadow: 0 3px 0 rgba(10, 30, 54, 0.6);
}
.hero-title .line {
display: block;
opacity: 0;
transform: translateY(22px);
animation: rise 0.7s cubic-bezier(0.2, 0.7, 0.2, 1) forwards;
}
.hero-title .line-2 { animation-delay: 0.12s; }
@keyframes rise {
to { opacity: 1; transform: translateY(0); }
}
.title-accent {
color: var(--orange);
position: relative;
}
.title-accent::after {
content: "";
position: absolute;
left: 2px;
right: 2px;
bottom: 0.04em;
height: 0.09em;
background: repeating-linear-gradient(90deg, var(--orange) 0 10px, transparent 10px 16px);
opacity: 0.7;
}
.hero-sub {
margin-top: 20px;
max-width: 480px;
font-size: clamp(15px, 1.6vw, 17px);
color: var(--kraft-l);
opacity: 0.86;
}
/* ---- buttons ---- */
.hero-ctas {
display: flex;
flex-wrap: wrap;
gap: 14px;
margin-top: 30px;
}
.btn {
display: inline-flex;
align-items: center;
gap: 9px;
font-family: inherit;
font-size: 15px;
font-weight: 700;
letter-spacing: 0.03em;
padding: 14px 26px;
border-radius: var(--r-md);
border: 2px solid transparent;
cursor: pointer;
transition: transform 0.15s, box-shadow 0.15s, background 0.15s, border-color 0.15s;
}
.btn:active { transform: translateY(1px) scale(0.99); }
.btn:focus-visible {
outline: 3px solid var(--orange);
outline-offset: 3px;
}
.btn-primary {
background: var(--orange);
color: var(--blueprint-d);
box-shadow: 0 8px 22px rgba(255, 107, 53, 0.36);
}
.btn-primary:hover {
background: var(--orange-d);
color: var(--white);
transform: translateY(-2px);
box-shadow: 0 12px 28px rgba(255, 107, 53, 0.44);
}
.btn-ghost {
background: transparent;
color: var(--kraft-l);
border-color: rgba(217, 199, 167, 0.5);
}
.btn-ghost:hover {
border-color: var(--orange);
color: var(--orange);
transform: translateY(-2px);
}
.btn-sm { padding: 8px 16px; font-size: 13px; border-radius: var(--r-sm); }
/* ---- stats ---- */
.stats {
display: flex;
flex-wrap: wrap;
gap: clamp(16px, 3vw, 40px);
margin-top: clamp(30px, 5vh, 52px);
padding-top: 26px;
border-top: 1px dashed rgba(217, 199, 167, 0.34);
}
.stat dt {
font-size: 10px;
font-weight: 600;
letter-spacing: 0.2em;
color: var(--kraft);
opacity: 0.85;
}
.stat-num {
margin-top: 4px;
font-size: clamp(24px, 3vw, 34px);
font-weight: 700;
color: var(--white);
font-variant-numeric: tabular-nums;
}
.stat-num::after {
content: "";
display: block;
width: 28px;
height: 3px;
margin-top: 6px;
background: var(--orange);
border-radius: 2px;
}
/* ---- hero SVG art ---- */
.hero-art {
position: relative;
justify-self: center;
width: min(100%, 440px);
}
.tools-svg {
width: 100%;
height: auto;
stroke: var(--kraft);
overflow: visible;
}
.tools-svg .frame { stroke: rgba(140, 180, 220, 0.5); }
.tools-svg .tool-wrench { stroke: var(--orange); }
.tools-svg .tool-driver { stroke: var(--kraft-l); }
.tools-svg .tool-iron { stroke: var(--kraft); }
.tools-svg .callouts { stroke: rgba(140, 180, 220, 0.7); }
.tools-svg .draw path,
.tools-svg .draw rect,
.tools-svg .draw line,
.tools-svg .draw circle {
stroke-dasharray: var(--len, 900);
stroke-dashoffset: var(--len, 900);
animation: drawIn 1.6s ease forwards;
}
.tools-svg .frame * { animation-delay: 0.1s; }
.tools-svg .tool-wrench * { animation-delay: 0.5s; }
.tools-svg .tool-driver * { animation-delay: 0.9s; }
.tools-svg .tool-iron * { animation-delay: 1.3s; }
.tools-svg .callouts * { animation-delay: 1.9s; animation-duration: 0.9s; }
@keyframes drawIn { to { stroke-dashoffset: 0; } }
.svg-label {
font-family: "JetBrains Mono", ui-monospace, monospace;
font-size: 10px;
letter-spacing: 0.14em;
fill: rgba(217, 199, 167, 0.85);
stroke: none;
opacity: 0;
animation: fadeIn 0.6s ease 2.2s forwards;
}
@keyframes fadeIn { to { opacity: 1; } }
.art-stamp {
margin-top: 10px;
text-align: center;
font-size: 10px;
letter-spacing: 0.24em;
color: rgba(217, 199, 167, 0.7);
}
/* ---- scroll hint ---- */
.scroll-hint {
position: relative;
z-index: 2;
align-self: center;
margin-bottom: 18px;
font-size: 10px;
letter-spacing: 0.24em;
color: rgba(217, 199, 167, 0.75);
text-decoration: none;
transition: color 0.15s;
}
.scroll-hint:hover, .scroll-hint:focus-visible { color: var(--orange); }
.scroll-hint span { display: inline-block; animation: bob 1.8s ease-in-out infinite; }
@keyframes bob {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(4px); }
}
@media (prefers-reduced-motion: reduce) {
.hero-title .line, .tools-svg .draw *, .svg-label { animation-duration: 0.01s !important; animation-delay: 0s !important; }
.kicker-dot, .scroll-hint span { animation: none; }
.hero-grid { transition: none; }
html { scroll-behavior: auto; }
}
/* ============ CATEGORIES ============ */
.categories {
max-width: 1240px;
margin: 0 auto;
padding: clamp(56px, 9vh, 96px) clamp(20px, 5vw, 56px);
}
.section-head { max-width: 640px; margin-bottom: 40px; }
.section-kicker {
font-size: 11px;
font-weight: 600;
letter-spacing: 0.24em;
color: var(--orange-d);
}
.section-title {
margin-top: 8px;
font-size: clamp(26px, 3.6vw, 40px);
font-weight: 800;
letter-spacing: 0.05em;
text-transform: uppercase;
color: var(--ink);
}
.section-sub { margin-top: 10px; color: var(--muted); font-size: 15px; }
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 22px;
}
.cat-card {
position: relative;
background: var(--white);
border: 1px solid var(--line);
border-radius: var(--r-lg);
padding: 30px 26px 26px;
cursor: pointer;
box-shadow: 0 2px 6px rgba(28, 39, 51, 0.05);
transition: transform 0.2s cubic-bezier(0.2, 0.7, 0.2, 1), box-shadow 0.2s, border-color 0.2s;
}
.cat-card:hover,
.cat-card:focus-visible {
transform: translateY(-6px);
border-color: var(--orange);
box-shadow: 0 16px 34px rgba(28, 39, 51, 0.14);
}
.cat-card:focus-visible { outline: 3px solid var(--orange); outline-offset: 3px; }
.rivet {
position: absolute;
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--kraft);
border: 1.5px solid var(--line-2);
transition: background 0.2s, transform 0.2s;
}
.rivet-tl { top: 10px; left: 10px; }
.rivet-tr { top: 10px; right: 10px; }
.rivet-bl { bottom: 10px; left: 10px; }
.rivet-br { bottom: 10px; right: 10px; }
.cat-card:hover .rivet, .cat-card:focus-visible .rivet { background: var(--orange); transform: scale(1.2); }
.cat-icon {
display: grid;
place-items: center;
width: 54px;
height: 54px;
border-radius: var(--r-md);
background: var(--kraft-l);
color: var(--blueprint);
border: 1px solid var(--line);
margin-bottom: 18px;
transition: background 0.2s, color 0.2s;
}
.cat-card:hover .cat-icon, .cat-card:focus-visible .cat-icon {
background: var(--orange-soft);
color: var(--orange-d);
}
.cat-ref {
font-size: 10px;
font-weight: 600;
letter-spacing: 0.2em;
color: var(--muted);
}
.cat-title {
margin-top: 6px;
font-size: 22px;
font-weight: 800;
letter-spacing: 0.02em;
text-transform: uppercase;
}
.cat-desc { margin-top: 8px; font-size: 14px; color: var(--ink-2); }
.cat-meta {
list-style: none;
margin-top: 16px;
padding: 12px 0 0;
border-top: 1px dashed var(--line-2);
display: grid;
gap: 6px;
}
.cat-meta li {
font-size: 10px;
font-weight: 600;
letter-spacing: 0.14em;
color: var(--ink-2);
display: flex;
align-items: center;
gap: 8px;
}
.cat-meta li::before {
content: "";
width: 6px;
height: 6px;
border-radius: 1px;
background: var(--orange);
flex: none;
}
.cat-cta {
display: inline-flex;
align-items: center;
gap: 6px;
margin-top: 18px;
font-size: 13px;
font-weight: 700;
color: var(--orange-d);
letter-spacing: 0.04em;
}
.cat-cta span { transition: transform 0.2s; }
.cat-card:hover .cat-cta span, .cat-card:focus-visible .cat-cta span { transform: translateX(4px); }
/* ============ FOOTER ============ */
.foot {
border-top: 1px solid var(--line);
padding: 26px clamp(20px, 5vw, 56px);
text-align: center;
}
.foot p {
font-size: 10px;
letter-spacing: 0.2em;
color: var(--muted);
}
/* ============ TOAST ============ */
.toast {
position: fixed;
left: 50%;
bottom: 26px;
transform: translate(-50%, 20px);
background: var(--blueprint-d);
color: var(--kraft-l);
border: 1px solid rgba(140, 180, 220, 0.35);
border-left: 4px solid var(--orange);
border-radius: var(--r-sm);
padding: 12px 18px;
font-size: 12px;
letter-spacing: 0.04em;
box-shadow: 0 12px 30px rgba(10, 30, 54, 0.4);
opacity: 0;
pointer-events: none;
transition: opacity 0.25s, transform 0.25s;
z-index: 50;
max-width: min(92vw, 460px);
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
/* ============ RESPONSIVE ============ */
@media (max-width: 900px) {
.hero-inner { grid-template-columns: 1fr; }
.hero-art { width: min(100%, 340px); }
}
@media (max-width: 520px) {
.topbar { padding: 14px 18px; }
.topbar-links a { display: none; }
.brand-tag { display: none; }
.hero-inner { padding: 34px 18px 24px; gap: 30px; }
.hero-title { font-size: 42px; }
.hero-ctas { flex-direction: column; align-items: stretch; }
.btn { justify-content: center; }
.stats { gap: 18px; }
.stat { flex: 1 1 40%; }
.categories { padding: 52px 18px; }
.card-grid { gap: 16px; }
.hero-art { width: min(100%, 280px); }
}/* DIY — Maker Workshop Hero
Vanilla JS: toast helper, SVG self-draw lengths, count-up stats,
grid parallax on mouse move. No external libraries. */
(function () {
"use strict";
var reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
/* ---------- Toast helper ---------- */
var toastEl = document.getElementById("toast");
var toastTimer = null;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("show");
}, 2600);
}
// Wire every element with a data-toast attribute (buttons + cards).
document.querySelectorAll("[data-toast]").forEach(function (el) {
el.addEventListener("click", function () {
toast(el.getAttribute("data-toast"));
});
// Cards are focusable articles — make Enter/Space act like a click.
if (el.tagName !== "BUTTON" && el.tagName !== "A") {
el.setAttribute("role", "button");
el.addEventListener("keydown", function (e) {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
toast(el.getAttribute("data-toast"));
}
});
}
});
/* ---------- SVG line-art: measure real path lengths ----------
CSS animates stroke-dashoffset from --len to 0; here we set --len
to each shape's true length so every stroke draws at a natural pace. */
document
.querySelectorAll(".tools-svg .draw path, .tools-svg .draw rect, .tools-svg .draw line, .tools-svg .draw circle")
.forEach(function (shape) {
var len;
try {
len = Math.ceil(shape.getTotalLength()) + 2;
} catch (err) {
len = 900; // fallback for shapes without getTotalLength
}
shape.style.setProperty("--len", String(len));
});
/* ---------- Count-up stats ---------- */
function animateCount(el) {
var target = parseInt(el.getAttribute("data-count"), 10) || 0;
var suffix = el.getAttribute("data-suffix") || "";
if (reducedMotion) {
el.textContent = target.toLocaleString("en-US") + suffix;
return;
}
var duration = 1400;
var start = null;
function step(ts) {
if (start === null) start = ts;
var p = Math.min((ts - start) / duration, 1);
// easeOutCubic
var eased = 1 - Math.pow(1 - p, 3);
el.textContent = Math.round(target * eased).toLocaleString("en-US") + (p === 1 ? suffix : "");
if (p < 1) requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
var statsStarted = false;
function startStats() {
if (statsStarted) return;
statsStarted = true;
document.querySelectorAll(".stat-num").forEach(animateCount);
}
var statsBlock = document.querySelector(".stats");
if (statsBlock && "IntersectionObserver" in window) {
var io = new IntersectionObserver(
function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
startStats();
io.disconnect();
}
});
},
{ threshold: 0.4 }
);
io.observe(statsBlock);
} else {
startStats();
}
/* ---------- Grid parallax on mouse move ---------- */
var hero = document.getElementById("hero");
var grid = document.querySelector(".hero-grid");
if (hero && grid && !reducedMotion) {
var ticking = false;
var mx = 0;
var my = 0;
hero.addEventListener("mousemove", function (e) {
var rect = hero.getBoundingClientRect();
// Normalize to -1 .. 1 from hero center
mx = ((e.clientX - rect.left) / rect.width) * 2 - 1;
my = ((e.clientY - rect.top) / rect.height) * 2 - 1;
if (!ticking) {
ticking = true;
requestAnimationFrame(function () {
grid.style.transform =
"translate(" + (mx * -14).toFixed(1) + "px, " + (my * -14).toFixed(1) + "px)";
ticking = false;
});
}
});
hero.addEventListener("mouseleave", function () {
grid.style.transform = "translate(0, 0)";
});
}
/* ---------- Welcome toast (small delight, once) ---------- */
setTimeout(function () {
toast("Bench is hot — 47 makers building right now.");
}, 2800);
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>DIY — Maker Workshop Hero</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- ============ HERO ============ -->
<header class="hero" id="hero">
<div class="hero-grid" aria-hidden="true"></div>
<nav class="topbar" aria-label="Primary">
<a class="brand" href="#hero">
<span class="brand-mark" aria-hidden="true">
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M14.7 6.3a5 5 0 0 0-6.9 6.1L3 17.2V21h3.8l4.8-4.8a5 5 0 0 0 6.1-6.9l-3 3-2.8-.7-.7-2.8 3-3z"/>
</svg>
</span>
<span class="brand-name">FORGE<span class="brand-amp">&</span>FIX</span>
<span class="brand-tag mono">WKSP-04</span>
</a>
<div class="topbar-links">
<a href="#categories">Guides</a>
<a href="#categories">Workbench</a>
<a href="#categories">Community</a>
<button class="btn btn-ghost btn-sm" type="button" data-toast="Sign-in demo — no account needed here.">Sign in</button>
</div>
</nav>
<div class="hero-inner">
<div class="hero-copy">
<p class="hero-kicker mono"><span class="kicker-dot" aria-hidden="true"></span> BLUEPRINT NO. 047 — REV C</p>
<h1 class="hero-title">
<span class="line line-1">BUILD IT</span>
<span class="line line-2">YOUR<span class="title-accent">SELF</span></span>
</h1>
<p class="hero-sub">
Step-by-step build guides, annotated schematics and tool know-how —
from your first soldered joint to a full workshop bench. No gatekeeping,
just sawdust and solder.
</p>
<div class="hero-ctas">
<button class="btn btn-primary" type="button" data-toast="Loading your first build plan…">
Start building
<svg aria-hidden="true" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
</button>
<button class="btn btn-ghost" type="button" data-toast="Guide library demo — 1,284 guides and counting.">Browse guides</button>
</div>
<dl class="stats" aria-label="Workshop stats">
<div class="stat">
<dt class="mono">GUIDES PUBLISHED</dt>
<dd class="mono stat-num" data-count="1284" data-suffix="">0</dd>
</div>
<div class="stat">
<dt class="mono">MAKERS ONBOARD</dt>
<dd class="mono stat-num" data-count="38650" data-suffix="+">0</dd>
</div>
<div class="stat">
<dt class="mono">TOOLS CATALOGUED</dt>
<dd class="mono stat-num" data-count="912" data-suffix="">0</dd>
</div>
</dl>
</div>
<!-- Animated blueprint tool line-art -->
<figure class="hero-art" aria-hidden="true">
<svg class="tools-svg" viewBox="0 0 420 420" fill="none" stroke-linecap="round" stroke-linejoin="round">
<!-- dimension frame -->
<g class="draw frame" stroke-width="1">
<rect x="18" y="18" width="384" height="384" rx="10" stroke-dasharray="6 8" />
<line x1="40" y1="396" x2="380" y2="396" />
<line x1="40" y1="390" x2="40" y2="402" />
<line x1="380" y1="390" x2="380" y2="402" />
</g>
<!-- wrench -->
<g class="draw tool-wrench" stroke-width="3">
<path d="M96 300 L200 196 a34 34 0 1 1 24 24 L116 324 a17 17 0 0 1-24 0 a17 17 0 0 1 4-24 z" />
<path d="M226 170 l30 -30 m-8 46 l30 -30" stroke-width="2" />
</g>
<!-- screwdriver -->
<g class="draw tool-driver" stroke-width="3">
<path d="M300 88 l32 32 -18 18 -32 -32 z" />
<path d="M282 106 L176 212 l-8 26 26 -8 L300 124" />
<path d="M168 238 l-14 14" stroke-width="2" />
</g>
<!-- soldering iron -->
<g class="draw tool-iron" stroke-width="3">
<path d="M108 96 l16 16 m0 0 l52 52 22 -6 6 -22 -52 -52 -16 -16" />
<path d="M204 158 l86 86" stroke-width="2" />
<circle cx="298" cy="252" r="10" />
<path d="M104 92 c-10 -14 2 -30 16 -22" stroke-width="2" />
</g>
<!-- callouts -->
<g class="draw callouts" stroke-width="1">
<circle cx="238" cy="176" r="4" />
<path d="M242 172 L300 60 L356 60" />
<circle cx="118" cy="312" r="4" />
<path d="M114 316 L64 366" />
</g>
<text class="svg-label" x="304" y="52">TQ-14 WRENCH</text>
<text class="svg-label" x="46" y="382">GRIP ±0.5mm</text>
<text class="svg-label" x="182" y="412">SCALE 1:1 — ALL DIMS IN MM</text>
</svg>
<figcaption class="art-stamp mono">FIG. 01 — ESSENTIAL KIT</figcaption>
</figure>
</div>
<a class="scroll-hint mono" href="#categories">SCROLL FOR BUILD PATHS <span aria-hidden="true">▾</span></a>
</header>
<!-- ============ CATEGORIES ============ -->
<main>
<section class="categories" id="categories" aria-labelledby="cat-heading">
<div class="section-head">
<p class="mono section-kicker">// PICK A LANE</p>
<h2 id="cat-heading" class="section-title">CHOOSE YOUR BUILD PATH</h2>
<p class="section-sub">Every path starts with a zero-experience project and a printable parts list.</p>
</div>
<div class="card-grid">
<article class="cat-card" tabindex="0" data-toast="Electronics path — starting with the BlinkBox LED kit.">
<span class="rivet rivet-tl" aria-hidden="true"></span>
<span class="rivet rivet-tr" aria-hidden="true"></span>
<span class="rivet rivet-bl" aria-hidden="true"></span>
<span class="rivet rivet-br" aria-hidden="true"></span>
<div class="cat-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" width="26" height="26" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<rect x="6" y="6" width="12" height="12" rx="2"/><path d="M9 2v4M15 2v4M9 18v4M15 18v4M2 9h4M2 15h4M18 9h4M18 15h4"/>
</svg>
</div>
<p class="mono cat-ref">PATH-EL · 412 GUIDES</p>
<h3 class="cat-title">Electronics</h3>
<p class="cat-desc">Solder your first blinking circuit, then work up to sensor rigs and a bench power supply.</p>
<ul class="cat-meta mono">
<li>FIRST BUILD: BLINKBOX v2</li>
<li>KIT COST: ~$18</li>
</ul>
<span class="cat-cta">Open path <span aria-hidden="true">→</span></span>
</article>
<article class="cat-card" tabindex="0" data-toast="Woodworking path — the Stub-Tenon Stool awaits.">
<span class="rivet rivet-tl" aria-hidden="true"></span>
<span class="rivet rivet-tr" aria-hidden="true"></span>
<span class="rivet rivet-bl" aria-hidden="true"></span>
<span class="rivet rivet-br" aria-hidden="true"></span>
<div class="cat-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" width="26" height="26" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 21l6-6M14 4l6 6-9 9-6-6 9-9zM14 4l2-2 6 6-2 2"/>
</svg>
</div>
<p class="mono cat-ref">PATH-WD · 367 GUIDES</p>
<h3 class="cat-title">Woodworking</h3>
<p class="cat-desc">Hand-tool joinery from square one — cut a clean tenon, build a stool, then a full workbench.</p>
<ul class="cat-meta mono">
<li>FIRST BUILD: STUB-TENON STOOL</li>
<li>KIT COST: ~$32</li>
</ul>
<span class="cat-cta">Open path <span aria-hidden="true">→</span></span>
</article>
<article class="cat-card" tabindex="0" data-toast="3D printing path — calibrate, then print the GhostGrip handle.">
<span class="rivet rivet-tl" aria-hidden="true"></span>
<span class="rivet rivet-tr" aria-hidden="true"></span>
<span class="rivet rivet-bl" aria-hidden="true"></span>
<span class="rivet rivet-br" aria-hidden="true"></span>
<div class="cat-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" width="26" height="26" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 2l8 4.5v9L12 20l-8-4.5v-9L12 2zM12 2v9m8-4.5L12 11 4 6.5M12 20v-9"/>
</svg>
</div>
<p class="mono cat-ref">PATH-3D · 505 GUIDES</p>
<h3 class="cat-title">3D Printing</h3>
<p class="cat-desc">Dial in your first layer, master supports and tolerances, and design parts that actually fit.</p>
<ul class="cat-meta mono">
<li>FIRST BUILD: GHOSTGRIP HANDLE</li>
<li>KIT COST: FILAMENT ONLY</li>
</ul>
<span class="cat-cta">Open path <span aria-hidden="true">→</span></span>
</article>
</div>
</section>
</main>
<footer class="foot">
<p class="mono">FORGE&FIX WORKSHOP — FICTIONAL DEMO · MEASURE TWICE, CLICK ONCE</p>
</footer>
<div class="toast mono" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Maker Workshop Hero
A full-viewport landing hero for a fictional maker-education site, Forge&Fix Workshop, set on the signature dark blueprint grid (fine 8px lines with a major line every 80px). The stencil-feel uppercase headline rises in two staggered lines, backed by a mono “BLUEPRINT NO. 047” kicker, a safety-orange “Start building” CTA and a kraft-outlined “Browse guides” ghost button. To the side, decorative SVG line-art of a wrench, screwdriver and soldering iron draws itself in on load — the script measures each path’s real length with getTotalLength() so every stroke animates at a natural pace via stroke-dashoffset.
A dashed-rule stats row (guides published, makers onboard, tools catalogued) counts up with an ease-out curve once it scrolls into view, using tabular-nums mono digits so the layout never jitters. The blueprint grid itself drifts a few pixels against the cursor for a subtle parallax depth effect, throttled through requestAnimationFrame and disabled entirely under prefers-reduced-motion.
Below the fold, three build-path cards — Electronics, Woodworking and 3D Printing — carry corner rivet dots, mono part-number references, first-build metadata behind a dashed “cut here” divider, and a hover lift that tints the rivets orange. Cards and buttons are keyboard-usable (Enter/Space triggers), and every interaction reports through a shared toast() helper with an aria-live status region.
Illustrative UI only — always follow real safety guidance when working with tools, electronics, or repairs.