DIY — Step-by-Step Project Chapters
A long-form maker project page for the fictional MAKELOG community, built around a folding camp stool made from a single board. It pairs a cover band carrying author, stats and action buttons with eight numbered chapters, each holding a CSS-drawn figure, prose, tip callouts and a per-step thumbs control. A sticky chapter rail tracks reading position with IntersectionObserver, the supplies chapter is a live checklist with mono part refs, and an I Made It gallery closes the page.
MCP
Code
:root{
--paper:#fffdfa;
--paper-2:#fbf6ee;
--primary:#e8552d;
--primary-d:#c8421f;
--primary-soft:#ffe6dd;
--teal:#0f8a8a;
--teal-d:#0b6b6b;
--teal-soft:#dff2f1;
--yellow:#ffd166;
--yellow-soft:#fff3d2;
--ink:#22201e;
--ink-2:#474341;
--muted:#7a7370;
--line:rgba(34,32,30,0.12);
--line-2:rgba(34,32,30,0.22);
--ok:#2f9e6f;
--warn:#d98a2b;
--danger:#d4503e;
--r-sm:8px; --r-md:14px; --r-lg:22px; --r-xl:30px;
--sh-1:0 1px 2px rgba(34,32,30,.06), 0 4px 14px rgba(34,32,30,.06);
--sh-2:0 10px 30px rgba(34,32,30,.10);
--sh-3:0 18px 48px rgba(34,32,30,.14);
}
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;scroll-padding-top:86px}
body{
margin:0;
background:var(--paper);
color:var(--ink);
font-family:Inter,system-ui,sans-serif;
font-size:16px;line-height:1.5;
-webkit-font-smoothing:antialiased;
text-rendering:optimizeLegibility;
}
img{max-width:100%}
.mono{font-family:"JetBrains Mono",ui-monospace,monospace}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.wrap{width:min(1180px,100% - 40px);margin-inline:auto}
:where(a,button,input,[tabindex]):focus-visible{
outline:3px solid var(--teal);outline-offset:2px;border-radius:6px;
}
.skip{
position:absolute;left:10px;top:-60px;z-index:60;
background:var(--ink);color:var(--paper);padding:10px 16px;border-radius:0 0 var(--r-sm) var(--r-sm);
font-weight:600;text-decoration:none;transition:top .18s;
}
.skip:focus{top:0}
/* ---------- BUTTONS ---------- */
.btn{
font:inherit;font-weight:600;cursor:pointer;
border:1px solid transparent;border-radius:999px;
padding:11px 20px;display:inline-flex;align-items:center;gap:8px;
transition:transform .14s ease, background .18s, color .18s, border-color .18s, box-shadow .18s;
}
.btn:active{transform:translateY(1px) scale(.99)}
.btn-sm{padding:8px 14px;font-size:14px}
.btn-lg{padding:15px 30px;font-size:17px}
.btn-primary{background:var(--primary);color:#fff;box-shadow:var(--sh-1)}
.btn-primary:hover{background:var(--primary-d);box-shadow:var(--sh-2)}
.btn-outline{background:var(--paper);color:var(--ink);border-color:var(--line-2)}
.btn-outline:hover{border-color:var(--ink);background:var(--paper-2)}
.btn-ghost{background:transparent;color:var(--ink-2);border-color:var(--line)}
.btn-ghost:hover{background:var(--paper-2);color:var(--ink)}
.btn-follow{background:var(--teal);color:#fff;padding:8px 18px;font-size:14px}
.btn-follow:hover{background:var(--teal-d)}
.btn-follow[aria-pressed="true"]{background:var(--teal-soft);color:var(--teal-d);border-color:var(--teal)}
.btn-primary[aria-pressed="true"]{background:var(--yellow);color:var(--ink)}
.btn-primary[aria-pressed="true"]:hover{background:#f0c04f}
/* ---------- TOPBAR ---------- */
.topbar{
position:sticky;top:0;z-index:40;
background:rgba(255,253,250,.9);backdrop-filter:blur(12px);
border-bottom:1px solid var(--line);
}
.topbar-in{display:flex;align-items:center;gap:22px;height:64px}
.brand{display:flex;align-items:center;gap:10px;text-decoration:none;color:var(--ink)}
.brand-mark{display:grid;place-items:center}
.brand-name{font-weight:800;letter-spacing:.14em;font-size:15px}
.topnav{display:flex;gap:20px;margin-left:auto}
.topnav a{
color:var(--ink-2);text-decoration:none;font-weight:500;font-size:15px;
padding-bottom:3px;border-bottom:2px solid transparent;
}
.topnav a:hover{color:var(--primary);border-color:var(--primary)}
/* ---------- COVER ---------- */
.cover{
padding:52px 0 44px;
background:
radial-gradient(900px 420px at 88% -10%, var(--yellow-soft), transparent 62%),
radial-gradient(700px 400px at 4% 8%, var(--primary-soft), transparent 60%),
var(--paper);
border-bottom:1px solid var(--line);
}
.cover-in{display:grid;grid-template-columns:1.15fr .85fr;gap:44px;align-items:center}
.eyebrow{
margin:0 0 12px;font-size:13px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;
color:var(--teal);
}
.cover h1{
margin:0 0 14px;font-size:clamp(30px,4.4vw,52px);line-height:1.08;letter-spacing:-.025em;font-weight:800;
}
.lede{margin:0 0 26px;font-size:18px;color:var(--ink-2);max-width:56ch}
.cover-meta{display:flex;flex-wrap:wrap;gap:24px;align-items:center;margin-bottom:24px}
.author{
display:flex;align-items:center;gap:12px;
background:var(--paper);border:1px solid var(--line);border-radius:999px;
padding:8px 8px 8px 10px;box-shadow:var(--sh-1);
}
.avatar{
width:40px;height:40px;border-radius:50%;display:grid;place-items:center;
background:linear-gradient(140deg,var(--primary),var(--yellow));
color:#fff;font-weight:800;font-size:14px;letter-spacing:.04em;
}
.author-txt{display:flex;flex-direction:column;line-height:1.25}
.author-txt strong{font-size:15px}
.author-txt em{font-style:normal;font-size:12.5px;color:var(--muted)}
.stats{display:flex;gap:22px;list-style:none;margin:0;padding:0}
.stats li{display:flex;flex-direction:column}
.stats b{font-size:18px;font-weight:700}
.stats span{font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em}
.cover-actions{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:22px}
.chips{display:flex;flex-wrap:wrap;gap:8px;list-style:none;margin:0;padding:0}
.chip{
font-size:13px;font-weight:600;color:var(--ink-2);
background:var(--paper);border:1px solid var(--line-2);border-radius:999px;padding:6px 14px;
}
.chip-hi{background:var(--yellow);border-color:transparent;color:var(--ink)}
/* ---------- ART BASE ---------- */
.art{
position:relative;width:100%;aspect-ratio:4/3;border-radius:var(--r-lg);overflow:hidden;
background:
linear-gradient(180deg,#fffaf3,#f3ece1),
var(--paper-2);
border:1px solid var(--line);
}
.art::after{
content:"";position:absolute;inset:0;pointer-events:none;
background-image:linear-gradient(rgba(34,32,30,.045) 1px,transparent 1px),
linear-gradient(90deg,rgba(34,32,30,.045) 1px,transparent 1px);
background-size:22px 22px;
}
.cover-art{margin:0}
.cover-art figcaption,.fig figcaption{
margin-top:10px;font-size:13.5px;color:var(--muted);
}
.art-stool{aspect-ratio:1/.86;box-shadow:var(--sh-3)}
.art-stool .leg{position:absolute;width:12px;border-radius:6px;background:linear-gradient(180deg,#d8b48a,#b8875a)}
.art-stool .l1{height:56%;left:30%;top:16%;transform:rotate(19deg)}
.art-stool .l2{height:56%;left:66%;top:16%;transform:rotate(-19deg)}
.art-stool .l3{height:56%;left:38%;top:16%;transform:rotate(-19deg);opacity:.72}
.art-stool .l4{height:56%;left:58%;top:16%;transform:rotate(19deg);opacity:.72}
.art-stool .seat{
position:absolute;left:22%;right:22%;top:15%;height:16px;border-radius:8px;
background:linear-gradient(180deg,var(--primary),var(--primary-d));
box-shadow:0 6px 14px rgba(232,85,45,.3);
}
.art-stool .pivot{position:absolute;width:14px;height:14px;border-radius:50%;background:var(--teal);top:44%;box-shadow:0 0 0 4px var(--teal-soft)}
.art-stool .p1{left:34%}
.art-stool .p2{left:62%}
.art-stool .ground{position:absolute;left:14%;right:14%;bottom:16%;height:3px;border-radius:2px;background:var(--line-2)}
.fig{margin:24px 0}
.fig .art{aspect-ratio:16/9}
.art-cuts .board{position:absolute;left:6%;right:6%;top:38%;height:24%;border-radius:8px;background:linear-gradient(90deg,#e6c79c,#cfa571)}
.art-cuts .cut{position:absolute;top:32%;height:36%;width:3px;background:var(--primary)}
.art-cuts .c1{left:22%}.art-cuts .c2{left:37%}.art-cuts .c3{left:52%}
.art-cuts .c4{left:65%}.art-cuts .c5{left:78%}
.art-cuts .dim{position:absolute;left:6%;right:6%;top:74%;height:1px;background:var(--teal)}
.art-cuts .dim::before,.art-cuts .dim::after{content:"";position:absolute;top:-5px;width:1px;height:11px;background:var(--teal)}
.art-cuts .dim::before{left:0}.art-cuts .dim::after{right:0}
.art-drill .plank{position:absolute;left:12%;right:12%;top:34%;height:32%;border-radius:8px;background:linear-gradient(180deg,#e6c79c,#cfa571)}
.art-drill .hole{position:absolute;left:47%;top:46%;width:26px;height:26px;border-radius:50%;background:#5c4227}
.art-drill .ring{position:absolute;left:44%;top:41%;width:52px;height:52px;border-radius:50%;border:2px dashed var(--teal)}
.art-drill .axis{position:absolute;background:var(--primary);opacity:.65}
.art-drill .ax-x{left:12%;right:12%;top:calc(46% + 13px);height:1px}
.art-drill .ax-y{top:14%;bottom:14%;left:calc(47% + 13px);width:1px}
.art-drill .bit{position:absolute;left:calc(47% + 8px);top:8%;width:10px;height:28%;border-radius:4px 4px 2px 2px;background:linear-gradient(180deg,#8d959c,#5c646b)}
.art-assembly .xleg{position:absolute;width:14px;height:62%;top:18%;border-radius:7px;background:linear-gradient(180deg,#d8b48a,#b8875a)}
.art-assembly .a{left:40%;transform:rotate(24deg)}
.art-assembly .b{left:56%;transform:rotate(-24deg)}
.art-assembly .railtop{position:absolute;left:26%;right:26%;top:16%;height:14px;border-radius:7px;background:var(--primary)}
.art-assembly .node{position:absolute;left:48.5%;top:47%;width:20px;height:20px;border-radius:50%;background:var(--teal);box-shadow:0 0 0 6px var(--teal-soft)}
.art-assembly .arrowc{
position:absolute;left:38%;top:40%;width:80px;height:80px;border-radius:50%;
border:2px dashed var(--primary);border-right-color:transparent;border-top-color:transparent;
}
.art-sand .grain{position:absolute;left:12%;right:12%;height:6px;border-radius:3px;background:linear-gradient(90deg,#e6c79c,#d7b184,#e6c79c)}
.art-sand .g1{top:36%}.art-sand .g2{top:50%;opacity:.8}.art-sand .g3{top:64%;opacity:.6}
.art-sand .pad{position:absolute;left:38%;top:26%;width:24%;height:20%;border-radius:10px;background:var(--teal);box-shadow:0 8px 18px rgba(15,138,138,.28)}
.art-sand .dust{position:absolute;width:7px;height:7px;border-radius:50%;background:var(--yellow)}
.art-sand .d1{left:32%;top:24%}.art-sand .d2{left:64%;top:30%}.art-sand .d3{left:58%;top:20%}
.art-finish .panel{position:absolute;top:24%;height:52%;width:36%;border-radius:10px}
.art-finish .raw{left:10%;background:linear-gradient(180deg,#f0dcc0,#e3caa5)}
.art-finish .oiled{right:10%;background:linear-gradient(180deg,#c99456,#a4682f);box-shadow:inset 0 0 40px rgba(0,0,0,.18)}
.art-finish .split{position:absolute;left:50%;top:16%;bottom:16%;width:2px;background:var(--ink);opacity:.25}
.art-finish .drop{position:absolute;right:26%;top:16%;width:16px;height:20px;border-radius:50% 50% 50% 50%/60% 60% 40% 40%;background:var(--yellow)}
.art-test .weight{position:absolute;left:36%;top:12%;width:28%;height:18%;border-radius:10px;background:var(--ink);opacity:.85}
.art-test .seatbar{position:absolute;left:22%;right:22%;top:34%;height:14px;border-radius:7px;background:var(--primary)}
.art-test .legt{position:absolute;width:12px;height:44%;top:38%;border-radius:6px;background:linear-gradient(180deg,#d8b48a,#b8875a)}
.art-test .lt1{left:32%;transform:rotate(15deg)}
.art-test .lt2{left:64%;transform:rotate(-15deg)}
.art-test .gauge{position:absolute;right:10%;top:40%;width:64px;height:64px;border-radius:50%;border:4px solid var(--teal);border-bottom-color:var(--yellow)}
.art-final .fold{position:absolute;width:16px;height:62%;top:20%;border-radius:8px;background:linear-gradient(180deg,#d8b48a,#b8875a);transform:rotate(7deg)}
.art-final .f1{left:44%}
.art-final .f2{left:52%;opacity:.8}
.art-final .strap{position:absolute;left:38%;width:24%;top:44%;height:12px;border-radius:6px;background:var(--teal)}
.art-final .tag{position:absolute;left:60%;top:56%;width:34px;height:22px;border-radius:5px;background:var(--yellow)}
/* ---------- LAYOUT ---------- */
.layout{display:grid;grid-template-columns:236px minmax(0,1fr);gap:56px;padding:48px 0 64px}
.rail{position:sticky;top:88px;align-self:start;max-height:calc(100vh - 120px);overflow:auto}
.rail-title{
margin:0 0 12px;font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
}
.rail-list{list-style:none;margin:0 0 22px;padding:0;border-left:2px solid var(--line)}
.rail-list a{
display:flex;align-items:center;gap:10px;
padding:9px 12px;margin-left:-2px;border-left:2px solid transparent;
text-decoration:none;color:var(--ink-2);font-size:14.5px;font-weight:500;
transition:color .16s,border-color .16s,background .16s;border-radius:0 var(--r-sm) var(--r-sm) 0;
}
.rail-list a:hover{color:var(--primary);background:var(--primary-soft)}
.rail-list .n{font-size:12px;color:var(--muted);font-weight:600}
.rail-list a.is-active{color:var(--primary);border-left-color:var(--primary);font-weight:700;background:var(--primary-soft)}
.rail-list a.is-active .n{color:var(--primary)}
.rail-list a.is-done .n{color:var(--teal)}
.rail-progress .bar{height:6px;border-radius:3px;background:var(--line);overflow:hidden}
.rail-progress .bar span{display:block;height:100%;width:0;border-radius:3px;background:linear-gradient(90deg,var(--primary),var(--yellow));transition:width .25s ease}
.rail-progress p{margin:8px 0 0;font-size:12px;color:var(--muted)}
/* ---------- CHAPTERS ---------- */
.chapter{padding-bottom:44px;margin-bottom:44px;border-bottom:1px dashed var(--line-2);scroll-margin-top:86px}
.chapter:last-child{border-bottom:0}
.ch-head{display:flex;align-items:center;gap:14px;margin-bottom:14px}
.badge{
width:44px;height:44px;flex:none;border-radius:14px;display:grid;place-items:center;
background:var(--primary);color:#fff;font-weight:700;font-size:15px;box-shadow:var(--sh-1);
}
.ch-head h2{margin:0;font-size:clamp(23px,3vw,30px);letter-spacing:-.02em;font-weight:800}
.chapter p{color:var(--ink-2);max-width:70ch}
.card{
background:var(--paper);border:1px solid var(--line);border-radius:var(--r-lg);
padding:22px;box-shadow:var(--sh-1);margin:22px 0;
}
.supplies-head{display:flex;justify-content:space-between;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:14px}
.supplies-head h3{margin:0;font-size:18px}
.supplies-head p{margin:0;font-size:13px;color:var(--teal);font-weight:600}
.supply-list{list-style:none;margin:0;padding:0}
.supply-list li + li{border-top:1px solid var(--line)}
.supply-list label{
display:flex;align-items:center;gap:12px;padding:11px 8px;cursor:pointer;border-radius:var(--r-sm);
transition:background .16s;
}
.supply-list label:hover{background:var(--paper-2)}
.supply-list input{width:19px;height:19px;accent-color:var(--primary);flex:none;cursor:pointer}
.supply-list .qty{font-size:13px;color:var(--primary);font-weight:700;min-width:30px}
.supply-list .nm{flex:1;font-size:15px}
.supply-list .ref{font-size:12px;color:var(--muted);background:var(--paper-2);border:1px solid var(--line);border-radius:6px;padding:3px 7px}
.supply-list li.is-got .nm{color:var(--muted);text-decoration:line-through}
.tools{margin-top:18px;padding-top:16px;border-top:1px dashed var(--line-2)}
.tools-title{margin:0 0 10px;font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--muted)}
.tools ul{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:8px}
.tools li{font-size:13.5px;background:var(--teal-soft);color:var(--teal-d);border-radius:999px;padding:6px 13px;font-weight:500}
.tip{
display:flex;gap:14px;align-items:flex-start;margin:22px 0;
background:var(--teal-soft);border-left:4px solid var(--teal);
border-radius:0 var(--r-md) var(--r-md) 0;padding:15px 18px;
}
.tip p{margin:0;color:var(--ink-2);font-size:15px}
.tip-k{
flex:none;font-size:11px;font-weight:700;letter-spacing:.1em;
background:var(--teal);color:#fff;border-radius:5px;padding:3px 8px;margin-top:2px;
}
.tip-warn{background:var(--yellow-soft);border-left-color:var(--warn)}
.tip-warn .tip-k{background:var(--warn)}
.cuts{width:100%;border-collapse:collapse;margin:22px 0;font-size:15px}
.cuts th,.cuts td{text-align:left;padding:11px 12px;border-bottom:1px solid var(--line)}
.cuts thead th{
font-size:11.5px;text-transform:uppercase;letter-spacing:.1em;color:var(--muted);
border-bottom:2px solid var(--line-2);
}
.cuts tbody tr:hover{background:var(--paper-2)}
.steps{margin:20px 0;padding-left:22px;color:var(--ink-2)}
.steps li{margin-bottom:9px;padding-left:6px}
.steps li::marker{color:var(--primary);font-weight:700}
.ch-foot{
display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;
margin-top:26px;padding:14px 18px;border:1px solid var(--line);border-radius:var(--r-md);
background:var(--paper-2);
}
.ch-foot p{margin:0;font-size:14.5px;font-weight:600;color:var(--ink)}
.thumbs{display:flex;gap:8px}
.thumbs button{
font:inherit;font-size:14px;cursor:pointer;display:inline-flex;align-items:center;gap:7px;
background:var(--paper);border:1px solid var(--line-2);border-radius:999px;padding:7px 15px;
transition:transform .14s,border-color .16s,background .16s;
}
.thumbs button:hover{border-color:var(--ink);transform:translateY(-1px)}
.thumbs button[aria-pressed="true"]{background:var(--primary-soft);border-color:var(--primary);color:var(--primary-d);font-weight:600}
.thumbs .c{font-size:12.5px;color:var(--muted)}
.thumbs button[aria-pressed="true"] .c{color:var(--primary-d)}
/* ---------- I MADE IT ---------- */
.madeit{
padding:60px 0 68px;
background:
radial-gradient(700px 380px at 92% 10%, var(--teal-soft), transparent 60%),
var(--paper-2);
border-top:1px solid var(--line);
}
.madeit-head{text-align:center;margin-bottom:34px}
.madeit-head h2{margin:0 0 8px;font-size:clamp(26px,3.4vw,36px);font-weight:800;letter-spacing:-.02em}
.madeit-head p{margin:0;color:var(--muted)}
.makes{list-style:none;margin:0 0 38px;padding:0;display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.make{
background:var(--paper);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;
box-shadow:var(--sh-1);transition:transform .18s ease,box-shadow .18s ease;
}
.make:hover{transform:translateY(-4px);box-shadow:var(--sh-2)}
.make-art{height:150px;position:relative}
.make-art::after{
content:"";position:absolute;inset:0;
background-image:linear-gradient(rgba(255,255,255,.16) 1px,transparent 1px),
linear-gradient(90deg,rgba(255,255,255,.16) 1px,transparent 1px);
background-size:20px 20px;
}
.m1{background:linear-gradient(140deg,#e8552d,#ffd166)}
.m2{background:linear-gradient(140deg,#0f8a8a,#7fd0c6)}
.m3{background:linear-gradient(140deg,#c8421f,#e8955a)}
.m4{background:linear-gradient(140deg,#ffd166,#e8552d)}
.m5{background:linear-gradient(140deg,#0b6b6b,#0f8a8a)}
.m6{background:linear-gradient(140deg,#b8875a,#e6c79c)}
.m7{background:linear-gradient(140deg,#22201e,#5c646b)}
.m8{background:linear-gradient(140deg,#e8552d,#0f8a8a)}
.m9{background:linear-gradient(140deg,#ffd166,#0f8a8a)}
.make-body{padding:15px 17px 18px}
.maker{display:flex;align-items:center;gap:9px;font-weight:700;font-size:14.5px;margin-bottom:7px}
.maker i{
width:28px;height:28px;border-radius:50%;display:grid;place-items:center;font-style:normal;
background:var(--ink);color:var(--paper);font-size:11px;font-weight:700;
}
.make-body p{margin:0;font-size:14px;color:var(--ink-2)}
.madeit-cta{text-align:center}
.madeit-cta p{margin:12px 0 0;font-size:14px;color:var(--muted)}
.foot{padding:34px 0 92px;border-top:1px solid var(--line);background:var(--paper)}
.foot-in{display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap}
.foot p{margin:0;font-size:13.5px;color:var(--muted)}
/* ---------- STICKY BAR ---------- */
.stickybar{
position:fixed;left:0;right:0;bottom:0;z-index:45;display:none;
align-items:center;justify-content:space-between;gap:10px;
padding:10px 14px;background:rgba(255,253,250,.96);backdrop-filter:blur(12px);
border-top:1px solid var(--line-2);box-shadow:0 -6px 20px rgba(34,32,30,.08);
}
.sb-btn{
font:inherit;font-weight:600;font-size:14px;cursor:pointer;
background:var(--primary);color:#fff;border:0;border-radius:999px;padding:10px 16px;
}
.sb-btn:disabled{background:var(--line);color:var(--muted);cursor:not-allowed}
.sb-now{font-size:12.5px;color:var(--ink-2);text-align:center;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* ---------- TOASTS ---------- */
.toasts{position:fixed;right:16px;bottom:16px;z-index:80;display:flex;flex-direction:column;gap:9px;pointer-events:none}
.toast{
background:var(--ink);color:var(--paper);border-radius:var(--r-md);
padding:12px 17px;font-size:14px;font-weight:500;box-shadow:var(--sh-3);
max-width:320px;opacity:0;transform:translateY(10px);
transition:opacity .22s ease,transform .22s ease;
}
.toast.in{opacity:1;transform:none}
.toast.ok{background:var(--teal-d)}
.toast.hi{background:var(--primary-d)}
/* ---------- RESPONSIVE ---------- */
@media (max-width:1000px){
.cover-in{grid-template-columns:1fr;gap:30px}
.layout{grid-template-columns:1fr;gap:0}
.rail{
position:sticky;top:64px;z-index:30;max-height:none;
background:rgba(255,253,250,.96);backdrop-filter:blur(10px);
margin:0 -20px 24px;padding:10px 20px;border-bottom:1px solid var(--line);
}
.rail-title,.rail-progress{display:none}
.rail-list{display:flex;gap:6px;overflow-x:auto;border-left:0;margin-bottom:0;padding-bottom:4px}
.rail-list li{flex:none}
.rail-list a{border-left:0;border-radius:999px;border:1px solid var(--line);white-space:nowrap;padding:7px 14px;margin-left:0}
.rail-list a.is-active{border-color:var(--primary)}
.makes{grid-template-columns:repeat(2,1fr)}
.stickybar{display:flex}
}
@media (max-width:520px){
.wrap{width:min(100% - 28px,100%)}
html{scroll-padding-top:120px}
.topnav{display:none}
.topbar-in{gap:12px}
.cover{padding:32px 0 30px}
.lede{font-size:16px}
.cover-meta{gap:16px}
.stats{gap:16px}
.stats b{font-size:16px}
.cover-actions .btn{flex:1 1 auto;justify-content:center}
.makes{grid-template-columns:1fr}
.chapter{padding-bottom:32px;margin-bottom:32px}
.card{padding:16px}
.supply-list label{flex-wrap:wrap;gap:9px}
.supply-list .nm{flex:1 1 60%}
.ch-foot{flex-direction:column;align-items:flex-start}
.cuts{font-size:14px}
.cuts th,.cuts td{padding:9px 7px}
.foot{padding-bottom:96px}
.toasts{left:14px;right:14px;bottom:74px}
.toast{max-width:none}
}
@media (prefers-reduced-motion:reduce){
html{scroll-behavior:auto}
*{transition-duration:.01ms !important;animation-duration:.01ms !important}
}(function () {
"use strict";
/* ---------- toast ---------- */
var host = document.getElementById("toasts");
function toast(msg, kind) {
if (!host) return;
var el = document.createElement("div");
el.className = "toast" + (kind ? " " + kind : "");
el.setAttribute("role", "status");
el.textContent = msg;
host.appendChild(el);
requestAnimationFrame(function () { el.classList.add("in"); });
setTimeout(function () {
el.classList.remove("in");
setTimeout(function () { el.remove(); }, 260);
}, 2600);
}
document.querySelectorAll("[data-toast]").forEach(function (b) {
b.addEventListener("click", function () { toast(b.dataset.toast); });
});
/* ---------- follow ---------- */
var follow = document.getElementById("followBtn");
if (follow) {
follow.addEventListener("click", function () {
var on = follow.getAttribute("aria-pressed") === "true";
follow.setAttribute("aria-pressed", String(!on));
follow.textContent = on ? "Follow" : "Following";
toast(on ? "Unfollowed Rin Halvorsen." : "Following Rin Halvorsen — new builds land in your feed.", on ? null : "ok");
});
}
/* ---------- favorite ---------- */
var fav = document.getElementById("favBtn");
if (fav) {
fav.addEventListener("click", function () {
var on = fav.getAttribute("aria-pressed") === "true";
fav.setAttribute("aria-pressed", String(!on));
fav.querySelector(".lbl").textContent = on ? "Favorite" : "Favorited";
toast(on ? "Removed from favorites." : "Added to your favorites.", on ? null : "hi");
});
}
/* ---------- supplies checklist ---------- */
var list = document.getElementById("supplyList");
var count = document.getElementById("suppliesCount");
if (list && count) {
var boxes = Array.prototype.slice.call(list.querySelectorAll("input[type=checkbox]"));
var sync = function (announce) {
var got = boxes.filter(function (b) { return b.checked; }).length;
count.textContent = got + " / " + boxes.length + " gathered";
if (announce && got === boxes.length) toast("Full kit gathered — time to cut.", "ok");
};
boxes.forEach(function (b) {
b.addEventListener("change", function () {
b.closest("li").classList.toggle("is-got", b.checked);
sync(true);
});
});
sync(false);
}
/* ---------- thumbs ---------- */
document.querySelectorAll(".thumbs").forEach(function (grp) {
var btns = Array.prototype.slice.call(grp.querySelectorAll("button"));
btns.forEach(function (btn) {
var c = btn.querySelector(".c");
var base = parseInt(c.textContent.replace(/\D/g, ""), 10) || 0;
btn.addEventListener("click", function () {
var on = btn.getAttribute("aria-pressed") === "true";
btns.forEach(function (o) {
if (o !== btn && o.getAttribute("aria-pressed") === "true") {
o.setAttribute("aria-pressed", "false");
var oc = o.querySelector(".c");
oc.textContent = String(parseInt(oc.textContent, 10) - 1);
}
});
btn.setAttribute("aria-pressed", String(!on));
c.textContent = String(on ? base : base + 1);
if (!on) toast(btn.dataset.vote === "up" ? "Thanks — marked this step as helpful." : "Noted. The author sees this feedback.");
});
});
});
/* ---------- chapter navigator ---------- */
var links = Array.prototype.slice.call(document.querySelectorAll("#railList a"));
var chapters = links.map(function (a) { return document.getElementById(a.dataset.target); }).filter(Boolean);
var current = 0;
var bar = document.getElementById("railBar");
var pct = document.getElementById("railPct");
var now = document.getElementById("sbNow");
var prev = document.getElementById("prevCh");
var next = document.getElementById("nextCh");
function setActive(i) {
if (i < 0 || i >= chapters.length) return;
current = i;
links.forEach(function (a, n) {
a.classList.toggle("is-active", n === i);
a.classList.toggle("is-done", n < i);
if (n === i) a.setAttribute("aria-current", "true");
else a.removeAttribute("aria-current");
});
var p = Math.round(((i + 1) / chapters.length) * 100);
if (bar) bar.style.width = p + "%";
if (pct) pct.textContent = p + "% read";
if (now) now.textContent = links[i].textContent.trim().replace(/\s+/g, " ");
if (prev) prev.disabled = i === 0;
if (next) next.disabled = i === chapters.length - 1;
var active = links[i];
if (active && active.parentElement && window.innerWidth <= 1000) {
active.scrollIntoView({ block: "nearest", inline: "center", behavior: "smooth" });
}
}
if (chapters.length) {
if ("IntersectionObserver" in window) {
var visible = new Map();
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (e) { visible.set(e.target.id, e.isIntersecting ? e.intersectionRatio : 0); });
var bestId = null, best = 0;
visible.forEach(function (v, k) { if (v > best) { best = v; bestId = k; } });
if (bestId) {
var idx = chapters.findIndex(function (c) { return c.id === bestId; });
if (idx > -1 && idx !== current) setActive(idx);
}
}, { rootMargin: "-84px 0px -55% 0px", threshold: [0, 0.15, 0.4, 0.75, 1] });
chapters.forEach(function (c) { io.observe(c); });
}
setActive(0);
}
links.forEach(function (a, i) {
a.addEventListener("click", function (e) {
e.preventDefault();
chapters[i].scrollIntoView({ behavior: "smooth", block: "start" });
setActive(i);
history.replaceState(null, "", "#" + chapters[i].id);
});
});
function go(delta) {
var i = Math.min(chapters.length - 1, Math.max(0, current + delta));
if (i === current) return;
chapters[i].scrollIntoView({ behavior: "smooth", block: "start" });
setActive(i);
}
if (prev) prev.addEventListener("click", function () { go(-1); });
if (next) next.addEventListener("click", function () { go(1); });
document.addEventListener("keydown", function (e) {
if (e.altKey && e.key === "ArrowDown") { e.preventDefault(); go(1); }
if (e.altKey && e.key === "ArrowUp") { e.preventDefault(); go(-1); }
});
/* ---------- post your make ---------- */
var post = document.getElementById("postMake");
var makes = document.getElementById("makeCount");
if (post) {
post.addEventListener("click", function () {
if (makes) {
var n = parseInt(makes.textContent.replace(/\D/g, ""), 10) + 1;
makes.textContent = n.toLocaleString("en-US");
}
toast("Draft started — add photos and a note about what you changed.", "hi");
});
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>MAKELOG — Build a folding camp stool from one board</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>
<a class="skip" href="#ch-supplies">Skip to the build steps</a>
<header class="topbar">
<div class="wrap topbar-in">
<a class="brand" href="#top" aria-label="MAKELOG home">
<span class="brand-mark" aria-hidden="true">
<svg viewBox="0 0 32 32" width="28" height="28" role="img" aria-hidden="true">
<rect x="1" y="1" width="30" height="30" rx="9" fill="#e8552d"/>
<path d="M8 22V10l5 6 3-4 3 4 5-6v12" fill="none" stroke="#fffdfa" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</span>
<span class="brand-name">MAKELOG</span>
</a>
<nav class="topnav" aria-label="Sections">
<a href="#ch-supplies">Supplies</a>
<a href="#ch-assembly">Assembly</a>
<a href="#made-it">I Made It</a>
</nav>
<button class="btn btn-ghost btn-sm" type="button" data-toast="Saved to your workshop queue.">Save draft</button>
</div>
</header>
<main id="top">
<!-- COVER -->
<section class="cover">
<div class="wrap cover-in">
<div class="cover-copy">
<p class="eyebrow">Woodworking · Weekend build</p>
<h1>Build a folding camp stool from one board</h1>
<p class="lede">Eight chapters, one 1×6 board, and a handful of hardware. Cut, drill, pivot, sand, oil — you end up with a stool that folds flat enough to slide behind a car seat.</p>
<div class="cover-meta">
<div class="author">
<span class="avatar" aria-hidden="true">RH</span>
<span class="author-txt">
<strong>Rin Halvorsen</strong>
<em>42 projects · Trondheim, NO</em>
</span>
<button class="btn btn-follow" id="followBtn" type="button" aria-pressed="false">Follow</button>
</div>
<ul class="stats" aria-label="Project stats">
<li><b class="mono">184,207</b><span>views</span></li>
<li><b class="mono">6,318</b><span>favorites</span></li>
<li><b class="mono" id="makeCount">247</b><span>makes</span></li>
</ul>
</div>
<div class="cover-actions">
<button class="btn btn-primary" id="favBtn" type="button" aria-pressed="false">
<span class="ico" aria-hidden="true">★</span> <span class="lbl">Favorite</span>
</button>
<button class="btn btn-outline" type="button" data-toast="Preparing a 12-page PDF with the cut list…">↓ Download PDF</button>
<button class="btn btn-outline" type="button" data-toast="Link copied to clipboard.">↗ Share</button>
</div>
<ul class="chips" aria-label="Project details">
<li class="chip">Difficulty: Easy</li>
<li class="chip">Time: 3 hours</li>
<li class="chip">Cost: ~ <span class="mono">$18</span></li>
<li class="chip chip-hi">Contest finalist</li>
</ul>
</div>
<figure class="cover-art" aria-label="Illustration of a folded wooden camp stool">
<div class="art art-stool">
<span class="leg l1"></span><span class="leg l2"></span>
<span class="leg l3"></span><span class="leg l4"></span>
<span class="seat"></span>
<span class="pivot p1"></span><span class="pivot p2"></span>
<span class="ground"></span>
</div>
<figcaption>Final piece — ash, hard-wax oil, 430 mm seat height.</figcaption>
</figure>
</div>
</section>
<!-- BODY -->
<div class="wrap layout">
<!-- RAIL -->
<aside class="rail" aria-label="Chapter navigator">
<p class="rail-title">Chapters</p>
<ol class="rail-list" id="railList">
<li><a href="#ch-supplies" data-target="ch-supplies"><span class="n mono">01</span> Supplies</a></li>
<li><a href="#ch-cutlist" data-target="ch-cutlist"><span class="n mono">02</span> Cut list</a></li>
<li><a href="#ch-drilling" data-target="ch-drilling"><span class="n mono">03</span> Drilling</a></li>
<li><a href="#ch-assembly" data-target="ch-assembly"><span class="n mono">04</span> Assembly</a></li>
<li><a href="#ch-sanding" data-target="ch-sanding"><span class="n mono">05</span> Sanding</a></li>
<li><a href="#ch-finish" data-target="ch-finish"><span class="n mono">06</span> Finish</a></li>
<li><a href="#ch-testing" data-target="ch-testing"><span class="n mono">07</span> Testing</a></li>
<li><a href="#ch-final" data-target="ch-final"><span class="n mono">08</span> Final</a></li>
</ol>
<div class="rail-progress">
<div class="bar"><span id="railBar"></span></div>
<p class="mono" id="railPct">0% read</p>
</div>
</aside>
<!-- CHAPTERS -->
<article class="chapters">
<section class="chapter" id="ch-supplies">
<header class="ch-head">
<span class="badge mono">01</span>
<h2>Supplies</h2>
</header>
<p>One 1×6×8′ board is enough for the whole stool with an offcut to spare. Everything else fits in a sandwich bag. Tick things off as you gather them — the counter at the top of the card keeps score.</p>
<div class="card supplies">
<div class="supplies-head">
<h3>Shopping checklist</h3>
<p class="mono" id="suppliesCount">0 / 8 gathered</p>
</div>
<ul class="supply-list" id="supplyList">
<li><label><input type="checkbox" /><span class="qty mono">1×</span><span class="nm">Ash board, 1×6×8′</span><span class="ref mono">BD-146</span></label></li>
<li><label><input type="checkbox" /><span class="qty mono">2×</span><span class="nm">M8 carriage bolt, 90 mm</span><span class="ref mono">HW-M8C</span></label></li>
<li><label><input type="checkbox" /><span class="qty mono">4×</span><span class="nm">M8 nylon-insert lock nut</span><span class="ref mono">HW-M8N</span></label></li>
<li><label><input type="checkbox" /><span class="qty mono">8×</span><span class="nm">Nylon washer, 8 mm ID</span><span class="ref mono">HW-W08</span></label></li>
<li><label><input type="checkbox" /><span class="qty mono">1×</span><span class="nm">Canvas duck, 10 oz — 380×300 mm</span><span class="ref mono">FB-CD10</span></label></li>
<li><label><input type="checkbox" /><span class="qty mono">1×</span><span class="nm">Hard-wax oil, 250 ml</span><span class="ref mono">FN-HWO</span></label></li>
<li><label><input type="checkbox" /><span class="qty mono">1×</span><span class="nm">Abrasive pack — 120 / 180 / 240</span><span class="ref mono">AB-P3</span></label></li>
<li><label><input type="checkbox" /><span class="qty mono">1×</span><span class="nm">Wood glue, 60 ml</span><span class="ref mono">AD-PVA</span></label></li>
</ul>
<div class="tools">
<p class="tools-title">Tools</p>
<ul>
<li>Handsaw or mitre saw</li><li>Drill + 8 mm brad point</li>
<li>Clamps ×2</li><li>Random-orbit sander</li>
<li>Combination square</li><li>13 mm spanner</li>
</ul>
</div>
</div>
<aside class="tip">
<span class="tip-k mono">TIP</span>
<p>Buy the board a day early and stand it indoors overnight. Store-warm ash moves as it dries and a bowed leg ruins the fold.</p>
</aside>
<div class="ch-foot">
<p>Did this step work for you?</p>
<div class="thumbs" role="group" aria-label="Was this step helpful?">
<button type="button" data-vote="up" aria-pressed="false">👍 <span class="c mono">312</span></button>
<button type="button" data-vote="down" aria-pressed="false">👎 <span class="c mono">4</span></button>
</div>
</div>
</section>
<section class="chapter" id="ch-cutlist">
<header class="ch-head"><span class="badge mono">02</span><h2>Cut list</h2></header>
<p>Six pieces, two lengths. Mark them all before you cut anything — a single pass with the square saves you from the classic mistake of trimming a long leg twice.</p>
<figure class="fig">
<div class="art art-cuts" aria-hidden="true">
<span class="board"></span>
<span class="cut c1"></span><span class="cut c2"></span><span class="cut c3"></span>
<span class="cut c4"></span><span class="cut c5"></span>
<span class="dim"></span>
</div>
<figcaption>Layout on the 2440 mm board — five cuts, 40 mm of waste per kerf.</figcaption>
</figure>
<table class="cuts">
<caption class="sr">Cut list</caption>
<thead><tr><th scope="col">Ref</th><th scope="col">Part</th><th scope="col">Qty</th><th scope="col">Length</th></tr></thead>
<tbody>
<tr><td class="mono">A</td><td>Outer leg</td><td class="mono">2</td><td class="mono">560 mm</td></tr>
<tr><td class="mono">B</td><td>Inner leg</td><td class="mono">2</td><td class="mono">520 mm</td></tr>
<tr><td class="mono">C</td><td>Seat rail</td><td class="mono">2</td><td class="mono">340 mm</td></tr>
</tbody>
</table>
<aside class="tip tip-warn">
<span class="tip-k mono">CARE</span>
<p>Cut the inner legs 40 mm shorter than the outer pair. That difference is the entire reason the two frames nest instead of clashing.</p>
</aside>
<div class="ch-foot">
<p>Did this step work for you?</p>
<div class="thumbs" role="group" aria-label="Was this step helpful?">
<button type="button" data-vote="up" aria-pressed="false">👍 <span class="c mono">268</span></button>
<button type="button" data-vote="down" aria-pressed="false">👎 <span class="c mono">9</span></button>
</div>
</div>
</section>
<section class="chapter" id="ch-drilling">
<header class="ch-head"><span class="badge mono">03</span><h2>Drilling</h2></header>
<p>The pivot hole sits exactly at the midpoint of each leg, 38 mm in from the edge. Clamp all four legs together and drill once — identical holes matter more than perfect holes.</p>
<figure class="fig">
<div class="art art-drill" aria-hidden="true">
<span class="plank"></span>
<span class="hole"></span>
<span class="ring"></span>
<span class="axis ax-x"></span><span class="axis ax-y"></span>
<span class="bit"></span>
</div>
<figcaption>Pivot at <span class="mono">280 mm × 38 mm</span> — brad point, backer board underneath.</figcaption>
</figure>
<p>Run the drill at a slow speed and back the bit out twice to clear chips. Ash burnishes quickly and a glazed hole grips the bolt in a way you will notice for years.</p>
<aside class="tip">
<span class="tip-k mono">TIP</span>
<p>Slip a scrap under the stack. Tear-out on the exit face is the only thing that shows once the stool is oiled.</p>
</aside>
<div class="ch-foot">
<p>Did this step work for you?</p>
<div class="thumbs" role="group" aria-label="Was this step helpful?">
<button type="button" data-vote="up" aria-pressed="false">👍 <span class="c mono">241</span></button>
<button type="button" data-vote="down" aria-pressed="false">👎 <span class="c mono">6</span></button>
</div>
</div>
</section>
<section class="chapter" id="ch-assembly">
<header class="ch-head"><span class="badge mono">04</span><h2>Assembly</h2></header>
<p>Stack washer, leg, washer, leg, washer on each bolt, then tighten the lock nut until the frame swings under its own weight and stops where you leave it. That is the whole trick.</p>
<figure class="fig">
<div class="art art-assembly" aria-hidden="true">
<span class="xleg a"></span><span class="xleg b"></span>
<span class="railtop"></span>
<span class="node"></span>
<span class="arrowc"></span>
</div>
<figcaption>Scissor geometry — the X crosses at <span class="mono">52°</span> when open.</figcaption>
</figure>
<ol class="steps">
<li>Dry-fit both frames and open them fully on a flat floor.</li>
<li>Glue and clamp the seat rails to the outer frame only.</li>
<li>Torque the lock nuts to finger-tight plus a quarter turn.</li>
<li>Fold and unfold twenty times, then re-check the nuts.</li>
</ol>
<aside class="tip tip-warn">
<span class="tip-k mono">CARE</span>
<p>Over-tightening crushes the nylon washers and the stool goes from smooth to sticky. Loose beats tight here.</p>
</aside>
<div class="ch-foot">
<p>Did this step work for you?</p>
<div class="thumbs" role="group" aria-label="Was this step helpful?">
<button type="button" data-vote="up" aria-pressed="false">👍 <span class="c mono">394</span></button>
<button type="button" data-vote="down" aria-pressed="false">👎 <span class="c mono">11</span></button>
</div>
</div>
</section>
<section class="chapter" id="ch-sanding">
<header class="ch-head"><span class="badge mono">05</span><h2>Sanding</h2></header>
<p>Three grits, no shortcuts: 120 to flatten the saw marks, 180 to erase the 120, 240 to make the oil sit evenly. Break every edge with a folded sheet — a 1 mm chamfer stops splinters where hands land.</p>
<figure class="fig">
<div class="art art-sand" aria-hidden="true">
<span class="grain g1"></span><span class="grain g2"></span><span class="grain g3"></span>
<span class="pad"></span>
<span class="dust d1"></span><span class="dust d2"></span><span class="dust d3"></span>
</div>
<figcaption>Grit ladder — <span class="mono">120 → 180 → 240</span>, always with the grain.</figcaption>
</figure>
<div class="ch-foot">
<p>Did this step work for you?</p>
<div class="thumbs" role="group" aria-label="Was this step helpful?">
<button type="button" data-vote="up" aria-pressed="false">👍 <span class="c mono">177</span></button>
<button type="button" data-vote="down" aria-pressed="false">👎 <span class="c mono">3</span></button>
</div>
</div>
</section>
<section class="chapter" id="ch-finish">
<header class="ch-head"><span class="badge mono">06</span><h2>Finish</h2></header>
<p>Hard-wax oil, wiped on thin with a lint-free rag and buffed back after ten minutes. Two coats with a light 400-grit rub between them. Thin coats cure; thick coats stay tacky for a week.</p>
<figure class="fig">
<div class="art art-finish" aria-hidden="true">
<span class="panel raw"></span>
<span class="panel oiled"></span>
<span class="split"></span>
<span class="drop"></span>
</div>
<figcaption>Left: bare ash. Right: one coat of hard-wax oil, buffed.</figcaption>
</figure>
<aside class="tip">
<span class="tip-k mono">TIP</span>
<p>Lay oily rags flat outdoors to dry. Bunched up they can self-heat — dispose of them the way the tin tells you.</p>
</aside>
<div class="ch-foot">
<p>Did this step work for you?</p>
<div class="thumbs" role="group" aria-label="Was this step helpful?">
<button type="button" data-vote="up" aria-pressed="false">👍 <span class="c mono">205</span></button>
<button type="button" data-vote="down" aria-pressed="false">👎 <span class="c mono">7</span></button>
</div>
</div>
</section>
<section class="chapter" id="ch-testing">
<header class="ch-head"><span class="badge mono">07</span><h2>Testing</h2></header>
<p>Load it before you trust it. Sit, shift your weight side to side, then stand on the seat rails near the pivots. If anything creaks, it is almost always a rail that did not get enough clamp pressure.</p>
<figure class="fig">
<div class="art art-test" aria-hidden="true">
<span class="weight"></span>
<span class="seatbar"></span>
<span class="legt lt1"></span><span class="legt lt2"></span>
<span class="gauge"></span>
</div>
<figcaption>Static load test — held <span class="mono">140 kg</span> with 3 mm of deflection.</figcaption>
</figure>
<div class="ch-foot">
<p>Did this step work for you?</p>
<div class="thumbs" role="group" aria-label="Was this step helpful?">
<button type="button" data-vote="up" aria-pressed="false">👍 <span class="c mono">158</span></button>
<button type="button" data-vote="down" aria-pressed="false">👎 <span class="c mono">2</span></button>
</div>
</div>
</section>
<section class="chapter" id="ch-final">
<header class="ch-head"><span class="badge mono">08</span><h2>Final</h2></header>
<p>Folded it is 65 mm thick and weighs 1.9 kg. Mine lives behind the passenger seat and has done two seasons of riverbank coffee without a single re-tighten.</p>
<figure class="fig">
<div class="art art-final" aria-hidden="true">
<span class="fold f1"></span><span class="fold f2"></span>
<span class="strap"></span>
<span class="tag"></span>
</div>
<figcaption>Folded profile — <span class="mono">65 mm</span> thick, 1.9 kg.</figcaption>
</figure>
<p>If you build one, change something. Longer legs for a camp kitchen, a webbing seat instead of canvas, a rope handle through the rail. Post it below — variations are the best part of the thread.</p>
<div class="ch-foot">
<p>Did this step work for you?</p>
<div class="thumbs" role="group" aria-label="Was this step helpful?">
<button type="button" data-vote="up" aria-pressed="false">👍 <span class="c mono">421</span></button>
<button type="button" data-vote="down" aria-pressed="false">👎 <span class="c mono">5</span></button>
</div>
</div>
</section>
</article>
</div>
<!-- I MADE IT -->
<section class="madeit" id="made-it">
<div class="wrap">
<header class="madeit-head">
<h2>I Made It!</h2>
<p>247 people built this stool. Here are the most recent nine.</p>
</header>
<ul class="makes">
<li class="make">
<div class="make-art m1" aria-hidden="true"></div>
<div class="make-body">
<span class="maker"><i aria-hidden="true">TA</i> Tomás A.</span>
<p>Swapped ash for reclaimed pallet oak. Heavier, but the colour is unreal.</p>
</div>
</li>
<li class="make">
<div class="make-art m2" aria-hidden="true"></div>
<div class="make-body">
<span class="maker"><i aria-hidden="true">JK</i> June K.</span>
<p>Built two in an afternoon with my daughter. Her cuts were straighter.</p>
</div>
</li>
<li class="make">
<div class="make-art m3" aria-hidden="true"></div>
<div class="make-body">
<span class="maker"><i aria-hidden="true">MR</i> Marek R.</span>
<p>Added a 40 mm webbing seat. Folds even flatter than canvas.</p>
</div>
</li>
<li class="make">
<div class="make-art m4" aria-hidden="true"></div>
<div class="make-body">
<span class="maker"><i aria-hidden="true">SD</i> Sofia D.</span>
<p>Scaled it to 300 mm for the kids' table. Same hardware works.</p>
</div>
</li>
<li class="make">
<div class="make-art m5" aria-hidden="true"></div>
<div class="make-body">
<span class="maker"><i aria-hidden="true">NB</i> Nadia B.</span>
<p>Milk-painted the legs teal before oiling. Held up to a rainy weekend.</p>
</div>
</li>
<li class="make">
<div class="make-art m6" aria-hidden="true"></div>
<div class="make-body">
<span class="maker"><i aria-hidden="true">EO</i> Eli O.</span>
<p>Used brass bolts instead of steel. Purely vanity, zero regrets.</p>
</div>
</li>
<li class="make">
<div class="make-art m7" aria-hidden="true"></div>
<div class="make-body">
<span class="maker"><i aria-hidden="true">HP</i> Hana P.</span>
<p>Third one for the shop. Now the standard gift for new neighbours.</p>
</div>
</li>
<li class="make">
<div class="make-art m8" aria-hidden="true"></div>
<div class="make-body">
<span class="maker"><i aria-hidden="true">CV</i> Chris V.</span>
<p>Drilled the pivot 5 mm high by accident — still folds, sits taller.</p>
</div>
</li>
<li class="make">
<div class="make-art m9" aria-hidden="true"></div>
<div class="make-body">
<span class="maker"><i aria-hidden="true">LW</i> Lian W.</span>
<p>Rope handle through the rail. Carries like a toolbox now.</p>
</div>
</li>
</ul>
<div class="madeit-cta">
<button class="btn btn-primary btn-lg" type="button" id="postMake">+ Post your make</button>
<p>Photos, notes, and mistakes all welcome.</p>
</div>
</div>
</section>
<footer class="foot">
<div class="wrap foot-in">
<p><strong>MAKELOG</strong> — a fictional project-sharing community built as a UI demo.</p>
<p class="mono">Illustrative content only. No real products or brands.</p>
</div>
</footer>
</main>
<!-- STICKY MOBILE BAR -->
<nav class="stickybar" aria-label="Chapter navigation">
<button type="button" id="prevCh" class="sb-btn">← Prev</button>
<span class="sb-now mono" id="sbNow" aria-live="polite">01 · Supplies</span>
<button type="button" id="nextCh" class="sb-btn">Next →</button>
</nav>
<div class="toasts" id="toasts" aria-live="polite" aria-atomic="false"></div>
<script src="script.js"></script>
</body>
</html>Step-by-Step Project Chapters
The page opens on a warm cover band: project title, an author chip with a follow toggle, three counters (views, favorites, makes) and a row of actions — favorite, download PDF, share — that all emit toasts. Beside it sits a purely CSS-drawn illustration of the finished stool, scissor legs, teal pivots and all.
The body is a two-column reading layout. On the left, a sticky chapter rail lists all eight chapters and highlights whichever one is in view; clicking scrolls smoothly and a small progress bar reports how far you have read. Each chapter carries a number badge, a big illustrated figure with a caption, prose, and occasional tip or care callouts. The Supplies chapter is a checklist card with quantities and monospaced part refs that strikes items through and keeps a running “gathered” count.
Every chapter ends with a “Did this step work for you?” thumbs control where the two buttons are mutually exclusive and the counts move with your vote. Further down, an “I Made It!” band shows nine community builds as gradient-illustrated cards with maker chips and captions, plus a big post-your-make button that bumps the make counter. Below 1000px the rail collapses into a horizontal pill scroller and a sticky bottom bar appears with prev/next chapter controls (also bound to Alt+Arrow keys).
How this look is built
The information architecture follows Instructables-style project pages as a stylistic reference —
long chapters, a supplies section, community makes — but the implementation is modern: a CSS grid
shell with position: sticky for the rail and the mobile bar, an IntersectionObserver with an
asymmetric rootMargin and multiple thresholds to pick the dominant chapter instead of the old
scroll + getBoundingClientRect() loop, scroll-padding-top plus scroll-margin-top so anchor
jumps clear the sticky header without JS offsets, and layered radial-gradient plus repeating
linear-gradient grids for the paper texture and every illustration, so the page ships zero images.
The observer approach costs nothing on the main thread and stays correct when chapter heights vary
wildly, which is exactly the failure mode of scroll-position math.
Illustrative UI only — always follow real safety guidance when working with tools, electronics, or repairs.