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 > pride dice bags | 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 = "pride dice bags | 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:image" content = "/img/pride-dice-bags.jpg" >
< meta property = "og:image:alt" content = "Several knitted drawstring dice bags sit in front of a bookshelf. They are in different pride flag colors; from right to left (skipping a few duplicates) bisexual, lesbian, nonbinary, trans, and genderqueer. The trans-colored dice bag in the center opens towards the camera, showing a variety of colorful dice inside." >
< 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 >
< 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 ;
}
. 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 );
}
/* 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 );
}
# 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 {
box-shadow : none ;
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 {
max-height : calc ( 90 vh - 2 rem );
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 ));
}
/* 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 {
line-height : 1.2 5 ;
margin-top : .65 rem ;
margin-bottom : .65 rem ;
}
li ul , li ol {
margin : .5 rem 0 ;
}
dt {
font-weight : 900 ;
margin-top : .5 rem ;
}
dd {
margin-left : 2 rem ;
margin-bottom : .75 rem ;
}
/* Blockquotes */
blockquote {
margin : .5 rem 0 ;
padding : 0 1 rem ;
border-radius : .25 rem 1 rem 1 rem .25 rem ;
line-height : 1.25 ;
border-left : .5 rem solid var ( -- color - pink );
}
blockquote ,
blockquote p ,
blockquote ol ,
blockquote ul {
background-color : var ( -- color - bg - alt );
padding : .5 rem ;
}
blockquote p {
margin : 0 ;
}
/* Tables */
table {
width : 100 % ;
border-spacing : 0 ; /* border collapse doesn't play nice with radii */
border-radius : .3 rem ;
border : thin solid var ( -- color - pink );
}
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 {
position : sticky ;
top : 0 ;
background-color : var ( -- color - bg );
padding : .75 rem 0 ;
z-index : 10 ;
border-bottom : thick solid var ( -- color - teal );
box-shadow : 0 .25 rem .15 rem var ( -- color - shadow );
}
/* Header links, pagination links */
header a ,
. pagination a ,
. webring ul a {
border-radius : 1 rem ;
border : .125 rem solid var ( -- color - pink );
color : var ( -- color - pink );
text-decoration : none ;
padding : 0 .25 rem ;
box-shadow : .15 rem .15 rem var ( -- color - shadow );
font-size : 1.2 rem ;
/* Click animation handling */
position : relative ;
top : 0 ;
left : 0 ;
transition : top .05 s ease-in , left .05 s ease-in ;
}
header a ,
. pagination . older a ,
. webring . prev a ,
. webring . rand a {
padding-right : .35 rem ;
}
. pagination . newer a ,
. webring . next a ,
. webring . rand a {
padding-left : .35 rem ;
}
header a : focus-visible ,
. pagination a : focus-visible ,
. webring ul a : focus-visible {
color : var ( -- color - bg );
border-color : var ( -- color - pink );
background-color : var ( -- color - pink );
outline : none ;
}
@ media ( any-hover : hover ) {
header a : hover ,
. pagination a : hover ,
. webring ul a : hover {
color : var ( -- color - bg );
border-color : var ( -- color - pink );
background-color : var ( -- color - pink );
}
}
@ media ( forced-colors : active ) {
header a : focus-visible ,
. pagination a : focus-visible ,
. webring ul a : focus-visible {
outline-offset : .125 rem ;
outline : .125 rem solid ;
}
@ media ( any-hover : hover ) {
header a : hover ,
. pagination a : hover ,
. webring ul a : hover {
outline-offset : .125 rem ;
outline : .125 rem solid ;
}
}
}
/* Click animation */
header a : active ,
. pagination a : active ,
. webring ul a : active {
top : .1 rem ;
left : .1 rem ;
box-shadow : .05 rem .05 rem var ( -- color - shadow );
}
/* Current page */
header a [ aria-current = "page" ] {
border-color : var ( -- color - teal );
color : var ( -- color - teal );
}
header a [ aria-current = "page" ] : focus-visible {
color : var ( -- color - bg );
border-color : var ( -- color - teal );
background-color : var ( -- color - teal );
}
@ media ( any-hover : hover ) {
header a [ aria-current = "page" ] : hover {
color : var ( -- color - bg );
background-color : var ( -- color - teal );
border-color : var ( -- color - teal );
}
}
/* Header link icons, pagination icons */
header i ,
. pagination i ,
. webring ul i {
color : var ( -- color - teal );
}
header i ,
. pagination . older i ,
. webring . prev i ,
. webring . rand i : nth-child ( 1 ) {
padding-left : .25 rem ;
}
. pagination . newer i ,
. webring . next i ,
. webring . rand i : nth-child ( 2 ) {
padding-right : .25 rem ;
}
header a [ aria-current = "page" ] i {
color : var ( -- color - pink );
}
header a : focus-visible i ,
a [ aria-current = "page" ] a : focus-visible i ,
. pagination a : focus-visible i ,
. webring ul a : focus-visible i {
color : var ( -- color - bg );
}
@ media ( any-hover : hover ) {
header a : hover i ,
header a [ aria-current = "page" ] : hover i ,
. pagination a : hover i ,
. webring ul a : hover i {
color : var ( -- color - bg );
}
}
/* Skip link */
# skip {
left : -999 px ;
position : absolute ;
top : auto ;
width : 1 px ;
height : 1 px ;
overflow : hidden ;
z-index : -99 ;
}
# skip : focus-visible {
display : inline-block ;
left : auto ;
top : auto ;
width : auto ;
height : auto ;
overflow : auto ;
margin : 0 10 % ;
z-index : 999 ;
}
/* Nav */
header ul {
display : flex ;
list-style : none ;
gap : 1 rem ;
justify-content : center ;
}
header ul ,
header li {
margin : 0 ;
}
@ media ( max-width : 650px ) {
. menu-text {
display : none ; /* Icons only on small screens */
}
header a {
padding : .15 rem .5 rem ;
}
header i {
padding : 0 ;
}
}
/* Footer */
footer {
padding : 1 rem 0 ;
font-size : .9 rem ;
border-top : thick solid var ( -- color - pink );
margin-top : 2 rem ;
}
footer ul {
display : flex ;
list-style : none ;
gap : .5 rem ;
justify-content : center ;
margin : 0 ;
}
footer li {
margin : 0 ;
}
footer li : nth-child ( 2 ) :: before ,
footer li : nth-child ( 2 ) :: after {
content : " ● " / "" ;
color : var ( -- color - teal );
}
@ media ( max-width : 650px ) {
footer ul {
flex-flow : column ;
text-align : center ;
}
footer li : nth-child ( 2 ) :: before ,
footer li : nth-child ( 2 ) :: after {
content : none ;
}
}
footer a {
text-decoration-color : var ( -- color - pink );
}
footer a : focus-visible {
outline-color : var ( -- color - pink );
}
/* Pagination */
. pagination ,
. pagination li {
margin : 0 ;
}
. pagination {
display : grid ;
grid-template-columns : repeat ( 2 , 1 fr );
grid-template-areas : "older newer" ;
list-style : none ;
margin-top : 3 rem ;
}
@ media ( max-width : 650px ) {
. post-pagination {
grid-template-columns : 1 fr ;
grid-template-areas :
"older"
"newer" ;
gap : .75 rem ;
}
}
. pagination . older {
grid-area : older ;
}
. pagination . newer {
grid-area : newer ;
text-align : right ;
}
/* webring navigation */
. webring {
margin-bottom : 3 rem ;
}
. webring ul {
display : flex ;
flex-flow : row wrap ;
list-style : none ;
justify-content : space-around ;
gap : .35 rem ;
}
. webring ul ,
. webring li {
margin-left : 0 ;
}
@ media print {
/* Nav elements */
header ,
footer ,
nav {
display : none !important ;
}
/* Base */
body {
background-color : #fff ;
color : #000 ;
}
main {
width : 95 vw ;
}
h1 , h2 , h3 , h4 , h5 , h6 {
color : #000 ;
}
/* Links */
/* Hover is not really necessary, but it's annoying when testing otherwise */
a ,
a : hover {
text-decoration-style : dotted ;
text-decoration-thickness : .1 rem ;
text-decoration-color : #000 ;
}
a :: after {
content : " (" attr ( href ) ")" ;
}
/* Code */
code ,
pre ,
code [ class *= language- ],
pre [ class *= language- ] {
text-shadow : none ;
background-color : var ( -- color - light );
color : #000 !important ;
}
. token . namespace {
opacity : 1 ;
}
. token . block-comment ,
. token . cdata ,
. token . comment ,
. token . doctype ,
. token . prolog ,
. token . punctuation ,
. token . attr-name ,
. token . deleted ,
. token . namespace ,
. token . tag ,
. token . boolean ,
. token . function ,
. token . number ,
. token . class-name ,
. token . constant ,
. token . property ,
. token . symbol ,
. token . attr-value ,
. token . char ,
. token . regex ,
. token . string ,
. token . variable ,
. token . inserted ,
. token . entity ,
. token . operator ,
. token . url ,
. token . function-name ,
. token . atrule ,
. token . builtin ,
. token . important ,
. token . keyword ,
. token . selector {
color : #000 ;
}
}</ style >
< script type = "module" > // Thank you to https://github.com/daviddarnes/heading-anchors
// Thank you to https://amberwilson.co.uk/blog/are-your-anchor-links-accessible/
let globalInstanceIndex = 0 ;
class HeadingAnchors extends HTMLElement {
static register ( tagName = "heading-anchors" , registry = window . customElements ) {
if ( registry && ! registry . get ( tagName )) {
registry . define ( tagName , this );
}
}
static attributes = {
exclude : "data-ha-exclude" ,
prefix : "prefix" ,
content : "content" ,
}
static classes = {
anchor : "ha" ,
placeholder : "ha-placeholder" ,
srOnly : "ha-visualhide" ,
}
static defaultSelector = "h2,h3,h4,h5,h6" ;
static css = `
. ${ HeadingAnchors . classes . srOnly } {
clip: rect(0 0 0 0);
height: 1px;
overflow: hidden;
position: absolute;
width: 1px;
}
. ${ HeadingAnchors . classes . anchor } {
position: absolute;
left: var(--ha_offsetx);
top: var(--ha_offsety);
text-decoration: none;
opacity: 0;
}
. ${ HeadingAnchors . classes . placeholder } {
opacity: .3;
}
. ${ HeadingAnchors . classes . anchor } :is(:focus-within, :hover) {
opacity: 1;
}
. ${ HeadingAnchors . classes . anchor } ,
. ${ HeadingAnchors . classes . placeholder } {
display: inline-block;
padding: 0 .25em;
/* Disable selection of visually hidden label */
-webkit-user-select: none;
user-select: none;
}
@supports (anchor-name: none) {
. ${ HeadingAnchors . classes . anchor } {
position: absolute;
left: anchor(left);
top: anchor(top);
}
}` ;
get supports () {
return "replaceSync" in CSSStyleSheet . prototype ;
}
get supportsAnchorPosition () {
return CSS . supports ( "anchor-name: none" );
}
constructor () {
super ();
if ( ! this . supports ) {
return ;
}
let sheet = new CSSStyleSheet ();
sheet . replaceSync ( HeadingAnchors . css );
document . adoptedStyleSheets = [... document . adoptedStyleSheets , sheet ];
this . headingStyles = {};
this . instanceIndex = globalInstanceIndex ++ ;
}
connectedCallback () {
if ( ! this . supports ) {
return ;
}
this . headings . forEach (( heading , index ) => {
if ( ! heading . hasAttribute ( HeadingAnchors . attributes . exclude )) {
let anchor = this . getAnchorElement ( heading );
let placeholder = this . getPlaceholderElement ();
// Prefers anchor position approach for better accessibility
// https://amberwilson.co.uk/blog/are-your-anchor-links-accessible/
if ( this . supportsAnchorPosition ) {
let anchorName = `--ha_ ${ this . instanceIndex } _ ${ index } ` ;
placeholder . style . setProperty ( "anchor-name" , anchorName );
anchor . style . positionAnchor = anchorName ;
}
heading . appendChild ( placeholder );
heading . after ( anchor );
}
});
}
// Polyfill-only
positionAnchorFromPlaceholder ( placeholder ) {
if ( ! placeholder ) {
return ;
}
let heading = placeholder . closest ( "h1,h2,h3,h4,h5,h6" );
if ( ! heading . nextElementSibling ) {
return ;
}
// TODO next element could be more defensive
this . positionAnchor ( heading . nextElementSibling );
}
// Polyfill-only
positionAnchor ( anchor ) {
if ( ! anchor || ! anchor . previousElementSibling ) {
return ;
}
// TODO previous element could be more defensive
let heading = anchor . previousElementSibling ;
this . setFontProp ( heading , anchor );
if ( this . supportsAnchorPosition ) {
// quit early
return ;
}
let placeholder = heading . querySelector ( `. ${ HeadingAnchors . classes . placeholder } ` );
if ( placeholder ) {
anchor . style . setProperty ( "--ha_offsetx" , ` ${ placeholder . offsetLeft } px` );
anchor . style . setProperty ( "--ha_offsety" , ` ${ placeholder . offsetTop } px` );
}
}
setFontProp ( heading , anchor ) {
let placeholder = heading . querySelector ( `. ${ HeadingAnchors . classes . placeholder } ` );
if ( placeholder ) {
let style = getComputedStyle ( placeholder );
let props = [ "font-weight" , "font-size" , "line-height" , "font-family" ];
let [ weight , size , lh , family ] = props . map ( name => style . getPropertyValue ( name ));
anchor . style . setProperty ( "font" , ` ${ weight } ${ size } / ${ lh } ${ family } ` );
let vars = style . getPropertyValue ( "font-variation-settings" );
if ( vars ) {
anchor . style . setProperty ( "font-variation-settings" , vars );
}
}
}
/* no longer used, using aria-labelledby instead - see getAnchorElement
getAccessibleTextPrefix() {
// Useful for i18n
return this.getAttribute(HeadingAnchors.attributes.prefix) || "Jump to section titled";
}
*/
getContent () {
if ( this . hasAttribute ( HeadingAnchors . attributes . content )) {
return this . getAttribute ( HeadingAnchors . attributes . content );
}
return "#" ;
}
// Placeholder nests inside of heading
getPlaceholderElement () {
let ph = document . createElement ( "span" );
ph . setAttribute ( "aria-hidden" , true );
ph . classList . add ( HeadingAnchors . classes . placeholder );
let content = this . getContent ();
if ( content ) {
ph . innerHTML = content ; // CHANGED HERE
}
ph . addEventListener ( "mouseover" , ( e ) => {
let placeholder = e . target . closest ( `. ${ HeadingAnchors . classes . placeholder } ` );
if ( placeholder ) {
this . positionAnchorFromPlaceholder ( placeholder );
}
});
return ph ;
}
getAnchorElement ( heading ) {
let anchor = document . createElement ( "a" );
anchor . href = `# ${ heading . id } ` ;
anchor . classList . add ( HeadingAnchors . classes . anchor );
let content = this . getContent ();
anchor . innerHTML = `<span aria-labelledby= ${ heading . id } > ${ content } </span>` ; // CHANGED HERE
anchor . addEventListener ( "focus" , e => {
let anchor = e . target . closest ( `. ${ HeadingAnchors . classes . anchor } ` );
if ( anchor ) {
this . positionAnchor ( anchor );
}
});
anchor . addEventListener ( "mouseover" , ( e ) => {
// when CSS anchor positioning is supported, this is only used to set the font
let anchor = e . target . closest ( `. ${ HeadingAnchors . classes . anchor } ` );
this . positionAnchor ( anchor );
});
return anchor ;
}
get headings () {
return this . querySelectorAll ( this . selector . split ( "," ). map ( entry => ` ${ entry . trim () } [id]` ));
}
get selector () {
return this . getAttribute ( "selector" ) || HeadingAnchors . defaultSelector ;
}
}
HeadingAnchors . register ();
export { HeadingAnchors }
/* don't even bother on mobile */
if ( window . innerWidth > 650 ) {
const dialog = document . querySelector ( "dialog" );
const closeButton = document . querySelector ( ".close-dialog" );
const hero = document . querySelector ( ".hero" );
hero . tabIndex = 0 ;
hero . addEventListener ( "click" , ( e ) => dialog . showModal ());
hero . addEventListener ( "keydown" , ( e ) => {
if ( e . key === "Enter" || e . key === " " ) {
e . preventDefault ();
dialog . showModal ();
}
});
closeButton . addEventListener ( "click" , ( e ) => dialog . close ());
closeButton . addEventListener ( "keydown" , ( e ) => {
if ( e . key === "Enter" || e . key === " " ) {
e . preventDefault ();
dialog . close ();
}
});
}</ 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 >
</ header >
< main id = "main" >
< heading-anchors content = "<i class='fa-solid fa-anchor'></i>" >
< article >
< h1 id = "pride-dice-bags" > pride dice bags</ h1 >
< div class = "post-metadata" >
< p >
posted on
< time datetime = "2022-11-18" > November 18, 2022</ time >
by Lee Cattarin
</ p >
< ul class = "post-tags" >
< li >
< a href = "/tags/knit/" > knit</ a >
</ li >
< li >
< a href = "/tags/gender/" > gender</ 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/pride-dice-bags.jpg" alt = "Several knitted drawstring dice bags sit in front of a bookshelf. They are in different pride flag colors; from right to left (skipping a few duplicates) bisexual, lesbian, nonbinary, trans, and genderqueer. The trans-colored dice bag in the center opens towards the camera, showing a variety of colorful dice inside." loading = "lazy" decoding = "async" width = "1000" height = "500" >
</ dialog >
< img class = "hero" src = "/img/pride-dice-bags.jpg" alt = "Several knitted drawstring dice bags sit in front of a bookshelf. They are in different pride flag colors; from right to left (skipping a few duplicates) bisexual, lesbian, nonbinary, trans, and genderqueer. The trans-colored dice bag in the center opens towards the camera, showing a variety of colorful dice inside." loading = "lazy" decoding = "async" width = "1000" height = "500" >
< p > Knitted dice bags in pride flag patterns.</ p >
< p > Available flags at current:</ p >
< ul >
< li > bisexual</ li >
< li > lesbian</ li >
< li > nonbinary</ li >
< li > transgender</ li >
< li > genderqueer</ li >
< li > genderfluid</ li >
< li > pansexual</ li >
< li > 6-stripe rainbow</ li >
</ ul >
< p > I also have several varieties of rainbow gradient yarn which will produce varying results.</ p >
< p > For any flag not on the list, please do still message - I'm happy to get the colors missing to do it! For example I would only need a gray for asexual, so it's easy to add :)</ p >
< h2 id = "details" > details</ h2 >
< h3 id = "dimensions" > dimensions</ h3 >
< p > usually sized to hold 1-3 dice sets, but I can aim for a specific size on request.</ p >
< h3 id = "coloration" > coloration</ h3 >
< p > Based on flag chosen</ p >
</ article >
< nav aria-label = "pagination" >
< ol class = "pagination post-pagination" >
< li class = "older" >
< a href = "/square-watercolor-pad/" >
< i class = "fa-solid fa-hand-point-left" aria-hidden = "true" ></ i > square watercolor pad
</ a >
</ li >
< li class = "newer" >
< a href = "/gender/" >
gender? < 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-06-30 23:29:05 +00:00
< li class = "post" >
< a class = "postlink" href = "/butch-hands-pattern/" >
< h2 data-ha-exclude = "" id = "butch-hands-pattern" > butch hands pattern </ h2 >
< ul class = "postlist-tags" >
< li > knit</ li >
< li > highlight</ li >
</ ul >
< img src = "/img/butch-hands.jpg" alt = "Hands wearing a pair of pink and grey gloves with convertable mitten tops." loading = "lazy" decoding = "async" width = "1000" height = "750" >
</ a >
</ li >
< li class = "post" >
< a class = "postlink" href = "/networks-of-trans-care/" >
< h2 data-ha-exclude = "" id = "networks-of-trans-care" > networks of trans care </ h2 >
< ul class = "postlist-tags" >
< li > gender</ li >
</ ul >
< img src = "/img/mushrooms-and-moss.jpg" alt = "Image unrelated to post. Close up on a cluster of orange-brown mushrooms on a mossy tree trunk." loading = "lazy" decoding = "async" width = "1000" height = "750" >
</ a >
</ li >
2026-05-15 09:20:43 -07:00
< li class = "post" >
2026-06-30 20:19:45 +00:00
< a class = "postlink" href = "/sideways-canvas-shirt/" >
< h2 data-ha-exclude = "" id = "sideways-canvas-shirt" > sideways canvas shirt </ h2 >
2026-05-15 09:20:43 -07:00
< ul class = "postlist-tags" >
2026-06-30 20:19:45 +00:00
< li > knit</ li >
2026-05-15 09:20:43 -07:00
</ ul >
2026-06-30 20:19:45 +00:00
< img src = "/img/sideways-canvas.jpg" alt = "someone's torso in a knitted short sleeve shirt. the front is teal, and the bit of back we can see is mustard yellow. looking closely, it's notable that the stitches are turned 90 degrees from a standard knit garment." loading = "lazy" decoding = "async" width = "1000" height = "1338" >
2026-05-15 16:24:45 +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 >
</ footer >
2026-06-30 23:29:05 +00:00
<!-- This page `/pride-dice-bags/` was built on 2026-06-30T23:28:51.263Z -->
2026-05-15 09:20:43 -07:00
</ body >
</ html >