Compare commits
	
		
			2 commits
		
	
	
		
			72bddf3c9f
			...
			5304273b28
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 5304273b28 | |||
| 0269ed5c60 | 
					 21 changed files with 73 additions and 534 deletions
				
			
		| 
						 | 
				
			
			@ -16,7 +16,7 @@ tags = ["all", "shower"]
 | 
			
		|||
why do we, as a society, fear sillyness?
 | 
			
		||||
 | 
			
		||||
    % id = "01JDJ0RH4DF8MQ3ZE7C7CYAE92"
 | 
			
		||||
    + this is not even something our company can fix, no matter how much it portrays to be rebellious or how big, red and bold we make the "*[WE BREAK RULES, WE MAKE RULES]{style="--recursive-casl: 0; --recursive-wght: 800;"}*" text on our website.
 | 
			
		||||
    + this is not even something our company can fix, no matter how much it portrays to be rebellious or how big, red and bold we make the "*[WE BREAK RULES, WE MAKE RULES]{style="--recursive-casl: 0; font-weight: 800;"}*" text on our website.
 | 
			
		||||
 | 
			
		||||
        % id = "01JDJ0RH4DHHD4QRNPCXNEWVSD"
 | 
			
		||||
        - which I find ironic considering we make games for mainstreamers.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -95,7 +95,7 @@ visibility = "Private"
 | 
			
		|||
        st
 | 
			
		||||
 | 
			
		||||
        [vfs target]: https://src.liquidev.net/liquidex/treehouse/src/commit/0f8d05adebfe323908be487187d9afe6aaa2df36/crates/treehouse/src/generate.rs#L511
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        % id = "01JDDE4YE6RQH27JGPN28ZAJYC"
 | 
			
		||||
        + this generally doesn't mean anything for you, but for me... man, does the treehouse feel fast to edit now!
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -127,7 +127,7 @@ visibility = "Private"
 | 
			
		|||
 | 
			
		||||
    % id = "01JBWHXTMCZN2Q7R0FS208A8FR"
 | 
			
		||||
    + page titles are now way bigger!
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
        % id = "01JBWHXTMCMVHB3T4GBM6SQM3D"
 | 
			
		||||
        - I like this change in particular because it clarifies the visual hierarchy between page titles and the commonly used level 3 header on pages
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -162,7 +162,7 @@ visibility = "Private"
 | 
			
		|||
 | 
			
		||||
        % id = "01J3NX4F6ZMB691JYM61RHP4ZN"
 | 
			
		||||
        - there are some minor exceptions to this, which include:
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
            % id = "01J3NX4F6Z59655NYTS3QTA9EQ"
 | 
			
		||||
            + pages themselves. we cannot cache those at all. well, maybe in release mode, for like 10 seconds, which defeats the point.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -180,9 +180,9 @@ visibility = "Private"
 | 
			
		|||
 | 
			
		||||
                    % id = "01J3NX4F6ZXB360N1XXGN58964"
 | 
			
		||||
                    - except for `/sandbox` maybe, because that tends to be fetched in short bursts... I'll think about it.
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            % id = "01J3NX4F6ZJE0JT8XY49DH52RX"
 | 
			
		||||
            - linked branches. it's hard and not worth it for the few extra kilobytes saved - for snappiness it would be much better to prefetch branch content when the user hovers over a branch. 
 | 
			
		||||
            - linked branches. it's hard and not worth it for the few extra kilobytes saved - for snappiness it would be much better to prefetch branch content when the user hovers over a branch.
 | 
			
		||||
 | 
			
		||||
                % id = "01J3NX4F6ZVA8PCQNMGMW2DDFB"
 | 
			
		||||
                - not sure what to do about mobile devices, because they don't have a hover state.
 | 
			
		||||
| 
						 | 
				
			
			@ -308,7 +308,7 @@ visibility = "Private"
 | 
			
		|||
    }
 | 
			
		||||
    </style>
 | 
			
		||||
    ```
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    each major content category now has an icon and a _liquidex brand color™_
 | 
			
		||||
    []{class="treehouse/changelog:liquidex-brand-color red"}[]{class="treehouse/changelog:liquidex-brand-color yellow"}[]{class="treehouse/changelog:liquidex-brand-color green"}[]{class="treehouse/changelog:liquidex-brand-color blue"}
 | 
			
		||||
    assigned to it
 | 
			
		||||
| 
						 | 
				
			
			@ -356,7 +356,7 @@ visibility = "Private"
 | 
			
		|||
    - this page will show you all the updates that have been happening since your last visit
 | 
			
		||||
 | 
			
		||||
    % id = "01HQ94FDZKXFRMCH5NXXAB146E"
 | 
			
		||||
    + it will also lightly nag you whenever there are new posts with a [1]{.badge .red} badge
 | 
			
		||||
    + it will also lightly nag you whenever there are new posts with a *1* badge
 | 
			
		||||
 | 
			
		||||
        % id = "01HQ94FDZK5TJDM3CMNKQKES6Z"
 | 
			
		||||
        - if that's too annoying for you, it's easy to disable - scroll down on the [news page][page:treehouse/new] and there's a (collapsed by default) settings section for the page
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -592,7 +592,7 @@ impl<'a> Writer<'a> {
 | 
			
		|||
                    // TODO: this could do with better alt text
 | 
			
		||||
                    write!(
 | 
			
		||||
                        out,
 | 
			
		||||
                        r#"<img data-cast="emoji" title=":{sym}:" alt="{sym}" src=""#
 | 
			
		||||
                        r#"<img class="emoji" title=":{sym}:" alt="{sym}" src=""#
 | 
			
		||||
                    )?;
 | 
			
		||||
                    write_attr(&url, out);
 | 
			
		||||
                    out.push('"');
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -97,7 +97,7 @@ fn guess_content_type(extension: &str) -> Option<&'static str> {
 | 
			
		|||
        "html" => Some("text/html"),
 | 
			
		||||
        "js" => Some("text/javascript"),
 | 
			
		||||
        "css" => Some("text/css"),
 | 
			
		||||
        "woff" => Some("font/woff2"),
 | 
			
		||||
        "woff2" => Some("font/woff2"),
 | 
			
		||||
        "svg" => Some("image/svg+xml"),
 | 
			
		||||
        "atom" => Some("application/atom+xml"),
 | 
			
		||||
        "png" => Some("image/png"),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,7 +49,7 @@ th-chat-asked {
 | 
			
		|||
        padding: 0.5em 0;
 | 
			
		||||
        margin-right: 2rem;
 | 
			
		||||
 | 
			
		||||
        --recursive-wght: 500;
 | 
			
		||||
        font-weight: 500;
 | 
			
		||||
        text-decoration: underline;
 | 
			
		||||
        text-align: right;
 | 
			
		||||
        opacity: 80%;
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +63,7 @@ th-chat-asked {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        &[disabled] {
 | 
			
		||||
            --recursive-wght: 600;
 | 
			
		||||
            font-weight: 600;
 | 
			
		||||
            cursor: default;
 | 
			
		||||
            opacity: 100%;
 | 
			
		||||
            text-decoration: none;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -100,7 +100,7 @@ main.doc {
 | 
			
		|||
            padding: 0.8rem var(--code-block-h-padding);
 | 
			
		||||
 | 
			
		||||
            & code {
 | 
			
		||||
                --recursive-wght: 500;
 | 
			
		||||
                font-weight: 500;
 | 
			
		||||
                --recursive-mono: 0.5; /* You didn't expect a proportional font being used for code, did you. */
 | 
			
		||||
                font-size: 95%;
 | 
			
		||||
                tab-size: 3ch;
 | 
			
		||||
| 
						 | 
				
			
			@ -198,7 +198,7 @@ main.doc {
 | 
			
		|||
                flex-direction: row;
 | 
			
		||||
                align-items: center;
 | 
			
		||||
 | 
			
		||||
                --recursive-wght: 600;
 | 
			
		||||
                font-weight: 600;
 | 
			
		||||
                border-bottom: 1px solid var(--border-1);
 | 
			
		||||
 | 
			
		||||
                cursor: pointer;
 | 
			
		||||
| 
						 | 
				
			
			@ -320,7 +320,7 @@ main.doc {
 | 
			
		|||
                border-right: none;
 | 
			
		||||
 | 
			
		||||
                & code {
 | 
			
		||||
                    --recursive-wght: 520;
 | 
			
		||||
                    font-weight: 520;
 | 
			
		||||
                    font-size: 90%;
 | 
			
		||||
                    tab-size: 2ch;
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,30 +0,0 @@
 | 
			
		|||
.version-history {
 | 
			
		||||
    & > .commit-count {
 | 
			
		||||
        margin-left: 2rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    & > ul.commits {
 | 
			
		||||
        --recursive-mono: 1;
 | 
			
		||||
 | 
			
		||||
        list-style: none;
 | 
			
		||||
        padding-left: 0;
 | 
			
		||||
 | 
			
		||||
        & > li {
 | 
			
		||||
            padding-top: 0.2rem;
 | 
			
		||||
            padding-bottom: 0.2rem;
 | 
			
		||||
 | 
			
		||||
            display: grid;
 | 
			
		||||
            grid-template-columns: 4em min-content auto;
 | 
			
		||||
            align-items: start;
 | 
			
		||||
            gap: 0.5em;
 | 
			
		||||
 | 
			
		||||
            & > .revision-number {
 | 
			
		||||
                justify-self: end;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            details > summary {
 | 
			
		||||
                cursor: pointer;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -106,6 +106,14 @@ body {
 | 
			
		|||
 | 
			
		||||
/* Set up typography */
 | 
			
		||||
 | 
			
		||||
html {
 | 
			
		||||
    font-size: 62.5%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
    font-size: 1.6rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body,
 | 
			
		||||
pre,
 | 
			
		||||
code,
 | 
			
		||||
| 
						 | 
				
			
			@ -120,14 +128,6 @@ dfn {
 | 
			
		|||
    text-size-adjust: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
html {
 | 
			
		||||
    font-size: 62.5%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
    font-size: 1.6rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pre,
 | 
			
		||||
code,
 | 
			
		||||
kbd,
 | 
			
		||||
| 
						 | 
				
			
			@ -138,17 +138,10 @@ input {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
:root {
 | 
			
		||||
    font-weight: 450;
 | 
			
		||||
    font-style: normal;
 | 
			
		||||
    --recursive-mono: 0;
 | 
			
		||||
    --recursive-casl: 0;
 | 
			
		||||
    --recursive-wght: 450;
 | 
			
		||||
    --recursive-slnt: 0;
 | 
			
		||||
    --recursive-crsv: 0.5;
 | 
			
		||||
 | 
			
		||||
    --recursive-simplified-f: "ss03";
 | 
			
		||||
    --recursive-simplified-g: "ss04";
 | 
			
		||||
    --recursive-simplified-l: "ss05";
 | 
			
		||||
    --recursive-simplified-r: "ss06";
 | 
			
		||||
    --recursive-no-serif-L-Z: "ss08";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
*,
 | 
			
		||||
| 
						 | 
				
			
			@ -156,38 +149,30 @@ input {
 | 
			
		|||
*:after {
 | 
			
		||||
    font-variation-settings:
 | 
			
		||||
        "MONO" var(--recursive-mono),
 | 
			
		||||
        "CASL" var(--recursive-casl),
 | 
			
		||||
        "wght" var(--recursive-wght),
 | 
			
		||||
        "slnt" var(--recursive-slnt),
 | 
			
		||||
        "CRSV" var(--recursive-crsv);
 | 
			
		||||
 | 
			
		||||
    font-feature-settings:
 | 
			
		||||
        var(--recursive-simplified-f), var(--recursive-simplified-g),
 | 
			
		||||
        var(--recursive-simplified-l), var(--recursive-simplified-r),
 | 
			
		||||
        var(--recursive-no-serif-L-Z);
 | 
			
		||||
    font-feature-settings: "ss03", "ss04", "ss05", "ss06", "ss08";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h1 {
 | 
			
		||||
    --recursive-wght: 900;
 | 
			
		||||
    font-weight: 900;
 | 
			
		||||
 | 
			
		||||
    font-size: 4.8rem;
 | 
			
		||||
    font-feature-settings: var(--recursive-simplified-r) 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h2 {
 | 
			
		||||
    --recursive-wght: 850;
 | 
			
		||||
    font-weight: 850;
 | 
			
		||||
 | 
			
		||||
    font-size: 3.2rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h3 {
 | 
			
		||||
    --recursive-wght: 850;
 | 
			
		||||
    font-weight: 850;
 | 
			
		||||
 | 
			
		||||
    font-size: 2.4rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h4 {
 | 
			
		||||
    --recursive-wght: 800;
 | 
			
		||||
    font-weight: 800;
 | 
			
		||||
 | 
			
		||||
    font-size: 1.6rem;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -201,23 +186,23 @@ pre code,
 | 
			
		|||
kbd,
 | 
			
		||||
th-literate-program {
 | 
			
		||||
    --recursive-mono: 1;
 | 
			
		||||
    --recursive-wght: 450;
 | 
			
		||||
    font-weight: 450;
 | 
			
		||||
    tab-size: 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
strong code {
 | 
			
		||||
    --recursive-wght: 800;
 | 
			
		||||
    font-weight: 800;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
b,
 | 
			
		||||
strong {
 | 
			
		||||
    --recursive-wght: 700;
 | 
			
		||||
    font-weight: 700;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
i,
 | 
			
		||||
em {
 | 
			
		||||
    --recursive-slnt: -16;
 | 
			
		||||
    font-style: normal;
 | 
			
		||||
    --recursive-crsv: 1;
 | 
			
		||||
    font-style: italic;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h1,
 | 
			
		||||
| 
						 | 
				
			
			@ -437,7 +422,7 @@ td {
 | 
			
		|||
th {
 | 
			
		||||
    background-color: var(--shaded-background);
 | 
			
		||||
 | 
			
		||||
    --recursive-wght: 700;
 | 
			
		||||
    font-weight: 700;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Horizontal rules */
 | 
			
		||||
| 
						 | 
				
			
			@ -490,42 +475,6 @@ button.push {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Style the noscript box a little more prettily. */
 | 
			
		||||
 | 
			
		||||
.noscript {
 | 
			
		||||
    padding: 1.6rem;
 | 
			
		||||
    background-color: #fde748;
 | 
			
		||||
    color: #55423e;
 | 
			
		||||
    border: 0.1rem solid #6c581c;
 | 
			
		||||
    border-radius: 0.8rem;
 | 
			
		||||
    width: fit-content;
 | 
			
		||||
    margin-left: auto;
 | 
			
		||||
    margin-right: auto;
 | 
			
		||||
    margin-top: 1.6rem;
 | 
			
		||||
    margin-bottom: 1.6rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.noscript:empty {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.noscript p {
 | 
			
		||||
    margin-top: 0;
 | 
			
		||||
    margin-bottom: 1.6rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.noscript p:last-child {
 | 
			
		||||
    margin-bottom: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.noscript a {
 | 
			
		||||
    color: #004ec8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.noscript a:visited {
 | 
			
		||||
    color: #6c2380;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Feeds */
 | 
			
		||||
 | 
			
		||||
section.feed {
 | 
			
		||||
| 
						 | 
				
			
			@ -550,14 +499,14 @@ section.feed {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    & h1 {
 | 
			
		||||
        --recursive-wght: 800;
 | 
			
		||||
        font-weight: 800;
 | 
			
		||||
        font-size: 125%;
 | 
			
		||||
        padding-top: 1.2rem;
 | 
			
		||||
        padding-bottom: 1.2rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    & h2 {
 | 
			
		||||
        --recursive-wght: 600;
 | 
			
		||||
        font-weight: 600;
 | 
			
		||||
        font-size: 100%;
 | 
			
		||||
        padding: 0;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -639,7 +588,7 @@ header.floof {
 | 
			
		|||
        line-height: 1;
 | 
			
		||||
        width: min-content;
 | 
			
		||||
 | 
			
		||||
        --recursive-wght: 900;
 | 
			
		||||
        font-weight: 900;
 | 
			
		||||
        font-size: 5.6rem;
 | 
			
		||||
        text-align: right;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -652,16 +601,6 @@ header.floof {
 | 
			
		|||
            padding: 0.1em;
 | 
			
		||||
 | 
			
		||||
            --shadow-color: var(--accent-pink);
 | 
			
		||||
            box-shadow:
 | 
			
		||||
                0.5px 0.5px 0 var(--shadow-color),
 | 
			
		||||
                1px 1px 0 var(--shadow-color),
 | 
			
		||||
                1.5px 1.5px 0 var(--shadow-color),
 | 
			
		||||
                2px 2px 0 var(--shadow-color),
 | 
			
		||||
                2.5px 2.5px 0 var(--shadow-color),
 | 
			
		||||
                3px 3px 0 var(--shadow-color),
 | 
			
		||||
                3.5px 3.5px 0 var(--shadow-color),
 | 
			
		||||
                4px 4px 0 var(--shadow-color);
 | 
			
		||||
 | 
			
		||||
            /*
 | 
			
		||||
                import math
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -701,11 +640,7 @@ header.floof {
 | 
			
		|||
                12.0px 12.0px 9.0px rgba(from var(--shadow-color) r g b / 0.015625),
 | 
			
		||||
                12.5px 12.5px 9.765625px rgba(from var(--shadow-color) r g b / 0.010467529296875),
 | 
			
		||||
                13.0px 13.0px 10.5625px rgba(from var(--shadow-color) r g b / 0.006591796875),
 | 
			
		||||
                13.5px 13.5px 11.390625px rgba(from var(--shadow-color) r g b / 0.003814697265625),
 | 
			
		||||
                14.0px 14.0px 12.25px rgba(from var(--shadow-color) r g b / 0.001953125),
 | 
			
		||||
                14.5px 14.5px 13.140625px rgba(from var(--shadow-color) r g b / 0.000823974609375),
 | 
			
		||||
                15.0px 15.0px 14.0625px rgba(from var(--shadow-color) r g b / 0.000244140625),
 | 
			
		||||
                15.5px 15.5px 15.015625px rgba(from var(--shadow-color) r g b / 3.0517578125e-05)
 | 
			
		||||
                13.5px 13.5px 11.390625px rgba(from var(--shadow-color) r g b / 0.003814697265625)
 | 
			
		||||
            ;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -726,7 +661,7 @@ header.floof {
 | 
			
		|||
            color: var(--text-color);
 | 
			
		||||
 | 
			
		||||
            & .adjectives {
 | 
			
		||||
                --recursive-wght: 800;
 | 
			
		||||
                font-weight: 800;
 | 
			
		||||
                font-size: 1.6rem;
 | 
			
		||||
                padding-top: 0.6rem;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -742,27 +677,11 @@ header.floof {
 | 
			
		|||
/* Navigation header (contains page title & breadcrumbs) */
 | 
			
		||||
 | 
			
		||||
h1.page-title {
 | 
			
		||||
    --recursive-wght: 900;
 | 
			
		||||
    font-weight: 900;
 | 
			
		||||
 | 
			
		||||
    line-height: 1.2;
 | 
			
		||||
    padding-top: 0.5lh;
 | 
			
		||||
    padding-bottom: 0.5lh;
 | 
			
		||||
 | 
			
		||||
    & a {
 | 
			
		||||
        color: var(--text-color);
 | 
			
		||||
        text-decoration: underline;
 | 
			
		||||
        text-decoration-color: transparent;
 | 
			
		||||
 | 
			
		||||
        &:hover {
 | 
			
		||||
            text-decoration-color: var(--text-color);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (hover: none) {
 | 
			
		||||
    h1.page-title a {
 | 
			
		||||
        text-decoration: underline;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (max-width: 700px) {
 | 
			
		||||
| 
						 | 
				
			
			@ -771,29 +690,6 @@ h1.page-title {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
span.badge {
 | 
			
		||||
    --recursive-wght: 800;
 | 
			
		||||
    --recursive-mono: 1;
 | 
			
		||||
 | 
			
		||||
    border-radius: 100rem;
 | 
			
		||||
    padding: 0.2rem 0.6rem;
 | 
			
		||||
    font-size: 0.9em;
 | 
			
		||||
 | 
			
		||||
    &.red {
 | 
			
		||||
        color: white;
 | 
			
		||||
        background-color: #d01243;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.blue {
 | 
			
		||||
        color: white;
 | 
			
		||||
        background-color: #058ef0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.before-content {
 | 
			
		||||
        margin-right: 0.6rem;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Style the footer */
 | 
			
		||||
 | 
			
		||||
footer {
 | 
			
		||||
| 
						 | 
				
			
			@ -889,7 +785,7 @@ footer.pink-space {
 | 
			
		|||
        background: none;
 | 
			
		||||
        border: none;
 | 
			
		||||
 | 
			
		||||
        --recursive-wght: 700;
 | 
			
		||||
        font-weight: 700;
 | 
			
		||||
        line-height: 1.3;
 | 
			
		||||
        font-size: 75%;
 | 
			
		||||
        opacity: 25%;
 | 
			
		||||
| 
						 | 
				
			
			@ -914,94 +810,13 @@ dialog[open] {
 | 
			
		|||
 | 
			
		||||
/* Style emojis to be readable */
 | 
			
		||||
 | 
			
		||||
img[data-cast~="emoji"] {
 | 
			
		||||
img.emoji {
 | 
			
		||||
    max-width: 1.3125em;
 | 
			
		||||
    max-height: 1.3125em;
 | 
			
		||||
    vertical-align: text-bottom;
 | 
			
		||||
    object-fit: contain;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Tooltips */
 | 
			
		||||
 | 
			
		||||
th-overlays {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    pointer-events: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
th-tooltip {
 | 
			
		||||
    display: block;
 | 
			
		||||
 | 
			
		||||
    position: fixed;
 | 
			
		||||
    width: max-content;
 | 
			
		||||
    z-index: 100;
 | 
			
		||||
 | 
			
		||||
    background-color: var(--background-color-tooltip);
 | 
			
		||||
    padding: 0.4rem 0.8rem;
 | 
			
		||||
    border-radius: 0.6rem;
 | 
			
		||||
 | 
			
		||||
    transition:
 | 
			
		||||
        opacity var(--transition-duration) cubic-bezier(0.22, 1, 0.36, 1),
 | 
			
		||||
        filter var(--transition-duration) cubic-bezier(0.22, 1, 0.36, 1),
 | 
			
		||||
        transform var(--transition-duration) cubic-bezier(0.22, 1, 0.36, 1);
 | 
			
		||||
    opacity: 0%;
 | 
			
		||||
    filter: blur(0.3rem);
 | 
			
		||||
    pointer-events: none;
 | 
			
		||||
 | 
			
		||||
    font-size: 0.9em;
 | 
			
		||||
 | 
			
		||||
    &[th-side="bottom"] {
 | 
			
		||||
        transform: translateX(-50%) translateY(-10%) scale(0.8);
 | 
			
		||||
 | 
			
		||||
        &.transitioned-in {
 | 
			
		||||
            transform: translateX(-50%) scale(1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &[th-side="left"] {
 | 
			
		||||
        transform: translateX(-90%) translateY(-50%) scale(0.8);
 | 
			
		||||
 | 
			
		||||
        &.transitioned-in {
 | 
			
		||||
            transform: translateX(-100%) translateY(-50%);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
th-tooltip.transitioned-in {
 | 
			
		||||
    opacity: 100%;
 | 
			
		||||
    filter: blur(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
th-tooltip.tooltip-emoji {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
 | 
			
		||||
    padding: 0.8rem;
 | 
			
		||||
    margin-top: 0.8rem;
 | 
			
		||||
 | 
			
		||||
    & > img {
 | 
			
		||||
        display: block;
 | 
			
		||||
        max-width: 7.2rem;
 | 
			
		||||
        max-height: 7.2rem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    & > p {
 | 
			
		||||
        color: var(--text-color);
 | 
			
		||||
        margin: 0;
 | 
			
		||||
        padding-top: 0.6rem;
 | 
			
		||||
        line-height: 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.th-emoji-unknown {
 | 
			
		||||
    text-decoration: 0.1rem underline var(--error-color);
 | 
			
		||||
    cursor: help;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Command line */
 | 
			
		||||
 | 
			
		||||
th-command-line {
 | 
			
		||||
| 
						 | 
				
			
			@ -1068,7 +883,7 @@ th-command-line {
 | 
			
		|||
 | 
			
		||||
            & > dfn {
 | 
			
		||||
                --recursive-crsv: 0;
 | 
			
		||||
                --recursive-wght: 700;
 | 
			
		||||
                font-weight: 700;
 | 
			
		||||
                margin-right: 2ch;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1239,7 +1054,7 @@ th-literate-program[data-mode="output"] {
 | 
			
		|||
 | 
			
		||||
.th-syntax-highlighting span {
 | 
			
		||||
    &.comment {
 | 
			
		||||
        --recursive-slnt: -8;
 | 
			
		||||
        font-style: oblique 8deg;
 | 
			
		||||
        color: var(--syntax-comment);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1310,11 +1125,3 @@ th-literate-program[data-mode="output"] {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Style settings sections */
 | 
			
		||||
 | 
			
		||||
section[data-cast~="settings"] {
 | 
			
		||||
    /* Don't display settings when JavaScript is disabled.
 | 
			
		||||
       JS overrides this value on the element itself. */
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -31,8 +31,8 @@
 | 
			
		|||
    & .south,
 | 
			
		||||
    & .west,
 | 
			
		||||
    & .north {
 | 
			
		||||
        --recursive-wght: 900;
 | 
			
		||||
        --recursive-slnt: 0;
 | 
			
		||||
        font-weight: 900;
 | 
			
		||||
        font-style: normal;
 | 
			
		||||
        --recursive-mono: 1;
 | 
			
		||||
 | 
			
		||||
        position: absolute;
 | 
			
		||||
| 
						 | 
				
			
			@ -108,9 +108,8 @@
 | 
			
		|||
 | 
			
		||||
.tileset-four-to-eight-demo th-bc {
 | 
			
		||||
    & .directions-square {
 | 
			
		||||
        --recursive-wght: 900;
 | 
			
		||||
        --recursive-casl: 0;
 | 
			
		||||
        --recursive-slnt: 0;
 | 
			
		||||
        font-weight: 900;
 | 
			
		||||
        font-style: normal;
 | 
			
		||||
        --recursive-mono: 1;
 | 
			
		||||
        color: #d3dce9;
 | 
			
		||||
        text-shadow:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
    /* Make issue titles bold */
 | 
			
		||||
    & > li > details > summary > th-bc,
 | 
			
		||||
    & > li > div > th-bc {
 | 
			
		||||
        font-weight: 600;
 | 
			
		||||
        --recursive-wght: 600;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,7 +42,7 @@
 | 
			
		|||
 | 
			
		||||
.breadcrumb a {
 | 
			
		||||
    --recursive-mono: 1;
 | 
			
		||||
    --recursive-wght: 500;
 | 
			
		||||
    font-weight: 500;
 | 
			
		||||
 | 
			
		||||
    color: var(--text-color);
 | 
			
		||||
    text-decoration: none;
 | 
			
		||||
| 
						 | 
				
			
			@ -452,7 +452,7 @@ ul.branch-quote {
 | 
			
		|||
    position: relative;
 | 
			
		||||
 | 
			
		||||
    &::before {
 | 
			
		||||
        --recursive-wght: 900;
 | 
			
		||||
        font-weight: 900;
 | 
			
		||||
 | 
			
		||||
        content: "“";
 | 
			
		||||
        position: absolute;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								static/font/README.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								static/font/README.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
To produce recursive-casl0.woff2:
 | 
			
		||||
 | 
			
		||||
    fonttools varLib.instancer Recursive_VF_1.085.woff2 -o recursive-casl0.woff2 CASL=0
 | 
			
		||||
 | 
			
		||||
Further optimisations can be done to the font, but removing the CASL axis makes the biggest difference.
 | 
			
		||||
It is not used anywhere on the website anyways, and saves about half the download size of the font.
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								static/font/recursive-casl0.woff2
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/font/recursive-casl0.woff2
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -1,31 +0,0 @@
 | 
			
		|||
// Emoji zoom-in functionality.
 | 
			
		||||
 | 
			
		||||
import { addSpell } from "treehouse/spells.js";
 | 
			
		||||
import { attachTooltip, Tooltip } from "treehouse/overlay.js";
 | 
			
		||||
 | 
			
		||||
function createEmojiTooltip(emoji, element) {
 | 
			
		||||
    let tooltip = new Tooltip(element, "bottom");
 | 
			
		||||
    tooltip.classList.add("tooltip-emoji");
 | 
			
		||||
 | 
			
		||||
    let img = tooltip.appendChild(new Image());
 | 
			
		||||
    img.src = element.src;
 | 
			
		||||
 | 
			
		||||
    let description = tooltip.appendChild(document.createElement("p"));
 | 
			
		||||
    description.textContent = emoji.emojiName;
 | 
			
		||||
 | 
			
		||||
    return tooltip;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Emoji {
 | 
			
		||||
    constructor(element) {
 | 
			
		||||
        this.emojiName = element.title;
 | 
			
		||||
 | 
			
		||||
        // title makes the browser add a tooltip. We replace browser tooltips with our own,
 | 
			
		||||
        // so remove the title.
 | 
			
		||||
        element.title = "";
 | 
			
		||||
 | 
			
		||||
        attachTooltip(element, () => createEmojiTooltip(this, element)).showOnHover();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
addSpell("emoji", Emoji);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,116 +0,0 @@
 | 
			
		|||
export class Overlay extends HTMLElement {}
 | 
			
		||||
 | 
			
		||||
/** @type Overlays */
 | 
			
		||||
export let overlays = null;
 | 
			
		||||
 | 
			
		||||
export class Overlays extends HTMLElement {
 | 
			
		||||
    overlays = new Set();
 | 
			
		||||
 | 
			
		||||
    connectedCallback() {
 | 
			
		||||
        overlays = this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    disconnectedCallback() {
 | 
			
		||||
        overlays = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    open(overlay) {
 | 
			
		||||
        this.appendChild(overlay);
 | 
			
		||||
        this.overlays.add(overlay);
 | 
			
		||||
        return overlay;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    close(overlay) {
 | 
			
		||||
        this.removeChild(overlay);
 | 
			
		||||
        this.overlays.delete(overlay);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
customElements.define("th-overlays", Overlays);
 | 
			
		||||
 | 
			
		||||
export class Tooltip extends Overlay {
 | 
			
		||||
    constructor(element, side) {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this.element = element;
 | 
			
		||||
        this.side = side;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    connectedCallback() {
 | 
			
		||||
        this.role = "tooltip";
 | 
			
		||||
        this.setAttribute("th-side", this.side);
 | 
			
		||||
 | 
			
		||||
        let bb = this.element.getBoundingClientRect();
 | 
			
		||||
        switch (this.side) {
 | 
			
		||||
            // NOTE: The elements are positioned directly at (width / 2) or (height / 2), because
 | 
			
		||||
            // they are transformed to the centre over on the CSS side.
 | 
			
		||||
 | 
			
		||||
            case "bottom":
 | 
			
		||||
                this.style.left = `${bb.left + bb.width / 2}px`;
 | 
			
		||||
                this.style.top = `${bb.bottom}px`;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case "left":
 | 
			
		||||
                this.style.left = `${bb.left}px`;
 | 
			
		||||
                this.style.top = `${bb.top + bb.height / 2}px`;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
                console.error(`th-tooltip: unknown attachment side ${this.side}`);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.addEventListener("transitionend", (event) => {
 | 
			
		||||
            if (event.propertyName == "opacity") {
 | 
			
		||||
                let style = getComputedStyle(this);
 | 
			
		||||
                if (style.opacity < 0.01) {
 | 
			
		||||
                    this.dispatchEvent(new Event(".close"));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        // Timeout is zero because we just want to execute this later, to be definitely sure
 | 
			
		||||
        // the transition plays out.
 | 
			
		||||
        setTimeout(() => this.classList.add("transitioned-in"), 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    close() {
 | 
			
		||||
        this.classList.remove("transitioned-in");
 | 
			
		||||
 | 
			
		||||
        // NOTE: In case there is no transition, we may need to trigger the close event immediately.
 | 
			
		||||
        let style = getComputedStyle(this);
 | 
			
		||||
        if (style.opacity < 0.01) {
 | 
			
		||||
            this.dispatchEvent(new Event(".close"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
customElements.define("th-tooltip", Tooltip);
 | 
			
		||||
 | 
			
		||||
export function attachTooltip(element, makeTooltip) {
 | 
			
		||||
    let show = () => {
 | 
			
		||||
        let tooltip = overlays.open(makeTooltip(element));
 | 
			
		||||
        let abortController = new AbortController();
 | 
			
		||||
 | 
			
		||||
        tooltip.addEventListener(".close", () => {
 | 
			
		||||
            overlays.close(tooltip);
 | 
			
		||||
            abortController.abort();
 | 
			
		||||
            console.log("closing tooltip");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        window.addEventListener("wheel", () => tooltip.close(), {
 | 
			
		||||
            signal: abortController.signal,
 | 
			
		||||
            passive: true,
 | 
			
		||||
        });
 | 
			
		||||
        element.addEventListener("mouseleave", () => tooltip.close(), {
 | 
			
		||||
            signal: abortController.signal,
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        show,
 | 
			
		||||
        showOnHover() {
 | 
			
		||||
            element.addEventListener("mouseenter", show);
 | 
			
		||||
            return this;
 | 
			
		||||
        },
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,29 +0,0 @@
 | 
			
		|||
import { addSpell } from "treehouse/spells.js";
 | 
			
		||||
 | 
			
		||||
const settingsKey = "treehouse.settings";
 | 
			
		||||
const settings = JSON.parse(localStorage.getItem(settingsKey)) || {};
 | 
			
		||||
 | 
			
		||||
const defaultSettingValues = {
 | 
			
		||||
    showNewPostIndicator: true,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function saveSettings() {
 | 
			
		||||
    localStorage.setItem(settingsKey, JSON.stringify(settings));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getSettingValue(setting) {
 | 
			
		||||
    return settings[setting] ?? defaultSettingValues[setting];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class SettingCheckbox {
 | 
			
		||||
    constructor(element) {
 | 
			
		||||
        element.checked = getSettingValue(element.id);
 | 
			
		||||
 | 
			
		||||
        element.addEventListener("change", () => {
 | 
			
		||||
            settings[element.id] = element.checked;
 | 
			
		||||
            saveSettings();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
addSpell("setting-checkbox", SettingCheckbox);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +0,0 @@
 | 
			
		|||
// Bits and pieces to make the treehouse just a bit more easy to explore.
 | 
			
		||||
 | 
			
		||||
// We want to let the user have a selection on collapsible blocks without collapsing them when
 | 
			
		||||
// the user finishes marking their selection.
 | 
			
		||||
document.addEventListener("click", event => {
 | 
			
		||||
    if (getSelection().type == "Range") {
 | 
			
		||||
        event.preventDefault();
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -1,43 +0,0 @@
 | 
			
		|||
<!DOCTYPE html>
 | 
			
		||||
 | 
			
		||||
<html lang="en-US" prefix="og: https://ogp.me/ns#">
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
    {{> components/_head.hbs }}
 | 
			
		||||
 | 
			
		||||
    <link rel="stylesheet" href="{{ asset 'css/history.css' }}">
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
    <span></span>
 | 
			
		||||
    {{> components/_noscript.hbs }}
 | 
			
		||||
 | 
			
		||||
    {{> components/_nav.hbs }}
 | 
			
		||||
    {{> components/_header.hbs }}
 | 
			
		||||
 | 
			
		||||
    <main class="version-history">
 | 
			
		||||
        <p class="commit-count">{{ len page.commits }} commits</p>
 | 
			
		||||
        
 | 
			
		||||
        <ul class="commits">
 | 
			
		||||
            {{#each page.commits}}
 | 
			
		||||
            <li>
 | 
			
		||||
                <a class="revision-number" href="{{ ../config.site }}/{{ ../page.tree_path }}@{{ revision_number }}">#{{ revision_number }}</a>
 | 
			
		||||
                <a href="{{ ../config.commit_base_url }}/{{ hash }}/content/{{ ../page.tree_path }}.tree"><code>{{ hash_short }}</code></a>
 | 
			
		||||
 | 
			
		||||
                {{#if body}}
 | 
			
		||||
                <details>
 | 
			
		||||
                    <summary class="summary">{{ summary }}</summary>
 | 
			
		||||
                    {{ body }}
 | 
			
		||||
                </details>
 | 
			
		||||
                {{else}}
 | 
			
		||||
                <span class="summary">{{ summary }}</span>
 | 
			
		||||
                {{/if}}
 | 
			
		||||
            </li>
 | 
			
		||||
            {{/each}}
 | 
			
		||||
        </ul>
 | 
			
		||||
    </main>
 | 
			
		||||
 | 
			
		||||
    {{> components/_footer.hbs }}
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
| 
						 | 
				
			
			@ -11,7 +11,18 @@
 | 
			
		|||
    <link rel="stylesheet" href="{{ asset (cat 'css/' this) }}">
 | 
			
		||||
    {{/each}}
 | 
			
		||||
 | 
			
		||||
    <script type="module">
 | 
			
		||||
    <script type="module" async>
 | 
			
		||||
        import "treehouse/spells.js";
 | 
			
		||||
        import "treehouse/tree.js";
 | 
			
		||||
        import "treehouse/ulid.js";
 | 
			
		||||
 | 
			
		||||
        // We want to let the user have a selection on collapsible blocks without collapsing them when
 | 
			
		||||
        // the user finishes marking their selection.
 | 
			
		||||
        document.addEventListener("click", event => {
 | 
			
		||||
        if (getSelection().type == "Range") {
 | 
			
		||||
            event.preventDefault();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        {{!-- Go through the import map for each script. --}}
 | 
			
		||||
        {{#each page.scripts}}
 | 
			
		||||
        import "{{ this }}";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,11 +7,11 @@
 | 
			
		|||
<style>
 | 
			
		||||
    @font-face {
 | 
			
		||||
        font-family: "RecVar";
 | 
			
		||||
        src: url("{{ asset 'font/Recursive_VF_1.085.woff2' }}");
 | 
			
		||||
        src: url("{{{ asset 'font/recursive-casl0.woff2' }}}");
 | 
			
		||||
    }
 | 
			
		||||
</style>
 | 
			
		||||
<link rel="stylesheet" href="{{ asset 'css/base.css' }}">
 | 
			
		||||
<link rel="stylesheet" href="{{ asset 'css/main.css' }}">
 | 
			
		||||
<link rel="stylesheet" href="{{ asset 'css/noncritical.css' }}">
 | 
			
		||||
<link rel="stylesheet" href="{{ asset 'css/icons.css' }}">
 | 
			
		||||
 | 
			
		||||
{{!--
 | 
			
		||||
| 
						 | 
				
			
			@ -42,13 +42,6 @@ clever to do while browser vendors figure that out, we'll just have to do a cach
 | 
			
		|||
</script>
 | 
			
		||||
<script type="module" async>
 | 
			
		||||
    import "treehouse/command-line.js";
 | 
			
		||||
    import "treehouse/emoji.js";
 | 
			
		||||
    import "treehouse/overlay.js";
 | 
			
		||||
    import "treehouse/settings.js";
 | 
			
		||||
    import "treehouse/spells.js";
 | 
			
		||||
    import "treehouse/tree.js";
 | 
			
		||||
    import "treehouse/ulid.js";
 | 
			
		||||
    import "treehouse/usability.js";
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<meta property="og:site_name" content="{{ config.user.title }}">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,20 +0,0 @@
 | 
			
		|||
<noscript>
 | 
			
		||||
    <div class="noscript" role="note">
 | 
			
		||||
        <p>hey! looks like you have <strong>JavaScript disabled.</strong><br>
 | 
			
		||||
            I respect that decision, but you may find the experience of browsing the treehouse… not great.<br>
 | 
			
		||||
            for example, links to branches may not work properly. I cannot do anything about this; it's due to how
 | 
			
		||||
            the <code><details></code> element works.<br>
 | 
			
		||||
            (a <code><details></code> will not expand itself automatically to reveal the linked element to
 | 
			
		||||
            you.)<br>
 | 
			
		||||
            I did my best to at least keep the site readable in this state, but you can only do so much with plain
 | 
			
		||||
            HTML and CSS.</p>
 | 
			
		||||
 | 
			
		||||
        <p><strong>Pinky promise this website does not contain any malicious code such as trackers or cryptocurrency
 | 
			
		||||
                miners.</strong><br>
 | 
			
		||||
            if you don't believe me, you're free to inspect the source yourself! all the scripts are written
 | 
			
		||||
            lovingly in vanilla JS (not minified!) by yours truly ❤️</p>
 | 
			
		||||
        <small>and if this box is annoying, feel free to block it with uBlock Origin or something. I have no
 | 
			
		||||
            way of remembering you closed it, and don't wanna add a database to this website. simplicity
 | 
			
		||||
            rules!</small>
 | 
			
		||||
    </div>
 | 
			
		||||
</noscript>
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue