2139 lines
51 KiB
HTML
2139 lines
51 KiB
HTML
<!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>.post-metadata {
|
||
|
|
display: flex;
|
||
|
|
flex-flow: row wrap;
|
||
|
|
justify-content: space-between;
|
||
|
|
align-items: baseline;
|
||
|
|
margin: 1.5rem 0 .5rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.post-metadata p {
|
||
|
|
font-size: .9rem;
|
||
|
|
margin: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.post-tags {
|
||
|
|
display: flex;
|
||
|
|
flex-flow: row wrap;
|
||
|
|
gap: .5rem;
|
||
|
|
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 .5rem;
|
||
|
|
border-radius: 1rem;
|
||
|
|
box-shadow: .15rem .15rem var(--color-shadow);
|
||
|
|
border: .08rem solid var(--color-teal);
|
||
|
|
line-height: 2;
|
||
|
|
/* Click animation handling */
|
||
|
|
position: relative;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
transition: top .1s ease-in, left .1s 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: .08rem;
|
||
|
|
outline: .08rem solid;
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (any-hover: hover) {
|
||
|
|
.post-tags li a:hover {
|
||
|
|
outline-offset: .08rem;
|
||
|
|
outline: .08rem solid;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Click animation */
|
||
|
|
.post-tags li a:active {
|
||
|
|
top: .1rem;
|
||
|
|
left: .1rem;
|
||
|
|
box-shadow: .05rem .05rem 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: .25rem solid var(--color-primary);
|
||
|
|
border-radius: 1.25rem;
|
||
|
|
box-shadow: .35rem .35rem var(--color-shadow);
|
||
|
|
margin: 2rem 0;
|
||
|
|
text-decoration: none;
|
||
|
|
/* Click animation handling */
|
||
|
|
position: relative;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
transition: top .05s ease-in, left .05s 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: .25rem;
|
||
|
|
outline: .25rem solid;
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (any-hover: hover) {
|
||
|
|
.postlink:hover,
|
||
|
|
.taglink:hover {
|
||
|
|
outline-offset: .25rem;
|
||
|
|
outline: .25rem solid;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Click animation */
|
||
|
|
.postlink:active,
|
||
|
|
.taglink:active {
|
||
|
|
top: .2rem;
|
||
|
|
left: .2rem;
|
||
|
|
box-shadow: .15rem .15rem 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: .25rem .5rem;
|
||
|
|
text-transform: uppercase;
|
||
|
|
font-size: 1.5rem;
|
||
|
|
color: var(--color-primary);
|
||
|
|
border-radius: 1rem 1rem 0 0;
|
||
|
|
border-bottom: .25rem 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(.75rem);
|
||
|
|
clip-path: inset(0 round 1rem);
|
||
|
|
}
|
||
|
|
|
||
|
|
.tag-imgs {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(2, 1fr);
|
||
|
|
gap: .15rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.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: 1rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.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: .5rem;
|
||
|
|
padding: .5rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.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 .5rem;
|
||
|
|
border-radius: 1rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.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: .5rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.tag:nth-child(odd) p {
|
||
|
|
text-align: right;
|
||
|
|
}
|
||
|
|
img[tabindex="0"] {
|
||
|
|
cursor: pointer;
|
||
|
|
}
|
||
|
|
|
||
|
|
img[tabindex="0"]:focus-visible {
|
||
|
|
outline: .15rem 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(4px);
|
||
|
|
}
|
||
|
|
|
||
|
|
body:has(dialog[open]) {
|
||
|
|
overflow: hidden;
|
||
|
|
}
|
||
|
|
|
||
|
|
.close-dialog {
|
||
|
|
background-color: rgba(from var(--color-teal) r g b / .35);
|
||
|
|
font-size: 1.5rem;
|
||
|
|
padding: 0 .5rem .15rem;
|
||
|
|
border-radius: 1rem;
|
||
|
|
color: var(--color-teal);
|
||
|
|
box-shadow: .15rem .15rem var(--color-shadow);
|
||
|
|
border: .08rem solid var(--color-teal);
|
||
|
|
align-self: flex-end;
|
||
|
|
justify-self: flex-start;
|
||
|
|
margin: 0 .1rem;
|
||
|
|
/* Click animation handling */
|
||
|
|
position: relative;
|
||
|
|
top: 1rem;
|
||
|
|
left: -.15rem;
|
||
|
|
transition: top .1s ease-in, left .1s 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: .08rem;
|
||
|
|
outline: .08rem solid;
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (any-hover: hover) {
|
||
|
|
.close-dialog:hover {
|
||
|
|
outline-offset: .08rem;
|
||
|
|
outline: .08rem solid;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Click animation */
|
||
|
|
.close-dialog:active {
|
||
|
|
top: 1.1rem;
|
||
|
|
left: -.05rem;
|
||
|
|
box-shadow: .05rem .05rem var(--color-shadow);
|
||
|
|
}
|
||
|
|
|
||
|
|
.modal-img {
|
||
|
|
max-height: calc(100vh - 2rem);
|
||
|
|
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));
|
||
|
|
}
|
||
|
|
|
||
|
|
: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: 60vw;
|
||
|
|
max-width: 1000px;
|
||
|
|
margin: 0 auto;
|
||
|
|
scroll-margin-top: 7rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (max-width: 1050px) {
|
||
|
|
main {
|
||
|
|
width: 75vw;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (max-width: 650px) {
|
||
|
|
main {
|
||
|
|
width: 92vw;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Headers */
|
||
|
|
h1, h2, h3, h4, h5, h6 {
|
||
|
|
line-height: 1.25;
|
||
|
|
color: var(--color-teal);
|
||
|
|
}
|
||
|
|
|
||
|
|
h1 {
|
||
|
|
margin-top: 3rem;
|
||
|
|
font-size: 3.5rem;
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
h2, h3, h4, h5, h6 {
|
||
|
|
scroll-margin-top: 5rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
h2 {
|
||
|
|
margin-top: 2rem;
|
||
|
|
font-size: 2.2rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
h3 {
|
||
|
|
margin-top: 1.5rem;
|
||
|
|
font-size: 1.6rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (max-width: 650px) {
|
||
|
|
h1 { font-size: 2.8rem; }
|
||
|
|
h2 { font-size: 1.8rem; }
|
||
|
|
h3 { font-size: 1.35rem; }
|
||
|
|
}
|
||
|
|
|
||
|
|
h4, h5, h6 {
|
||
|
|
margin-top: 1rem;
|
||
|
|
font-size: 1.2rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Images */
|
||
|
|
img {
|
||
|
|
display: block;
|
||
|
|
max-width: 100%;
|
||
|
|
height: auto;
|
||
|
|
border-radius: 1rem;
|
||
|
|
margin: 0 auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Paragraphs */
|
||
|
|
p {
|
||
|
|
margin: 1.25rem 0;
|
||
|
|
line-height: 1.4;
|
||
|
|
}
|
||
|
|
|
||
|
|
strong,
|
||
|
|
b {
|
||
|
|
font-weight: 900;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Links */
|
||
|
|
a {
|
||
|
|
color: var(--color-text);
|
||
|
|
border-radius: .25rem;
|
||
|
|
text-decoration: underline;
|
||
|
|
text-decoration-style: solid;
|
||
|
|
text-decoration-thickness: .2em;
|
||
|
|
text-decoration-color: var(--color-teal);
|
||
|
|
transition: text-decoration-thickness .5s;
|
||
|
|
}
|
||
|
|
|
||
|
|
a:focus-visible {
|
||
|
|
text-decoration: none;
|
||
|
|
outline: .15rem solid var(--color-teal);
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (any-hover: hover) {
|
||
|
|
a:hover {
|
||
|
|
text-decoration-thickness: .4em;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
a:active {
|
||
|
|
text-decoration-thickness: .4em;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Heading anchors */
|
||
|
|
a.ha,
|
||
|
|
span.ha-placeholder {
|
||
|
|
color: var(--color-pink);
|
||
|
|
font-size: .8em;
|
||
|
|
vertical-align: .1em;
|
||
|
|
}
|
||
|
|
span.ha-placeholder {
|
||
|
|
opacity: .55;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Lists */
|
||
|
|
::marker {
|
||
|
|
color: var(--color-pink);
|
||
|
|
}
|
||
|
|
|
||
|
|
ul, ol, dl, li {
|
||
|
|
margin-left: 1rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (max-width: 650px) {
|
||
|
|
ul, ol, dl {
|
||
|
|
margin-left: 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
li {
|
||
|
|
line-height: 1.2;
|
||
|
|
margin-top: .65rem;
|
||
|
|
margin-bottom: .65rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
li ul, li ol {
|
||
|
|
margin: .5rem 0;
|
||
|
|
margin-left: 1rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (max-width: 650px) {
|
||
|
|
li ul, li ol {
|
||
|
|
margin-left: 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
dt {
|
||
|
|
font-weight: 900;
|
||
|
|
margin-top: .5rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
dd {
|
||
|
|
margin-left: 2rem;
|
||
|
|
margin-bottom: .75rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Blockquotes */
|
||
|
|
blockquote {
|
||
|
|
margin: .5rem 0;
|
||
|
|
padding: 0 1rem;
|
||
|
|
border-radius: .25rem 1rem 1rem .25rem;
|
||
|
|
line-height: 1.25;
|
||
|
|
border-left: .5rem solid var(--color-pink);
|
||
|
|
}
|
||
|
|
|
||
|
|
blockquote,
|
||
|
|
blockquote p,
|
||
|
|
blockquote ol,
|
||
|
|
blockquote ul {
|
||
|
|
background-color: var(--color-bg-alt);
|
||
|
|
padding: .5rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
blockquote p {
|
||
|
|
margin: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Tables */
|
||
|
|
table {
|
||
|
|
width: 100%;
|
||
|
|
border-spacing: 0; /* border collapse doesn't play nice with radii */
|
||
|
|
border-radius: .3rem;
|
||
|
|
border: thin solid var(--color-pink);
|
||
|
|
margin: 1.25rem 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: .5rem;
|
||
|
|
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: .25rem; }
|
||
|
|
th:last-child { border-top-right-radius: .25rem; }
|
||
|
|
td:not(:first-child) { border-left: thin solid var(--color-pink); }
|
||
|
|
|
||
|
|
/* Times */
|
||
|
|
time {
|
||
|
|
color: var(--color-grey);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Horizontal rules */
|
||
|
|
hr {
|
||
|
|
border: .25rem solid var(--color-pink);
|
||
|
|
margin: 2rem 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: .75rem 0;
|
||
|
|
border-bottom: thick solid var(--color-teal);
|
||
|
|
box-shadow: 0 .25rem .15rem var(--color-shadow);
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Header links, pagination links */
|
||
|
|
header a,
|
||
|
|
.pagination a,
|
||
|
|
.webring ul a {
|
||
|
|
border-radius: 1rem;
|
||
|
|
border: .125rem solid var(--color-pink);
|
||
|
|
color: var(--color-pink);
|
||
|
|
text-decoration: none;
|
||
|
|
padding: 0 .25rem;
|
||
|
|
box-shadow: .15rem .15rem var(--color-shadow);
|
||
|
|
font-size: 1.2rem;
|
||
|
|
/* Click animation handling */
|
||
|
|
position: relative;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
transition: top .05s ease-in, left .05s ease-in;
|
||
|
|
}
|
||
|
|
|
||
|
|
header a,
|
||
|
|
.pagination .older a,
|
||
|
|
.webring .prev a,
|
||
|
|
.webring .rand a {
|
||
|
|
padding-right: .35rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pagination .newer a,
|
||
|
|
.webring .next a,
|
||
|
|
.webring .rand a {
|
||
|
|
padding-left: .35rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
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: .125rem;
|
||
|
|
outline: .125rem solid;
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (any-hover: hover) {
|
||
|
|
header a:hover,
|
||
|
|
.pagination a:hover,
|
||
|
|
.webring ul a:hover {
|
||
|
|
outline-offset: .125rem;
|
||
|
|
outline: .125rem solid;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Click animation */
|
||
|
|
header a:active,
|
||
|
|
.pagination a:active,
|
||
|
|
.webring ul a:active {
|
||
|
|
top: .1rem;
|
||
|
|
left: .1rem;
|
||
|
|
box-shadow: .05rem .05rem 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: .25rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pagination .newer i,
|
||
|
|
.webring .next i,
|
||
|
|
.webring .rand i:nth-child(2) {
|
||
|
|
padding-right: .25rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
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: -999px;
|
||
|
|
position: absolute;
|
||
|
|
top: auto;
|
||
|
|
width: 1px;
|
||
|
|
height: 1px;
|
||
|
|
overflow: hidden;
|
||
|
|
z-index: -99;
|
||
|
|
}
|
||
|
|
|
||
|
|
#skip:focus-visible {
|
||
|
|
display: inline-block;
|
||
|
|
left: auto;
|
||
|
|
top: auto;
|
||
|
|
width: auto;
|
||
|
|
height: auto;
|
||
|
|
overflow: auto;
|
||
|
|
margin: -.125rem 10%;
|
||
|
|
z-index: 999;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Nav */
|
||
|
|
header ul {
|
||
|
|
display: flex;
|
||
|
|
list-style: none;
|
||
|
|
gap: 1rem;
|
||
|
|
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: .15rem .5rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
header i {
|
||
|
|
padding: 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Footer */
|
||
|
|
footer {
|
||
|
|
padding: 1rem 0;
|
||
|
|
font-size: .9rem;
|
||
|
|
border-top: thick solid var(--color-pink);
|
||
|
|
margin-top: 2rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
footer ul {
|
||
|
|
display: flex;
|
||
|
|
list-style: none;
|
||
|
|
gap: .5rem;
|
||
|
|
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: .5rem auto 0;
|
||
|
|
padding: 0 .75rem .5rem;
|
||
|
|
width: fit-content;
|
||
|
|
border: .125rem solid var(--color-teal);
|
||
|
|
border-radius: 2rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
#theme legend {
|
||
|
|
margin: 0 auto;
|
||
|
|
color: var(--color-teal);
|
||
|
|
}
|
||
|
|
|
||
|
|
footer label {
|
||
|
|
cursor: pointer;
|
||
|
|
border: .125rem solid var(--color-pink);
|
||
|
|
padding: 0 .25rem;
|
||
|
|
color: var(--color-pink);
|
||
|
|
background-color: var(--color-bg); /* this stops the box shadows from showing through */
|
||
|
|
box-shadow: .15em .15em var(--color-shadow);
|
||
|
|
/* Click animation handling */
|
||
|
|
position: relative;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
transition: top .05s ease-in, left .05s 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: .09em;
|
||
|
|
left: .09em;
|
||
|
|
box-shadow: .05em .05em var(--color-shadow);
|
||
|
|
}
|
||
|
|
|
||
|
|
label.theme-light {
|
||
|
|
border-top-left-radius: 1rem;
|
||
|
|
border-bottom-left-radius: 1rem;
|
||
|
|
border-right: none;
|
||
|
|
padding-left: .35rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
label.theme-auto {
|
||
|
|
}
|
||
|
|
|
||
|
|
label.theme-dark {
|
||
|
|
border-top-right-radius: 1rem;
|
||
|
|
border-bottom-right-radius: 1rem;
|
||
|
|
border-left: none;
|
||
|
|
padding-right: .35rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
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, 1fr);
|
||
|
|
grid-template-areas: "older newer";
|
||
|
|
list-style: none;
|
||
|
|
margin-top: 3rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (max-width: 650px) {
|
||
|
|
.post-pagination {
|
||
|
|
grid-template-columns: 1fr;
|
||
|
|
grid-template-areas:
|
||
|
|
"older"
|
||
|
|
"newer";
|
||
|
|
gap: .75rem;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.pagination .older {
|
||
|
|
grid-area: older;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pagination .newer {
|
||
|
|
grid-area: newer;
|
||
|
|
text-align: right;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* webring navigation */
|
||
|
|
.webring {
|
||
|
|
margin-bottom: 3rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.webring ul {
|
||
|
|
display: flex;
|
||
|
|
flex-flow: row wrap;
|
||
|
|
list-style: none;
|
||
|
|
justify-content: center;
|
||
|
|
gap: .5rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.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: 1rem auto 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
pagefind-searchbox {
|
||
|
|
/* Shadows */
|
||
|
|
--pf-scroll-shadow: var(--color-shadow) !important;
|
||
|
|
--pf-shadow-sm: .15rem .15rem 0 var(--color-shadow) !important;
|
||
|
|
--pf-shadow-md: .25rem .25rem 0 var(--color-shadow) !important;
|
||
|
|
--pf-shadow-lg: 1rem 1rem 0 var(--color-shadow) !important;
|
||
|
|
|
||
|
|
/* Typography */
|
||
|
|
--pf-font: var(--font-family) !important;
|
||
|
|
|
||
|
|
/* Border */
|
||
|
|
--pf-border-radius: 1.5rem !important;
|
||
|
|
|
||
|
|
/* Focus */
|
||
|
|
--pf-outline-width: .125rem !important;
|
||
|
|
--pf-outline-offset: 0 !important;
|
||
|
|
|
||
|
|
/* Width */
|
||
|
|
--pf-searchbox-max-width: min(550px, 92vw) !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: .125rem !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: .125rem !important;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pf-error {
|
||
|
|
margin-top: .5rem !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: .9em;
|
||
|
|
text-shadow: 0 1px 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: 1rem 0;
|
||
|
|
padding: 1rem;
|
||
|
|
line-height: 1.5;
|
||
|
|
white-space: pre-wrap;
|
||
|
|
word-break: break-word;
|
||
|
|
overflow-wrap: break-word;
|
||
|
|
border-radius: .5rem;
|
||
|
|
overflow: auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
:not(pre)>code,
|
||
|
|
:not(pre)>code[class*=language-] {
|
||
|
|
padding: .2rem;
|
||
|
|
border-radius: .25rem;
|
||
|
|
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: 95vw;
|
||
|
|
}
|
||
|
|
|
||
|
|
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: .1rem;
|
||
|
|
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 id="leatherworking-zine">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">
|
||
|
|
|
||
|
|
|
||
|
|
<p>This page contains textual representation of and supplementary material for my Leatherworking Tools zine (purchase link to be added in the future), including links to all tools and additional information as needed.</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-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-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-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-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-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-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="" id="related-posts">related posts</h2>
|
||
|
|
<ol id="postlist">
|
||
|
|
|
||
|
|
<li class="post">
|
||
|
|
<a class="postlink" href="/vertical-zipper-card-wallet/">
|
||
|
|
<h2 data-ha-exclude="" id="vertical-zipper-card-wallet">vertical zipper card wallet </h2>
|
||
|
|
|
||
|
|
<ul class="postlist-tags">
|
||
|
|
|
||
|
|
<li>leather</li>
|
||
|
|
|
||
|
|
</ul>
|
||
|
|
<img src="/img/vertical-zipper-card-wallet.jpg" alt="A collage showing a hand-stitched leather card wallet with 3 card pockets, a hidden pocket, and a zippered coin pouch." loading="lazy" decoding="async" width="1000" height="1000">
|
||
|
|
|
||
|
|
</a>
|
||
|
|
</li>
|
||
|
|
|
||
|
|
<li class="post">
|
||
|
|
<a class="postlink" href="/vertical-bifold/">
|
||
|
|
<h2 data-ha-exclude="" id="vertical-bifold">vertical bifold </h2>
|
||
|
|
|
||
|
|
<ul class="postlist-tags">
|
||
|
|
|
||
|
|
<li>leather</li>
|
||
|
|
|
||
|
|
</ul>
|
||
|
|
<img src="/img/vertical-bifold.jpg" alt="A collage showing a hand-stitched leather vertical bifold wallet with 6 card pockets, 2 hidden pockets, and 1 bill pocket." loading="lazy" decoding="async" width="1000" height="1777">
|
||
|
|
|
||
|
|
</a>
|
||
|
|
</li>
|
||
|
|
|
||
|
|
<li class="post">
|
||
|
|
<a class="postlink" href="/zipper-bifold-green/">
|
||
|
|
<h2 data-ha-exclude="" id="zipper-bifold-green">zipper bifold (green) </h2>
|
||
|
|
|
||
|
|
<ul class="postlist-tags">
|
||
|
|
|
||
|
|
<li>leather</li>
|
||
|
|
|
||
|
|
</ul>
|
||
|
|
<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">
|
||
|
|
|
||
|
|
</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>
|
||
|
|
|
||
|
|
|
||
|
|
<!-- This page `/leatherworking-zine/` was built on 2026-09-15T21:48:29.730Z -->
|
||
|
|
</body>
|
||
|
|
</html>
|