Xiaomi MiMo V2.6 Flash – Hobbies and Interests

via Io Net · Generated

  • AIMAC Debt 5.03
  • Cost $0.007
  • Total Violations 24
  • HTML Size 77 KB
  • Em Dashes 35

Screenshot

View Xiaomi MiMo V2.6 Flash Hobbies and Interests page View Live Page

Accessibility Issues Found

24 Serious

  • color-contrast serious 24 instances

    Elements must meet minimum color contrast ratio thresholds

    Example HTML <span class="tag">Made by hand · Made together</span>

Artifacts

View Generated HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Craftbound — Skills, Supplies &amp; Community for People Who Make Things by Hand</title>
<meta name="description" content="Craftbound is a maker community and learning platform for woodworking, textiles, ceramics, paper crafts and beyond. Advanced techniques, honest tool reviews, DIY tutorials and live classes.">
<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=Fraunces:opsz,wght@9..144,400;9..144,600;9..144,700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
/* ============================================================
   CRAFTBOUND — Design tokens
   ============================================================ */
:root{
  --ink:#17130F;
  --ink-soft:#4A423A;
  --cream:#FAF4EB;
  --paper:#FFFFFF;
  --sand:#F0E6D8;
  --clay:#C0562B;
  --clay-dark:#9E4320;
  --sage:#65795B;
  --gold:#DDA13A;
  --line:rgba(23,19,15,.12);
  --shadow-sm:0 2px 10px rgba(23,19,15,.06);
  --shadow-md:0 14px 40px -18px rgba(23,19,15,.35);
  --shadow-lg:0 30px 70px -30px rgba(23,19,15,.45);
  --radius:18px;
  --radius-sm:10px;
  --maxw:1200px;
  --ease:cubic-bezier(.22,.61,.36,1);
}
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0;
  font-family:'Inter',system-ui,-apple-system,Segoe UI,sans-serif;
  color:var(--ink);
  background:var(--cream);
  font-size:16.5px;
  line-height:1.7;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
h1,h2,h3,h4{font-family:'Fraunces',Georgia,serif;font-weight:600;line-height:1.08;margin:0 0 .5em;letter-spacing:-.015em}
h1{font-size:clamp(2.6rem,6vw,4.4rem)}
h2{font-size:clamp(2rem,4vw,3rem)}
h3{font-size:clamp(1.25rem,2vw,1.6rem);line-height:1.2}
h4{font-size:1.05rem;line-height:1.3}
p{margin:0 0 1.1em;color:var(--ink-soft)}
.container{width:100%;max-width:var(--maxw);margin:0 auto;padding:0 24px}
section{padding:96px 0;position:relative}
.alt{background:var(--sand)}
.dark{background:var(--ink);color:#EDE4D8}
.dark p{color:#B9AE9F}
.dark h2,.dark h3,.dark h4{color:#FBF6EE}

/* ---------- helpers ---------- */
.eyebrow{
  display:inline-flex;align-items:center;gap:10px;
  font-size:.75rem;font-weight:700;letter-spacing:.22em;text-transform:uppercase;
  color:var(--clay);margin-bottom:18px;
}
.eyebrow::before{content:"";width:34px;height:2px;background:var(--clay);display:block}
.dark .eyebrow{color:var(--gold)}
.dark .eyebrow::before{background:var(--gold)}
.lead{font-size:1.15rem;color:var(--ink-soft);max-width:62ch}
.section-head{max-width:760px;margin-bottom:52px}
.section-head.center{margin-left:auto;margin-right:auto;text-align:center}
.section-head.center .eyebrow{justify-content:center}
.grid{display:grid;gap:26px}
.g2{grid-template-columns:repeat(2,1fr)}
.g3{grid-template-columns:repeat(3,1fr)}
.g4{grid-template-columns:repeat(4,1fr)}
.badge{
  display:inline-block;font-size:.7rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  padding:5px 11px;border-radius:99px;background:rgba(192,86,43,.1);color:var(--clay-dark);
}
.badge.sage{background:rgba(101,121,91,.14);color:#4B5B44}
.badge.gold{background:rgba(221,161,58,.18);color:#8A6413}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:9px;
  font-family:'Inter',sans-serif;font-size:.94rem;font-weight:600;letter-spacing:.01em;
  padding:14px 26px;border-radius:99px;border:1.5px solid transparent;cursor:pointer;
  transition:.28s var(--ease);white-space:nowrap;
}
.btn-primary{background:var(--ink);color:var(--cream)}
.btn-primary:hover{background:var(--clay);transform:translateY(-2px);box-shadow:var(--shadow-md)}
.btn-clay{background:var(--clay);color:#fff}
.btn-clay:hover{background:var(--clay-dark);transform:translateY(-2px);box-shadow:var(--shadow-md)}
.btn-ghost{background:transparent;color:var(--ink);border-color:rgba(23,19,15,.28)}
.btn-ghost:hover{background:var(--ink);color:var(--cream);border-color:var(--ink)}
.dark .btn-ghost{color:#EDE4D8;border-color:rgba(237,228,216,.35)}
.dark .btn-ghost:hover{background:var(--cream);color:var(--ink)}
.btn-sm{padding:10px 18px;font-size:.85rem}
.link-arrow{
  font-weight:600;font-size:.93rem;color:var(--clay-dark);display:inline-flex;gap:8px;align-items:center;
  border-bottom:1.5px solid rgba(192,86,43,.35);padding-bottom:2px;transition:.25s;
}
.link-arrow:hover{gap:14px;border-color:var(--clay)}

/* ---------- announcement ---------- */
.announce{
  background:var(--ink);color:#E6DBCC;font-size:.83rem;text-align:center;padding:9px 16px;letter-spacing:.02em;
}
.announce a{color:var(--gold);font-weight:600;border-bottom:1px solid rgba(221,161,58,.5)}

/* ---------- header ---------- */
header.site{
  position:sticky;top:0;z-index:60;background:rgba(250,244,235,.92);
  backdrop-filter:blur(14px);border-bottom:1px solid transparent;transition:.3s var(--ease);
}
header.site.stuck{border-bottom-color:var(--line);box-shadow:0 6px 26px -18px rgba(23,19,15,.6)}
.header-inner{display:flex;align-items:center;gap:26px;padding:14px 0;min-height:86px}
.brand{display:flex;align-items:center;gap:13px;flex-shrink:0}
.brand img{width:52px;height:52px;border-radius:14px;box-shadow:var(--shadow-sm)}
.brand .name{font-family:'Fraunces',serif;font-size:1.42rem;font-weight:700;letter-spacing:-.02em;line-height:1}
.brand .tag{font-size:.7rem;letter-spacing:.16em;text-transform:uppercase;color:var(--clay);font-weight:600;margin-top:5px}
nav.primary{margin-left:auto;display:flex;align-items:center;gap:4px}
nav.primary a{
  font-size:.9rem;font-weight:500;padding:9px 14px;border-radius:99px;position:relative;transition:.22s;
}
nav.primary a:hover{background:rgba(23,19,15,.06);color:var(--clay-dark)}
nav.primary a.nav-cta{background:var(--clay);color:#fff;font-weight:600;padding:11px 20px;margin-left:8px}
nav.primary a.nav-cta:hover{background:var(--clay-dark);color:#fff}
.header-actions{display:flex;align-items:center;gap:10px}
.burger{display:none;width:46px;height:46px;border:1.5px solid var(--line);background:transparent;border-radius:12px;cursor:pointer;padding:12px 11px}
.burger span{display:block;height:2px;background:var(--ink);margin:4px 0;transition:.3s var(--ease);border-radius:2px}
.burger.open span:nth-child(1){transform:translateY(6px) rotate(45deg)}
.burger.open span:nth-child(2){opacity:0}
.burger.open span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}
.mobile-nav{display:none;border-top:1px solid var(--line);background:var(--cream);padding:14px 24px 26px}
.mobile-nav.open{display:block}
.mobile-nav a{display:block;padding:13px 4px;font-weight:500;border-bottom:1px dashed var(--line)}
.mobile-nav .btn{width:100%;margin-top:18px}

/* ---------- hero ---------- */
.hero{padding:80px 0 76px;overflow:hidden;position:relative}
.hero::after{
  content:"";position:absolute;right:-180px;top:-140px;width:520px;height:520px;border-radius:50%;
  background:radial-gradient(circle at 30% 30%,rgba(221,161,58,.28),rgba(221,161,58,0) 65%);z-index:-1;
}
.hero-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:60px;align-items:center}
.hero h1 span.hl{color:var(--clay);font-style:italic;font-weight:400}
.hero .lead{font-size:1.2rem;max-width:52ch}
.hero-cta{display:flex;flex-wrap:wrap;gap:14px;margin-top:32px}
.hero-meta{display:flex;align-items:center;gap:16px;margin-top:34px;font-size:.86rem;color:var(--ink-soft)}
.faces{display:flex}
.faces img{width:42px;height:42px;border-radius:50%;border:3px solid var(--cream);margin-left:-14px;object-fit:cover}
.faces img:first-child{margin-left:0}
.hero-visual{position:relative}
.hero-visual .main{
  border-radius:26px;box-shadow:var(--shadow-lg);aspect-ratio:4/4.4;object-fit:cover;width:100%;
}
.hero-card{
  position:absolute;left:-34px;bottom:34px;background:var(--paper);border-radius:16px;padding:16px 20px;
  box-shadow:var(--shadow-md);display:flex;gap:14px;align-items:center;max-width:290px;
}
.hero-card .ico{width:44px;height:44px;border-radius:12px;background:rgba(101,121,91,.16);display:grid;place-items:center;font-size:1.3rem;flex-shrink:0}
.hero-card strong{display:block;font-size:.95rem}
.hero-card span{font-size:.78rem;color:var(--ink-soft)}
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-top:64px;border-top:1px solid var(--line);padding-top:34px}
.stat b{font-family:'Fraunces',serif;font-size:2.1rem;display:block;line-height:1;color:var(--ink)}
.stat span{font-size:.8rem;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-soft)}

/* ---------- marquee ---------- */
.marquee{background:var(--ink);color:#E6DBCC;padding:16px 0;overflow:hidden;white-space:nowrap}
.marquee-track{display:inline-block;animation:slide 34s linear infinite;font-family:'Fraunces',serif;font-size:1.15rem;letter-spacing:.02em}
.marquee-track span{margin:0 8px;color:var(--gold)}
@keyframes slide{from{transform:translateX(0)}to{transform:translateX(-50%)}}

/* ---------- feature cards ---------- */
.feature{
  background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);padding:30px 26px;
  transition:.3s var(--ease);position:relative;overflow:hidden;
}
.feature:hover{transform:translateY(-6px);box-shadow:var(--shadow-md);border-color:transparent}
.feature .num{font-family:'Fraunces',serif;font-size:.95rem;color:var(--clay);letter-spacing:.1em}
.feature h3{margin-top:14px}
.feature p{margin-bottom:0;font-size:.95rem}
.feature .bar{position:absolute;left:0;top:0;height:4px;width:0;background:var(--clay);transition:.45s var(--ease)}
.feature:hover .bar{width:100%}

/* ---------- split section ---------- */
.split{display:grid;grid-template-columns:1fr 1fr;gap:64px;align-items:center}
.split.rev .split-media{order:2}
.split-media{position:relative}
.split-media img{border-radius:22px;box-shadow:var(--shadow-md);width:100%;aspect-ratio:5/4;object-fit:cover}
.split-media .float{
  position:absolute;right:-22px;bottom:-26px;background:var(--paper);border-radius:16px;padding:14px 18px;
  box-shadow:var(--shadow-md);font-size:.85rem;max-width:230px;border-left:4px solid var(--gold);
}
.split-media .float b{display:block;font-family:'Fraunces',serif;font-size:1.5rem;color:var(--ink)}
.checklist{list-style:none;padding:0;margin:0 0 26px}
.checklist li{position:relative;padding-left:34px;margin-bottom:14px;color:var(--ink-soft)}
.checklist li::before{
  content:"";position:absolute;left:0;top:8px;width:20px;height:20px;border-radius:50%;
  background:rgba(101,121,91,.18);
}
.checklist li::after{
  content:"";position:absolute;left:6px;top:13px;width:8px;height:5px;border-left:2px solid var(--sage);
  border-bottom:2px solid var(--sage);transform:rotate(-45deg);
}
.checklist strong{color:var(--ink)}

/* ---------- tool reviews + sidebar ---------- */
.review-layout{display:grid;grid-template-columns:1.9fr 1fr;gap:34px;align-items:start}
.tool-card{
  background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);padding:24px;
  display:grid;grid-template-columns:120px 1fr;gap:22px;margin-bottom:20px;transition:.3s var(--ease);
}
.tool-card:hover{box-shadow:var(--shadow-md);transform:translateX(4px)}
.tool-card img{border-radius:12px;aspect-ratio:1;object-fit:cover;width:120px}
.tool-top{display:flex;justify-content:space-between;gap:16px;align-items:flex-start}
.score{font-family:'Fraunces',serif;font-size:2rem;line-height:1;color:var(--clay);text-align:right}
.score small{display:block;font-family:'Inter';font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-soft);margin-top:5px}
.meter{height:7px;background:rgba(23,19,15,.1);border-radius:99px;overflow:hidden;margin:12px 0 14px}
.meter i{display:block;height:100%;background:linear-gradient(90deg,var(--gold),var(--clay));border-radius:99px}
.verdict{display:flex;gap:8px;flex-wrap:wrap;font-size:.78rem;margin-bottom:12px}
.verdict span{background:rgba(23,19,15,.06);padding:4px 10px;border-radius:6px;color:var(--ink-soft)}
.sidebar{position:sticky;top:110px;display:flex;flex-direction:column;gap:22px}
.panel{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);padding:26px}
.panel h4{font-family:'Fraunces',serif;font-size:1.2rem;margin-bottom:16px}
.panel.dark-panel{background:var(--ink);color:#E6DBCC;border-color:transparent}
.panel.dark-panel h4{color:#FBF6EE}
.panel.dark-panel li{border-color:rgba(230,219,204,.18)}
.panel ul{list-style:none;margin:0;padding:0}
.panel li{display:flex;gap:13px;padding:12px 0;border-bottom:1px dashed var(--line);font-size:.9rem;align-items:center}
.panel li:last-child{border-bottom:0}
.panel li img{width:46px;height:46px;border-radius:9px;object-fit:cover}
.panel li b{display:block;font-size:.92rem}
.panel li span{font-size:.76rem;color:var(--ink-soft)}
.panel.dark-panel li span{color:#A99C8C}
.rank{font-family:'Fraunces',serif;font-size:1.3rem;color:var(--clay);width:24px}
.deal{background:rgba(221,161,58,.15);border:1px dashed var(--gold);border-radius:12px;padding:14px 16px;margin-bottom:12px;font-size:.88rem}
.deal b{color:var(--clay-dark)}
.deal .code{font-family:ui-monospace,monospace;background:var(--paper);border:1px solid var(--line);padding:2px 8px;border-radius:5px;font-size:.8rem}

/* ---------- tutorials tabs ---------- */
.tabs{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:34px}
.tab{
  border:1.5px solid rgba(23,19,15,.18);background:transparent;padding:11px 20px;border-radius:99px;
  font-family:'Inter';font-size:.88rem;font-weight:600;cursor:pointer;transition:.25s var(--ease);color:var(--ink-soft);
}
.tab:hover{border-color:var(--clay);color:var(--clay-dark)}
.tab.active{background:var(--ink);color:var(--cream);border-color:var(--ink)}
.tab-panel{display:none;animation:fade .5s var(--ease)}
.tab-panel.active{display:grid;grid-template-columns:1fr 1.1fr;gap:48px;align-items:center}
@keyframes fade{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
.steps{list-style:none;counter-reset:s;padding:0;margin:24px 0 30px}
.steps li{
  counter-increment:s;position:relative;padding:0 0 20px 56px;border-left:2px dotted rgba(23,19,15,.2);
  margin-left:14px;
}
.steps li:last-child{border-left-color:transparent;padding-bottom:0}
.steps li::before{
  content:counter(s);position:absolute;left:-17px;top:-3px;width:34px;height:34px;border-radius:50%;
  background:var(--paper);border:2px solid var(--clay);color:var(--clay);display:grid;place-items:center;
  font-family:'Fraunces',serif;font-weight:700;font-size:.9rem;
}
.steps li b{display:block;font-family:'Fraunces',serif;font-size:1.08rem;margin-bottom:3px;color:var(--ink)}
.steps li p{margin:0;font-size:.93rem}
.tab-media img{border-radius:22px;box-shadow:var(--shadow-md);aspect-ratio:4/3.2;object-fit:cover;width:100%}
.difficulty{display:flex;gap:16px;flex-wrap:wrap;font-size:.82rem;color:var(--ink-soft);margin-bottom:6px}
.difficulty b{color:var(--ink)}

/* ---------- gallery ---------- */
.filters{display:flex;flex-wrap:wrap;gap:10px;justify-content:center;margin-bottom:36px}
.filter{
  border:1.5px solid rgba(237,228,216,.28);background:transparent;color:#CFC3B4;padding:10px 20px;
  border-radius:99px;font-family:'Inter';font-size:.85rem;font-weight:600;cursor:pointer;transition:.25s var(--ease);
}
.filter:hover{border-color:var(--gold);color:var(--gold)}
.filter.active{background:var(--gold);border-color:var(--gold);color:var(--ink)}
.gallery{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
.g-item{
  position:relative;border-radius:16px;overflow:hidden;cursor:pointer;background:#241E19;
  transition:.4s var(--ease);border:1px solid rgba(237,228,216,.12);
}
.g-item img{aspect-ratio:1;object-fit:cover;width:100%;transition:.55s var(--ease);opacity:.92}
.g-item:hover{transform:translateY(-6px);box-shadow:var(--shadow-lg)}
.g-item:hover img{transform:scale(1.07);opacity:1}
.g-cap{
  position:absolute;left:0;right:0;bottom:0;padding:34px 16px 15px;
  background:linear-gradient(to top,rgba(12,9,7,.94),rgba(12,9,7,0));
  transform:translateY(6px);opacity:.94;transition:.35s var(--ease);
}
.g-item:hover .g-cap{transform:none;opacity:1}
.g-cap b{display:block;font-family:'Fraunces',serif;font-size:1.02rem;color:#FBF6EE}
.g-cap span{font-size:.75rem;color:var(--gold);letter-spacing:.1em;text-transform:uppercase}
.g-item.hide{display:none}

/* modal */
.modal{
  position:fixed;inset:0;background:rgba(10,8,6,.86);backdrop-filter:blur(6px);z-index:200;
  display:none;place-items:center;padding:24px;
}
.modal.open{display:grid;animation:fade .3s ease}
.modal-inner{
  background:var(--cream);border-radius:22px;max-width:840px;width:100%;overflow:hidden;
  display:grid;grid-template-columns:1.15fr .85fr;box-shadow:var(--shadow-lg);max-height:90vh;
}
.modal-inner img{width:100%;height:100%;object-fit:cover;min-height:280px}
.modal-body{padding:34px 30px;overflow:auto}
.modal-body h3{margin-bottom:8px}
.modal-close{
  position:absolute;top:22px;right:26px;width:46px;height:46px;border-radius:50%;border:none;
  background:var(--cream);color:var(--ink);font-size:1.3rem;cursor:pointer;transition:.25s;
}
.modal-close:hover{background:var(--clay);color:#fff;transform:rotate(90deg)}
.m-meta{display:flex;gap:10px;flex-wrap:wrap;margin-top:16px}
.m-meta span{background:rgba(23,19,15,.07);padding:5px 12px;border-radius:99px;font-size:.78rem}

/* ---------- classes ---------- */
.class-card{
  background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;
  display:flex;flex-direction:column;transition:.3s var(--ease);
}
.class-card:hover{transform:translateY(-7px);box-shadow:var(--shadow-md)}
.class-card .thumb{position:relative;overflow:hidden}
.class-card .thumb img{aspect-ratio:16/10;object-fit:cover;width:100%;transition:.5s var(--ease)}
.class-card:hover .thumb img{transform:scale(1.06)}
.class-card .thumb .badge{position:absolute;top:14px;left:14px;background:var(--paper)}
.class-body{padding:22px 22px 24px;display:flex;flex-direction:column;flex:1}
.class-body h3{font-size:1.24rem}
.class-body p{font-size:.9rem;flex:1}
.class-foot{display:flex;justify-content:space-between;align-items:center;border-top:1px dashed var(--line);padding-top:16px;margin-top:6px}
.class-foot .who{display:flex;align-items:center;gap:9px;font-size:.8rem;color:var(--ink-soft)}
.class-foot .who img{width:32px;height:32px;border-radius:50%}
.price{font-family:'Fraunces',serif;font-size:1.35rem;color:var(--clay)}

/* ---------- testimonials ---------- */
.quote-card{
  background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);padding:30px 28px;
  display:flex;flex-direction:column;gap:16px;position:relative;
}
.quote-card::before{
  content:"“";font-family:'Fraunces',serif;font-size:4.5rem;line-height:.6;color:rgba(192,86,43,.22);
  position:absolute;top:24px;right:24px;
}
.quote-card p{font-size:1rem;color:var(--ink);margin:0;position:relative;z-index:1}
.who-row{display:flex;align-items:center;gap:13px;margin-top:auto;padding-top:8px}
.who-row img{width:48px;height:48px;border-radius:50%;object-fit:cover}
.who-row b{display:block;font-size:.95rem}
.who-row span{font-size:.78rem;color:var(--ink-soft)}
.stars{color:var(--gold);letter-spacing:3px;font-size:.9rem}

/* ---------- faq ---------- */
.faq{max-width:840px;margin:0 auto}
details{
  background:var(--paper);border:1px solid var(--line);border-radius:14px;margin-bottom:14px;overflow:hidden;
  transition:.3s var(--ease);
}
details[open]{box-shadow:var(--shadow-sm);border-color:rgba(192,86,43,.4)}
summary{
  list-style:none;cursor:pointer;padding:20px 58px 20px 24px;font-family:'Fraunces',serif;
  font-size:1.08rem;font-weight:600;position:relative;
}
summary::-webkit-details-marker{display:none}
summary::after{
  content:"+";position:absolute;right:22px;top:50%;transform:translateY(-50%);width:28px;height:28px;
  border-radius:50%;background:rgba(192,86,43,.12);color:var(--clay);display:grid;place-items:center;
  font-family:'Inter';font-size:1.1rem;transition:.3s var(--ease);
}
details[open] summary::after{content:"–";background:var(--clay);color:#fff;transform:translateY(-50%) rotate(180deg)}
details .answer{padding:0 60px 24px 24px}
details .answer p{margin:0;font-size:.96rem}

/* ---------- newsletter ---------- */
.news{
  background:linear-gradient(135deg,#1E1813,#2A211A);border-radius:26px;padding:56px 48px;
  display:grid;grid-template-columns:1.1fr .9fr;gap:44px;align-items:center;color:#EDE4D8;position:relative;overflow:hidden;
}
.news::before{
  content:"";position:absolute;width:340px;height:340px;right:-90px;top:-120px;border-radius:50%;
  background:radial-gradient(circle,rgba(221,161,58,.3),transparent 65%);
}
.news h2{color:#FBF6EE;position:relative}
.news p{color:#B9AE9F;position:relative}
.news form{display:flex;gap:10px;position:relative;flex-wrap:wrap}
.news input{
  flex:1;min-width:220px;padding:15px 20px;border-radius:99px;border:1.5px solid rgba(237,228,216,.25);
  background:rgba(255,255,255,.06);color:#F5EDE1;font-family:'Inter';font-size:.95rem;
}
.news input::placeholder{color:#8E8375}
.news input:focus{outline:none;border-color:var(--gold)}
.news .note{font-size:.78rem;color:#8E8375;margin-top:12px}
.form-msg{font-size:.9rem;color:var(--gold);margin-top:12px;display:none;position:relative}
.form-msg.show{display:block}

/* ---------- footer ---------- */
footer.site{background:var(--ink);color:#B9AE9F;padding:74px 0 30px;font-size:.92rem}
.foot-grid{display:grid;grid-template-columns:1.5fr 1fr 1fr 1.2fr;gap:40px;padding-bottom:44px;border-bottom:1px solid rgba(237,228,216,.14)}
footer .brand .name{color:#FBF6EE}
footer .brand img{width:48px;height:48px}
footer h5{
  font-family:'Fraunces',serif;color:#FBF6EE;font-size:1rem;margin:0 0 18px;letter-spacing:.01em;
}
footer ul{list-style:none;padding:0;margin:0}
footer li{margin-bottom:11px}
footer a{transition:.22s;color:#B9AE9F}
footer a:hover{color:var(--gold);padding-left:4px}
.socials{display:flex;gap:10px;margin-top:20px}
.socials a{
  width:42px;height:42px;border-radius:12px;border:1px solid rgba(237,228,216,.2);display:grid;place-items:center;
  font-size:.72rem;font-weight:700;letter-spacing:.05em;transition:.25s var(--ease);
}
.socials a:hover{background:var(--gold);color:var(--ink);border-color:var(--gold);padding-left:0;transform:translateY(-3px)}
.contact-line{display:flex;gap:10px;margin-bottom:12px}
.contact-line b{color:#EDE4D8;font-weight:600}
.foot-bottom{display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;padding-top:26px;font-size:.83rem}
.foot-bottom ul{display:flex;gap:22px;flex-wrap:wrap}

/* ---------- reveal ---------- */
.reveal{opacity:0;transform:translateY(26px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
.reveal.in{opacity:1;transform:none}

/* ============================================================
   Responsive
   ============================================================ */
@media(max-width:1080px){
  nav.primary{display:none}
  .burger{display:block}
  .header-actions .btn{display:none}
  .hero-grid{gap:40px}
  .g4{grid-template-columns:repeat(2,1fr)}
  .gallery{grid-template-columns:repeat(3,1fr)}
  .review-layout{grid-template-columns:1fr}
  .sidebar{position:static;flex-direction:row;flex-wrap:wrap}
  .sidebar .panel{flex:1;min-width:270px}
}
@media(max-width:900px){
  section{padding:74px 0}
  .hero-grid,.split,.tab-panel.active,.news,.modal-inner{grid-template-columns:1fr}
  .split.rev .split-media{order:0}
  .split-media .float{right:14px}
  .g3{grid-template-columns:repeat(2,1fr)}
  .stats{grid-template-columns:repeat(2,1fr);gap:26px}
  .hero-visual .main{aspect-ratio:4/3.4}
  .hero-card{left:14px;bottom:14px}
  .modal-inner img{max-height:280px}
  .modal-body{max-height:50vh}
}
@media(max-width:640px){
  .g2,.g3,.g4{grid-template-columns:1fr}
  .gallery{grid-template-columns:repeat(2,1fr)}
  .tool-card{grid-template-columns:1fr}
  .tool-card img{width:100%;aspect-ratio:16/9}
  .news{padding:38px 26px}
  .foot-grid{grid-template-columns:1fr;gap:32px}
  .hero-meta{flex-wrap:wrap}
  .section-head{margin-bottom:38px}
  .brand .tag{display:none}
}
</style>
</head>
<body>

<!-- ===================== ANNOUNCEMENT ===================== -->
<div class="announce">
  Spring Workshop Series is open — 12 live classes, small cohorts, all materials shipped. <a href="#classes">See the schedule →</a>
</div>

<!-- ===================== HEADER ===================== -->
<header class="site" id="top">
  <div class="container header-inner">
    <a class="brand" href="#top" aria-label="Craftbound home">
      <img src="https://placehold.co/104x104/17130F/DDA13A?text=CB&font=playfair%20display" alt="Craftbound logo mark">
      <span>
        <span class="name">Craftbound</span>
        <span class="tag">Made by hand · Made together</span>
      </span>
    </a>

    <nav class="primary" aria-label="Primary">
      <a href="#top">Home</a>
      <a href="#techniques">Techniques</a>
      <a href="#tutorials">Tutorials</a>
      <a href="#tools">Tool Reviews</a>
      <a href="#classes">Classes</a>
      <a href="#shop">Shop</a>
      <a href="#blog">Blog</a>
      <a href="#community" class="nav-cta">Community</a>
    </nav>

    <div class="header-actions">
      <a href="#newsletter" class="btn btn-ghost btn-sm">Join free</a>
      <button class="burger" id="burger" aria-label="Toggle navigation" aria-expanded="false">
        <span></span><span></span><span></span>
      </button>
    </div>
  </div>

  <div class="mobile-nav" id="mobileNav">
    <a href="#top">Home</a>
    <a href="#techniques">Advanced Techniques</a>
    <a href="#tutorials">DIY Tutorials</a>
    <a href="#tools">Tool Reviews</a>
    <a href="#classes">Classes</a>
    <a href="#shop">Shop</a>
    <a href="#blog">Blog</a>
    <a href="#community">Community Gallery</a>
    <a href="#faq">FAQ</a>
    <a href="#newsletter" class="btn btn-clay">Join the collective</a>
  </div>
</header>

<!-- ===================== HERO ===================== -->
<section class="hero">
  <div class="container">
    <div class="hero-grid">
      <div class="reveal">
        <span class="eyebrow">Hobbies, crafts &amp; DIY since 2016</span>
        <h1>Make something<br><span class="hl">worth keeping.</span></h1>
        <p class="lead">Craftbound is where curious hands become capable makers. We publish advanced technique breakdowns, brutally honest tool reviews, and step-by-step DIY tutorials — then connect you to a community that will actually look at your work and tell you the truth.</p>

        <div class="hero-cta">
          <a href="#tutorials" class="btn btn-clay">Start a project →</a>
          <a href="#community" class="btn btn-ghost">Browse the gallery</a>
        </div>

        <div class="hero-meta">
          <div class="faces">
            <img src="https://i.pravatar.cc/96?u=maker-amelie" alt="Member portrait">
            <img src="https://i.pravatar.cc/96?u=maker-joel" alt="Member portrait">
            <img src="https://i.pravatar.cc/96?u=maker-priya" alt="Member portrait">
            <img src="https://i.pravatar.cc/96?u=maker-tomas" alt="Member portrait">
          </div>
          <span><strong>38,400+ makers</strong> sharing work in 42 countries — no algorithm, no ads, just critique circles.</span>
        </div>
      </div>

      <div class="hero-visual reveal">
        <img class="main" src="https://picsum.photos/760/840" alt="A maker's workbench with hand tools, wood shavings and a work in progress">
        <div class="hero-card">
          <div class="ico">🪵</div>
          <div>
            <strong>Project of the Week</strong>
            <span>Steam-bent walnut magazine rack · 6 hrs · beginner+ </span>
          </div>
        </div>
      </div>
    </div>

    <div class="stats reveal">
      <div class="stat"><b>240+</b><span>Video lessons</span></div>
      <div class="stat"><b>1,180</b><span>Tools reviewed</span></div>
      <div class="stat"><b>640</b><span>Free patterns</span></div>
      <div class="stat"><b>96%</b><span>Finish project one</span></div>
    </div>
  </div>
</section>

<!-- ===================== MARQUEE ===================== -->
<div class="marquee" aria-hidden="true">
  <div class="marquee-track">
    Woodworking <span>✦</span> Hand Lettering <span>✦</span> Wheel-Thrown Ceramics <span>✦</span> Sashiko &amp; Embroidery <span>✦</span> Leathercraft <span>✦</span> Miniature Painting <span>✦</span> Bookbinding <span>✦</span> Rigid Heddle Weaving <span>✦</span> Whittling <span>✦</span> Luthiery <span>✦</span> Paper Marbling <span>✦</span>
    Woodworking <span>✦</span> Hand Lettering <span>✦</span> Wheel-Thrown Ceramics <span>✦</span> Sashiko &amp; Embroidery <span>✦</span> Leathercraft <span>✦</span> Miniature Painting <span>✦</span> Bookbinding <span>✦</span> Rigid Heddle Weaving <span>✦</span> Whittling <span>✦</span> Luthiery <span>✦</span> Paper Marbling <span>✦</span>
  </div>
</div>

<!-- ===================== FEATURE GRID ===================== -->
<section id="about">
  <div class="container">
    <div class="section-head center reveal">
      <span class="eyebrow">What you get</span>
      <h2>A workshop, a library and a critique circle — in one tab</h2>
      <p class="lead" style="margin-inline:auto">Most hobby content stops at "look what I made." Craftbound goes one step further: we explain <em>why</em> the joint failed, which blade dulls first, and how the pattern was drafted. Everything here is written and filmed by working makers who sell what they build.</p>
    </div>

    <div class="grid g4">
      <article class="feature reveal">
        <span class="bar"></span>
        <span class="num">01 / Curriculum</span>
        <h3>Structured skill paths</h3>
        <p>Twelve guided tracks from first cut to commissioned work — each with prerequisites, tool lists, and a checkpoint project you submit for feedback from a mentor maker.</p>
      </article>
      <article class="feature reveal">
        <span class="bar"></span>
        <span class="num">02 / Testing</span>
        <h3>Honest tool reviews</h3>
        <p>Every review unit is bought or returned — never gifted. We run 90-day wear tests, measure runout with dial indicators, and publish the failures alongside the wins.</p>
      </article>
      <article class="feature reveal">
        <span class="bar"></span>
        <span class="num">03 / Patterns</span>
        <h3>The pattern vault</h3>
        <p>640 downloadable templates: full-scale woodworking plans, embroidery transfers, sewing blocks and print-ready sticker sheets. Print at home or send to a CNC.</p>
      </article>
      <article class="feature reveal">
        <span class="bar"></span>
        <span class="num">04 / Community</span>
        <h3>Critique circles</h3>
        <p>Six-person groups that meet twice monthly. Post your work in progress, get structured notes on grain direction, tension and finish, and return the favour.</p>
      </article>
    </div>
  </div>
</section>

<!-- ===================== ADVANCED TECHNIQUES ===================== -->
<section id="techniques" class="alt">
  <div class="container">
    <div class="split">
      <div class="split-media reveal">
        <img src="https://picsum.photos/820/660" alt="Close-up of a hand plane taking a gossamer shaving from a board">
        <div class="float">
          <b>0.02 mm</b>
          Tolerance we hold on the shooting board before calling a mitre "done."
        </div>
      </div>

      <div class="reveal">
        <span class="eyebrow">Advanced techniques</span>
        <h2>Move past square boxes and straight seams</h2>
        <p>You've built the cutting board. You've hemmed the napkins. The next level isn't more projects — it's control. Our advanced series breaks down the small, unglamorous decisions that separate work you give away from work people ask you to sell.</p>

        <ul class="checklist">
          <li><strong>Grain reading &amp; cut geometry.</strong> Orienting a board so the growth rings work with the joint, reading figure before you rip, and choosing bevel direction for a mitre that closes itself.</li>
          <li><strong>Finishing schedules.</strong> Grain-raising sequences, cut-in coats vs. build coats, scuff-sand intervals, and how to fix a blush bloom without stripping the piece back to bare stock.</li>
          <li><strong>Jig-making &amp; fixtures.</strong> Build the jig once, use it for a decade. Sled registration, stop-block repeatability, and sacrificial fences you can replace in four minutes.</li>
          <li><strong>Textile tension control.</strong> Matching thread weight to fabric hand, needle-to-fibre pairing, and the blocking discipline that keeps a hand-blocked shape true after washing.</li>
        </ul>

        <div class="hero-cta" style="margin-top:6px">
          <a href="#tutorials" class="btn btn-primary">▶ Watch video series</a>
          <a href="#blog" class="btn btn-ghost">Download the technique guide</a>
        </div>
      </div>
    </div>

    <div class="split rev" style="margin-top:96px">
      <div class="split-media reveal">
        <img src="https://picsum.photos/820/660" alt="A workbench with layout lines, marking gauge and dovetail saw">
        <div class="float" style="border-left-color:var(--clay)">
          <b>11 lessons</b>
          Dovetails from layout to paring — including the recovery chapter nobody films.
        </div>
      </div>

      <div class="reveal">
        <span class="eyebrow">Deep dives</span>
        <h2>The parts of the craft that are hard to Google</h2>
        <p>Some skills don't compress into a listicle. Our deep dives run 40–90 minutes of edited footage plus a printable spec sheet, because half of what matters happens in the judgement calls: when the chisel is sharp enough, when the clay has had enough wedging, when the sizing has set.</p>
        <p>Each deep dive includes a "failure library" — real, unedited footage of the technique going wrong, with a voiceover explaining exactly which variable drifted. Members tell us this is the section they return to most, because seeing a blown mitre diagnosed is worth more than watching a perfect one get made.</p>
        <div class="hero-cta" style="margin-top:6px">
          <a href="#classes" class="btn btn-clay">Enrol in a deep dive</a>
          <a href="#community" class="btn btn-ghost">Share project</a>
        </div>
      </div>
    </div>
  </div>
</section>

<!-- ===================== TOOL REVIEWS + SIDEBAR ===================== -->
<section id="tools">
  <div class="container">
    <div class="section-head reveal">
      <span class="eyebrow">Tool reviews</span>
      <h2>Tested on a real bench, not a press bench</h2>
      <p class="lead">We buy our own tools, run them for 90 days in a working studio, and publish the scores along with the wear photos. No affiliate-shaped conclusions, no "sponsored but honest" disclaimers.</p>
    </div>

    <div class="review-layout">
      <!-- main column -->
      <div>
        <article class="tool-card reveal">
          <img src="https://picsum.photos/300/300" alt="Block plane on a workbench">
          <div>
            <div class="tool-top">
              <div>
                <span class="badge sage">Hand tools</span>
                <h3 style="margin:10px 0 4px">Meridian 60½ Low-Angle Block Plane</h3>
              </div>
              <div class="score">9.4<small>Verdict</small></div>
            </div>
            <div class="meter"><i style="width:94%"></i></div>
            <div class="verdict"><span>Depth adjuster: buttery</span><span>Iron: holds ~4 hrs</span><span>Sole flat to 0.01 mm</span></div>
            <p style="font-size:.94rem;margin-bottom:10px">Out of the box the sole needed one pass on sandpaper and the edge needed a proper honing — after that it's the plane we reach for on end grain. Knurling on the adjustment wheel is the only weak point; it loosens in a dusty shop.</p>
            <a href="#blog" class="link-arrow">Read the full 90-day review →</a>
          </div>
        </article>

        <article class="tool-card reveal">
          <img src="https://picsum.photos/300/300" alt="Cordless drill and driver set">
          <div>
            <div class="tool-top">
              <div>
                <span class="badge">Power tools</span>
                <h3 style="margin:10px 0 4px">Northgate 18V Brushless Impact Driver</h3>
              </div>
              <div class="score">8.7<small>Verdict</small></div>
            </div>
            <div class="meter"><i style="width:87%"></i></div>
            <div class="verdict"><span>Fastener repeatable</span><span>No visible cam-out</span><span>Chuck: average</span></div>
            <p style="font-size:.94rem;margin-bottom:10px">Three modes, and mode two is the one that matters — it drives a 3-inch screw into construction pine without shearing the head. The collet developed slight play at week eleven; Northgate replaced it under warranty in four days.</p>
            <a href="#blog" class="link-arrow">Read the full 90-day review →</a>
          </div>
        </article>

        <article class="tool-card reveal">
          <img src="https://picsum.photos/300/300" alt="Set of sharpening stones and strops">
          <div>
            <div class="top tool-top">
              <div>
                <span class="badge gold">Sharpening</span>
                <h3 style="margin:10px 0 4px">Kiln&amp;Stone 8000/6000 Ceramic Splash Set</h3>
              </div>
              <div class="score">9.1<small>Verdict</small></div>
            </div>
            <div class="meter"><i style="width:91%"></i></div>
            <div class="verdict"><span>Dishing: minimal</span><span>Slurry: light</span><span>Value: excellent</span></div>
            <p style="font-size:.94rem;margin-bottom:10px">A splash stone that actually stays flat after six months of daily chisel work. We logged 0.06 mm of dishing across the centre — a third of the budget competitor. The 8000 grit leaves a polish that takes a strop to mirror in under a minute.</p>
            <a href="#blog" class="link-arrow">Read the full 90-day review →</a>
          </div>
        </article>

        <div style="display:flex;gap:14px;flex-wrap:wrap;align-items:center;margin-top:28px">
          <a href="#shop" class="btn btn-clay">Get supplies</a>
          <a href="#blog" class="btn btn-ghost">See all 1,180 reviews</a>
        </div>
      </div>

      <!-- sidebar -->
      <aside class="sidebar">
        <div class="panel">
          <h4>Community picks</h4>
          <ul>
            <li>
              <img src="https://picsum.photos/120/120" alt="Chisel set">
              <span><b>Morakniv Wood Carving Knife</b><span>Picked by 2,140 members · $34</span></span>
            </li>
            <li>
              <img src="https://picsum.photos/121/121" alt="Yarn skeins">
              <span><b>Hedgeborn Gotland DK (6-ply)</b><span>Picked by 1,708 members · $18/skein</span></span>
            </li>
            <li>
              <img src="https://picsum.photos/122/122" alt="Cutting mats and blades">
              <span><span><b>Olmstead Self-Healing Mat, A2</b><span>Picked by 1,455 members · $42</span></span></span>
            </li>
            <li>
              <img src="https://picsum.photos/123/123" alt="Clay tools">
              <span><b>Rib &amp; Rounding Tool Set (7pc)</b><span>Picked by 980 members · $26</span></span>
            </li>
          </ul>
          <a href="#shop" class="btn btn-ghost btn-sm" style="width:100%;margin-top:18px">Open the shop</a>
        </div>

        <div class="panel">
          <h4>Supply deals</h4>
          <div class="deal"><b>20% off</b> hardwood offcut boxes — this week only.<br>Code <span class="code">OFFCUT20</span></div>
          <div class="deal"><b>Free shipping</b> on wool orders over $60.<br>Code <span class="code">SPINFREE</span></div>
          <div class="deal"><b>Buy 2, get 1</b> on all Craftbound printed patterns.<br>Code <span class="code">PATTERN3</span></div>
          <p style="font-size:.78rem;margin:14px 0 0">Deals curated weekly by our supply desk. Some links are affiliate-supported; prices are checked daily.</p>
        </div>

        <div class="panel dark-panel">
          <h4>Popular projects</h4>
          <ul>
            <li><span class="rank">1</span><span><b>Shaker step stool</b><span>Woodworking · 4 hrs · beginner</span></span></li>
            <li><span class="rank">2</span><span><b>Sashiko denim repair</b><span>Textiles · 90 min · beginner</span></span></li>
            <li><span class="rank">3</span><span><b>Coptic-stitch notebook</b><span>Paper · 3 hrs · intermediate</span></span></li>
            <li><span class="rank">4</span><span><b>Tapered candle holders</b><span>Woodturning · 2 hrs · intermediate</span></span></li>
          </ul>
          <a href="#community" class="btn btn-ghost btn-sm" style="width:100%;margin-top:18px">Share project</a>
        </div>
      </aside>
    </div>
  </div>
</section>

<!-- ===================== DIY TUTORIALS (tabs) ===================== -->
<section id="tutorials" class="alt">
  <div class="container">
    <div class="section-head reveal">
      <span class="eyebrow">DIY tutorials</span>
      <h2>Three builds you can finish this weekend</h2>
      <p class="lead">Each tutorial ships with a cut list, a printable full-scale pattern, a tool checklist and the exact mistakes we made the first time. Pick a track and start cutting.</p>
    </div>

    <div class="tabs reveal" role="tablist">
      <button class="tab active" data-tab="t1" role="tab">01 · Dovetail Box</button>
      <button class="tab" data-tab="t2" role="tab">02 · Block-Printed Tote</button>
      <button class="tab" data-tab="t3" role="tab">03 · Hand-Bound Journal</button>
    </div>

    <!-- panel 1 -->
    <div class="tab-panel active" id="t1">
      <div>
        <div class="difficulty"><span><b>Skill:</b> Intermediate</span><span><b>Time:</b> 6–8 hrs</span><span><b>Cost:</b> ~$45</span></div>
        <h3>The Through-Dovetail Keepsake Box</h3>
        <p>A four-corner through-dovetail box in quartersawn white oak — the project that teaches you more about layout, saw control and paring than anything else on the bench. We use a 1:7 slope, hand-cut tails first, and a single pass of the shooting board to true every mitre before glue-up.</p>
        <ol class="steps">
          <li><b>Mill &amp; dimension</b><p>Flatten one face, square an edge, then rip all four sides to identical width so the tails register perfectly.</p></li>
          <li><b>Layout the tails</b><p>Mark with a cutting gauge set to stock thickness plus a whisker. Half-pins at each corner get laid out first — they set the rhythm.</p></li>
          <li><b>Cut &amp; pare to the line</b><p>Waste-side only. Chisel back to the baseline in two stages, never more than 2 mm per pass.</p></li>
          <li><b>Transfer, cut pins, dry-fit</b><p>Tails over pins, knife the transfer, and test the fit before you ever reach for glue.</p></li>
          <li><b>Finish schedule</b><p>Two cut-in coats of hardwax oil, 400-grit scuff between, then a third coat on end grain only.</p></li>
        </ol>
        <div class="hero-cta" style="margin-top:0">
          <a href="#shop" class="btn btn-clay">Get supplies</a>
          <a href="#community" class="btn btn-ghost">Share project</a>
        </div>
      </div>
      <div class="tab-media">
        <img src="https://picsum.photos/760/600" alt="Hand-cut dovetail joint in progress">
      </div>
    </div>

    <!-- panel 2 -->
    <div class="tab-panel" id="t2">
      <div>
        <div class="difficulty"><span><b>Skill:</b> Beginner</span><span><b>Time:</b> 2–3 hrs</span><span><b>Cost:</b> ~$28</span></div>
        <h3>Block-Printed Canvas Tote</h3>
        <p>Cut your own lino block, register a repeating motif, and print onto a heavy canvas tote with water-based ink. This is the fastest route into surface design: you learn negative space, ink load and repeat layout in a single afternoon, and every tote comes out unrepeatable.</p>
        <ol class="steps">
          <li><b>Draft the motif</b><p>Draw at final size, then transfer in reverse — remember the print flips horizontally on the block.</p></li>
          <li><b>Carve the negative</b><p>V-gouge for outlines, U-gouge for the field. Always cut away from your holding hand and keep the brayer side clear.</p></li>
          <li><b>Ink the slab</b><p>Roll ink out to a tacky hiss. Too much ink fills your fine lines; too little leaves the print speckled.</p></li>
          <li><b>Register the repeat</b><p>Build a cardboard jig on the tote so each impression lands with a consistent 18 mm gutter.</p></li>
          <li><b>Heat-set</b><p>24 hours of cure, then 5 minutes under a press cloth at medium heat for a wash-fast finish.</p></li>
        </ol>
        <div class="hero-cta" style="margin-top:0">
          <a href="#shop" class="btn btn-clay">Get supplies</a>
          <a href="#classes" class="btn btn-ghost">Take the live class</a>
        </div>
      </div>
      <div class="tab-media">
        <img src="https://picsum.photos/761/600" alt="Lino block carving tools and printed fabric samples">
      </div>
    </div>

    <!-- panel 3 -->
    <div class="tab-panel" id="t3">
      <div>
        <div class="difficulty"><span><b>Skill:</b> Beginner+</span><span><b>Time:</b> 3–4 hrs</span><span><b>Cost:</b> ~$22</span></div>
        <h3>Coptic-Stitch Field Journal</h3>
        <p>A lay-flat journal with an exposed Coptic spine, 96 pages of 120 gsm mixed stock and a marbled cover board. The chain stitch is meditative once the tension clicks, and a well-executed Coptic spine opens completely flat — which is why sketchbook makers swear by it.</p>
        <ol class="steps">
          <li><b>Collate &amp; fold signatures</b><p>Six signatures of eight leaves. Bone-fold each one and pierce stations with an awl at 25 mm spacing.</p></li>
          <li><b>Prepare the covers</b><p>Wrap 2 mm greyboard in book cloth, leave a 10 mm turn-in, and hollow the spine for swell.</p></li>
          <li><b>Thread &amp; wax</b><p>Three-ply linen, waxed twice. Cut to three times the spine height — you will always need more than you think.</p></li>
          <li><b>Work the chain</b><p>Anchor, loop, pull with consistent tension. The kettle stitch locks each new signature to the last.</p></li>
          <li><b>Press overnight</b><p>Under weight between boards. Swell should read evenly along the whole spine before you call it finished.</p></li>
        </ol>
        <div class="hero-cta" style="margin-top:0">
          <a href="#shop" class="btn btn-clay">Get supplies</a>
          <a href="#community" class="btn btn-ghost">Share project</a>
        </div>
      </div>
      <div class="tab-media">
        <img src="https://picsum.photos/762/600" alt="Hand-bound journals with exposed Coptic stitching">
      </div>
    </div>
  </div>
</section>

<!-- ===================== COMMUNITY GALLERY (interactive) ===================== -->
<section id="community" class="dark">
  <div class="container">
    <div class="section-head center reveal">
      <span class="eyebrow">Community gallery</span>
      <h2>38,400 makers. Zero gatekeeping.</h2>
      <p class="lead" style="margin-inline:auto;color:#B9AE9F">Filter the wall by craft, open any piece for the build notes, then post your own. Every submission gets at least three structured critiques within 48 hours — what works, what drifted, and what to try next time.</p>
    </div>

    <div class="filters reveal" id="filters">
      <button class="filter active" data-filter="all">Everything</button>
      <button class="filter" data-filter="wood">Woodwork</button>
      <button class="filter" data-filter="textile">Textiles</button>
      <button class="filter" data-filter="paper">Paper &amp; Print</button>
      <button class="filter" data-filter="clay">Clay</button>
    </div>

    <div class="gallery" id="gallery">
      <figure class="g-item reveal" data-cat="wood" data-title="Walnut &amp; Ash Side Table" data-author="Amelie R. · Portland" data-notes="Mortise-and-tenon base, wedged through the top. Finished with three coats of hardwax oil and a 600-grit buff between coats two and three." data-meta="Intermediate|14 hrs|Hardwax oil">
        <img src="https://picsum.photos/520/520" alt="Handmade walnut side table">
        <figcaption class="g-cap"><span>Woodwork</span><b>Walnut &amp; Ash Side Table</b></figcaption>
      </figure>

      <figure class="g-item reveal" data-cat="textile" data-title="Indigo Shibori Panel" data-author="Joel M. · Lisbon" data-notes="Itajime clamp resist on linen-cotton, six dip cycles in a 1:20 vat. The ghosting on the left panel came from an uneven clamp — kept it intentionally." data-meta="Advanced|3 days|Natural indigo">
        <img src="https://picsum.photos/521/520" alt="Indigo shibori dyed textile">
        <figcaption class="g-cap"><span>Textiles</span><b>Indigo Shibori Panel</b></figcaption>
      </figure>

      <figure class="g-item reveal" data-cat="paper" data-title="Coptic Sketchbook, 96pp" data-author="Priya S. · Toronto" data-notes="Six signatures, waxed linen, marbled paste paper covers. Swell measured at 4.2 mm — slightly heavy, next one drops to five signatures." data-meta="Beginner+|4 hrs|120 gsm">
        <img src="https://picsum.photos/522/520" alt="Hand bound coptic sketchbook">
        <figcaption class="g-cap"><span>Paper &amp; Print</span><b>Coptic Sketchbook, 96pp</b></figcaption>
      </figure>

      <figure class="g-item reveal" data-cat="clay" data-title="Faceted Stoneware Vessels" data-author="Tomas K. · Kraków" data-notes="Wheel-thrown, altered while leather-hard with a wire loop. Cone 6 oxidation, satin glaze wiped from the foot to keep the throwing rings visible." data-meta="Intermediate|9 hrs|Cone 6">
        <img src="https://picsum.photos/523/520" alt="Faceted stoneware vessels">
        <figcaption class="g-cap"><span>Clay</span><b>Faceted Stoneware Vessels</b></figcaption>
      </figure>

      <figure class="g-item reveal" data-cat="wood" data-title="Carved Spoon Set (4)" data-author="Nadia B. · Oslo" data-notes="Green birch, carved wet then dried slowly in rice to avoid checking. Sanded to 320 and finished with food-safe mineral oil and beeswax." data-meta="Beginner|6 hrs|Food-safe">
        <img src="https://picsum.photos/524/520" alt="Carved wooden spoons">
        <figcaption class="g-cap"><span>Woodwork</span><b>Carved Spoon Set (4)</b></figcaption>
      </figure>

      <figure class="g-item reveal" data-cat="textile" data-title="Sashiko-Mended Denim" data-author="Ines V. · Kyoto" data-notes="Boro-inspired repair on a blown knee. Eight sashiko patterns, cotton thread weight 8, worked with a distributing needle over 22 hours." data-meta="Intermediate|22 hrs|Cotton sashiko">
        <img src="https://picsum.photos/525/520" alt="Sashiko stitched denim repair">
        <figcaption class="g-cap"><span>Textiles</span><b>Sashiko-Mended Denim</b></figcaption>
      </figure>

      <figure class="g-item reveal" data-cat="paper" data-title="Marbled Endpaper Suite" data-author="Louis D. · Lyon" data-notes="Carrageenan size, eleven colours, traditional stone pattern pulled onto Arches text weight. Each sheet took four minutes of nerve." data-meta="Advanced|5 hrs|Arches 145 gsm">
        <img src="https://picsum.photos/526/520" alt="Marbled paper endpapers">
        <figcaption class="g-cap"><span>Paper &amp; Print</span><b>Marbled Endpaper Suite</b></figcaption>
      </figure>

      <figure class="g-item reveal" data-cat="clay" data-title="Breakfast Set, Ten Pieces" data-author="Sara H. · Melbourne" data-notes="Stoneware with a tenmoku glaze, poured rather than dipped for a heavier break over the rim. Fired to cone 10 in reduction." data-meta="Advanced|2 days|Tenmoku">
        <img src="https://picsum.photos/527/520" alt="Handmade ceramic breakfast set">
        <figcaption class="g-cap"><span>Clay</span><b>Breakfast Set, Ten Pieces</b></figcaption>
      </figure>
    </div>

    <div style="text-align:center;margin-top:44px" class="reveal">
      <a href="#newsletter" class="btn btn-clay">Share project</a>
      <a href="#classes" class="btn btn-ghost" style="margin-left:12px">Join a critique circle</a>
    </div>
  </div>
</section>

<!-- ===================== CLASSES ===================== -->
<section id="classes">
  <div class="container">
    <div class="section-head reveal">
      <span class="eyebrow">Classes</span>
      <h2>Live cohorts, capped at twelve seats</h2>
      <p class="lead">Every class meets twice weekly over four weeks on video, with materials shipped to your door before session one. Recordings stay in your library forever, and each cohort ends with a group critique and a printable certificate of completion.</p>
    </div>

    <div class="grid g4">
      <article class="class-card reveal">
        <div class="thumb">
          <img src="https://picsum.photos/520/330" alt="Woodworking class in progress">
          <span class="badge">Starts 14 Apr</span>
        </div>
        <div class="class-body">
          <h3>Hand-Cut Joinery Fundamentals</h3>
          <p>Eight sessions on layout, saw control and paring. You'll leave with a dovetailed box and a shooting board you built yourself.</p>
          <div class="class-foot">
            <span class="who"><img src="https://i.pravatar.cc/64?u=teacher-elsa" alt="Instructor"> Elsa V.</span>
            <span class="price">$180</span>
          </div>
          <a href="#newsletter" class="btn btn-primary btn-sm" style="margin-top:14px">Enrol now</a>
        </div>
      </article>

      <article class="class-card reveal">
        <div class="thumb">
          <img src="https://picsum.photos/521/330" alt="Natural dyeing workshop">
          <span class="badge sage">Starts 21 Apr</span>
        </div>
        <div class="class-body">
          <h3>Natural Dyeing &amp; Vat Care</h3>
          <p>Build and maintain an indigo vat, mordant protein vs. cellulose fibres, and troubleshoot the three problems that kill most first dyes.</p>
          <div class="class-foot">
            <span class="who"><img src="https://i.pravatar.cc/64?u=teacher-marcus" alt="Instructor"> Marcus O.</span>
            <span class="price">$145</span>
          </div>
          <a href="#newsletter" class="btn btn-primary btn-sm" style="margin-top:14px">Enrol now</a>
        </div>
      </article>

      <article class="class-card reveal">
        <div class="thumb">
          <img src="https://picsum.photos/522/330" alt="Ceramics wheel class">
          <span class="badge gold">Starts 05 May</span>
        </div>
        <div class="class-body">
          <h3>Wheel Throwing: Form &amp; Consistency</h3>
          <p>Centring, pulling even walls and throwing a matched set. Includes a glaze lab where you mix three studio recipes from scratch.</p>
          <div class="class-foot">
            <span class="who"><img src="https://i.pravatar.cc/64?u=teacher-yuki" alt="Instructor"> Yuki T.</span>
            <span class="price">$210</span>
          </div>
          <a href="#newsletter" class="btn btn-primary btn-sm" style="margin-top:14px">Enrol now</a>
        </div>
      </article>

      <article class="class-card reveal">
        <div class="thumb">
          <img src="https://picsum.photos/523/330" alt="Bookbinding studio table">
          <span class="badge">Starts 12 May</span>
        </div>
        <div class="class-body">
          <h3>Bookbinding: Three Structural Styles</h3>
          <p>Pamphlet, Coptic and case binding in four weeks. We cover grain direction, swell calculation and how to press without crushing your spine.</p>
          <div class="class-foot">
            <span class="who"><img src="https://i.pravatar.cc/64?u=teacher-hana" alt="Instructor"> Hana B.</span>
            <span class="price">$165</span>
          </div>
          <a href="#newsletter" class="btn btn-primary btn-sm" style="margin-top:14px">Enrol now</a>
        </div>
      </article>
    </div>

    <div style="margin-top:36px;display:flex;gap:14px;flex-wrap:wrap;align-items:center" class="reveal">
      <a href="#newsletter" class="btn btn-clay">See all 26 classes</a>
      <span style="font-size:.9rem;color:var(--ink-soft)">Seats remaining this term: <strong style="color:var(--ink)">41</strong> · Payment plans available at checkout.</span>
    </div>
  </div>
</section>

<!-- ===================== SHOP STRIP ===================== -->
<section id="shop" class="alt" style="padding-top:0">
  <div class="container">
    <div class="split" style="align-items:stretch">
      <div class="split-media reveal">
        <img src="https://picsum.photos/840/640" alt="Curated craft supplies laid out on a linen surface" style="height:100%;aspect-ratio:auto;min-height:340px">
      </div>
      <div class="reveal" style="background:var(--paper);border:1px solid var(--line);border-radius:22px;padding:44px 40px;display:flex;flex-direction:column;justify-content:center">
        <span class="eyebrow">The shop</span>
        <h2>Supplies we've actually tested</h2>
        <p>Our store carries 900+ SKUs, and nothing earns a shelf spot until a Craftbound maker has used it for a month. That means no mystery steel, no unlabelled fibre content, and no affiliate-only brands we wouldn't bench ourselves.</p>
        <p>Orders ship within one business day from two warehouses (Portland and Rotterdam), patterns download instantly, and every order over $75 includes a printed technique card from the archive.</p>
        <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin:22px 0 26px">
          <div style="background:var(--cream);border-radius:12px;padding:16px"><b style="font-family:'Fraunces',serif;font-size:1.4rem">900+</b><br><span style="font-size:.78rem;text-transform:uppercase;letter-spacing:.1em">Curated SKUs</span></div>
          <div style="background:var(--cream);border-radius:12px;padding:16px"><b style="font-family:'Fraunces',serif;font-size:1.4rem">24h</b><br><span style="font-size:.78rem;text-transform:uppercase;letter-spacing:.1em">Dispatch</span></div>
          <div style="background:var(--cream);border-radius:12px;padding:16px"><b style="font-family:'Fraunces',serif;font-size:1.4rem">60 day</b><br><span style="font-size:.78rem;text-transform:uppercase;letter-spacing:.1em">Returns</span></div>
        </div>
        <div class="hero-cta" style="margin-top:0">
          <a href="#newsletter" class="btn btn-clay">Get supplies</a>
          <a href="#tools" class="btn btn-ghost">Read tool reviews</a>
        </div>
      </div>
    </div>
  </div>
</section>

<!-- ===================== TESTIMONIALS ===================== -->
<section>
  <div class="container">
    <div class="section-head center reveal">
      <span class="eyebrow">Member stories</span>
      <h2>From "I'm not really creative" to sold-out market stall</h2>
    </div>

    <div class="grid g3">
      <article class="quote-card reveal">
        <div class="stars">★★★★★</div>
        <p>I'd been woodworking for two years and still hiding every gap with filler. One critique circle later I understood my shooting board was out of square — that single fix changed everything. My boxes now sell at the Saturday market and I waitlist commissions.</p>
        <div class="who-row">
          <img src="https://i.pravatar.cc/120?u=member-amelie" alt="Amelie R.">
          <span><b>Amélie Roussel</b><span>Woodworker · Portland, OR</span></span>
        </div>
      </article>

      <article class="quote-card reveal">
        <div class="stars">★★★★★</div>
        <p>The tool reviews saved me about $400 in bad purchases. I nearly bought a router that runs 0.4 mm off-centre — Craftbound's runout chart caught it. The failure library is the best-kept secret on the site: watching someone diagnose a blush bloom beat three hours of forum searching.</p>
        <div class="who-row">
          <img src="https://i.pravatar.cc/120?u=member-joel" alt="Joel M.">
          <span><b>Joel Medina</b><span>Furniture maker · Lisbon, PT</span></span>
        </div>
      </article>

      <article class="quote-card reveal">
        <div class="stars">★★★★★</div>
        <p>I joined for the free patterns and stayed for the people. My first Coptic journal was lumpy and the feedback was kind, specific and genuinely useful. Eighteen months on I teach the beginner bookbinding class here. That's a strange sentence to type.</p>
        <div class="who-row">
          <img src="https://i.pravatar.cc/120?u=member-priya" alt="Priya S.">
          <span><b>Priya Sharma</b><span>Bookbinder · Toronto, ON</span></span>
        </div>
      </article>
    </div>
  </div>
</section>

<!-- ===================== BLOG / JOURNAL ===================== -->
<section id="blog" class="alt">
  <div class="container">
    <div class="section-head reveal" style="display:flex;justify-content:space-between;align-items:flex-end;max-width:none;gap:30px;flex-wrap:wrap">
      <div style="max-width:640px">
        <span class="eyebrow">From the journal</span>
        <h2>Field notes, shop talk and long-form testing</h2>
        <p class="lead">Two new essays every week from our bench team and rotating guest makers.</p>
      </div>
      <a href="#newsletter" class="btn btn-ghost">All articles →</a>
    </div>

    <div class="grid g3">
      <article class="feature reveal" style="padding:0;overflow:hidden">
        <img src="https://picsum.photos/600/380" alt="Workshop tool wall" style="aspect-ratio:16/10;object-fit:cover">
        <div style="padding:26px 24px 30px">
          <span class="badge sage">Tool testing</span>
          <h3 style="margin-top:14px">We measured runout on 14 benchtop drills</h3>
          <p>Dial indicator, three bits per machine, cold and warm. Two models we'd previously recommended landed outside tolerance — here's the raw data and what actually causes chuck wobble.</p>
          <a href="#tools" class="link-arrow">Read the test →</a>
        </div>
      </article>

      <article class="feature reveal" style="padding:0;overflow:hidden">
        <img src="https://picsum.photos/601/380" alt="Fabric and pattern drafting" style="aspect-ratio:16/10;object-fit:cover">
        <div style="padding:26px 24px 30px">
          <span class="badge">Pattern design</span>
          <h3 style="margin-top:14px">Drafting a repeat that survives the corner</h3>
          <p>Half-drop, brick and mirror repeats explained with a printable grid. Includes the registration trick that keeps your block prints from drifting three millimetres by the fourth row.</p>
          <a href="#tutorials" class="link-arrow">Read the guide →</a>
        </div>
      </article>

      <article class="feature reveal" style="padding:0;overflow:hidden">
        <img src="https://picsum.photos/602/380" alt="Finished handmade objects on a shelf" style="aspect-ratio:16/10;object-fit:cover">
        <div style="padding:26px 24px 30px">
          <span class="badge gold">Selling handmade</span>
          <h3 style="margin-top:14px">Pricing custom design work without guilt</h3>
          <p>Materials, bench hours, overhead and the 12-week lead-time buffer most makers forget. A pricing worksheet you can copy, plus three real invoices torn apart line by line.</p>
          <a href="#classes" class="link-arrow">Get the worksheet →</a>
        </div>
      </article>
    </div>
  </div>
</section>

<!-- ===================== FAQ ===================== -->
<section id="faq">
  <div class="container">
    <div class="section-head center reveal">
      <span class="eyebrow">Questions</span>
      <h2>Everything worth knowing before you join</h2>
    </div>

    <div class="faq">
      <details open class="reveal">
        <summary>Do I need my own tools to take a class?</summary>
        <div class="answer"><p>Every class page publishes a full tool and materials list two weeks before the cohort starts, with budget, mid-range and "already in most workshops" options for each item. For our bookbinding and block-printing tracks we ship a materials box directly to you — it's included in the tuition, not sold separately. For heavier woodworking classes we'd rather you borrow or hire than buy a bench full of gear for one project.</p></div>
      </details>

      <details class="reveal">
        <summary>Is Craftbound membership actually free?</summary>
        <div class="answer"><p>The community gallery, critique circles, 640 free patterns, weekly journal essays and the tool review archive are free forever — supported by shop revenue and clearly labelled affiliate links. Craftbound Unlimited ($9/month or $84/year) unlocks the 240-video lesson library, full-length deep dives, downloadable cut lists, and 15% off everything in the shop. Students and members of partner maker spaces get 40% off; just email us proof.</p></div>
      </details>

      <details class="reveal">
        <summary>How do critique circles work, and will my work get ripped off?</summary>
        <div class="answer"><p>You're placed in a group of six at a similar skill level in your craft. Circles meet twice monthly on video and use a fixed feedback format: three things that work, two things that drifted, one thing to try next. Posts are timestamped and the thread is visible only to your circle and our moderation team — never public. We take original design seriously; if a dispute ever arises, your upload timestamp is your evidence, and our IP policy is spelled out in full in the Terms.</p></div>
      </details>

      <details class="reveal">
        <summary>Are the tool reviews sponsored or affiliate-funded?</summary>
        <div class="answer"><p>Our review units are purchased at retail or returned after testing. We do run affiliate links on some shop pages, and we say so on the page itself. Reviewers never see commission rates before publishing a score, and a brand cannot pay to remove a product from our "avoid" list — two manufacturers have asked, and both requests are documented in our editorial policy.</p></div>
      </details>

      <details class="reveal">
        <summary>Can I sell the things I make from Craftbound patterns?</summary>
        <div class="answer"><p>Yes. Patterns you download are licensed for unlimited personal and commercial use, so you're welcome to build and sell finished pieces at markets, in your shop or through commissions. What you can't do is resell, re-upload or republish the pattern files themselves, or present our video lessons as your own teaching material. Attribution is appreciated but not required on physical work.</p></div>
      </details>

      <details class="reveal">
        <summary>What's your refund policy on classes and digital downloads?</summary>
        <div class="answer"><p>Live classes are fully refundable up to seven days before session one — no questions, no form. After that we'll transfer your seat to a later cohort once, free of charge. Digital pattern and video purchases can be refunded within 30 days if you tell us what didn't work for you; that feedback goes straight to the instructor. Physical goods can be returned within 60 days in unused condition.</p></div>
      </details>
    </div>
  </div>
</section>

<!-- ===================== NEWSLETTER ===================== -->
<section id="newsletter" style="padding-top:0">
  <div class="container">
    <div class="news reveal">
      <div>
        <span class="eyebrow">Join the collective</span>
        <h2>One email a week: a technique, a tool, a pattern.</h2>
        <p>The Craftbound Dispatch goes out every Thursday morning — one long-form technique breakdown, one tool we tested (with scores), one free pattern download and the week's best community builds. Read in under six minutes, unsubscribe in one click.</p>
        <p style="font-size:.85rem;color:#8E8375;margin-bottom:0">Joined by 61,200 hobbyists, craft teachers and small-batch producers.</p>
      </div>
      <div>
        <form id="signup" novalidate>
          <input type="email" id="email" placeholder="you@yourworkshop.com" aria-label="Email address" required>
          <button type="submit" class="btn btn-clay">Get the Dispatch</button>
        </form>
        <div class="form-msg" id="formMsg">Thanks — check your inbox to confirm your subscription. 🎉</div>
        <p class="note">No spam, no reselling your data. We send one email per week and a shop notice on the rare occasion something's genuinely on sale.</p>
      </div>
    </div>
  </div>
</section>

<!-- ===================== FOOTER ===================== -->
<footer class="site">
  <div class="container">
    <div class="foot-grid">
      <div>
        <a class="brand" href="#top" style="margin-bottom:18px">
          <img src="https://placehold.co/96x96/2A211A/DDA13A?text=CB&font=playfair%20display" alt="Craftbound logo mark">
          <span>
            <span class="name">Craftbound</span>
            <span class="tag" style="color:var(--gold)">Made by hand · Made together</span>
          </span>
        </a>
        <p style="max-width:34ch">A learning platform and community for hobbyists, craftspeople and DIY makers — built by people who sell what they build. Independent testing, real critique, no gatekeeping.</p>
        <div class="socials">
          <a href="#top" aria-label="Instagram">IG</a>
          <a href="#top" aria-label="YouTube">YT</a>
          <a href="#top" aria-label="Pinterest">PN</a>
          <a href="#top" aria-label="Reddit">RD</a>
          <a href="#top" aria-label="Newsletter">NL</a>
        </div>
      </div>

      <div>
        <h5>Learn</h5>
        <ul>
          <li><a href="#classes">All classes</a></li>
          <li><a href="#tutorials">DIY tutorials</a></li>
          <li><a href="#techniques">Advanced techniques</a></li>
          <li><a href="#tools">Tool reviews</a></li>
          <li><a href="#blog">The journal</a></li>
          <li><a href="#faq">Skill-path FAQ</a></li>
        </ul>
      </div>

      <div>
        <h5>Explore</h5>
        <ul>
          <li><a href="#community">Community gallery</a></li>
          <li><a href="#shop">Shop supplies</a></li>
          <li><a href="#shop">Pattern vault</a></li>
          <li><a href="#community">Critique circles</a></li>
          <li><a href="#newsletter">Become an instructor</a></li>
          <li><a href="#newsletter">Gift membership</a></li>
        </ul>
      </div>

      <div>
        <h5>Get in touch</h5>
        <div class="contact-line"><span>Studio</span><span><b>Craftbound Collective</b><br>1412 Kiln Street, Suite 3<br>Portland, OR 97214, USA</span></div>
        <div class="contact-line"><span>Email</span><span><a href="mailto:hello@craftbound.co">hello@craftbound.co</a></span></div>
        <div class="contact-line"><span>Support</span><span><a href="mailto:support@craftbound.co">support@craftbound.co</a></span></div>
        <div class="contact-line"><span>Phone</span><span><a href="tel:+15035550148">+1 (503) 555-0148</a></span></div>
        <div class="contact-line"><span>Hours</span><span>Mon–Fri · 9:00–17:00 PT</span></div>
      </div>
    </div>

    <div class="foot-bottom">
      <span>© <span id="year">2025</span> Craftbound Collective LLC. All rights reserved. Made by hand, obviously.</span>
      <ul>
        <li><a href="#faq">Privacy Policy</a></li>
        <li><a href="#faq">Terms of Service</a></li>
        <li><a href="#faq">Cookie Preferences</a></li>
        <li><a href="#faq">Editorial Policy</a></li>
        <li><a href="#top">Back to top ↑</a></li>
      </ul>
    </div>
  </div>
</footer>

<!-- ===================== MODAL ===================== -->
<div class="modal" id="modal" role="dialog" aria-modal="true" aria-label="Community project detail">
  <button class="modal-close" id="modalClose" aria-label="Close">✕</button>
  <div class="modal-inner">
    <img id="mImg" src="" alt="">
    <div class="modal-body">
      <span class="badge" id="mCat">Project</span>
      <h3 id="mTitle" style="margin-top:14px">Project</h3>
      <p style="font-size:.9rem" id="mAuthor">Maker</p>
      <p id="mNotes">Build notes…</p>
      <div class="m-meta" id="mMeta"></div>
      <div style="display:flex;gap:10px;flex-wrap:wrap;margin-top:22px">
        <a href="#newsletter" class="btn btn-clay btn-sm">Share project</a>
        <a href="#tutorials" class="btn btn-ghost btn-sm">Watch video</a>
      </div>
    </div>
  </div>
</div>

<script>
(function(){
  "use strict";

  /* ---------- current year ---------- */
  document.getElementById('year').textContent = new Date().getFullYear();

  /* ---------- sticky header shadow ---------- */
  var header = document.querySelector('header.site');
  var onScroll = function(){
    if(window.scrollY > 12){ header.classList.add('stuck'); }
    else { header.classList.remove('stuck'); }
  };
  window.addEventListener('scroll', onScroll, {passive:true}); onScroll();

  /* ---------- mobile nav ---------- */
  var burger = document.getElementById('burger');
  var mobileNav = document.getElementById('mobileNav');
  burger.addEventListener('click', function(){
    var open = mobileNav.classList.toggle('open');
    burger.classList.toggle('open', open);
    burger.setAttribute('aria-expanded', open ? 'true' : 'false');
  });
  mobileNav.querySelectorAll('a').forEach(function(a){
    a.addEventListener('click', function(){
      mobileNav.classList.remove('open');
      burger.classList.remove('open');
      burger.setAttribute('aria-expanded','false');
    });
  });

  /* ---------- tutorial tabs ---------- */
  document.querySelectorAll('.tab').forEach(function(tab){
    tab.addEventListener('click', function(){
      document.querySelectorAll('.tab').forEach(function(t){ t.classList.remove('active'); });
      document.querySelectorAll('.tab-panel').forEach(function(p){ p.classList.remove('active'); });
      tab.classList.add('active');
      var panel = document.getElementById(tab.dataset.tab);
      if(panel) panel.classList.add('active');
    });
  });

  /* ---------- gallery filters ---------- */
  var items = Array.prototype.slice.call(document.querySelectorAll('#gallery .g-item'));
  document.querySelectorAll('#filters .filter').forEach(function(btn){
    btn.addEventListener('click', function(){
      document.querySelectorAll('#filters .filter').forEach(function(b){ b.classList.remove('active'); });
      btn.classList.add('active');
      var f = btn.dataset.filter;
      items.forEach(function(it){
        var show = (f === 'all' || it.dataset.cat === f);
        it.classList.toggle('hide', !show);
        if(show){
          it.style.animation = 'none';
          /* force reflow to restart animation */
          void it.offsetWidth;
          it.style.animation = 'fade .45s cubic-bezier(.22,.61,.36,1) both';
        }
      });
    });
  });

  /* ---------- gallery modal ---------- */
  var modal   = document.getElementById('modal');
  var mImg    = document.getElementById('mImg');
  var mTitle  = document.getElementById('mTitle');
  var mAuthor = document.getElementById('mAuthor');
  var mNotes  = document.getElementById('mNotes');
  var mMeta   = document.getElementById('mMeta');
  var mCat    = document.getElementById('mCat');

  function openModal(el){
    var img = el.querySelector('img');
    mImg.src = img ? img.src.replace('/520/520','/900/700') : '';
    mImg.alt = img ? img.alt : '';
    mTitle.innerHTML = el.dataset.title || '';
    mAuthor.textContent = el.dataset.author || '';
    mNotes.textContent  = el.dataset.notes || '';
    mCat.textContent    = (el.querySelector('.g-cap span') || {}).textContent || 'Project';
    mMeta.innerHTML = '';
    (el.dataset.meta || '').split('|').forEach(function(m){
      if(!m) return;
      var s = document.createElement('span'); s.textContent = m; mMeta.appendChild(s);
    });
    modal.classList.add('open');
    document.body.style.overflow = 'hidden';
  }
  function closeModal(){
    modal.classList.remove('open');
    document.body.style.overflow = '';
  }
  items.forEach(function(it){
    it.setAttribute('tabindex','0');
    it.setAttribute('role','button');
    it.addEventListener('click', function(){ openModal(it); });
    it.addEventListener('keydown', function(e){
      if(e.key === 'Enter' || e.key === ' '){ e.preventDefault(); openModal(it); }
    });
  });
  document.getElementById('modalClose').addEventListener('click', closeModal);
  modal.addEventListener('click', function(e){ if(e.target === modal) closeModal(); });
  document.addEventListener('keydown', function(e){ if(e.key === 'Escape') closeModal(); });

  /* ---------- newsletter form ---------- */
  var form = document.getElementById('signup');
  form.addEventListener('submit', function(e){
    e.preventDefault();
    var email = document.getElementById('email');
    var msg = document.getElementById('formMsg');
    if(!email.value || email.value.indexOf('@') === -1){
      msg.textContent = 'Please enter a valid email address.';
      msg.classList.add('show');
      email.focus();
      return;
    }
    msg.textContent = 'Thanks — check your inbox to confirm your subscription. 🎉';
    msg.classList.add('show');
    form.reset();
  });

  /* ---------- reveal on scroll ---------- */
  var reveals = document.querySelectorAll('.reveal');
  if('IntersectionObserver' in window){
    var io = new IntersectionObserver(function(entries){
      entries.forEach(function(en){
        if(en.isIntersecting){ en.target.classList.add('in'); io.unobserve(en.target); }
      });
    }, {threshold:0.12, rootMargin:'0px 0px -40px 0px'});
    reveals.forEach(function(r, i){
      r.style.transitionDelay = (Math.min(i % 4, 3) * 70) + 'ms';
      io.observe(r);
    });
  } else {
    reveals.forEach(function(r){ r.classList.add('in'); });
  }
})();
</script>
</body>
</html>
View Axe Report (JSON)
{
  "testEngine": {
    "name": "axe-core",
    "version": "4.10.2"
  },
  "testRunner": {
    "name": "axe"
  },
  "testEnvironment": {
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36",
    "windowWidth": 1280,
    "windowHeight": 720,
    "orientationAngle": 0,
    "orientationType": "landscape-primary"
  },
  "timestamp": "2026-11-12T10:04:59.831Z",
  "url": "https://benchmark.aimac.invalid/fda54ca6719696a175651c19c7e4990896ac0c1f033c012183e26ce554ef61cb.html",
  "toolOptions": {
    "runOnly": {
      "type": "tag",
      "values": [
        "wcag2a",
        "wcag2aa",
        "wcag21a",
        "wcag21aa",
        "wcag22a",
        "wcag22aa"
      ]
    },
    "resultTypes": [
      "violations"
    ],
    "reporter": "v1"
  },
  "inapplicable": [
    {
      "id": "area-alt",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag244",
        "wcag412",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT6.a",
        "EN-301-549",
        "EN-9.2.4.4",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure <area> elements of image maps have alternative text",
      "help": "Active <area> elements must have alternative text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/area-alt?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-braille-equivalent",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure aria-braillelabel and aria-brailleroledescription have a non-braille equivalent",
      "help": "aria-braille attributes must have a non-braille equivalent",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-braille-equivalent?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-command-name",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "TTv5",
        "TT6.a",
        "EN-301-549",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure every ARIA button, link and menuitem has an accessible name",
      "help": "ARIA commands must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-command-name?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-input-field-name",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "TTv5",
        "TT5.c",
        "EN-301-549",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure every ARIA input field has an accessible name",
      "help": "ARIA input fields must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-input-field-name?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-meter-name",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag111",
        "EN-301-549",
        "EN-9.1.1.1"
      ],
      "description": "Ensure every ARIA meter node has an accessible name",
      "help": "ARIA meter nodes must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-meter-name?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-progressbar-name",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag111",
        "EN-301-549",
        "EN-9.1.1.1"
      ],
      "description": "Ensure every ARIA progressbar node has an accessible name",
      "help": "ARIA progressbar nodes must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-progressbar-name?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-toggle-field-name",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "TTv5",
        "TT5.c",
        "EN-301-549",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure every ARIA toggle field has an accessible name",
      "help": "ARIA toggle fields must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-toggle-field-name?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-tooltip-name",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure every ARIA tooltip node has an accessible name",
      "help": "ARIA tooltip nodes must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-tooltip-name?application=axeAPI",
      "nodes": []
    },
    {
      "id": "autocomplete-valid",
      "impact": null,
      "tags": [
        "cat.forms",
        "wcag21aa",
        "wcag135",
        "EN-301-549",
        "EN-9.1.3.5",
        "ACT"
      ],
      "description": "Ensure the autocomplete attribute is correct and suitable for the form field",
      "help": "autocomplete attribute must be used correctly",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/autocomplete-valid?application=axeAPI",
      "nodes": []
    },
    {
      "id": "blink",
      "impact": null,
      "tags": [
        "cat.time-and-media",
        "wcag2a",
        "wcag222",
        "section508",
        "section508.22.j",
        "TTv5",
        "TT2.b",
        "EN-301-549",
        "EN-9.2.2.2"
      ],
      "description": "Ensure <blink> elements are not used",
      "help": "<blink> elements are deprecated and must not be used",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/blink?application=axeAPI",
      "nodes": []
    },
    {
      "id": "definition-list",
      "impact": null,
      "tags": [
        "cat.structure",
        "wcag2a",
        "wcag131",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure <dl> elements are structured correctly",
      "help": "<dl> elements must only directly contain properly-ordered <dt> and <dd> groups, <script>, <template> or <div> elements",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/definition-list?application=axeAPI",
      "nodes": []
    },
    {
      "id": "dlitem",
      "impact": null,
      "tags": [
        "cat.structure",
        "wcag2a",
        "wcag131",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure <dt> and <dd> elements are contained by a <dl>",
      "help": "<dt> and <dd> elements must be contained by a <dl>",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/dlitem?application=axeAPI",
      "nodes": []
    },
    {
      "id": "duplicate-id-aria",
      "impact": null,
      "tags": [
        "cat.parsing",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure every id attribute value used in ARIA and in labels is unique",
      "help": "IDs used in ARIA and labels must be unique",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/duplicate-id-aria?application=axeAPI",
      "nodes": []
    },
    {
      "id": "frame-focusable-content",
      "impact": null,
      "tags": [
        "cat.keyboard",
        "wcag2a",
        "wcag211",
        "TTv5",
        "TT4.a",
        "EN-301-549",
        "EN-9.2.1.1"
      ],
      "description": "Ensure <frame> and <iframe> elements with focusable content do not have tabindex=-1",
      "help": "Frames with focusable content must not have tabindex=-1",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/frame-focusable-content?application=axeAPI",
      "nodes": []
    },
    {
      "id": "frame-title-unique",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag412",
        "TTv5",
        "TT12.d",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure <iframe> and <frame> elements contain a unique title attribute",
      "help": "Frames must have a unique title attribute",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/frame-title-unique?application=axeAPI",
      "nodes": []
    },
    {
      "id": "frame-title",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag412",
        "section508",
        "section508.22.i",
        "TTv5",
        "TT12.d",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure <iframe> and <frame> elements have an accessible name",
      "help": "Frames must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/frame-title?application=axeAPI",
      "nodes": []
    },
    {
      "id": "html-xml-lang-mismatch",
      "impact": null,
      "tags": [
        "cat.language",
        "wcag2a",
        "wcag311",
        "EN-301-549",
        "EN-9.3.1.1",
        "ACT"
      ],
      "description": "Ensure that HTML elements with both valid lang and xml:lang attributes agree on the base language of the page",
      "help": "HTML elements with lang and xml:lang must have the same base language",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/html-xml-lang-mismatch?application=axeAPI",
      "nodes": []
    },
    {
      "id": "input-button-name",
      "impact": null,
      "tags": [
        "cat.name-role-value",
        "wcag2a",
        "wcag412",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT5.c",
        "EN-301-549",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure input buttons have discernible text",
      "help": "Input buttons must have discernible text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/input-button-name?application=axeAPI",
      "nodes": []
    },
    {
      "id": "input-image-alt",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag111",
        "wcag412",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT7.a",
        "EN-301-549",
        "EN-9.1.1.1",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure <input type=\"image\"> elements have alternative text",
      "help": "Image buttons must have alternative text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/input-image-alt?application=axeAPI",
      "nodes": []
    },
    {
      "id": "marquee",
      "impact": null,
      "tags": [
        "cat.parsing",
        "wcag2a",
        "wcag222",
        "TTv5",
        "TT2.b",
        "EN-301-549",
        "EN-9.2.2.2"
      ],
      "description": "Ensure <marquee> elements are not used",
      "help": "<marquee> elements are deprecated and must not be used",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/marquee?application=axeAPI",
      "nodes": []
    },
    {
      "id": "meta-refresh",
      "impact": null,
      "tags": [
        "cat.time-and-media",
        "wcag2a",
        "wcag221",
        "TTv5",
        "TT8.a",
        "EN-301-549",
        "EN-9.2.2.1"
      ],
      "description": "Ensure <meta http-equiv=\"refresh\"> is not used for delayed refresh",
      "help": "Delayed refresh under 20 hours must not be used",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/meta-refresh?application=axeAPI",
      "nodes": []
    },
    {
      "id": "object-alt",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag111",
        "section508",
        "section508.22.a",
        "EN-301-549",
        "EN-9.1.1.1"
      ],
      "description": "Ensure <object> elements have alternative text",
      "help": "<object> elements must have alternative text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/object-alt?application=axeAPI",
      "nodes": []
    },
    {
      "id": "role-img-alt",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag111",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT7.a",
        "EN-301-549",
        "EN-9.1.1.1",
        "ACT"
      ],
      "description": "Ensure [role=\"img\"] elements have alternative text",
      "help": "[role=\"img\"] elements must have an alternative text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/role-img-alt?application=axeAPI",
      "nodes": []
    },
    {
      "id": "scrollable-region-focusable",
      "impact": null,
      "tags": [
        "cat.keyboard",
        "wcag2a",
        "wcag211",
        "wcag213",
        "TTv5",
        "TT4.a",
        "EN-301-549",
        "EN-9.2.1.1",
        "EN-9.2.1.3"
      ],
      "description": "Ensure elements that have scrollable content are accessible by keyboard",
      "help": "Scrollable region must have keyboard access",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/scrollable-region-focusable?application=axeAPI",
      "nodes": []
    },
    {
      "id": "select-name",
      "impact": null,
      "tags": [
        "cat.forms",
        "wcag2a",
        "wcag412",
        "section508",
        "section508.22.n",
        "TTv5",
        "TT5.c",
        "EN-301-549",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure select element has an accessible name",
      "help": "Select element must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/select-name?application=axeAPI",
      "nodes": []
    },
    {
      "id": "server-side-image-map",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag211",
        "section508",
        "section508.22.f",
        "TTv5",
        "TT4.a",
        "EN-301-549",
        "EN-9.2.1.1"
      ],
      "description": "Ensure that server-side image maps are not used",
      "help": "Server-side image maps must not be used",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/server-side-image-map?application=axeAPI",
      "nodes": []
    },
    {
      "id": "svg-img-alt",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag111",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT7.a",
        "EN-301-549",
        "EN-9.1.1.1",
        "ACT"
      ],
      "description": "Ensure <svg> elements with an img, graphics-document or graphics-symbol role have an accessible text",
      "help": "<svg> elements with an img role must have an alternative text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/svg-img-alt?application=axeAPI",
      "nodes": []
    },
    {
      "id": "td-headers-attr",
      "impact": null,
      "tags": [
        "cat.tables",
        "wcag2a",
        "wcag131",
        "section508",
        "section508.22.g",
        "TTv5",
        "TT14.b",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure that each cell in a table that uses the headers attribute refers only to other cells in that table",
      "help": "Table cells that use the headers attribute must only refer to cells in the same table",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/td-headers-attr?application=axeAPI",
      "nodes": []
    },
    {
      "id": "th-has-data-cells",
      "impact": null,
      "tags": [
        "cat.tables",
        "wcag2a",
        "wcag131",
        "section508",
        "section508.22.g",
        "TTv5",
        "TT14.b",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure that <th> elements and elements with role=columnheader/rowheader have data cells they describe",
      "help": "Table headers in a data table must refer to data cells",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/th-has-data-cells?application=axeAPI",
      "nodes": []
    },
    {
      "id": "valid-lang",
      "impact": null,
      "tags": [
        "cat.language",
        "wcag2aa",
        "wcag312",
        "TTv5",
        "TT11.b",
        "EN-301-549",
        "EN-9.3.1.2",
        "ACT"
      ],
      "description": "Ensure lang attributes have valid values",
      "help": "lang attribute must have a valid value",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/valid-lang?application=axeAPI",
      "nodes": []
    },
    {
      "id": "video-caption",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag122",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT17.a",
        "EN-301-549",
        "EN-9.1.2.2"
      ],
      "description": "Ensure <video> elements have captions",
      "help": "<video> elements must have captions",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/video-caption?application=axeAPI",
      "nodes": []
    },
    {
      "id": "no-autoplay-audio",
      "impact": null,
      "tags": [
        "cat.time-and-media",
        "wcag2a",
        "wcag142",
        "TTv5",
        "TT2.a",
        "EN-301-549",
        "EN-9.1.4.2",
        "ACT"
      ],
      "description": "Ensure <video> or <audio> elements do not autoplay audio for more than 3 seconds without a control mechanism to stop or mute the audio",
      "help": "<video> or <audio> elements must not play automatically",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/no-autoplay-audio?application=axeAPI",
      "nodes": []
    }
  ],
  "passes": [
    {
      "id": "aria-allowed-attr",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure an element's role supports its ARIA attributes",
      "help": "Elements must only use supported ARIA attributes",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-allowed-attr?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [
            {
              "id": "aria-allowed-attr",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "ARIA attributes are used correctly for the defined role"
            }
          ],
          "none": [
            {
              "id": "aria-unsupported-attr",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "ARIA attribute is supported"
            }
          ],
          "impact": null,
          "html": "<a class=\"brand\" href=\"#top\" aria-label=\"Craftbound home\">",
          "target": [
            "a[aria-label=\"Craftbound home\"]"
          ]
        }
      ]
    },
    {
      "id": "aria-conditional-attr",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure ARIA attributes are used as described in the specification of the element's role",
      "help": "ARIA attributes must be used as specified for the element's role",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-conditional-attr?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [
            {
              "id": "aria-conditional-attr",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "ARIA attribute is allowed"
            }
          ],
          "none": [],
          "impact": null,
          "html": "<a class=\"brand\" href=\"#top\" aria-label=\"Craftbound home\">",
          "target": [
            "a[aria-label=\"Craftbound home\"]"
          ]
        }
      ]
    },
    {
      "id": "aria-deprecated-role",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure elements do not use deprecated roles",
      "help": "Deprecated ARIA roles must not be used",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-deprecated-role?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [],
          "none": [
            {
              "id": "deprecatedrole",
              "data": null,
              "relatedNodes": [],
              "impact": "minor",
              "message": "ARIA role is not deprecated"
            }
          ],
          "impact": null,
          "html": "<div class=\"tabs reveal\" role=\"tablist\" style=\"transition-delay: 70ms;\">",
          "target": [
            ".tabs"
          ]
        }
      ]
    },
    {
      "id": "aria-hidden-body",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag131",
        "wcag412",
        "EN-301-549",
        "EN-9.1.3.1",
        "EN-9.4.1.2"
      ],
      "description": "Ensure aria-hidden=\"true\" is not present on the document body.",
      "help": "aria-hidden=\"true\" must not be present on the document body",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-hidden-body?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "aria-hidden-body",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "No aria-hidden attribute is present on document body"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<body>",
          "target": [
            "body"
          ]
        }
      ]
    },
    {
      "id": "aria-hidden-focus",
      "impact": null,
      "tags": [
        "cat.name-role-value",
        "wcag2a",
        "wcag412",
        "TTv5",
        "TT6.a",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure aria-hidden elements are not focusable nor contain focusable elements",
      "help": "ARIA hidden element must not be focusable or contain focusable elements",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-hidden-focus?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [
            {
              "id": "focusable-modal-open",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "No focusable elements while a modal is open"
            },
            {
              "id": "focusable-disabled",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "No focusable elements contained within element"
            },
            {
              "id": "focusable-not-tabbable",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "No focusable elements contained within element"
            }
          ],
          "none": [],
          "impact": null,
          "html": "<div class=\"marquee\" aria-hidden=\"true\">",
          "target": [
            ".marquee"
          ]
        }
      ]
    },
    {
      "id": "aria-prohibited-attr",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure ARIA attributes are not prohibited for an element's role",
      "help": "Elements must only use permitted ARIA attributes",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-prohibited-attr?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [],
          "none": [
            {
              "id": "aria-prohibited-attr",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "ARIA attribute is allowed"
            }
          ],
          "impact": null,
          "html": "<a class=\"brand\" href=\"#top\" aria-label=\"Craftbound home\">",
          "target": [
            "a[aria-label=\"Craftbound home\"]"
          ]
        }
      ]
    },
    {
      "id": "aria-required-attr",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure elements with ARIA roles have all required ARIA attributes",
      "help": "Required ARIA attributes must be provided",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-required-attr?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "aria-required-attr",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "All required ARIA attributes are present"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<div class=\"tabs reveal\" role=\"tablist\" style=\"transition-delay: 70ms;\">",
          "target": [
            ".tabs"
          ]
        }
      ]
    },
    {
      "id": "aria-required-children",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag131",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure elements with an ARIA role that require child roles contain them",
      "help": "Certain ARIA roles must contain particular children",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-required-children?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "aria-required-children",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "Required ARIA children are present"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<div class=\"tabs reveal\" role=\"tablist\" style=\"transition-delay: 70ms;\">",
          "target": [
            ".tabs"
          ]
        }
      ]
    },
    {
      "id": "aria-required-parent",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag131",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure elements with an ARIA role that require parent roles are contained by them",
      "help": "Certain ARIA roles must be contained by particular parents",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-required-parent?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "aria-required-parent",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "Required ARIA parent role present"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<button class=\"tab active\" data-tab=\"t1\" role=\"tab\">01 \u00b7 Dovetail Box</button>",
          "target": [
            "button[data-tab=\"t1\"]"
          ]
        }
      ]
    },
    {
      "id": "aria-roles",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure all elements with a role attribute use a valid value",
      "help": "ARIA roles used must conform to valid values",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-roles?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [],
          "none": [
            {
              "id": "invalidrole",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "ARIA role is valid"
            },
            {
              "id": "abstractrole",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "Abstract roles are not used"
            },
            {
              "id": "unsupportedrole",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "ARIA role is supported"
            }
          ],
          "impact": null,
          "html": "<div class=\"tabs reveal\" role=\"tablist\" style=\"transition-delay: 70ms;\">",
          "target": [
            ".tabs"
          ]
        }
      ]
    },
    {
      "id": "aria-valid-attr-value",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure all ARIA attributes have valid values",
      "help": "ARIA attributes must conform to valid values",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-valid-attr-value?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [
            {
              "id": "aria-valid-attr-value",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "ARIA attribute values are valid"
            },
            {
              "id": "aria-errormessage",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "aria-errormessage exists and references elements visible to screen readers that use a supported aria-errormessage technique"
            },
            {
              "id": "aria-level",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "aria-level values are valid"
            }
          ],
          "none": [],
          "impact": null,
          "html": "<a class=\"brand\" href=\"#top\" aria-label=\"Craftbound home\">",
          "target": [
            "a[aria-label=\"Craftbound home\"]"
          ]
        }
      ]
    },
    {
      "id": "aria-valid-attr",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure attributes that begin with aria- are valid ARIA attributes",
      "help": "ARIA attributes must conform to valid names",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-valid-attr?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "aria-valid-attr",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "ARIA attribute name is valid"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<a class=\"brand\" href=\"#top\" aria-label=\"Craftbound home\">",
          "target": [
            "a[aria-label=\"Craftbound home\"]"
          ]
        }
      ]
    },
    {
      "id": "avoid-inline-spacing",
      "impact": null,
      "tags": [
        "cat.structure",
        "wcag21aa",
        "wcag1412",
        "EN-301-549",
        "EN-9.1.4.12",
        "ACT"
      ],
      "description": "Ensure that text spacing set through style attributes can be adjusted with custom stylesheets",
      "help": "Inline text spacing must be adjustable with custom stylesheets",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/avoid-inline-spacing?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [
            {
              "id": "important-letter-spacing",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Letter-spacing in the style attribute is not set to !important, or meets the minimum"
            },
            {
              "id": "important-word-spacing",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "word-spacing in the style attribute is not set to !important, or meets the minimum"
            },
            {
              "id": "important-line-height",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "line-height in the style attribute is not set to !important, or meets the minimum"
            }
          ],
          "none": [],
          "impact": null,
          "html": "<div class=\"reveal in\" style=\"transition-delay: 0ms;\">",
          "target": [
            ".in.reveal:nth-child(1)"
          ]
        }
      ]
    },
    {
      "id": "button-name",
      "impact": null,
      "tags": [
        "cat.name-role-value",
        "wcag2a",
        "wcag412",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT6.a",
        "EN-301-549",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure buttons have discernible text",
      "help": "Buttons must have discernible text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/button-name?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "button-has-visible-text",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "Element has inner text that is visible to screen readers"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<button class=\"tab active\" data-tab=\"t1\" role=\"tab\">01 \u00b7 Dovetail Box</button>",
          "target": [
            "button[data-tab=\"t1\"]"
          ]
        }
      ]
    },
    {
      "id": "bypass",
      "impact": null,
      "tags": [
        "cat.keyboard",
        "wcag2a",
        "wcag241",
        "section508",
        "section508.22.o",
        "TTv5",
        "TT9.a",
        "EN-301-549",
        "EN-9.2.4.1"
      ],
      "description": "Ensure each page has at least one mechanism for a user to bypass navigation and jump straight to the content",
      "help": "Page must have means to bypass repeated blocks",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/bypass?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "internal-link-present",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Valid skip link found"
            },
            {
              "id": "header-present",
              "data": null,
              "relatedNodes": [
                {
                  "html": "<h1>Make something<br><span class=\"hl\">worth keeping.</span></h1>",
                  "target": [
                    "h1"
                  ]
                },
                {
                  "html": "<h2>A workshop, a library and a critique circle \u2014 in one tab</h2>",
                  "target": [
                    "#about > .container > .center.section-head.reveal > h2"
                  ]
                },
                {
                  "html": "<h3>Structured skill paths</h3>",
                  "target": [
                    ".feature:nth-child(1) > h3"
                  ]
                },
                {
                  "html": "<h3>Honest tool reviews</h3>",
                  "target": [
                    ".feature:nth-child(2) > h3"
                  ]
                },
                {
                  "html": "<h3>The pattern vault</h3>",
                  "target": [
                    ".feature:nth-child(3) > h3"
                  ]
                },
                {
                  "html": "<h3>Critique circles</h3>",
                  "target": [
                    ".feature:nth-child(4) > h3"
                  ]
                },
                {
                  "html": "<h2>Move past square boxes and straight seams</h2>",
                  "target": [
                    "#techniques > .container > .split:nth-child(1) > .reveal:nth-child(2) > h2"
                  ]
                },
                {
                  "html": "<h2>The parts of the craft that are hard to Google</h2>",
                  "target": [
                    ".rev > .reveal:nth-child(2) > h2"
                  ]
                },
                {
                  "html": "<h2>Tested on a real bench, not a press bench</h2>",
                  "target": [
                    "#tools > .container > .section-head.reveal > h2"
                  ]
                },
                {
                  "html": "<h3 style=\"margin:10px 0 4px\">Meridian 60\u00bd Low-Angle Block Plane</h3>",
                  "target": [
                    ".tool-card:nth-child(1) > div > .tool-top > div:nth-child(1) > h3"
                  ]
                },
                {
                  "html": "<h3 style=\"margin:10px 0 4px\">Northgate 18V Brushless Impact Driver</h3>",
                  "target": [
                    ".tool-card:nth-child(2) > div > .tool-top > div:nth-child(1) > h3"
                  ]
                },
                {
                  "html": "<h3 style=\"margin:10px 0 4px\">Kiln&amp;Stone 8000/6000 Ceramic Splash Set</h3>",
                  "target": [
                    ".top > div:nth-child(1) > h3"
                  ]
                },
                {
                  "html": "<h4>Community picks</h4>",
                  "target": [
                    ".panel:nth-child(1) > h4"
                  ]
                },
                {
                  "html": "<h4>Supply deals</h4>",
                  "target": [
                    ".panel:nth-child(2) > h4"
                  ]
                },
                {
                  "html": "<h4>Popular projects</h4>",
                  "target": [
                    ".dark-panel > h4"
                  ]
                },
                {
                  "html": "<h2>Three builds you can finish this weekend</h2>",
                  "target": [
                    "#tutorials > .container > .section-head.reveal > h2"
                  ]
                },
                {
                  "html": "<h3>The Through-Dovetail Keepsake Box</h3>",
                  "target": [
                    "#t1 > div:nth-child(1) > h3"
                  ]
                },
                {
                  "html": "<h2>38,400 makers. Zero gatekeeping.</h2>",
                  "target": [
                    "#community > .container > .center.section-head.reveal > h2"
                  ]
                },
                {
                  "html": "<h2>Live cohorts, capped at twelve seats</h2>",
                  "target": [
                    "#classes > .container > .section-head.reveal > h2"
                  ]
                },
                {
                  "html": "<h3>Hand-Cut Joinery Fundamentals</h3>",
                  "target": [
                    ".class-card:nth-child(1) > .class-body > h3"
                  ]
                },
                {
                  "html": "<h3>Natural Dyeing &amp; Vat Care</h3>",
                  "target": [
                    ".class-card:nth-child(2) > .class-body > h3"
                  ]
                },
                {
                  "html": "<h3>Wheel Throwing: Form &amp; Consistency</h3>",
                  "target": [
                    ".class-card:nth-child(3) > .class-body > h3"
                  ]
                },
                {
                  "html": "<h3>Bookbinding: Three Structural Styles</h3>",
                  "target": [
                    ".class-card:nth-child(4) > .class-body > h3"
                  ]
                },
                {
                  "html": "<h2>Supplies we've actually tested</h2>",
                  "target": [
                    "#shop > .container > .split > .reveal:nth-child(2) > h2"
                  ]
                },
                {
                  "html": "<h2>From \"I'm not really creative\" to sold-out market stall</h2>",
                  "target": [
                    "section:nth-child(12) > .container > .center.section-head.reveal > h2"
                  ]
                },
                {
                  "html": "<h2>Field notes, shop talk and long-form testing</h2>",
                  "target": [
                    ".section-head.reveal > div > h2"
                  ]
                },
                {
                  "html": "<h3 style=\"margin-top:14px\">We measured runout on 14 benchtop drills</h3>",
                  "target": [
                    ".feature:nth-child(1) > div > h3"
                  ]
                },
                {
                  "html": "<h3 style=\"margin-top:14px\">Drafting a repeat that survives the corner</h3>",
                  "target": [
                    ".feature:nth-child(2) > div > h3"
                  ]
                },
                {
                  "html": "<h3 style=\"margin-top:14px\">Pricing custom design work without guilt</h3>",
                  "target": [
                    ".feature:nth-child(3) > div > h3"
                  ]
                },
                {
                  "html": "<h2>Everything worth knowing before you join</h2>",
                  "target": [
                    "#faq > .container > .center.section-head.reveal > h2"
                  ]
                },
                {
                  "html": "<h2>One email a week: a technique, a tool, a pattern.</h2>",
                  "target": [
                    ".news > div:nth-child(1) > h2"
                  ]
                },
                {
                  "html": "<h5>Learn</h5>",
                  "target": [
                    "div:nth-child(2) > h5"
                  ]
                },
                {
                  "html": "<h5>Explore</h5>",
                  "target": [
                    "div:nth-child(3) > h5"
                  ]
                },
                {
                  "html": "<h5>Get in touch</h5>",
                  "target": [
                    "div:nth-child(4) > h5"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Page has a heading"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<html lang=\"en\">",
          "target": [
            "html"
          ]
        }
      ]
    },
    {
      "id": "color-contrast",
      "impact": "serious",
      "tags": [
        "cat.color",
        "wcag2aa",
        "wcag143",
        "TTv5",
        "TT13.c",
        "EN-301-549",
        "EN-9.1.4.3",
        "ACT"
      ],
      "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
      "help": "Elements must meet minimum color contrast ratio thresholds",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/color-contrast?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e6dbcc",
                "bgColor": "#17130f",
                "contrastRatio": 13.52,
                "fontSize": "10.0pt (13.28px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [],
              "impact": "serious",
              "message": "Element has sufficient color contrast of 13.52"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<div class=\"announce\">\n  Spring Workshop Series is open \u2014 12 live classes, small cohorts, all materials shipped. <a href=\"#classes\">See the schedule \u2192</a>\n</div>",
          "target": [
            ".announce"
          ]
        }
      ]
    },
    {
      "id": "document-title",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag242",
        "TTv5",
        "TT12.a",
        "EN-301-549",
        "EN-9.2.4.2",
        "ACT"
      ],
      "description": "Ensure each HTML document contains a non-empty <title> element",
      "help": "Documents must have <title> element to aid in navigation",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/document-title?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "doc-has-title",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Document has a non-empty <title> element"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<html lang=\"en\">",
          "target": [
            "html"
          ]
        }
      ]
    },
    {
      "id": "form-field-multiple-labels",
      "impact": null,
      "tags": [
        "cat.forms",
        "wcag2a",
        "wcag332",
        "TTv5",
        "TT5.c",
        "EN-301-549",
        "EN-9.3.3.2"
      ],
      "description": "Ensure form field does not have multiple label elements",
      "help": "Form field must not have multiple label elements",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/form-field-multiple-labels?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [],
          "none": [
            {
              "id": "multiple-label",
              "data": null,
              "relatedNodes": [],
              "impact": "moderate",
              "message": "Form field does not have multiple label elements"
            }
          ],
          "impact": null,
          "html": "<input type=\"email\" id=\"email\" placeholder=\"you@yourworkshop.com\" aria-label=\"Email address\" required=\"\">",
          "target": [
            "#email"
          ]
        }
      ]
    },
    {
      "id": "html-has-lang",
      "impact": null,
      "tags": [
        "cat.language",
        "wcag2a",
        "wcag311",
        "TTv5",
        "TT11.a",
        "EN-301-549",
        "EN-9.3.1.1",
        "ACT"
      ],
      "description": "Ensure every HTML document has a lang attribute",
      "help": "<html> element must have a lang attribute",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/html-has-lang?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "has-lang",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "The <html> element has a lang attribute"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<html lang=\"en\">",
          "target": [
            "html"
          ]
        }
      ]
    },
    {
      "id": "html-lang-valid",
      "impact": null,
      "tags": [
        "cat.language",
        "wcag2a",
        "wcag311",
        "TTv5",
        "TT11.a",
        "EN-301-549",
        "EN-9.3.1.1",
        "ACT"
      ],
      "description": "Ensure the lang attribute of the <html> element has a valid value",
      "help": "<html> element must have a valid value for the lang attribute",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/html-lang-valid?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [],
          "none": [
            {
              "id": "valid-lang",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Value of lang attribute is included in the list of valid languages"
            }
          ],
          "impact": null,
          "html": "<html lang=\"en\">",
          "target": [
            "html"
          ]
        }
      ]
    },
    {
      "id": "image-alt",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag111",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT7.a",
        "TT7.b",
        "EN-301-549",
        "EN-9.1.1.1",
        "ACT"
      ],
      "description": "Ensure <img> elements have alternative text or a role of none or presentation",
      "help": "Images must have alternative text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/image-alt?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "has-alt",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "Element has an alt attribute"
            }
          ],
          "all": [],
          "none": [
            {
              "id": "alt-space-value",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "Element has a valid alt attribute value"
            }
          ],
          "impact": null,
          "html": "<img src=\"https://placehold.co/104x104/17130F/DDA13A?text=CB&amp;font=playfair%20display\" alt=\"Craftbound logo mark\">",
          "target": [
            "a[aria-label=\"Craftbound home\"] > img[alt=\"Craftbound logo mark\"]"
          ]
        }
      ]
    },
    {
      "id": "label",
      "impact": null,
      "tags": [
        "cat.forms",
        "wcag2a",
        "wcag412",
        "section508",
        "section508.22.n",
        "TTv5",
        "TT5.c",
        "EN-301-549",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure every form element has a label",
      "help": "Form elements must have labels",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/label?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "aria-label",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "aria-label attribute exists and is not empty"
            },
            {
              "id": "non-empty-placeholder",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "Element has a placeholder attribute"
            }
          ],
          "all": [],
          "none": [
            {
              "id": "hidden-explicit-label",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "Form element has a visible explicit <label>"
            }
          ],
          "impact": null,
          "html": "<input type=\"email\" id=\"email\" placeholder=\"you@yourworkshop.com\" aria-label=\"Email address\" required=\"\">",
          "target": [
            "#email"
          ]
        }
      ]
    },
    {
      "id": "link-in-text-block",
      "impact": null,
      "tags": [
        "cat.color",
        "wcag2a",
        "wcag141",
        "TTv5",
        "TT13.a",
        "EN-301-549",
        "EN-9.1.4.1"
      ],
      "description": "Ensure links are distinguished from surrounding text in a way that does not rely on color",
      "help": "Links must be distinguishable without relying on color",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/link-in-text-block?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "link-in-text-block-style",
              "data": null,
              "relatedNodes": [
                {
                  "html": "<div class=\"announce\">\n  Spring Workshop Series is open \u2014 12 live classes, small cohorts, all materials shipped. <a href=\"#classes\">See the schedule \u2192</a>\n</div>",
                  "target": [
                    ".announce"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Links can be distinguished from surrounding text by visual styling"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<a href=\"#classes\">See the schedule \u2192</a>",
          "target": [
            ".announce > a[href$=\"#classes\"]"
          ]
        }
      ]
    },
    {
      "id": "link-name",
      "impact": null,
      "tags": [
        "cat.name-role-value",
        "wcag2a",
        "wcag244",
        "wcag412",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT6.a",
        "EN-301-549",
        "EN-9.2.4.4",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure links have discernible text",
      "help": "Links must have discernible text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/link-name?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "has-visible-text",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Element has text that is visible to screen readers"
            }
          ],
          "all": [],
          "none": [
            {
              "id": "focusable-no-name",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Element is not in tab order or has accessible text"
            }
          ],
          "impact": null,
          "html": "<a href=\"#classes\">See the schedule \u2192</a>",
          "target": [
            ".announce > a[href$=\"#classes\"]"
          ]
        }
      ]
    },
    {
      "id": "list",
      "impact": null,
      "tags": [
        "cat.structure",
        "wcag2a",
        "wcag131",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure that lists are structured correctly",
      "help": "<ul> and <ol> must only directly contain <li>, <script> or <template> elements",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/list?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [],
          "none": [
            {
              "id": "only-listitems",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "List element only has direct children that are allowed inside <li> elements"
            }
          ],
          "impact": null,
          "html": "<ul class=\"checklist\">",
          "target": [
            ".checklist"
          ]
        }
      ]
    },
    {
      "id": "listitem",
      "impact": null,
      "tags": [
        "cat.structure",
        "wcag2a",
        "wcag131",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure <li> elements are used semantically",
      "help": "<li> elements must be contained in a <ul> or <ol>",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/listitem?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "listitem",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "List item has a <ul>, <ol> or role=\"list\" parent element"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<li><strong>Grain reading &amp; cut geometry.</strong> Orienting a board so the growth rings work with the joint, reading figure before you rip, and choosing bevel direction for a mitre that closes itself.</li>",
          "target": [
            ".checklist > li:nth-child(1)"
          ]
        }
      ]
    },
    {
      "id": "meta-viewport",
      "impact": null,
      "tags": [
        "cat.sensory-and-visual-cues",
        "wcag2aa",
        "wcag144",
        "EN-301-549",
        "EN-9.1.4.4",
        "ACT"
      ],
      "description": "Ensure <meta name=\"viewport\"> does not disable text scaling and zooming",
      "help": "Zooming and scaling must not be disabled",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/meta-viewport?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "meta-viewport",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "<meta> tag does not disable zooming on mobile devices"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">",
          "target": [
            "meta[name=\"viewport\"]"
          ]
        }
      ]
    },
    {
      "id": "nested-interactive",
      "impact": null,
      "tags": [
        "cat.keyboard",
        "wcag2a",
        "wcag412",
        "TTv5",
        "TT6.a",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure interactive controls are not nested as they are not always announced by screen readers or can cause focus problems for assistive technologies",
      "help": "Interactive controls must not be nested",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/nested-interactive?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "no-focusable-content",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Element does not have focusable descendants"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<img src=\"https://placehold.co/104x104/17130F/DDA13A?text=CB&amp;font=playfair%20display\" alt=\"Craftbound logo mark\">",
          "target": [
            "a[aria-label=\"Craftbound home\"] > img[alt=\"Craftbound logo mark\"]"
          ]
        }
      ]
    },
    {
      "id": "summary-name",
      "impact": null,
      "tags": [
        "cat.name-role-value",
        "wcag2a",
        "wcag412",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT6.a",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure summary elements have discernible text",
      "help": "Summary elements must have discernible text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/summary-name?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "has-visible-text",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Element has text that is visible to screen readers"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<summary>Do I need my own tools to take a class?</summary>",
          "target": [
            "details[open=\"\"] > summary"
          ]
        }
      ]
    },
    {
      "id": "target-size",
      "impact": null,
      "tags": [
        "cat.sensory-and-visual-cues",
        "wcag22aa",
        "wcag258"
      ],
      "description": "Ensure touch targets have sufficient size and space",
      "help": "All touch targets must be 24px large, or leave sufficient space",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/target-size?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "target-size",
              "data": {
                "minSize": 24,
                "width": 440,
                "height": 52
              },
              "relatedNodes": [],
              "impact": "serious",
              "message": "Control has sufficient size (440px by 52px, should be at least 24px by 24px)"
            },
            {
              "id": "target-offset",
              "data": {
                "closestOffset": 24,
                "minOffset": 24
              },
              "relatedNodes": [],
              "impact": "serious",
              "message": "Target has sufficient space from its closest neighbors. Safe clickable space has a diameter of 24px which is at least 24px."
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<a class=\"brand\" href=\"#top\" aria-label=\"Craftbound home\">",
          "target": [
            "a[aria-label=\"Craftbound home\"]"
          ]
        }
      ]
    }
  ],
  "incomplete": [
    {
      "id": "color-contrast",
      "impact": "serious",
      "tags": [
        "cat.color",
        "wcag2aa",
        "wcag143",
        "TTv5",
        "TT13.c",
        "EN-301-549",
        "EN-9.1.4.3",
        "ACT"
      ],
      "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
      "help": "Elements must meet minimum color contrast ratio thresholds",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/color-contrast?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": "pseudoContent",
                "expectedContrastRatio": "4.5:1"
              },
              "relatedNodes": [
                {
                  "html": "<section class=\"hero\">",
                  "target": [
                    ".hero"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element's background color could not be determined due to a pseudo element"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Hobbies, crafts &amp; DIY since 2016</span>",
          "target": [
            ".in.reveal:nth-child(1) > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element's background color could not be determined due to a pseudo element"
        }
      ]
    }
  ],
  "violations": [
    {
      "id": "color-contrast",
      "impact": "serious",
      "tags": [
        "cat.color",
        "wcag2aa",
        "wcag143",
        "TTv5",
        "TT13.c",
        "EN-301-549",
        "EN-9.1.4.3",
        "ACT"
      ],
      "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
      "help": "Elements must meet minimum color contrast ratio thresholds",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/color-contrast?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#faf4eb",
                "contrastRatio": 4.16,
                "fontSize": "8.4pt (11.2px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<header class=\"site\" id=\"top\">",
                  "target": [
                    "#top"
                  ]
                },
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 8.4pt (11.2px), font weight: normal). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"tag\">Made by hand \u00b7 Made together</span>",
          "target": [
            "a[aria-label=\"Craftbound home\"] > span > .tag"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 8.4pt (11.2px), font weight: normal). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#4a423a",
                "bgColor": "#17130f",
                "contrastRatio": 1.87,
                "fontSize": "11.0pt (14.72px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<footer class=\"site\">",
                  "target": [
                    "footer"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 1.87 (foreground color: #4a423a, background color: #17130f, font size: 11.0pt (14.72px), font weight: normal). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<p style=\"max-width:34ch\">A learning platform and community for hobbyists, craftspeople and DIY makers \u2014 built by people who sell what they build. Independent testing, real critique, no gatekeeping.</p>",
          "target": [
            ".foot-grid > div:nth-child(1) > p"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 1.87 (foreground color: #4a423a, background color: #17130f, font size: 11.0pt (14.72px), font weight: normal). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#faf4eb",
                "contrastRatio": 4.16,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">What you get</span>",
          "target": [
            ".center.in.section-head > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#faf4eb",
                "contrastRatio": 4.16,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">What you get</span>",
          "target": [
            ".center.section-head.in > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#f0e6d8",
                "contrastRatio": 3.69,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<section id=\"techniques\" class=\"alt\">",
                  "target": [
                    "#techniques"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Advanced techniques</span>",
          "target": [
            ".in.reveal:nth-child(2) > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#f0e6d8",
                "contrastRatio": 3.69,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<section id=\"techniques\" class=\"alt\">",
                  "target": [
                    "#techniques"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Advanced techniques</span>",
          "target": [
            ".split:nth-child(1) > .in.reveal:nth-child(2) > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#f0e6d8",
                "contrastRatio": 3.69,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<section id=\"techniques\" class=\"alt\">",
                  "target": [
                    "#techniques"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Deep dives</span>",
          "target": [
            ".rev > .in.reveal:nth-child(2) > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#faf4eb",
                "contrastRatio": 4.16,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Tool reviews</span>",
          "target": [
            "#tools > .container > .section-head.in.reveal > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#f0e6d8",
                "contrastRatio": 3.69,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<section id=\"tutorials\" class=\"alt\">",
                  "target": [
                    "#tutorials"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">DIY tutorials</span>",
          "target": [
            "#tutorials > .container > .section-head.in.reveal > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#faf4eb",
                "contrastRatio": 4.16,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">What you get</span>",
          "target": [
            "#about > .container > .center.section-head.in > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#faf4eb",
                "contrastRatio": 4.16,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Classes</span>",
          "target": [
            "#classes > .container > .section-head.in.reveal > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#f0e6d8",
                "contrastRatio": 3.69,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<section id=\"techniques\" class=\"alt\">",
                  "target": [
                    "#techniques"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Advanced techniques</span>",
          "target": [
            "#techniques > .container > .split:nth-child(1) > .in.reveal:nth-child(2) > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#faf4eb",
                "contrastRatio": 4.16,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Member stories</span>",
          "target": [
            "section:nth-child(12) > .container > .center.section-head.in > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#f0e6d8",
                "contrastRatio": 3.69,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<section id=\"blog\" class=\"alt\">",
                  "target": [
                    "#blog"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">From the journal</span>",
          "target": [
            ".section-head.in.reveal > div > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#faf4eb",
                "contrastRatio": 4.16,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Questions</span>",
          "target": [
            "#faq > .container > .center.section-head.in > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#faf4eb",
                "contrastRatio": 4.16,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">What you get</span>",
          "target": [
            "#about > .container > .center.section-head.reveal > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#f0e6d8",
                "contrastRatio": 3.69,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<section id=\"techniques\" class=\"alt\">",
                  "target": [
                    "#techniques"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Advanced techniques</span>",
          "target": [
            "#techniques > .container > .split:nth-child(1) > .reveal.in:nth-child(2) > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#f0e6d8",
                "contrastRatio": 3.69,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<section id=\"techniques\" class=\"alt\">",
                  "target": [
                    "#techniques"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Deep dives</span>",
          "target": [
            ".rev > .reveal.in:nth-child(2) > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#faf4eb",
                "contrastRatio": 4.16,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Tool reviews</span>",
          "target": [
            "#tools > .container > .section-head.reveal.in > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#f0e6d8",
                "contrastRatio": 3.69,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<section id=\"tutorials\" class=\"alt\">",
                  "target": [
                    "#tutorials"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">DIY tutorials</span>",
          "target": [
            "#tutorials > .container > .section-head.reveal.in > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#faf4eb",
                "contrastRatio": 4.16,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Classes</span>",
          "target": [
            "#classes > .container > .section-head.reveal.in > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#faf4eb",
                "contrastRatio": 4.16,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Member stories</span>",
          "target": [
            "section:nth-child(12) > .container > .center.section-head.reveal > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#f0e6d8",
                "contrastRatio": 3.69,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<section id=\"blog\" class=\"alt\">",
                  "target": [
                    "#blog"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">From the journal</span>",
          "target": [
            ".section-head.reveal.in > div > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 3.69 (foreground color: #c0562b, background color: #f0e6d8, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#c0562b",
                "bgColor": "#faf4eb",
                "contrastRatio": 4.16,
                "fontSize": "9.0pt (12px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"eyebrow\">Questions</span>",
          "target": [
            "#faq > .container > .center.section-head.reveal > .eyebrow"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.16 (foreground color: #c0562b, background color: #faf4eb, font size: 9.0pt (12px), font weight: bold). Expected contrast ratio of 4.5:1"
        }
      ]
    }
  ],
  "coverage": {
    "contract": "main-document-vertical-scroll",
    "complete": true,
    "positions": [
      {
        "y": 0,
        "height": 13906
      },
      {
        "y": 576,
        "height": 13906
      },
      {
        "y": 1152,
        "height": 13906
      },
      {
        "y": 1728,
        "height": 13906
      },
      {
        "y": 2304,
        "height": 13906
      },
      {
        "y": 2880,
        "height": 13906
      },
      {
        "y": 3456,
        "height": 13906
      },
      {
        "y": 4032,
        "height": 13906
      },
      {
        "y": 4608,
        "height": 13906
      },
      {
        "y": 5184,
        "height": 13906
      },
      {
        "y": 5760,
        "height": 13906
      },
      {
        "y": 6336,
        "height": 13906
      },
      {
        "y": 6912,
        "height": 13906
      },
      {
        "y": 7488,
        "height": 13906
      },
      {
        "y": 8064,
        "height": 13906
      },
      {
        "y": 8640,
        "height": 13906
      },
      {
        "y": 9216,
        "height": 13906
      },
      {
        "y": 9792,
        "height": 13906
      },
      {
        "y": 10368,
        "height": 13906
      },
      {
        "y": 10944,
        "height": 13906
      },
      {
        "y": 11520,
        "height": 13906
      },
      {
        "y": 12096,
        "height": 13906
      },
      {
        "y": 12672,
        "height": 13906
      },
      {
        "y": 13186,
        "height": 13906
      }
    ],
    "scans": 25,
    "max_states": 512,
    "settle_ms": 5000,
    "page_timeout_seconds": 150,
    "layout_stability": "consecutive 100ms size samples within one CSS pixel",
    "animation_settling": "finite animations present when scroll resources are ready finish or are cancelled",
    "interactive_states": "not exercised",
    "horizontal_scroll": "not exercised"
  }
}
System Prompt
You are a lead web developer at a top digital agency, tasked with creating a one-page website for a new client based on the given specifications, delivered as an HTML file. First non-whitespace char '<', last non-whitespace char '>'. Use the following services to generate placeholder images where needed:
- placehold.co (text): https://placehold.co/[{w}x{h}|{size}][/{bg-color}/{text-color}]?text={text}&font=[lato|lora|montserrat|noto sans|open sans|oswald|playfair display|poppins|pt sans|raleway|roboto|source sans|source sans pro]
- picsum.photos (photos): https://picsum.photos/[{w}/{h}|{size}]?[grayscale][&blur={1-10}]
- pravatar.cc (avatars): https://i.pravatar.cc/{size}?u={identifier}
Choose sizes appropriate to layout.
User Prompt
Create a **complete, polished, production-quality** primary web page for a new client in the "Hobbies and Interests" sector.
Your goal is to generate the full HTML code for a page that is not just functional but also visually compelling, content-rich, and feels like a finished product ready for launch.

**Client & Category:**
- Industry: "Hobbies and Interests"
- Description: Hobbies, crafts, DIY projects, collecting, and special interest communities.

**Your Creative Task:**
1.  **Invent:** Create a unique, professional-sounding site name and a strong tagline fitting the "Hobbies and Interests" category.
2.  **Define Page:** Determine the most effective primary page type (e.g., homepage, service landing page, category portal) to showcase this fictional entity.
3.  **Design:** Develop an opinionated, modern, and professional layout. Make distinct choices about structure and flow.

**Content & Structure Requirements (Deliver a COMPLETE page):**
-   **Overall:** The final page must feel substantial and complete, with realistic amounts of text (multiple paragraphs per section where appropriate, avoid single sentences), well-integrated placeholder images, and logical flow. It should look like a real website a business would proudly use.
-   **HEADER:** Include the invented site name, tagline, a logo placeholder image, and a primary navigation bar. Ensure the navigation has **at least 5-7 clearly defined, relevant links** including: "Classes", "Shop", "Blog".
-   **MAIN CONTENT:** Structure this area with **at least 3-4 distinct, well-developed sections**.
    -   Address key topics relevant to the "Hobbies and Interests" category. Consider themes similar to: "Advanced Techniques", "Tool Reviews", "DIY Tutorials".
    -   **Content Depth:** Populate each section with **substantial, realistic text** (multiple sentences/paragraphs). Use authentic industry language and terminology like: "custom design", "handmade", "pattern design".
    -   **Visuals:** Integrate relevant placeholder images logically within the content sections.
    -   **Calls to Action:** Include clear and contextually relevant CTAs. Use strong verbs similar to: "Share Project", "Watch Video", "Get Supplies".
-   **ENGAGEMENT (Recommended):** Strongly consider incorporating **one meaningful interactive element** that would genuinely benefit a user in the "Hobbies and Interests" sector. Ideas similar but not limited to: "community gallery".
-   **SIDEBAR (Optional):** If your design includes a sidebar, populate it with **useful, relevant content**. Ideas: "community picks", "supply deals", "popular projects".
-   **FOOTER:** Include a professional footer with invented contact details, copyright (current year), social media links, and standard links (Privacy, Terms).
-   **MODERN WEB PATTERNS:** Include modern web patterns like testimonial cards, feature grids, or FAQ accordions where appropriate.