2026-05-15 09:20:43 -07: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 favorites | 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 favorites | 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" >
2026-08-26 23:55:56 +00:00
< meta property = "og:url" content = "https://leecat.art/leatherworking-favorites/" >
2026-05-15 09:20:43 -07:00
2026-09-15 01:17:56 +00:00
< meta property = "og:image" content = "https://leecat.art/img/leather-harness-wip.jpg" >
2026-05-15 09:20:43 -07:00
< meta property = "og:image:alt" content = "two pieces of a chest harness sitting on a messy workbench. both pieces are about 8 inches long total and consist of two large o-rings joined by a dark teal leather strap. the o rings and rivets are matte black." >
< meta name = "generator" content = "Eleventy v3.1.2" >
2026-05-21 23:35:46 +00:00
< meta itemprop = "ai-content-declaration:version" content = "1.0.0" >
< meta itemprop = "ai-content-declaration:level" content = "none" >
2026-05-15 09:20:43 -07:00
< 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 >
2026-09-08 17:40:59 +00:00
2026-09-11 18:57:10 +00:00
2026-05-15 09:20:43 -07:00
< style >. 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 ;
2026-08-25 20:13:52 +00:00
margin-left : auto ;
2026-05-15 09:20:43 -07:00
}
. 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-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 {
2026-08-21 00:13:19 +00:00
max-height : calc ( 100 vh - 2 rem );
2026-05-15 09:20:43 -07:00
object-fit : contain ;
width : auto ;
max-width : 90 % ;
margin : 0 auto ;
}
: root {
color-scheme : light dark ;
--font-family : '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 ));
}
2026-09-09 20:38:19 +00:00
: root : has ( # theme-light : checked ) {
color-scheme : light ;
}
: root : has ( # theme-dark : checked ) {
color-scheme : dark ;
}
2026-05-15 09:20:43 -07:00
/* 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 ;
scroll-margin-top : 7 rem ;
}
@ media ( max-width : 1050px ) {
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 );
}
h1 {
margin-top : 3 rem ;
font-size : 3.5 rem ;
text-align : center ;
}
h2 , h3 , h4 , h5 , h6 {
scroll-margin-top : 5 rem ;
}
h2 {
margin-top : 2 rem ;
font-size : 2.2 rem ;
}
h3 {
margin-top : 1.5 rem ;
font-size : 1.6 rem ;
}
@ media ( max-width : 650px ) {
h1 { font-size : 2.8 rem ; }
h2 { font-size : 1.8 rem ; }
h3 { font-size : 1.35 rem ; }
}
h4 , h5 , h6 {
margin-top : 1 rem ;
font-size : 1.2 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 {
2026-09-09 20:38:19 +00:00
line-height : 1.2 ;
2026-05-15 09:20:43 -07:00
margin-top : .65 rem ;
margin-bottom : .65 rem ;
}
li ul , li ol {
margin : .5 rem 0 ;
2026-09-08 17:34:46 +00:00
margin-left : 1 rem ;
}
@ media ( max-width : 650px ) {
li ul , li ol {
margin-left : 0 ;
}
2026-05-15 09:20:43 -07:00
}
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 );
2026-08-06 18:38:23 +00:00
margin : 1.25 rem 0 ;
2026-05-15 09:20:43 -07:00
}
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 );
2026-09-11 18:57:10 +00:00
display : grid ;
grid-template-columns : auto ;
2026-05-15 09:20:43 -07:00
}
/* 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 ;
2026-09-11 18:57:10 +00:00
margin : -.125 rem 10 % ;
2026-05-15 09:20:43 -07:00
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 );
}
2026-09-09 20:38:19 +00:00
/* 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 ;
}
2026-05-15 09:20:43 -07:00
/* 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 ;
2026-08-28 19:00:43 +00:00
justify-content : center ;
gap : .5 rem ;
2026-05-15 09:20:43 -07:00
}
. webring ul ,
. webring li {
margin-left : 0 ;
}
2026-09-11 18:57:10 +00:00
/* 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 ;
}
2026-09-12 17:51:15 +00:00
@ media ( max-width : 650px ) {
. pf-trigger-shortcut {
display : none !important ;
}
}
2026-09-11 18:57:10 +00:00
. pf-searchbox-dropdown ,
. pf-searchbox-footer {
border-width : .125 rem !important ;
}
. pf-error {
margin-top : .5 rem !important ;
}
2026-09-08 17:40:59 +00:00
/* 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 );
}
2026-05-15 09:20:43 -07:00
@ 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 >
2026-09-09 20:38:19 +00:00
2026-05-15 09:20:43 -07:00
< 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 ();
}
});
2026-09-09 20:38:19 +00:00
}
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 ;
2026-09-09 21:03:37 +00:00
themeAuto . checked = false ;
2026-09-09 20:38:19 +00:00
break ;
case "dark" :
themeDark . checked = true ;
2026-09-09 21:03:37 +00:00
themeAuto . checked = false ;
2026-09-09 20:38:19 +00:00
break ;
2026-09-09 21:03:37 +00:00
case "auto" :
2026-09-09 20:38:19 +00:00
default :
themeAuto . checked = true ;
2026-05-15 09:20:43 -07:00
}</ script >
2026-09-11 18:57:10 +00:00
< link href = "/pagefind/pagefind-component-ui.css" rel = "stylesheet" >
< script src = "/pagefind/pagefind-component-ui.js" type = "module" ></ script >
2026-05-15 09:20:43 -07:00
</ 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 >
2026-09-11 18:57:10 +00:00
< div class = "dark searchbox" data-pf-theme = "dark" >
< pagefind-searchbox ></ pagefind-searchbox >
</ div >
< div class = "light searchbox" >
< pagefind-searchbox ></ pagefind-searchbox >
</ div >
2026-05-15 09:20:43 -07:00
</ header >
2026-09-12 17:14:18 +00:00
< main id = "main" >
2026-05-15 09:20:43 -07:00
< heading-anchors content = "<i class='fa-solid fa-anchor'></i>" >
2026-09-12 17:14:18 +00:00
< article data-pagefind-body = "" >
2026-05-15 09:20:43 -07:00
< h1 id = "leatherworking-favorites" > leatherworking favorites</ h1 >
< div class = "post-metadata" >
< p >
posted on
< time datetime = "2023-10-08" > October 8, 2023</ time >
by Lee Cattarin
</ p >
< ul class = "post-tags" >
< 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/leather-harness-wip.jpg" alt = "two pieces of a chest harness sitting on a messy workbench. both pieces are about 8 inches long total and consist of two large o-rings joined by a dark teal leather strap. the o rings and rivets are matte black." loading = "lazy" decoding = "async" width = "1000" height = "750" >
</ dialog >
< img class = "hero" src = "/img/leather-harness-wip.jpg" alt = "two pieces of a chest harness sitting on a messy workbench. both pieces are about 8 inches long total and consist of two large o-rings joined by a dark teal leather strap. the o rings and rivets are matte black." loading = "lazy" decoding = "async" width = "1000" height = "750" >
< h2 id = "practices" > practices</ h2 >
< ul >
< li > cardboard templates have been really handy for the spacing of rivets and such. I use cereal boxes since they are not corrugated.</ li >
</ ul >
< h2 id = "tools" > tools</ h2 >
< p > If I have linked a tool, I really like that specific tool and find it stands out. Otherwise, idk, I've used precisely one edge beveler, I have no idea how it compares.</ p >
< ul >
< li > (need to have) some kind of scratch awl for marking</ li >
< li > (need to have) cutproof mat</ li >
< li > (need to have basically whenever you are using a mallet) < a href = "https://www.buckleguy.com/cutting-board-multiple-sizes/" target = "_blank" rel = "external" > " poundo board" or cutting board</ a > (this is just an example, I got mine elsewhere) - importantly, this is distinct from your cutproof mat. you < em > can</ em > use this in place of your cutproof mat but it tends to pick up a lot of punctures which can leave indents in your leather with pressure - so I only use mine for mallet-ing and otherwise use my cutproof mat</ li >
< li > (nice to have) < a href = "https://www.weaverleathersupply.com/products/pattern-sheet-24-x-45" target = "_blank" rel = "external" > pattern plastic</ a > - but like I said above you can use non-corrugated cardboard</ li >
< li > (nice to have) < a href = "https://www.buckleguy.com/bg-acrylic-tool-leather-thickness-gauge/" target = "_blank" rel = "external" > acrylic leather thickness gauge</ a > - but you can also just use a ruler or calipers, or learn to gauge by eye/feel</ li >
</ ul >
< h3 id = "cutting" > cutting</ h3 >
< ul >
< li > (need to have) metal cork-backed ruler (cork backing will keep it from slip-sliding around)</ li >
< li > (nice to have, but any sharp blade will do) < a href = "https://www.buckleguy.com/ergo-kiwi-knife-2-0/" target = "_blank" rel = "external" > ergo kiwi knife</ a ></ li >
< li > (nice to have for harnesses, belts) strap cutter</ li >
< li > (nice to have for small objects with a lot of layers at the seams, like wallets) skiving knife of some kind. there's a lot of different types out there. I have a CS Osborne leather knife and I don't love it, but idk if that's just because I am still learning how to skive.
< ul >
< li > you're supposed to skive on a fucken < a href = "https://www.weaverleathersupply.com/products/marble-tooling-slab" target = "_blank" rel = "external" > rock</ a > so as not to absolutely wreck your cutproof mat. I haven't got my rock yet but I haven't ruined my mat yet either.</ li >
< li > ok so I got a < a href = "https://www.weaverleathersupply.com/products/flat-leather-knife" target = "_blank" rel = "external" > skiving knife</ a > from Weaver and it < em > definitely</ em > beats out the CS Osborne leather knife</ li >
</ ul >
</ li >
</ ul >
< h3 id = "edging-and-burnishing" > edging and burnishing</ h3 >
< ul >
< li > (nice to have) edge beveler</ li >
< li > (need to have) sandpaper in maybe two grits. I have 100 and 600 sitting around right now</ li >
< li > (need to have) some small pieces of heavy canvas</ li >
< li > (nice to have) < a href = "https://www.buckleguy.com/seiwa-tokonole-leather-burnishing-gum-multiple-sizes-colors/" target = "_blank" rel = "external" > tokonole!!!</ a >
< ul >
< li > tokonole can even burnish chrome tan leather and flesh side of veg tan</ li >
</ ul >
</ li >
< li > (nice to have) < a href = "https://www.buckleguy.com/leather-edge-slicker-burnishing-tool-beech-wood/" target = "_blank" rel = "external" > wooden edge burnishing tool</ a > but tbh I find myself just using canvas instead of my burnishing tool
< ul >
< li > you can also use wooden tool handles, if you have for example an edge beveler with a wooden handle sitting around</ li >
</ ul >
</ li >
< li > (nice to have/need to have if you don't get tokonole) beeswax</ li >
< li > (nice to have) < a href = "https://www.dickblick.com/items/lineco-micro-spatula-flat/" target = "_blank" rel = "external" > micro spatula</ a > - I bought this for bookbinding but I find it useful for applying tokonole or doing other odd lil jobs</ li >
</ ul >
< h3 id = "punching" > punching</ h3 >
< ul >
< li > (need to have) a mallet or something for hitting things. yes there are $100 mauls you can buy. idk a shitty mallet is working fine for me so far
< ul >
< li > alright i splurged on a maul and it was worth it. dammit.</ li >
</ ul >
</ li >
2026-09-12 17:51:15 +00:00
< li > (nice to have) < a href = "https://www.talasonline.com/Japanese-Push-Drill" target = "_blank" rel = "external" > japanese push drill</ a > and < a href = "https://www.talasonline.com/Japanese-Push-Drill-Replacement-Bits" target = "_blank" rel = "external" > bits</ a ></ li >
< li > if you don't want to go in on a $50 push drill, start with just some simple < a href = "https://www.buckleguy.com/245-belt-punch-multiple-sizes/" target = "_blank" rel = "external" > single-hole punches</ a > or a < a href = "https://www.buckleguy.com/223-revolving-punch/" target = "_blank" rel = "external" > rotary punch</ a > . rotary punches are pretty heavily recommended since they come with a range of punch sizes; I avoid them like the plague because I have small shitty hands and I think those would pair poorly with a rotary punch.</ li >
2026-05-15 09:20:43 -07:00
< li > if you're going to be attaching buckles, you'll need oblong holes for the buckle tongue. two options:
< ul >
< li > punch a standard hole at each end of your eventual oblong, then using a ruler and sharp small blade cut between those holes to create your oblong
< img src = "/img/oblong-punch-alternative.jpg" alt = "A small piece of leather showing the steps to creating an oblong hole. First there is just a straight 1-inch line drawn by scratch awl. Holes are punched at both ends of that line. Two cuts are made coming from the right-side hole inwards (shown by arrows), about halfway. Similar cuts are then made from the left-hand hole inwards to meet them." loading = "lazy" decoding = "async" width = "1000" height = "1000" ></ li >
< li > get an < a href = "https://www.buckleguy.com/151-bag-punch-multiple-sizes/" target = "_blank" rel = "external" > oblong punch</ a > . shaped punches are < em > expensive as shit</ em > but if you're doing more than a few buckles this is worth it.</ li >
</ ul >
</ li >
< li > another shaped punch: the < a href = "https://www.buckleguy.com/0150-strap-end-punch-english-point-multiple-sizes-1/" target = "_blank" rel = "external" > english point strap end punch</ a > . I don't own this yet but am heavily considering it if I am going to make more harnesses (and I am). you don't specifically need english point - there's other strap end styles - but having < em > a</ em > strap end punch in the size of your choosing is useful for harnesses, belts, anything with a lot of straps.
< ul >
< li > with strap end punches, you can use a larger punch on a smaller strap (for an imperfect result, tbf) but not vice versa</ li >
< li > there are also strap end acrylic templates out there on several retailers sites - I have a tandy one</ li >
</ ul >
</ li >
</ ul >
< h3 id = "riveting-snapping-etc" > riveting, snapping, etc</ h3 >
< ul >
2026-09-12 17:51:15 +00:00
< li > for any given size/brand of rivets, you can usually buy a < a href = "https://www.buckleguy.com/bg-rivet-setter-9-2mm-concave-end/" 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 > for maybe $25 together
2026-05-15 09:20:43 -07:00
< ul >
< li > also I have one extra of both of those specific linked items, so if you're short on cash lmk and I will ship em to ya - since I have switched over to the next option</ li >
</ ul >
</ li >
2026-09-12 17:51:15 +00:00
< li > however, if you think you might get really into leatherworking, or if you think you will be getting multiple sizes of rivets, attaching snaps, attaching other types of rivet-style clasps, whatever, I would highly recommend < a href = "https://www.buckleguy.com/bg-setter-post-base-for-screw-in-dies/" target = "_blank" rel = "external" > this setter post and base</ a > and < a href = "https://www.buckleguy.com/bg-rivet-setter-die-multiple-sizes-requires-hand-tool-post-base-or-bg-hand-press/" target = "_blank" rel = "external" > a rivet setter die</ a > or whichever setter die you need for your specific thing
2026-05-15 09:20:43 -07:00
< ul >
< li > these dies also work with < a href = "https://www.buckleguy.com/bg-180-convertible-hand-or-foot-press/" target = "_blank" rel = "external" > larger presses</ a > and make it much more possible to transition from a hand press to a full press without having to re-buy all your dies</ li >
< li > according to Corter Leather at the very least (I don't really have the experience to make a full comparison) this system is much more reliable for well-balanced, well-rounded rivets, snaps, etc</ li >
</ ul >
</ li >
</ ul >
< h3 id = "stitching" > stitching</ h3 >
< ul >
< li > (nice to have) wing divider for drawing stitching lines</ li >
< li > (need to have) stitching chisels! if you want to save some money, you mostly need the 6-tooth and the 2-tooth - 6 for straightaways, 2 for curves. I occasionally use my 4-tooth and < em > very</ em > occasionally use my 1-tooth (except for zippers. if you wanna do zippers get a 1-tooth).
< ul >
< li > my stitching chisels are 4mm spacing. I picked this pretty arbitrarily :)</ li >
< li > technically you could just buy a diamond awl or a 1-tooth chisel and poke each hole individually and that < em > would</ em > be cheaper but oh my god love yourself</ li >
</ ul >
</ li >
< li > (nice to have, any needles will do but oh my god these are pretty hashtag worth) < a href = "https://www.buckleguy.com/517-harness-needles-for-hand-sewing-blunt-tip-5-needles/" target = "_blank" rel = "external" > cs osborne harness needles, blunt tip</ a ></ li >
2026-09-12 17:51:15 +00:00
< li > (need to have) thread - I am using < a href = "https://www.buckleguy.com/ritza-25-tiger-thread/" target = "_blank" rel = "external" > Ritza 25 Tiger Thread</ a > (currently I have the 1.0mm size. I find it a little large and will probably size down when I order other colors - update, sized down to .8 and even have some .6 - much preferable) and have also used < a href = "https://threadsofmeisi.com/collections/meisi-superfine-linen-threads" target = "_blank" rel = "external" > MeiSi Superfine Linen Thread</ a > but polyester threads are easier to seal off with a lighter</ li >
2026-05-15 09:20:43 -07:00
< li > (nice to have) some kind of < a href = "https://www.joann.com/needle-pullers-3-pkg/3500295.html" target = "_blank" rel = "external" > silicone needle puller</ a > (I don't actually have this one, I was having trouble finding what I have - little pink finger covers that are all grippy) for gripping needles. or just use the back of a mousepad? or something?</ li >
</ ul >
< h3 id = "tool-care" > tool care</ h3 >
< ul >
< li > (need to have for certain blades such as skiving knife) jeweler's rouge for stropping
< ul >
< li > I am not an expert here so I am not making firm recommendations. I got mine from Springfield Leather</ li >
</ ul >
</ li >
</ ul >
< h3 id = "tooling" > tooling</ h3 >
< ul >
< li > (need to have) swivel knife</ li >
< li > (need to have) a beveler. I have a smooth beveler at the moment, but am waiting on a checked beveler in the mail as I think I will like that look better</ li >
< li > (need to have) as mentioned previously, mallet or maul</ li >
< li > (nice to have) literally any other stamps i guess</ li >
< li > (nice to have) templates! it really helps to start out with some designs made for swivel knife. I got a few (both free and paid) from < a href = "https://www.dadhands.ca/" target = "_blank" rel = "external" > dadhands</ a ></ li >
</ ul >
< h3 id = "zippers" > zippers</ h3 >
< ul >
< li > okay so I bought them because they are pretty but these < a href = "https://www.buckleguy.com/riri-zipper-continuous-chain-combi-eloxal-teeth-elox/" target = "_blank" rel = "external" > rainbow zippers</ a > actually make it so much easier because you can differentiate each tooth from the next!!!</ li >
< li > (nice to have) tape such as < a href = "https://www.buckleguy.com/double-sided-tape/" target = "_blank" rel = "external" > ted's tape</ a ></ li >
</ ul >
< h2 id = "resources" > resources</ h2 >
< ul >
< li >< a href = "https://www.youtube.com/@Corter" target = "_blank" rel = "external" > Corter Leather on YouTube</ a ></ li >
< li >< a href = "https://www.youtube.com/@Leodis.Leather" target = "_blank" rel = "external" > Leodis Leather on YouTube</ a ></ li >
< li >< a href = "https://www.youtube.com/@dadhands" target = "_blank" rel = "external" > dadhands on YouTube</ a ></ li >
< li >< a href = "https://www.youtube.com/@majutworks" target = "_blank" rel = "external" > Maju T Works on YouTube</ a ></ li >
</ ul >
< h2 id = "retailers" > retailers</ h2 >
< ul >
< li >< a href = "https://www.buckleguy.com/" target = "_blank" rel = "external" > buckleguy</ a > has been super speedy and reliable so far - for sure my favorite</ li >
< li >< a href = "https://www.springfieldleather.com/" target = "_blank" rel = "external" > springfield leather</ a ></ li >
< li >< a href = "https://tandyleather.com/" target = "_blank" rel = "external" > tandy</ a ></ li >
< li >< a href = "https://www.weaverleathersupply.com/" target = "_blank" rel = "external" > weaver leather supply</ a ></ li >
< li >< a href = "https://www.longviewleather.com/" target = "_blank" rel = "external" > longview leather (canada)</ a ></ li >
</ ul >
</ article >
< nav aria-label = "pagination" >
< ol class = "pagination post-pagination" >
< li class = "older" >
< a href = "/anarchy-autism/" >
< i class = "fa-solid fa-hand-point-left" aria-hidden = "true" ></ i > anarchy autism
</ a >
</ li >
< li class = "newer" >
< a href = "/leather-chest-harness/" >
leather chest harness < 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 = "" id = "related-posts" > related posts</ h2 >
< ol id = "postlist" >
2026-09-06 16:03:27 +00:00
< li class = "post" >
2026-09-18 00:05:19 +00:00
< a class = "postlink" href = "/vertical-card-wallet/" >
< h2 data-ha-exclude = "" id = "vertical-card-wallet" > vertical card wallet </ h2 >
2026-09-06 16:03:27 +00:00
< ul class = "postlist-tags" >
< li > leather</ li >
</ ul >
2026-09-18 00:05:19 +00:00
< img src = "/img/vertical-card-wallet.jpg" alt = "A collage showing a hand-stitched leather card wallet with 3 card pockets and 1 interior pocket." loading = "lazy" decoding = "async" width = "1000" height = "750" >
2026-07-01 21:48:31 +00:00
</ a >
</ li >
2026-09-18 00:58:08 +00:00
< li class = "post" >
2026-09-18 00:59:41 +00:00
< a class = "postlink" href = "/brookes-cuff-bracelets/" >
< h2 data-ha-exclude = "" id = "brookes-cuff-bracelets" > brooke' s cuff bracelets </ h2 >
2026-09-18 00:58:08 +00:00
< ul class = "postlist-tags" >
< li > leather</ li >
</ ul >
2026-09-18 00:59:41 +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-18 00:58:08 +00:00
</ a >
</ li >
< li class = "post" >
2026-09-18 00:59:41 +00:00
< a class = "postlink" href = "/zipper-bifold-green/" >
< h2 data-ha-exclude = "" id = "zipper-bifold-green" > zipper bifold (green) </ h2 >
2026-09-18 00:58:08 +00:00
< ul class = "postlist-tags" >
< li > leather</ li >
</ ul >
2026-09-18 00:59:41 +00:00
< img src = "/img/zipper-bifold-green.jpg" alt = "A collage showing a green leather wallet with a zippered pocket built into one external side." loading = "lazy" decoding = "async" width = "1000" height = "1332" >
2026-09-18 00:58:08 +00:00
</ a >
</ li >
2026-05-15 09:20:43 -07:00
</ 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 >
2026-09-09 20:38:19 +00:00
< 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 >
2026-09-09 21:03:37 +00:00
< input type = "radio" id = "theme-auto" name = "theme" value = "auto" checked = "" >
2026-09-09 20:38:19 +00:00
< 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 >
2026-05-15 09:20:43 -07:00
</ footer >
2026-09-18 00:59:41 +00:00
<!-- This page `/leatherworking-favorites/` was built on 2026-09-18T00:59:26.534Z -->
2026-05-15 09:20:43 -07:00
</ body >
</ html >