2026-09-21 20:56:03 +00:00
<!doctype html>
< html lang = "en" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< link rel = "icon" type = "image/x-icon" href = "/favicon.ico" >
< title > leatherworking zine | hello hello</ title >
< meta name = "description" content = "Lee Cattarin... on the internet!" >
< link rel = "alternate" href = "/feed.xml" type = "application/atom+xml" title = "hello hello" >
< meta property = "og:title" content = "leatherworking zine | hello hello" >
< meta property = "og:type" content = "website" >
< meta property = "og:description" content = "Lee Cattarin... on the internet!" >
< meta property = "og:site_name" content = "hello hello" >
< meta property = "og:url" content = "https://leecat.art/leatherworking-zine/" >
< meta property = "og:image" content = "https://leecat.art/img/leatherworking-zine.jpg" >
< meta property = "og:image:alt" content = "3 copies of the same zine with different colored cardstock covers. The cover reads 'Leatherworking Tools' and lists myself as the author. Surrounding the text are many small icons of tools and explanatory diagrams. The text is dark teal and the icons are dark pink." >
< meta name = "generator" content = "Eleventy v3.1.2" >
< meta itemprop = "ai-content-declaration:version" content = "1.0.0" >
< meta itemprop = "ai-content-declaration:level" content = "none" >
< 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=Atkinson+Hyperlegible+Mono:ital,wght@0,200..800;1,200..800&family=Atkinson+Hyperlegible+Next:ital,wght@0,200..800;1,200..800&display=swap" rel = "stylesheet" >
< script src = "https://kit.fontawesome.com/884dded219.js" crossorigin = "anonymous" ></ script >
< style ># toc {
float : right ;
margin : 1 rem 0 1.5 rem 1.5 rem ;
2026-09-21 22:56:13 +00:00
width : fit-content ;
max-width : 55 % ;
2026-09-21 20:56:03 +00:00
}
2026-09-21 23:08:43 +00:00
@ media ( max-width : 900px ) {
2026-09-21 20:56:03 +00:00
# toc {
float : unset ;
margin-top : 2 rem ;
margin-left : .5 rem ;
width : calc ( 100 % - .5 rem );
2026-09-21 22:56:13 +00:00
max-width : unset ;
2026-09-21 20:56:03 +00:00
}
}
# toc details {
border : thick solid var ( -- color - pink );
border-radius : 1 rem ;
margin-top : 1 rem ;
background-color : var ( -- color - bg );
}
# toc summary {
position : relative ;
top : -1.5 rem ;
left : -.75 rem ;
width : fit-content ;
background : var ( -- color - bg );
border-radius : .5 rem ;
cursor : pointer ;
2026-09-21 22:56:13 +00:00
padding-inline-end : .25 rem ;
2026-09-21 20:56:03 +00:00
}
# toc summary : focus-visible {
outline : .15 rem solid var ( -- color - teal );
}
# toc summary :: marker {
font-size : 2.35 rem ;
}
# toc h2 {
margin-top : 0 ;
display : inline ;
line-height : normal ;
}
# toc nav {
position : relative ;
top : -1.25 rem ;
}
2026-09-21 22:40:57 +00:00
/* `tree` style toc */
# toc nav > ol {
2026-09-21 22:56:13 +00:00
margin-inline : 1 rem ;
2026-09-21 20:56:03 +00:00
}
# toc ol {
2026-09-21 22:40:57 +00:00
margin : 0 ;
2026-09-21 20:56:03 +00:00
}
# toc li {
2026-09-21 22:40:57 +00:00
position : relative ;
padding-inline-start : 1 em ;
list-style : none ;
margin-block : 0 ;
margin-left : .35 rem ;
}
# toc li :: before ,
# toc li :: after {
display : block ;
position : absolute ;
box-sizing : border-box ;
inset-block : 0 auto ;
inset-inline : 0 auto ;
inline-size : .75 em ;
border-inline-start : .1 rem solid var ( -- color - pink );
2026-09-21 20:56:03 +00:00
}
# toc li :: before {
2026-09-21 22:40:57 +00:00
block-size : .5 lh ;
border-block-end : .1 rem solid var ( -- color - pink );
content : "" ;
2026-09-21 20:56:03 +00:00
}
2026-09-21 22:40:57 +00:00
# toc li : not ( : last-child ) :: after {
block-size : 100 % ;
content : "" ;
2026-09-21 20:56:03 +00:00
}
/* underlines are unnecessary in this context */
# toc a {
text-decoration : none ;
color : var ( -- color - blue );
font-weight : bold ;
}
# toc a : focus-visible {
outline-color : var ( -- color - pink );
}
. post-metadata {
display : flex ;
flex-flow : row wrap ;
justify-content : space-between ;
align-items : baseline ;
margin : 1.5 rem 0 .5 rem ;
}
. post-metadata p {
font-size : .9 rem ;
margin : 0 ;
}
. post-tags {
display : flex ;
flex-flow : row wrap ;
gap : .5 rem ;
list-style : none ;
margin : 0 ;
margin-left : auto ;
}
. post-tags li {
margin : 0 ;
}
. post-tags li a {
text-decoration : none ;
color : var ( -- color - teal );
padding : 0 .5 rem ;
border-radius : 1 rem ;
box-shadow : .15 rem .15 rem var ( -- color - shadow );
border : .08 rem solid var ( -- color - teal );
line-height : 2 ;
/* Click animation handling */
position : relative ;
top : 0 ;
left : 0 ;
transition : top .1 s ease-in , left .1 s ease-in ;
}
. post-tags li a : focus-visible {
outline : none ;
background-color : var ( -- color - teal );
color : var ( -- color - bg );
}
@ media ( any-hover : hover ) {
. post-tags li a : hover {
outline : none ;
background-color : var ( -- color - teal );
color : var ( -- color - bg );
}
}
@ media ( forced-colors : active ) {
. post-tags li a : focus-visible {
outline-offset : .08 rem ;
outline : .08 rem solid ;
}
@ media ( any-hover : hover ) {
. post-tags li a : hover {
outline-offset : .08 rem ;
outline : .08 rem solid ;
}
}
}
/* Click animation */
. post-tags li a : active {
top : .1 rem ;
left : .1 rem ;
box-shadow : .05 rem .05 rem var ( -- color - shadow );
}
# postlist ,
# taglist {
list-style : none ;
}
# postlist , . post ,
# taglist , . tag {
margin : 0 ;
}
/* Odd-numbered posts & tag layout/coloration */
. post : nth-child ( odd ) . postlink ,
. tag : nth-child ( odd ) . taglink {
grid-template-areas :
'img h2'
'img info'
'img .' ;
grid-template-columns : 45 % auto ;;
--color-primary : var ( -- color - teal );
--color-accent : var ( -- color - pink );
}
/* Even-numbered posts & tags layout/coloration */
. post : nth-child ( even ) . postlink ,
. tag : nth-child ( even ) . taglink {
grid-template-areas :
'h2 img'
'info img'
'. img' ;
grid-template-columns : auto 45 % ;
--color-primary : var ( -- color - pink );
--color-accent : var ( -- color - teal );
}
/* Layout for all posts on mobile */
@ media ( max-width : 650px ) {
. post : nth-child ( n ) . postlink ,
. tag : nth-child ( n ) . taglink {
grid-template-areas :
'img'
'h2'
'info' ;
grid-template-columns : auto ;
}
}
/* Link */
. postlink ,
. taglink {
display : grid ;
border : .25 rem solid var ( -- color - primary );
border-radius : 1.25 rem ;
box-shadow : .35 rem .35 rem var ( -- color - shadow );
margin : 2 rem 0 ;
text-decoration : none ;
/* Click animation handling */
position : relative ;
top : 0 ;
left : 0 ;
transition : top .05 s ease-in , left .05 s ease-in ;
}
. postlink : focus-visible ,
. taglink : focus-visible {
background-color : var ( -- color - primary );
outline : none ;
}
@ media ( any-hover : hover ) {
. postlink : hover ,
. taglink : hover {
background-color : var ( -- color - primary );
}
}
/* Forced colors */
@ media ( forced-colors : active ) {
. postlink : focus-visible ,
. taglink : focus-visible {
outline-offset : .25 rem ;
outline : .25 rem solid ;
}
@ media ( any-hover : hover ) {
. postlink : hover ,
. taglink : hover {
outline-offset : .25 rem ;
outline : .25 rem solid ;
}
}
}
/* Click animation */
. postlink : active ,
. taglink : active {
top : .2 rem ;
left : .2 rem ;
box-shadow : .15 rem .15 rem var ( -- color - shadow );
}
/* Post & tag elements */
. post h2 , . post img ,
. post ul , . post li ,
. tag h2 , . tag p ,
. tag img {
margin : 0 ;
}
. post h2 ,
. tag h2 {
grid-area : h2 ;
padding : .25 rem .5 rem ;
text-transform : uppercase ;
font-family : var ( -- font - family );
font-size : 1.5 rem ;
color : var ( -- color - primary );
border-radius : 1 rem 1 rem 0 0 ;
border-bottom : .25 rem solid var ( -- color - accent );
}
. post : nth-child ( even ) h2 ,
. tag : nth-child ( even ) h2 {
text-align : right ;
}
. postlink : focus-visible h2 ,
. taglink : focus-visible h2 {
color : var ( -- color - bg );
border-color : var ( -- color - bg );
}
@ media ( any-hover : hover ) {
. postlink : hover h2 ,
. taglink : hover h2 {
color : var ( -- color - bg );
border-color : var ( -- color - bg );
}
}
/* Images */
. post img ,
. tag-imgs {
grid-area : img ;
}
. blur {
filter : blur ( .75 rem );
clip-path : inset ( 0 round 1 rem );
}
. tag-imgs {
display : grid ;
grid-template-columns : repeat ( 2 , 1 fr );
gap : .15 rem ;
}
. tag-imgs img {
aspect-ratio : 3 / 2 ;
object-fit : cover ;
}
. missing-image {
width : 100 % ;
aspect-ratio : 3 / 2 ;
background-color : var ( -- color - bg - alt );
border-radius : 1 rem ;
}
. taglink : focus-visible . missing-image {
opacity : .7 ;
}
@ media ( any-hover : hover ) {
. taglink : hover . missing-image {
opacity : .7 ;
}
}
/* Post tags */
. postlist-tags {
grid-area : info ;
list-style : none ;
display : flex ;
flex-flow : row wrap ;
gap : .5 rem ;
padding : .5 rem ;
}
. post : nth-child ( odd ) . postlist-tags {
justify-content : flex-end ;
}
. postlist-tags li ,
. tagcount {
background-color : var ( -- color - primary );
color : var ( -- color - bg );
padding : 0 .5 rem ;
border-radius : 1 rem ;
}
. postlink : focus-visible . postlist-tags li ,
. taglink : focus-visible . tagcount {
background-color : var ( -- color - bg );
color : var ( -- color - primary );
}
@ media ( any-hover : hover ) {
. postlink : hover . postlist-tags li ,
. taglink : hover . tagcount {
background-color : var ( -- color - bg );
color : var ( -- color - primary );
}
}
/* Tag count */
. tag p {
grid-area : info ;
padding : .5 rem ;
}
. tag : nth-child ( odd ) p {
text-align : right ;
}
img [ tabindex = "0" ] {
cursor : pointer ;
}
img [ tabindex = "0" ] : focus-visible {
outline : .15 rem solid var ( -- color - teal );
}
dialog {
margin : auto ;
flex-flow : column ;
background : transparent ;
border : none ;
position : absolute ;
}
dialog [ open ] {
display : flex ;
}
dialog :: backdrop {
background-color : rgba ( from var ( -- color - bg ) r g b / .8 );
backdrop-filter : blur ( 4 px );
}
body : has ( dialog [ open ]) {
overflow : hidden ;
}
. close-dialog {
background-color : rgba ( from var ( -- color - teal ) r g b / .35 );
font-size : 1.5 rem ;
padding : 0 .5 rem .15 rem ;
border-radius : 1 rem ;
color : var ( -- color - teal );
box-shadow : .15 rem .15 rem var ( -- color - shadow );
border : .08 rem solid var ( -- color - teal );
align-self : flex-end ;
justify-self : flex-start ;
margin : 0 .1 rem ;
/* Click animation handling */
position : relative ;
top : 1 rem ;
left : -.15 rem ;
transition : top .1 s ease-in , left .1 s ease-in ;
}
. close-dialog : focus-visible {
outline : none ;
background-color : var ( -- color - teal );
color : var ( -- color - bg );
}
@ media ( any-hover : hover ) {
. close-dialog : hover {
outline : none ;
background-color : var ( -- color - teal );
color : var ( -- color - bg );
}
}
@ media ( forced-colors : active ) {
. close-dialog : focus-visible {
outline-offset : .08 rem ;
outline : .08 rem solid ;
}
@ media ( any-hover : hover ) {
. close-dialog : hover {
outline-offset : .08 rem ;
outline : .08 rem solid ;
}
}
}
/* Click animation */
. close-dialog : active {
top : 1.1 rem ;
left : -.05 rem ;
box-shadow : .05 rem .05 rem var ( -- color - shadow );
}
. modal-img {
max-height : calc ( 100 vh - 2 rem );
object-fit : contain ;
width : auto ;
max-width : 90 % ;
margin : 0 auto ;
}
@ font-face {
font-family : "Peritel" ;
src :
url ( "/fonts/Peritel/Peritel-Regular.woff2" ) format ( "woff2" ),
url ( "/fonts/Peritel/Peritel-Regular.otf" ) format ( "opentype" );
}
: root {
color-scheme : light dark ;
--font-family : 'Atkinson Hyperlegible Next' , sans-serif ;
/* if you change the header font, go to post-toc.css and fuck about with the width
of the table of contents */
--font-family-headers : 'Peritel' , 'Atkinson Hyperlegible Next' , sans-serif ;
--font-family-code : 'Atkinson Hyperlegible Mono' , monospace ;
--color-dark : #2e303e ;
--color-dark-alt : #3c3f52 ;
--color-light : #ebeeef ;
--color-light-alt : #dbe1e3 ;
--color-teal-dark : #18737b ;
--color-teal-light : #25b0bc ;
--color-pink-dark : #94195d ;
--color-pink-light : #ee9fcb ;
--color-shadow : rgba ( 2 , 10 , 40 , .25 );
/* Used for syntax highlighting */
--color-red-light : #f195aa ;
--color-orange-light : #fab795 ;
--color-yellow-light : #fbe6bc ;
--color-green-light : #29d398 ;
--color-blue-light : #26bbd9 ;
--color-purple-light : #ddaeea ;
--color-grey-light : #b9c3c6 ;
--color-red-dark : #991433 ;
--color-orange-dark : #883206 ;
--color-yellow-dark : #6a4906 ;
--color-green-dark : #125940 ;
--color-blue-dark : #125663 ;
--color-purple-dark : #722999 ;
--color-grey-dark : #4a4b64 ;
--color-text : light-dark ( var ( -- color - dark ), var ( -- color - light ));
--color-bg : light-dark ( var ( -- color - light ), var ( -- color - dark ));
--color-text-alt : light-dark ( var ( -- color - dark - alt ), var ( -- color - light - alt ));
--color-bg-alt : light-dark ( var ( -- color - light - alt ), var ( -- color - dark - alt ));
--color-teal : light-dark ( var ( -- color - teal - dark ), var ( -- color - teal - light ));
--color-pink : light-dark ( var ( -- color - pink - dark ), var ( -- color - pink - light ));
--color-red : light-dark ( var ( -- color - red - dark ), var ( -- color - red - light ));
--color-orange : light-dark ( var ( -- color - orange - dark ), var ( -- color - orange - light ));
--color-yellow : light-dark ( var ( -- color - yellow - dark ), var ( -- color - yellow - light ));
--color-green : light-dark ( var ( -- color - green - dark ), var ( -- color - green - light ));
--color-blue : light-dark ( var ( -- color - blue - dark ), var ( -- color - blue - light ));
--color-purple : light-dark ( var ( -- color - purple - dark ), var ( -- color - purple - light ));
--color-grey : light-dark ( var ( -- color - grey - dark ), var ( -- color - grey - light ));
}
: root : has ( # theme-light : checked ) {
color-scheme : light ;
}
: root : has ( # theme-dark : checked ) {
color-scheme : dark ;
}
/* Base */
* {
box-sizing : border-box ;
margin : 0 ;
padding : 0 ;
}
body {
font-family : var ( -- font - family );
color : var ( -- color - text );
background-color : var ( -- color - bg );
}
main {
width : 60 vw ;
max-width : 1000 px ;
margin : 0 auto ;
}
2026-09-21 23:08:43 +00:00
@ media ( max-width : 1100px ) {
2026-09-21 20:56:03 +00:00
main {
width : 75 vw ;
}
}
@ media ( max-width : 650px ) {
main {
width : 92 vw ;
}
}
/* Headers */
h1 , h2 , h3 , h4 , h5 , h6 {
line-height : 1.25 ;
color : var ( -- color - teal );
font-family : var ( -- font - family - headers );
letter-spacing : 0.1 rem ;
}
h1 {
margin-top : 3 rem ;
font-size : 3.7 rem ;
text-align : center ;
}
h2 {
margin-top : 2 rem ;
font-size : 2.35 rem ;
}
h3 {
margin-top : 1.5 rem ;
font-size : 1.7 rem ;
}
@ media ( max-width : 650px ) {
2026-10-05 23:59:36 +00:00
h1 {
margin-top : 1 rem ;
font-size : 2.25 rem ;
}
h2 { font-size : 1.8 rem ; }
2026-09-21 20:56:03 +00:00
h3 { font-size : 1.4 rem ; }
}
h4 , h5 , h6 {
margin-top : 1 rem ;
font-size : 1.25 rem ;
}
/* Images */
img {
display : block ;
max-width : 100 % ;
height : auto ;
border-radius : 1 rem ;
margin : 0 auto ;
}
/* Paragraphs */
p {
margin : 1.25 rem 0 ;
line-height : 1.4 ;
}
strong ,
b {
font-weight : 900 ;
}
/* Links */
a {
color : var ( -- color - text );
border-radius : .25 rem ;
text-decoration : underline ;
text-decoration-style : solid ;
text-decoration-thickness : .2 em ;
text-decoration-color : var ( -- color - teal );
transition : text - decoration-thickness .5 s ;
}
a : focus-visible {
text-decoration : none ;
outline : .15 rem solid var ( -- color - teal );
}
@ media ( any-hover : hover ) {
a : hover {
text-decoration-thickness : .4 em ;
}
}
a : active {
text-decoration-thickness : .4 em ;
}
/* Heading anchors */
a . ha ,
span . ha-placeholder {
color : var ( -- color - pink );
font-size : .8 em ;
vertical-align : .1 em ;
}
span . ha-placeholder {
opacity : .55 ;
}
/* Lists */
:: marker {
color : var ( -- color - pink );
}
ul , ol , dl , li {
margin-left : 1 rem ;
}
@ media ( max-width : 650px ) {
ul , ol , dl {
margin-left : 0 ;
}
}
li {
line-height : 1.4 ;
margin-top : .65 rem ;
margin-bottom : .65 rem ;
}
li ul , li ol {
margin : .5 rem 0 ;
margin-left : 1 rem ;
}
@ media ( max-width : 650px ) {
li ul , li ol {
margin-left : 0 ;
}
}
dt {
font-weight : 900 ;
margin-top : .5 rem ;
}
dd {
margin-left : 2 rem ;
margin-bottom : .75 rem ;
}
/* Blockquotes */
blockquote {
margin : .5 rem 0 ;
padding : 0 1 rem ;
border-radius : .25 rem 1 rem 1 rem .25 rem ;
line-height : 1.25 ;
border-left : .5 rem solid var ( -- color - pink );
}
blockquote ,
blockquote p ,
blockquote ol ,
blockquote ul {
background-color : var ( -- color - bg - alt );
padding : .5 rem ;
}
blockquote p {
margin : 0 ;
}
/* Tables */
table {
width : 100 % ;
border-spacing : 0 ; /* border collapse doesn't play nice with radii */
border-radius : .3 rem ;
border : thin solid var ( -- color - pink );
margin : 1.25 rem 0 ;
}
th {
color : var ( -- color - bg );
background-color : var ( -- color - pink );
}
th code {
color : var ( -- color - text ); /* Yes, I actually do this somewhere */
}
th , td {
padding : .5 rem ;
text-align : left ;
}
tr : nth-child ( even ) { background-color : var ( -- color - bg - alt ); }
th : not ( : first-child ) { border-left : thin solid var ( -- color - bg ); }
th : first-child { border-top-left-radius : .25 rem ; }
th : last-child { border-top-right-radius : .25 rem ; }
td : not ( : first-child ) { border-left : thin solid var ( -- color - pink ); }
/* Times */
time {
color : var ( -- color - grey );
}
/* Horizontal rules */
hr {
border : .25 rem solid var ( -- color - pink );
margin : 2 rem 0 ;
}
/* Used on home, reference, gallery pages */
. centered {
text-align : center ;
}
/* Currently only used for resume, but it's generalizable */
. upper {
text-transform : uppercase ;
}
/* Header */
header {
background-color : var ( -- color - bg );
padding : .75 rem 0 ;
border-bottom : thick solid var ( -- color - teal );
box-shadow : 0 .25 rem .15 rem var ( -- color - shadow );
display : grid ;
grid-template-columns : auto ;
}
/* Header links, pagination links */
header a ,
. pagination a ,
. webring ul a {
border-radius : 1 rem ;
border : .125 rem solid var ( -- color - pink );
color : var ( -- color - pink );
text-decoration : none ;
padding : 0 .25 rem ;
box-shadow : .15 rem .15 rem var ( -- color - shadow );
font-size : 1.2 rem ;
/* Click animation handling */
position : relative ;
top : 0 ;
left : 0 ;
transition : top .05 s ease-in , left .05 s ease-in ;
}
header a ,
. pagination . older a ,
. webring . prev a ,
. webring . rand a {
padding-right : .35 rem ;
}
. pagination . newer a ,
. webring . next a ,
. webring . rand a {
padding-left : .35 rem ;
}
header a : focus-visible ,
. pagination a : focus-visible ,
. webring ul a : focus-visible {
color : var ( -- color - bg );
border-color : var ( -- color - pink );
background-color : var ( -- color - pink );
outline : none ;
}
@ media ( any-hover : hover ) {
header a : hover ,
. pagination a : hover ,
. webring ul a : hover {
color : var ( -- color - bg );
border-color : var ( -- color - pink );
background-color : var ( -- color - pink );
}
}
@ media ( forced-colors : active ) {
header a : focus-visible ,
. pagination a : focus-visible ,
. webring ul a : focus-visible {
outline-offset : .125 rem ;
outline : .125 rem solid ;
}
@ media ( any-hover : hover ) {
header a : hover ,
. pagination a : hover ,
. webring ul a : hover {
outline-offset : .125 rem ;
outline : .125 rem solid ;
}
}
}
/* Click animation */
header a : active ,
. pagination a : active ,
. webring ul a : active {
top : .1 rem ;
left : .1 rem ;
box-shadow : .05 rem .05 rem var ( -- color - shadow );
}
/* Current page */
header a [ aria-current = "page" ] {
border-color : var ( -- color - teal );
color : var ( -- color - teal );
}
header a [ aria-current = "page" ] : focus-visible {
color : var ( -- color - bg );
border-color : var ( -- color - teal );
background-color : var ( -- color - teal );
}
@ media ( any-hover : hover ) {
header a [ aria-current = "page" ] : hover {
color : var ( -- color - bg );
background-color : var ( -- color - teal );
border-color : var ( -- color - teal );
}
}
/* Header link icons, pagination icons */
header i ,
. pagination i ,
. webring ul i {
color : var ( -- color - teal );
}
header i ,
. pagination . older i ,
. webring . prev i ,
. webring . rand i : nth-child ( 1 ) {
padding-left : .25 rem ;
}
. pagination . newer i ,
. webring . next i ,
. webring . rand i : nth-child ( 2 ) {
padding-right : .25 rem ;
}
header a [ aria-current = "page" ] i {
color : var ( -- color - pink );
}
header a : focus-visible i ,
a [ aria-current = "page" ] a : focus-visible i ,
. pagination a : focus-visible i ,
. webring ul a : focus-visible i {
color : var ( -- color - bg );
}
@ media ( any-hover : hover ) {
header a : hover i ,
header a [ aria-current = "page" ] : hover i ,
. pagination a : hover i ,
. webring ul a : hover i {
color : var ( -- color - bg );
}
}
/* Skip link */
# skip {
left : -999 px ;
position : absolute ;
top : auto ;
width : 1 px ;
height : 1 px ;
overflow : hidden ;
z-index : -99 ;
}
# skip : focus-visible {
display : inline-block ;
left : auto ;
top : auto ;
width : auto ;
height : auto ;
overflow : auto ;
margin : -.125 rem 10 % ;
z-index : 999 ;
}
/* Nav */
header ul {
display : flex ;
list-style : none ;
gap : 1 rem ;
justify-content : center ;
}
header ul ,
header li {
margin : 0 ;
}
@ media ( max-width : 650px ) {
. menu-text {
display : none ; /* Icons only on small screens */
}
header a {
padding : .15 rem .5 rem ;
}
header i {
padding : 0 ;
}
}
/* Footer */
footer {
padding : 1 rem 0 ;
font-size : .9 rem ;
border-top : thick solid var ( -- color - pink );
margin-top : 2 rem ;
}
footer ul {
display : flex ;
list-style : none ;
gap : .5 rem ;
justify-content : center ;
margin : 0 ;
}
footer li {
margin : 0 ;
}
footer li : nth-child ( 2 ) :: before ,
footer li : nth-child ( 2 ) :: after {
content : " ● " / "" ;
color : var ( -- color - teal );
}
@ media ( max-width : 650px ) {
footer ul {
flex-flow : column ;
text-align : center ;
}
footer li : nth-child ( 2 ) :: before ,
footer li : nth-child ( 2 ) :: after {
content : none ;
}
}
footer a {
text-decoration-color : var ( -- color - pink );
}
footer a : focus-visible {
outline-color : var ( -- color - pink );
}
/* color picker */
# theme {
display : flex ;
justify-content : center ;
margin : .5 rem auto 0 ;
padding : 0 .75 rem .5 rem ;
width : fit-content ;
border : .125 rem solid var ( -- color - teal );
border-radius : 2 rem ;
}
# theme legend {
margin : 0 auto ;
color : var ( -- color - teal );
}
footer label {
cursor : pointer ;
border : .125 rem solid var ( -- color - pink );
padding : 0 .25 rem ;
color : var ( -- color - pink );
background-color : var ( -- color - bg ); /* this stops the box shadows from showing through */
box-shadow : .15 em .15 em var ( -- color - shadow );
/* Click animation handling */
position : relative ;
top : 0 ;
left : 0 ;
transition : top .05 s ease-in , left .05 s ease-in ;
}
footer input : checked + label {
color : var ( -- color - blue );
border-color : var ( -- color - blue );
}
footer label i {
color : var ( -- color - teal );
}
footer input : checked + label i {
color : var ( -- color - pink );
}
@ media ( any-hover : hover ) {
footer label : hover ,
footer input : checked + label : hover ,
footer label : hover i ,
footer input : checked + label : hover i {
color : var ( -- color - bg );
}
footer label : hover {
background-color : var ( -- color - pink );
}
footer input : checked + label : hover {
background-color : var ( -- color - teal );
}
}
footer input : focus-visible + label ,
footer input : focus-visible + label i {
color : var ( -- color - bg );
background-color : var ( -- color - pink );
border-color : var ( -- color - pink );
}
footer input : checked : focus-visible + label ,
footer input : checked : focus-visible + label i {
color : var ( -- color - bg );
background-color : var ( -- color - teal );
border-color : var ( -- color - teal );
}
footer label : active {
top : .09 em ;
left : .09 em ;
box-shadow : .05 em .05 em var ( -- color - shadow );
}
label . theme-light {
border-top-left-radius : 1 rem ;
border-bottom-left-radius : 1 rem ;
border-right : none ;
padding-left : .35 rem ;
}
label . theme-auto {
}
label . theme-dark {
border-top-right-radius : 1 rem ;
border-bottom-right-radius : 1 rem ;
border-left : none ;
padding-right : .35 rem ;
}
footer input {
/* To allow screen reader to still access these. */
/* From https://lyra.horse/blog/2025/08/you-dont-need-js/ */
opacity : 0 ;
position : absolute ;
pointer-events : none ;
}
/* Pagination */
. pagination ,
. pagination li {
margin : 0 ;
}
. pagination {
display : grid ;
grid-template-columns : repeat ( 2 , 1 fr );
grid-template-areas : "older newer" ;
list-style : none ;
margin-top : 3 rem ;
}
@ media ( max-width : 650px ) {
. post-pagination {
grid-template-columns : 1 fr ;
grid-template-areas :
"older"
"newer" ;
gap : .75 rem ;
}
}
. pagination . older {
grid-area : older ;
}
. pagination . newer {
grid-area : newer ;
text-align : right ;
}
/* webring navigation */
. webring {
margin-bottom : 3 rem ;
}
. webring ul {
display : flex ;
flex-flow : row wrap ;
list-style : none ;
justify-content : center ;
gap : .5 rem ;
}
. webring ul ,
. webring li {
margin-left : 0 ;
}
/* Handle color schemes */
: root : has ( # theme-light : checked ) . dark {
display : none ;
}
: root : has ( # theme-dark : checked ) . light {
display : none ;
}
@ media ( prefers-color-scheme : light ) {
: root : not ( : has ( # theme-dark : checked )) . dark {
display : none ;
}
}
@ media ( prefers-color-scheme : dark ) {
: root : not ( : has ( # theme-light : checked )) . light {
display : none ;
}
}
. searchbox {
margin : 1 rem auto 0 ;
}
pagefind-searchbox {
/* Shadows */
--pf-scroll-shadow : var ( -- color - shadow ) !important ;
--pf-shadow-sm : .15 rem .15 rem 0 var ( -- color - shadow ) !important ;
--pf-shadow-md : .25 rem .25 rem 0 var ( -- color - shadow ) !important ;
--pf-shadow-lg : 1 rem 1 rem 0 var ( -- color - shadow ) !important ;
/* Typography */
--pf-font : var ( -- font - family ) !important ;
/* Border */
--pf-border-radius : 1.5 rem !important ;
/* Focus */
--pf-outline-width : .125 rem !important ;
--pf-outline-offset : 0 !important ;
/* Width */
--pf-searchbox-max-width : min ( 550 px , 92 vw ) !important ;
}
. light pagefind-searchbox {
--pf-text : var ( -- color - dark ) !important ;
--pf-text-secondary : var ( -- color - dark - alt ) !important ;
--pf-text-muted : var ( -- color - dark - alt ) !important ;
--pf-background : var ( -- color - light - alt ) !important ;
--pf-border : var ( -- color - pink - dark ) !important ;
--pf-border-focus : var ( -- color - pink - dark ) !important ;
--pf-skeleton : var ( -- color - light ) !important ;
--pf-skeleton-shine : var ( -- color - dark ) !important ;
--pf-hover : var ( -- color - light ) !important ;
--pf-mark : var ( -- color - teal - dark ) !important ;
--pf-outline-focus : var ( -- color - teal - dark ) !important ;
/* Error */
--pf-error-bg : var ( -- color - light - alt ) !important ;
--pf-error-border : var ( -- color - red - dark ) !important ;
--pf-error-text : var ( -- color - red - dark ) !important ;
--pf-error-text-secondary : var ( -- color - red - dark ) !important ;
}
. dark pagefind-searchbox {
--pf-text : var ( -- color - light ) !important ;
--pf-text-secondary : var ( -- color - light - alt ) !important ;
--pf-text-muted : var ( -- color - light - alt ) !important ;
--pf-background : var ( -- color - dark - alt ) !important ;
--pf-border : var ( -- color - pink - light ) !important ;
--pf-border-focus : var ( -- color - pink - light ) !important ;
--pf-skeleton : var ( -- color - dark ) !important ;
--pf-skeleton-shine : var ( -- color - dark ) !important ;
--pf-hover : var ( -- color - dark ) !important ;
--pf-mark : var ( -- color - teal - light ) !important ;
--pf-outline-focus : var ( -- color - teal - light ) !important ;
/* Error */
--pf-error-bg : var ( -- color - dark - alt ) !important ;
--pf-error-border : var ( -- color - red - light ) !important ;
--pf-error-text : var ( -- color - red - light ) !important ;
--pf-error-text-secondary : var ( -- color - red - light ) !important ;
}
pagefind-searchbox input {
border-width : .125 rem !important ;
}
pagefind-searchbox input : not ( : focus-visible ) {
box-shadow : var ( -- pf - shadow - md ) !important ;
}
@ media ( max-width : 650px ) {
. pf-trigger-shortcut {
display : none !important ;
}
}
. pf-searchbox-dropdown ,
. pf-searchbox-footer {
border-width : .125 rem !important ;
}
. pf-error {
margin-top : .5 rem !important ;
}
/* Adapted from PrismJS 1.30.0 Tomorrow Night theme
https://prismjs.com/download
*/
code ,
pre ,
code [ class *= language- ],
pre [ class *= language- ] {
font-family : var ( -- font - family - code );
background-color : var ( -- color - bg - alt );
font-size : .9 em ;
text-shadow : 0 1 px var ( -- color - shadow );
-moz- tab-size : 4 ;
-o- tab-size : 4 ;
tab-size : 4 ;
-webkit- hyphens : none ;
-moz- hyphens : none ;
-ms- hyphens : none ;
hyphens : none ;
}
pre ,
pre [ class *= language- ] {
margin : 1 rem 0 ;
padding : 1 rem ;
line-height : 1.5 ;
white-space : pre-wrap ;
word-break : break-word ;
overflow-wrap : break-word ;
border-radius : .5 rem ;
overflow : auto ;
}
: not ( pre )> code ,
: not ( pre )> code [ class *= language- ] {
padding : .2 rem ;
border-radius : .25 rem ;
white-space : normal ;
}
/* Selected text */
code :: -moz-selection ,
code :: -moz-selection ,
pre :: -moz-selection ,
pre :: -moz-selection ,
code [ class *= language- ] :: -moz-selection ,
code [ class *= language- ] :: -moz-selection ,
pre [ class *= language- ] :: -moz-selection ,
pre [ class *= language- ] :: -moz-selection ,
code :: selection ,
code :: selection ,
pre :: selection ,
pre :: selection ,
code [ class *= language- ] :: selection ,
code [ class *= language- ] :: selection ,
pre [ class *= language- ] :: selection ,
pre [ class *= language- ] :: selection {
text-shadow : none ;
background-color : var ( -- color - bg );
}
/* Syntax highlighting */
. token . namespace {
opacity : .7 ;
}
. token . bold ,
. token . important {
font-weight : 700
}
. token . italic {
font-style : italic
}
. token . block-comment ,
. token . cdata ,
. token . comment ,
. token . doctype ,
. token . prolog ,
. token . punctuation {
color : var ( -- color - grey );
}
. token . attr-name ,
. token . deleted ,
. token . namespace ,
. token . tag {
color : var ( -- color - red );
}
. token . boolean ,
. token . function ,
. token . number {
color : var ( -- color - orange );
}
. token . class-name ,
. token . constant ,
. token . property ,
. token . symbol {
color : var ( -- color - yellow );
}
. token . attr-value ,
. token . char ,
. token . regex ,
. token . string ,
. token . variable ,
. token . inserted {
color : var ( -- color - green );
}
. token . entity ,
. token . operator ,
. token . url ,
. token . function-name {
color : var ( -- color - blue );
}
. token . atrule ,
. token . builtin ,
. token . important ,
. token . keyword ,
. token . selector {
color : var ( -- color - purple );
}
@ media print {
/* Nav elements */
header ,
footer ,
nav {
display : none !important ;
}
/* Base */
body {
background-color : #fff ;
color : #000 ;
}
main {
width : 95 vw ;
}
h1 , h2 , h3 , h4 , h5 , h6 {
color : #000 ;
}
/* Links */
/* Hover is not really necessary, but it's annoying when testing otherwise */
a ,
a : hover {
text-decoration-style : dotted ;
text-decoration-thickness : .1 rem ;
text-decoration-color : #000 ;
}
a :: after {
content : " (" attr ( href ) ")" ;
}
/* Code */
code ,
pre ,
code [ class *= language- ],
pre [ class *= language- ] {
text-shadow : none ;
background-color : var ( -- color - light );
color : #000 !important ;
}
. token . namespace {
opacity : 1 ;
}
. token . block-comment ,
. token . cdata ,
. token . comment ,
. token . doctype ,
. token . prolog ,
. token . punctuation ,
. token . attr-name ,
. token . deleted ,
. token . namespace ,
. token . tag ,
. token . boolean ,
. token . function ,
. token . number ,
. token . class-name ,
. token . constant ,
. token . property ,
. token . symbol ,
. token . attr-value ,
. token . char ,
. token . regex ,
. token . string ,
. token . variable ,
. token . inserted ,
. token . entity ,
. token . operator ,
. token . url ,
. token . function-name ,
. token . atrule ,
. token . builtin ,
. token . important ,
. token . keyword ,
. token . selector {
color : #000 ;
}
}</ style >
< script type = "module" > // Thank you to https://github.com/daviddarnes/heading-anchors
// Thank you to https://amberwilson.co.uk/blog/are-your-anchor-links-accessible/
let globalInstanceIndex = 0 ;
class HeadingAnchors extends HTMLElement {
static register ( tagName = "heading-anchors" , registry = window . customElements ) {
if ( registry && ! registry . get ( tagName )) {
registry . define ( tagName , this );
}
}
static attributes = {
exclude : "data-ha-exclude" ,
prefix : "prefix" ,
content : "content" ,
}
static classes = {
anchor : "ha" ,
placeholder : "ha-placeholder" ,
srOnly : "ha-visualhide" ,
}
static defaultSelector = "h2,h3,h4,h5,h6" ;
static css = `
. ${ HeadingAnchors . classes . srOnly } {
clip: rect(0 0 0 0);
height: 1px;
overflow: hidden;
position: absolute;
width: 1px;
}
. ${ HeadingAnchors . classes . anchor } {
position: absolute;
left: var(--ha_offsetx);
top: var(--ha_offsety);
text-decoration: none;
opacity: 0;
}
. ${ HeadingAnchors . classes . placeholder } {
opacity: .3;
}
. ${ HeadingAnchors . classes . anchor } :is(:focus-within, :hover) {
opacity: 1;
}
. ${ HeadingAnchors . classes . anchor } ,
. ${ HeadingAnchors . classes . placeholder } {
display: inline-block;
padding: 0 .25em;
/* Disable selection of visually hidden label */
-webkit-user-select: none;
user-select: none;
}
@supports (anchor-name: none) {
. ${ HeadingAnchors . classes . anchor } {
position: absolute;
left: anchor(left);
top: anchor(top);
}
}` ;
get supports () {
return "replaceSync" in CSSStyleSheet . prototype ;
}
get supportsAnchorPosition () {
return CSS . supports ( "anchor-name: none" );
}
constructor () {
super ();
if ( ! this . supports ) {
return ;
}
let sheet = new CSSStyleSheet ();
sheet . replaceSync ( HeadingAnchors . css );
document . adoptedStyleSheets = [... document . adoptedStyleSheets , sheet ];
this . headingStyles = {};
this . instanceIndex = globalInstanceIndex ++ ;
}
connectedCallback () {
if ( ! this . supports ) {
return ;
}
this . headings . forEach (( heading , index ) => {
if ( ! heading . hasAttribute ( HeadingAnchors . attributes . exclude )) {
let anchor = this . getAnchorElement ( heading );
let placeholder = this . getPlaceholderElement ();
// Prefers anchor position approach for better accessibility
// https://amberwilson.co.uk/blog/are-your-anchor-links-accessible/
if ( this . supportsAnchorPosition ) {
let anchorName = `--ha_ ${ this . instanceIndex } _ ${ index } ` ;
placeholder . style . setProperty ( "anchor-name" , anchorName );
anchor . style . positionAnchor = anchorName ;
}
heading . appendChild ( placeholder );
heading . after ( anchor );
}
});
}
// Polyfill-only
positionAnchorFromPlaceholder ( placeholder ) {
if ( ! placeholder ) {
return ;
}
let heading = placeholder . closest ( "h1,h2,h3,h4,h5,h6" );
if ( ! heading . nextElementSibling ) {
return ;
}
// TODO next element could be more defensive
this . positionAnchor ( heading . nextElementSibling );
}
// Polyfill-only
positionAnchor ( anchor ) {
if ( ! anchor || ! anchor . previousElementSibling ) {
return ;
}
// TODO previous element could be more defensive
let heading = anchor . previousElementSibling ;
this . setFontProp ( heading , anchor );
if ( this . supportsAnchorPosition ) {
// quit early
return ;
}
let placeholder = heading . querySelector ( `. ${ HeadingAnchors . classes . placeholder } ` );
if ( placeholder ) {
anchor . style . setProperty ( "--ha_offsetx" , ` ${ placeholder . offsetLeft } px` );
anchor . style . setProperty ( "--ha_offsety" , ` ${ placeholder . offsetTop } px` );
}
}
setFontProp ( heading , anchor ) {
let placeholder = heading . querySelector ( `. ${ HeadingAnchors . classes . placeholder } ` );
if ( placeholder ) {
let style = getComputedStyle ( placeholder );
let props = [ "font-weight" , "font-size" , "line-height" , "font-family" ];
let [ weight , size , lh , family ] = props . map ( name => style . getPropertyValue ( name ));
anchor . style . setProperty ( "font" , ` ${ weight } ${ size } / ${ lh } ${ family } ` );
let vars = style . getPropertyValue ( "font-variation-settings" );
if ( vars ) {
anchor . style . setProperty ( "font-variation-settings" , vars );
}
}
}
/* no longer used, using aria-labelledby instead - see getAnchorElement
getAccessibleTextPrefix() {
// Useful for i18n
return this.getAttribute(HeadingAnchors.attributes.prefix) || "Jump to section titled";
}
*/
getContent () {
if ( this . hasAttribute ( HeadingAnchors . attributes . content )) {
return this . getAttribute ( HeadingAnchors . attributes . content );
}
return "#" ;
}
// Placeholder nests inside of heading
getPlaceholderElement () {
let ph = document . createElement ( "span" );
ph . setAttribute ( "aria-hidden" , true );
ph . classList . add ( HeadingAnchors . classes . placeholder );
let content = this . getContent ();
if ( content ) {
ph . innerHTML = content ; // CHANGED HERE
}
ph . addEventListener ( "mouseover" , ( e ) => {
let placeholder = e . target . closest ( `. ${ HeadingAnchors . classes . placeholder } ` );
if ( placeholder ) {
this . positionAnchorFromPlaceholder ( placeholder );
}
});
return ph ;
}
getAnchorElement ( heading ) {
let anchor = document . createElement ( "a" );
anchor . href = `# ${ heading . id } ` ;
anchor . classList . add ( HeadingAnchors . classes . anchor );
let content = this . getContent ();
anchor . innerHTML = `<span aria-labelledby= ${ heading . id } > ${ content } </span>` ; // CHANGED HERE
anchor . addEventListener ( "focus" , e => {
let anchor = e . target . closest ( `. ${ HeadingAnchors . classes . anchor } ` );
if ( anchor ) {
this . positionAnchor ( anchor );
}
});
anchor . addEventListener ( "mouseover" , ( e ) => {
// when CSS anchor positioning is supported, this is only used to set the font
let anchor = e . target . closest ( `. ${ HeadingAnchors . classes . anchor } ` );
this . positionAnchor ( anchor );
});
return anchor ;
}
get headings () {
return this . querySelectorAll ( this . selector . split ( "," ). map ( entry => ` ${ entry . trim () } [id]` ));
}
get selector () {
return this . getAttribute ( "selector" ) || HeadingAnchors . defaultSelector ;
}
}
HeadingAnchors . register ();
export { HeadingAnchors }
/* don't even bother on mobile */
if ( window . innerWidth > 650 ) {
const dialog = document . querySelector ( "dialog" );
const closeButton = document . querySelector ( ".close-dialog" );
const hero = document . querySelector ( ".hero" );
hero . tabIndex = 0 ;
hero . addEventListener ( "click" , ( e ) => dialog . showModal ());
hero . addEventListener ( "keydown" , ( e ) => {
if ( e . key === "Enter" || e . key === " " ) {
e . preventDefault ();
dialog . showModal ();
}
});
closeButton . addEventListener ( "click" , ( e ) => dialog . close ());
closeButton . addEventListener ( "keydown" , ( e ) => {
if ( e . key === "Enter" || e . key === " " ) {
e . preventDefault ();
dialog . close ();
}
});
}
const THEME = "theme" ;
const saveTheme = ( themeValue ) => {
localStorage . setItem ( THEME , themeValue );
};
const themeLight = document . getElementById ( "theme-light" );
themeLight . addEventListener ( "input" , ( e ) => {
saveTheme ( themeLight . value );
});
const themeAuto = document . getElementById ( "theme-auto" );
themeAuto . addEventListener ( "input" , ( e ) => {
saveTheme ( themeAuto . auto );
});
const themeDark = document . getElementById ( "theme-dark" );
themeDark . addEventListener ( "input" , ( e ) => {
saveTheme ( themeDark . value );
});
var currentThemeValue = localStorage . getItem ( THEME );
switch ( currentThemeValue ) {
case "light" :
themeLight . checked = true ;
themeAuto . checked = false ;
break ;
case "dark" :
themeDark . checked = true ;
themeAuto . checked = false ;
break ;
case "auto" :
default :
themeAuto . checked = true ;
}</ script >
< link href = "/pagefind/pagefind-component-ui.css" rel = "stylesheet" >
< script src = "/pagefind/pagefind-component-ui.js" type = "module" ></ script >
</ head >
< body >
< header >
< a href = "#main" id = "skip" title = "skip to main content" >
< i class = "fa-solid fa-forward" aria-hidden = "true" ></ i > skip
</ a >
< nav aria-label = "main navigation" >
< ul >
< li >
< a href = "/reference/" title = "read reference posts" >
< i class = "fa-regular fa-folder-open" aria-hidden = "true" ></ i >
< span class = "menu-text" > reference</ span >
</ a >
</ li >
< li >
< a href = "/gallery/" title = "view the gallery" >
< i class = "fa-regular fa-images" aria-hidden = "true" ></ i >
< span class = "menu-text" > gallery</ span >
</ a >
</ li >
< li >
< a href = "/" title = "home" >
< i class = "fa fa-solid fa-crow" aria-hidden = "true" ></ i >
< span class = "menu-text" > home</ span >
</ a >
</ li >
< li >
< a href = "/about/" title = "about Lee" >
< i class = "fa-regular fa-user" aria-hidden = "true" ></ i >
< span class = "menu-text" > about</ span >
</ a >
</ li >
< li >
< a href = "/contact/" title = "contact Lee" >
< i class = "fa-solid fa-envelope-open-text" aria-hidden = "true" ></ i >
< span class = "menu-text" > contact</ span >
</ a >
</ li >
</ ul >
</ nav >
< div class = "dark searchbox" data-pf-theme = "dark" >
< pagefind-searchbox ></ pagefind-searchbox >
</ div >
< div class = "light searchbox" >
< pagefind-searchbox ></ pagefind-searchbox >
</ div >
</ header >
< main id = "main" >
< heading-anchors content = "<i class='fa-solid fa-anchor'></i>" >
< article data-pagefind-body = "" >
< h1 > leatherworking zine</ h1 >
< div class = "post-metadata" >
< p >
posted on
< time datetime = "2026-08-28" > August 28, 2026</ time >
by Lee Cattarin
</ p >
< ul class = "post-tags" >
< li >
< a href = "/tags/zine/" > zine</ a >
</ li >
< li >
< a href = "/tags/leather/" > leather</ a >
</ li >
</ ul >
</ div >
< dialog closedby = "any" aria-label = "image modal" tabindex = "-1" >
< button class = "close-dialog" autofocus = "" aria-label = "close the image modal" > × </ button >
< img class = "modal-img" src = "/img/leatherworking-zine.jpg" alt = "3 copies of the same zine with different colored cardstock covers. The cover reads 'Leatherworking Tools' and lists myself as the author. Surrounding the text are many small icons of tools and explanatory diagrams. The text is dark teal and the icons are dark pink." loading = "lazy" decoding = "async" width = "1000" height = "750" >
</ dialog >
< img class = "hero" src = "/img/leatherworking-zine.jpg" alt = "3 copies of the same zine with different colored cardstock covers. The cover reads 'Leatherworking Tools' and lists myself as the author. Surrounding the text are many small icons of tools and explanatory diagrams. The text is dark teal and the icons are dark pink." loading = "lazy" decoding = "async" width = "1000" height = "750" >
< aside id = "toc" >
< details >
< summary >< h2 > table of contents</ h2 ></ summary >
< nav class = "toc" >
< ol >
< li >< a href = "#on-tool-links" > On tool links</ a >
</ li >
< li >< a href = "#retailers" > Retailers</ a >
</ li >
< li >< a href = "#cover" > Cover</ a >
</ li >
< li >< a href = "#page-1%3A-basics" > Page 1: Basics</ a >
</ li >
< li >< a href = "#page-2%3A-cut" > Page 2: Cut</ a >
</ li >
< li >< a href = "#page-3%3A-burnish" > Page 3: Burnish</ a >
< ol >
< li >< a href = "#my-core-tools" > My core tools</ a >
</ li >
< li >< a href = "#other-potential-tools" > Other potential tools</ a >
</ li >
</ ol >
</ li >
< li >< a href = "#page-4%3A-punch" > Page 4: Punch</ a >
< ol >
< li >< a href = "#simulating-an-oblong-punch" > Simulating an oblong punch</ a >
</ li >
</ ol >
</ li >
< li >< a href = "#page-6%3A-stitch" > Page 6: Stitch</ a >
< ol >
< li >< a href = "#saddle-stitch" > Saddle stitch</ a >
</ li >
</ ol >
</ li >
< li >< a href = "#page-8%3A-rivet" > Page 8: Rivet</ a >
</ li >
</ ol >
</ nav >
</ details >
</ aside >
< p > This page contains textual representation of and supplementary material for my Leatherworking Tools zine, including links to all tools and additional information as needed.</ p >
< p > The Leatherworking Tools zine has been created for < a href = "/fedizinefest-2026-2027" > FediZineFest 2026-2027</ a > and will be part of the physical and digital bundles. For digital material, there will be a home-printable version and a version for reading on digital devices. If you want the delightfully illustrated zine itself, < a href = "https://ko-fi.com/inherentlee/shop/fedizinefest2026_2027" target = "_blank" rel = "external" > buy a bundle now</ a > .</ p >
< h2 id = "on-tool-links" > On tool links</ h2 >
< p > Please note that links are examples, and you do not need the precise model linked. Where possible, I have found cheaper versions of tools - for example, you < em > can</ em > get a fancy mallet or maul (they < em > are</ em > nice), or you can get a 16oz or 32oz hardware store rubber mallet. I have linked the hardware store version.</ p >
< p > Some things, like thread or rivets, come in other colors or finishes. Feel free to explore; I have linked only one.</ p >
< h2 id = "retailers" > Retailers</ h2 >
< p > Please note that I am familiar with US retailers, and cannot make recommendations for other countries.</ p >
< p > My favorite leatherworking retailer is < a href = "https://www.buckleguy.com/" target = "_blank" rel = "external" > Buckleguy</ a > . They offer tools, hardware, leather, supplies, etc. and are generally extremely high quality with good customer service.</ p >
< p > Occasionally, I will link other retailers such as < a href = "https://tandyleather.com/" target = "_blank" rel = "external" > Tandy</ a > (a common retailer, but with products that may be lower quality - great for bulk leather for prototype and practice though!), < a href = "https://www.weaverleathersupply.com/" target = "_blank" rel = "external" > Weaver</ a > , or < a href = "https://springfieldleather.com/" target = "_blank" rel = "external" > Springfield</ a > . I will also link to non-leather specific retailers such as < a href = "https://www.dickblick.com/" target = "_blank" rel = "external" > Blick</ a > and < a href = "https://www.acehardware.com/" target = "_blank" rel = "external" > Ace Hardware</ a > as is relevant.</ p >
< h2 id = "cover" > Cover</ h2 >
< p > The front and back cover spread is patterned with many small icons of leatherworking tools and explanatory diagrams in dark pink. Dark teal text reads " Leatherworking tools" " by Lee," and, on the back " 2026." </ p >
< h2 id = "page-1%3A-basics" > Page 1: Basics</ h2 >
< ul >
< li >< a href = "https://www.buckleguy.com/4-2-scratch-awl-3-1-2/" target = "_blank" rel = "external" > Scratch awl</ a > for marking
< ul >
< li > Do not use a pen/sharpie/similar for marking as it will very much show on the finished product</ li >
</ ul >
</ li >
< li >< a href = "https://www.weaverleathersupply.com/products/pattern-sheet-24-x-45" target = "_blank" rel = "external" > Pattern plastic</ a > for templating</ li >
< li >< a href = "https://www.buckleguy.com/bg-acrylic-tool-leather-thickness-gauge/" target = "_blank" rel = "external" > Leather thickness gauge</ a > for measuring
< ul >
< li > You can also use calipers and a table of sizes, but this is very handy</ li >
</ ul >
</ li >
</ ul >
< h2 id = "page-2%3A-cut" > Page 2: Cut</ h2 >
< ul >
< li >< a href = "https://www.dickblick.com/products/x-acto-1-knife/" target = "_blank" rel = "external" > Craft knife</ a >
< ul >
< li > Replace blades often</ li >
</ ul >
</ li >
< li >< a href = "https://www.dickblick.com/products/blick-aluminum-non-slip-rulers/" target = "_blank" rel = "external" > Non-slip metal ruler</ a >
< ul >
< li > Metal is a must if you don't want to cut into your ruler</ li >
</ ul >
</ li >
< li >< a href = "https://www.dickblick.com/products/blick-self-healing-cutting-mats/" target = "_blank" rel = "external" > Cutproof mat</ a ></ li >
< li >< a href = "https://www.buckleguy.com/bg-acrylic-tool-belt-tabs-multiple-styles/" target = "_blank" rel = "external" > Strap end template</ a ></ li >
</ ul >
< p > If you're cutting a curve, make many straight cuts rather than one curved cut.</ p >
< h2 id = "page-3%3A-burnish" > Page 3: Burnish</ h2 >
< h3 id = "my-core-tools" > My core tools</ h3 >
< ul >
< li >< a href = "https://springfieldleather.com/products/burnishing-cloth-10-pk" target = "_blank" rel = "external" > Canvas</ a >
< ul >
< li > Of course you can just go find some at a fabric store, but this lets you buy just a few small pieces</ li >
</ ul >
</ li >
< li >< a href = "tandyleather.com/products/tokonole-burnishing-agent" > Tokonole</ a >
< ul >
< li > You'll want clear Tokonole</ li >
< li > Shake before use</ li >
< li > You can apply this with a bit of cloth, < a href = "https://www.buckleguy.com/wool-daubers-5-length-12-per-bag/" target = "_blank" rel = "external" > wool dauber</ a > , < a href = "https://www.dickblick.com/products/lineco-micro-spatula/" target = "_blank" rel = "external" > micro spatula</ a > , etc... I just use my finger</ li >
</ ul >
</ li >
</ ul >
< h3 id = "other-potential-tools" > Other potential tools</ h3 >
< ul >
< li >< a href = "https://www.buckleguy.com/bg-leather-edge-beveler-multiple-sizes/" target = "_blank" rel = "external" > Edge beveler</ a >
< ul >
< li > Proper finished edges should be beveled, but you can get away without this when starting</ li >
</ ul >
</ li >
< li >< a href = "https://www.acehardware.com/departments/paint-and-supplies/painting-tools-and-supplies/sandpaper/F035922?variationProductCode=19808" target = "_blank" rel = "external" > Sandpaper</ a >
< ul >
< li > Grit varies; use significantly higher grits for final finish</ li >
</ ul >
</ li >
< li >< a href = "https://www.buckleguy.com/fiebing-s-beeswax-1oz/" target = "_blank" rel = "external" > Beeswax</ a ></ li >
</ ul >
< h2 id = "page-4%3A-punch" > Page 4: Punch</ h2 >
< ul >
< li >< a href = "https://www.buckleguy.com/cutting-board-multiple-sizes/" target = "_blank" rel = "external" > Cutting board</ a >
< ul >
< li > Don't use hole punches on your cutproof mat!</ li >
</ ul >
</ li >
< li >< a href = "https://www.acehardware.com/departments/tools/hand-tools/deadblow-hammers-mallets/2037238" target = "_blank" rel = "external" > Mallet</ a >
< ul >
< li > Mauls are also an option</ li >
</ ul >
</ li >
< li >< a href = "https://www.buckleguy.com/245-belt-punch-multiple-sizes/" target = "_blank" rel = "external" > Single hole punches</ a > , or...</ li >
< li >< a href = "https://www.buckleguy.com/cs-osborne-223-revolving-punch/" target = "_blank" rel = "external" > Rotary punch</ a >
< ul >
< li > If you choose a rotary punch, you don't need the cutting board and mallet (at least for this)</ li >
< li > I find rotary punches are too big for my small hands! So I prefer single hole punches</ li >
</ ul >
</ li >
< li >< a href = "https://www.buckleguy.com/cs-osborne-151-bag-punch-oblong-multiple-sizes/" target = "_blank" rel = "external" > Oblong punches</ a >
< ul >
< li > If you're setting buckles, you might want this, or...</ li >
</ ul >
</ li >
</ ul >
< h3 id = "simulating-an-oblong-punch" > Simulating an oblong punch</ h3 >
< ol >
< li >< strong > Plan:</ strong > draw your oblong shape. You'll probably want it about as long as your leather strap is wide, and the width should be determined by the width of the buckle tongue</ li >
< li >< strong > Punch two holes:</ strong > punch a hole at each end of the oblong</ li >
< li >< strong > Cut from one side < em > halfway</ em > in:</ strong > from one hole, cut halfway through the oblong</ li >
< li >< strong > Cut remainder of line from other side:</ strong > meet your existing cut</ li >
< li >< strong > Success!</ strong ></ li >
</ ol >
< h2 id = "page-6%3A-stitch" > Page 6: Stitch</ h2 >
< ul >
< li >< a href = "https://www.buckleguy.com/bg-leather-wing-divider-compass-0-20mm/" target = "_blank" rel = "external" > Wing divider/scratch compass</ a >
< ul >
< li > Lets you draw guidelines an even distance from edges</ li >
< li > Craft store compasses < em > may</ em > work, but you'd want to ensure that they are pointed enough to mark a line</ li >
</ ul >
</ li >
< li >< a href = "https://www.buckleguy.com/bg-stitching-punch/" target = "_blank" rel = "external" > Stitching chisels</ a >
< ul >
< li > Get a 2-tooth and one with lots of teeth - a full set is nice, but not as necessary</ li >
< li > Also called " pricking irons" </ li >
< li >< strong > Use these with your cutting board, < em > not</ em > your cutproof mat</ strong ></ li >
< li > You can also use a combination of a < a href = "https://www.buckleguy.com/japanese-stitching-marking-wheel-curved-handle/" target = "_blank" rel = "external" > marking wheel</ a > and < a href = "https://www.buckleguy.com/bg-leather-awls-detachable-needle/" target = "_blank" rel = "external" > awl</ a > , but this < em > will</ em > be slower and you won't be able to punch out 6-9 stitches at once</ li >
</ ul >
</ li >
< li > 2 < a href = "https://www.buckleguy.com/517-harness-needles-for-hand-sewing-blunt-tip-5-needles/" target = "_blank" rel = "external" > Blunt tip needles</ a ></ li >
< li >< a href = "https://www.buckleguy.com/ritza-25-tiger-thread-waxed-polyester-cream/" target = "_blank" rel = "external" > Waxed polyester thread</ a >
< ul >
< li > I use 0.8mm thickness</ li >
</ ul >
</ li >
< li > Lighter (you don't need a link</ li >
</ ul >
< h3 id = "saddle-stitch" > Saddle stitch</ h3 >
< p > I recommend watching < a href = "https://www.youtube.com/watch?v=nHL_duaJxWQ" target = "_blank" rel = "external" > How to Saddle Stitch</ a > in addition to reading my single-page overview. Particularly useful is his method of securing the thread to the needle (I just didn't have the space to cover this).</ p >
< ol >
< li > Pre-punch holes</ li >
< li > Thread needles on both ends</ li >
< li > Thread through first hole</ li >
< li > Needle 1 through next hole</ li >
< li > Follow with needle 2. Pull existing thread to the side to avoid piercing it</ li >
< li > Pull tight with even tension</ li >
< li > Repeat</ li >
</ ol >
< p > To finish, stitch backwards for a few stitches. Trim ends short. Melt. Flatten by rubbing against metal end of lighter.</ p >
< h2 id = "page-8%3A-rivet" > Page 8: Rivet</ h2 >
< p > One end of the rivet sits in the bowl of the < strong > anvil</ strong > . The other end caps on and is nested in the < strong > setter</ strong > , which is then hit with a mallet (or maul).</ p >
< p > A basic setter and anvil has an anvil that is larger than the rivet.</ p >
< ul >
< li >< strong > Good:</ strong > works with multiple rivet sizes; cheap and common</ li >
< li >< strong > Bad:</ strong > hard to set evenly</ li >
</ ul >
< p > My preference is a fixed-size setter and anvil. The anvil is sized to the rivet cap size.</ p >
< ul >
< li >
< p >< strong > Good:</ strong > better looking and easier</ p >
</ li >
< li >
< p >< strong > Bad:</ strong > only one size of rivet; often higher quality which raises the price</ p >
</ li >
< li >
< p >< a href = "https://tandyleather.com/products/easy-to-do-rivets-setter" target = "_blank" rel = "external" > Basic double-cap rivets, setter, and anvil set</ a ></ p >
</ li >
< li >
< p > Fixed-size < a href = "https://www.buckleguy.com/bg-rivet-setter-concave-end-multiple-sizes/" target = "_blank" rel = "external" > setter</ a > and < a href = "https://www.buckleguy.com/bg-rivet-setter-base-for-9-2-11-13mm-cap-rivets/" target = "_blank" rel = "external" > anvil</ a > ; paired < a href = "https://www.buckleguy.com/double-cap-rivet-antique-brass-solid-brass-ll-100-sets-per-bag-multiple-sizes/" target = "_blank" rel = "external" > double-cap rivets</ a ></ p >
</ li >
</ ul >
</ article >
< nav aria-label = "pagination" >
< ol class = "pagination post-pagination" >
< li class = "older" >
< a href = "/pink-lime-and-grey-shawl/" >
< i class = "fa-solid fa-hand-point-left" aria-hidden = "true" ></ i > pink, lime, and grey shawl
</ a >
</ li >
< li class = "newer" >
< a href = "/framer-accessibility/" >
framer accessibility < i class = "fa-solid fa-hand-point-right" aria-hidden = "true" ></ i >
</ a >
</ li >
</ ol >
</ nav >
< hr >
< section class = "related-posts" >
< h2 data-ha-exclude = "" > related posts</ h2 >
< ol id = "postlist" >
< li class = "post" >
2026-10-05 23:59:36 +00:00
< a class = "postlink" href = "/leather-long-stitch-journals/" >
< h2 data-ha-exclude = "" > leather long-stitch journals </ h2 >
< ul class = "postlist-tags" >
< li > leather</ li >
< li > book</ li >
</ ul >
< img src = "/img/long-stitch-journals.jpg" alt = "A stack of hand-bound journals showing long stitches aligned with the spines. They are leather bound and have tie closures." loading = "lazy" decoding = "async" width = "1000" height = "1333" >
</ a >
</ li >
< li class = "post" >
< a class = "postlink" href = "/bag-strap/" >
< h2 data-ha-exclude = "" > bag strap </ h2 >
2026-09-21 20:56:03 +00:00
< ul class = "postlist-tags" >
< li > leather</ li >
</ ul >
2026-10-05 23:59:36 +00:00
< img src = "/img/bag-strap.jpg" alt = "A nylon webbing shoulder strap in bright teal with clips on each end." loading = "lazy" decoding = "async" width = "1000" height = "750" >
2026-09-21 20:56:03 +00:00
</ a >
</ li >
< li class = "post" >
2026-10-05 23:59:36 +00:00
< a class = "postlink" href = "/brookes-cuff-bracelets/" >
< h2 data-ha-exclude = "" > brooke' s cuff bracelets </ h2 >
2026-09-21 20:56:03 +00:00
< ul class = "postlist-tags" >
2026-09-24 03:26:44 +00:00
< li > leather</ li >
2026-09-21 20:56:03 +00:00
</ ul >
2026-10-05 23:59:36 +00:00
< img src = "/img/brooke-cuffs.jpg" alt = "Olive green leather cuffs with silver spikes and a shearling lining." loading = "lazy" decoding = "async" width = "900" height = "1200" >
2026-09-21 20:56:03 +00:00
</ a >
</ li >
</ ol >
</ section >
</ heading-anchors >
</ main >
< footer >
< ul >
< li >
< a href = "/colophon/" >
colophon
</ a >
</ li >
< li >
< a href = "/" title = "go home" aria-label = "go home | hello hello from Lee Cattarin, copyright 2022-2026" >
hello hello from Lee Cattarin, © 2022-2026</ a >
</ li >
< li >
< a href = "https://heckin.technology/inherentlee/leecat.art" title = "source code" aria-label = "source code" target = "_blank" rel = "external" >
src
</ a >
</ li >
</ ul >
< fieldset id = "theme" >
< legend > color scheme</ legend >
< input type = "radio" id = "theme-light" name = "theme" value = "light" >
< label class = "theme-light" for = "theme-light" >
< i class = "fa-regular fa-sun" aria-hidden = "true" ></ i >
light
</ label >
< input type = "radio" id = "theme-auto" name = "theme" value = "auto" checked = "" >
< label class = "theme-auto" for = "theme-auto" >
auto
</ label >
< input type = "radio" id = "theme-dark" name = "theme" value = "dark" >
< label class = "theme-dark" for = "theme-dark" >
dark
< i class = "fa-regular fa-moon" aria-hidden = "true" ></ i >
</ label >
</ fieldset >
</ footer >
2026-10-05 23:59:36 +00:00
<!-- This page `/leatherworking-zine/` was built on 2026-10-05T23:58:43.946Z -->
2026-09-21 20:56:03 +00:00
</ body >
</ html >