/* Main layout */ body { --main-min-size: 100vh; margin: 0; display: grid; grid-template-columns: [left] minmax(0, 1fr) [right] auto; grid-template-rows: [nav] auto [main] minmax(var(--main-min-size), auto) [virtual] 100vh; } html { /* Leave a bunch of space at the top when scrolling to elements. I'm honestly not sure why this is needed on and not the scrolled-to element... */ scroll-padding-top: 10vh; } .sidebar-sticky { grid-column: right; grid-row: main; } aside.sidebar { position: sticky; top: 0px; max-width: 50rem; height: 100vh; padding: 0.8rem; display: flex; } main { grid-column: left; grid-row: main; min-width: 0; } footer.pink-space { grid-column: 1 / -1; grid-row: virtual; } /* Narrower layout: sidebar is pushed to the top */ @media (max-width: 1280px) { body { --main-min-size: 0; } .sidebar-sticky { grid-column: left; grid-row: nav; display: flex; justify-content: center; } aside.sidebar { position: relative; height: auto; padding: 0; } } /* Choose more pretty colors than vanilla HTML */ body { background-color: var(--background-color); color: var(--text-color); } :root { scrollbar-color: var(--border-2) var(--shaded-background); scrollbar-width: auto; scrollbar-gutter: stable; } :focus-visible { outline: 0.1rem solid var(--accent-blue); outline-offset: 0.2rem; } ::selection { background-color: color-mix( in srgb, var(--background-color), var(--accent-pink) 75% ); color: var(--text-color); } @media (prefers-color-scheme: dark) { ::selection { background-color: var(--accent-pink); color: var(--background-color); } } /* Set up typography */ body, pre, code, kbd, button, select, input, dfn { font-family: "RecVar", sans-serif; font-style: normal; line-height: 1.5; text-size-adjust: none; } html { font-size: 62.5%; } body { font-size: 1.6rem; } pre, code, kbd, button, select, input { font-size: inherit; } :root { --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"; } *, *:before, *: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); } h1 { --recursive-wght: 900; font-size: 4.8rem; font-feature-settings: var(--recursive-simplified-r) 0; } h2 { --recursive-wght: 850; font-size: 3.2rem; } h3 { --recursive-wght: 850; font-size: 2.4rem; } h4 { --recursive-wght: 800; font-size: 1.6rem; } code { --recursive-mono: 0.5; } pre, pre code, kbd, th-literate-program { --recursive-mono: 1; --recursive-wght: 450; tab-size: 4; } strong code { --recursive-wght: 800; } b, strong { --recursive-wght: 700; } i, em { --recursive-slnt: -16; font-style: normal; } h1, h2, h3, h4, h5, h6 { text-wrap: balance; } /* Other classes for controlling typography */ .nowrap { white-space: nowrap; } /* Lay out elements a bit more compactly */ p, pre { margin: 0 0; } h1, h2, h3, h4, h5, h6 { margin: 0.4rem 0; } /* Make code examples a little prettier by giving them visual separation from the rest of the page */ code, th-literate-program { padding: 0.3rem 0.4rem; background-color: var(--shaded-background); border-radius: 0.4rem; } th-literate-program, th-literate-output { display: block; } kbd { padding: 0.3rem 0.6rem; border: 0.1rem solid var(--border-1); border-radius: 0.4rem; } pre, th-literate-program { padding: 0.8rem 1.2rem; margin: 1.2rem 0; background-color: var(--shaded-background); border-radius: 0.4em; transition: background-color var(--transition-duration); } @media (prefers-color-scheme: light) { pre, th-literate-program { background-color: transparent; border: 0.1rem solid var(--border-1); } } pre > code, th-literate-program > code { padding: 0; background: none; border-radius: 0; } th-literate-program { white-space: pre; } /* And don't let code examples fly off and overflow the window */ pre, th-literate-program { min-width: 0; width: auto; overflow: auto; } /* Images */ img { /* Prevent images from causing horizontal scrolling */ max-width: 100%; height: auto; } img.pic { border-radius: 0.6rem; margin: 0.8rem 0; } img { /* Hints for tweaking rendering */ &[src*="+pixel"] { image-rendering: pixelated; border-radius: 0; } &[src*="+illust"] { border-radius: 0; } /* TODO: These could be autogenerated! */ &[src*="+width72"] { width: 7.2rem; height: auto; } &[src*="+width160"] { width: 16rem; height: auto; } &[src*="+width640"] { width: 64rem; height: auto; } &[src*="+width752"] { width: 75.2rem; height: auto; } /* Resources for use in JavaScript. */ &.resource { display: none; } } /* Fix the default blue and ugly purple links normally have */ a { color: var(--link-color); } a:visited { color: var(--link-color-visited); } a.secret { color: var(--text-color); text-decoration: none; } /* Make blockquotes a bit prettier */ blockquote { margin: 0; padding: 0.4rem 1.2rem; margin: 0.4rem 0; border-left: 0.4rem solid var(--border-1); } /* And tables. */ table { margin: 0.8rem 0; } table, th, td { border: 0.1rem solid var(--border-2); border-collapse: collapse; padding: 0.4rem 1rem; } th { background-color: var(--shaded-background); --recursive-wght: 700; } /* Horizontal rules */ hr { width: 100%; border: none; border-top: 0.1rem solid var(--border-1); margin-top: 2em; margin-bottom: 2em; } /* 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 { display: flex; flex-direction: column; /* Titles */ & h2 { & a, & a:visited { color: var(--text-color); } & a:visited { color: color-mix( in srgb, var(--background-color), var(--text-color) 60% ); } } & h1 { --recursive-wght: 800; font-size: 125%; padding-top: 1.2rem; padding-bottom: 1.2rem; } & h2 { --recursive-wght: 600; font-size: 100%; padding: 0; } /* Articles */ & article { display: flex; flex-direction: column; padding-bottom: 1.2rem; line-height: 1.4; & .info { display: flex; flex-direction: row; flex-wrap: wrap; font-size: 87.5%; & > *:not(:first-child)::before { content: "ยท"; padding: 0 0.4rem; } } & .categories { display: flex; flex-direction: row; flex-wrap: wrap; list-style: none; margin: 0; padding: 0; & > *:not(:first-child) { padding-left: 1ch; } & a, & a:visited { color: var(--text-color); } } } } /* Page sidebar */ aside.sidebar { overflow: clip; & > a { display: block; height: min-content; margin-top: auto; } } header.floof { margin-top: auto; position: relative; & > img { display: block; min-width: 0; object-fit: cover; object-position: 33% 0; } & > h1 { position: absolute; top: 3rem; left: 3rem; display: flex; flex-direction: column; line-height: 1; width: min-content; --recursive-wght: 900; font-size: 5.6rem; text-align: right; transform: skew(-5deg, -5deg); & .rikis { width: max-content; background-color: var(--text-color); color: var(--background-color); 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 print("box-shadow:") x = 0 max_x = 16 while x < max_x: print(f"{x}px {x}px {math.pow(x / max_x, 2) * 16}px rgba(from var(--shadow-color) r g b / {math.pow(1 - x / max_x, 3)}),") x += 0.5 */ /* prettier-ignore */ box-shadow: 0px 0px 0.0px rgba(from var(--shadow-color) r g b / 1.0), 0.5px 0.5px 0.015625px rgba(from var(--shadow-color) r g b / 0.909149169921875), 1.0px 1.0px 0.0625px rgba(from var(--shadow-color) r g b / 0.823974609375), 1.5px 1.5px 0.140625px rgba(from var(--shadow-color) r g b / 0.744293212890625), 2.0px 2.0px 0.25px rgba(from var(--shadow-color) r g b / 0.669921875), 2.5px 2.5px 0.390625px rgba(from var(--shadow-color) r g b / 0.600677490234375), 3.0px 3.0px 0.5625px rgba(from var(--shadow-color) r g b / 0.536376953125), 3.5px 3.5px 0.765625px rgba(from var(--shadow-color) r g b / 0.476837158203125), 4.0px 4.0px 1.0px rgba(from var(--shadow-color) r g b / 0.421875), 4.5px 4.5px 1.265625px rgba(from var(--shadow-color) r g b / 0.371307373046875), 5.0px 5.0px 1.5625px rgba(from var(--shadow-color) r g b / 0.324951171875), 5.5px 5.5px 1.890625px rgba(from var(--shadow-color) r g b / 0.282623291015625), 6.0px 6.0px 2.25px rgba(from var(--shadow-color) r g b / 0.244140625), 6.5px 6.5px 2.640625px rgba(from var(--shadow-color) r g b / 0.209320068359375), 7.0px 7.0px 3.0625px rgba(from var(--shadow-color) r g b / 0.177978515625), 7.5px 7.5px 3.515625px rgba(from var(--shadow-color) r g b / 0.149932861328125), 8.0px 8.0px 4.0px rgba(from var(--shadow-color) r g b / 0.125), 8.5px 8.5px 4.515625px rgba(from var(--shadow-color) r g b / 0.102996826171875), 9.0px 9.0px 5.0625px rgba(from var(--shadow-color) r g b / 0.083740234375), 9.5px 9.5px 5.640625px rgba(from var(--shadow-color) r g b / 0.067047119140625), 10.0px 10.0px 6.25px rgba(from var(--shadow-color) r g b / 0.052734375), 10.5px 10.5px 6.890625px rgba(from var(--shadow-color) r g b / 0.040618896484375), 11.0px 11.0px 7.5625px rgba(from var(--shadow-color) r g b / 0.030517578125), 11.5px 11.5px 8.265625px rgba(from var(--shadow-color) r g b / 0.022247314453125), 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) ; } & .fluffy-little-house { display: flex; flex-direction: column; background-color: var(--background-color); width: min-content; align-self: end; padding-left: 0.8rem; padding-right: 0.8rem; padding-top: 0.4rem; z-index: -1; color: var(--text-color); & .adjectives { --recursive-wght: 800; font-size: 1.6rem; padding-top: 0.6rem; } & .house { margin-top: -0.2em; font-size: 3.6rem; } } } } /* Navigation header (contains page title & breadcrumbs) */ h1.page-title { --recursive-wght: 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; transition: var(--transition-duration) text-decoration-color; &:hover { text-decoration-color: var(--text-color); } } } @media (hover: none) { h1.page-title a { text-decoration: underline; } } @media (max-width: 700px) { h1.page-title { font-size: 4rem; } } 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 { width: 100%; max-width: 90ch; padding: 1.6rem 0.8rem; display: flex; flex-direction: row; & > .left { flex-grow: 1; } & > .right { flex-shrink: 0; } & #footer-icon { display: block; & > svg { display: block; color: var(--text-color); opacity: 40%; } } & #open-command-line { width: 3.2rem; height: 3.2rem; background: none; border: none; padding: 0; background-image: var(--icon-cmd); background-repeat: no-repeat; background-position: 50% 50%; opacity: 50%; transition: var(--transition-duration) opacity; &:hover { opacity: 100%; } &:active { opacity: 75%; } } } footer.pink-space { display: block; max-width: none; position: relative; & .copyright { position: absolute; right: 0; top: 0; opacity: 70%; padding: 1.6rem; } & pre.meow { position: absolute; right: 0; bottom: 0; width: min-content; background: none; border: none; --recursive-wght: 700; line-height: 1.3; font-size: 75%; opacity: 25%; user-select: none; } } /* Style dialogues */ dialog[open] { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); color: var(--text-color); background-color: var(--background-color); border: 0.1rem solid var(--border-1); border-radius: 1.2rem; } /* Style emojis to be readable */ img[data-cast~="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 { --recursive-mono: 1; display: none; flex-direction: column; background-color: var(--background-color-tooltip); font-size: 87.5%; &.visible { display: flex; position: fixed; left: 0; bottom: 0; width: 100%; } & > .input-wrapper { display: flex; flex-direction: row; align-items: center; padding: 0 0.4rem; width: 100%; &::before { content: ":"; padding-right: 0.2rem; opacity: 50%; } & > input { background: none; color: var(--text-color); border: none; flex-grow: 1; padding: 0.2rem 0; &:focus { outline: none; } } } & > ul.suggestions { list-style: none; display: flex; flex-direction: column; margin: 0; padding: 0; max-height: 25vh; overflow: auto; & > li { padding: 0.2rem 0.8rem; cursor: default; & > dfn { --recursive-crsv: 0; --recursive-wght: 700; margin-right: 2ch; } &:hover, &.tabbed { background-color: var(--accent-purple); color: white; } &.immediate { cursor: pointer; } } } } @media (hover: none) { th-command-line { & > ul.suggestions > li { border-bottom: 0.1rem solid var(--border-1); } } } @media (pointer: coarse) { th-command-line { & > .input-wrapper > input { padding: 0.8rem 0; } & > ul.suggestions > li { padding: 0.8rem 0.8rem; } } } /* Literate programming support */ :root { --error-color: #d94141; } @media (prefers-color-scheme: dark) { :root { --error-color: #e39393; } } th-literate-program[data-mode="input"] { /* Override the cursor with an I-beam, because the editor captures clicks and does not bubble them back up to the caller */ cursor: text; } th-literate-program[data-mode="output"] { padding: 0; background: none; border: none; border-radius: 0; & iframe, & img.placeholder-image { border-style: none; border-radius: 0.4rem; display: block; } & iframe { width: 100%; } & img.placeholder-image.js { transition: opacity var(--transition-duration); } & iframe, & img.placeholder-image.loading { opacity: 50%; } & iframe.loaded { opacity: 100%; } /* The inner iframe is hidden until something requests display. */ & iframe.hidden { display: none; } & pre > code { display: block; } & pre.error { color: var(--error-color); position: relative; &:empty { display: none; } &::after { content: "Error"; padding: 0.8rem; position: absolute; right: 0; top: 0; color: var(--text-color); opacity: 50%; } } & pre.console, & pre.placeholder-console { position: relative; margin-top: 0; margin-bottom: 0; &:empty { display: none; } &::after { content: "Console"; padding: 0.8rem; position: absolute; right: 0; top: 0; color: var(--text-color); opacity: 50%; } } } /* Syntax highlighting */ :root { --syntax-comment: #78579f; --syntax-identifier: var(--text-color); --syntax-keyword1: #b03b0d; --syntax-keyword2: #02739d; --syntax-operator: #ac4141; --syntax-function: #9940b9; --syntax-literal: #4c49a8; --syntax-string: #2c7754; --syntax-punct: #6c657b; } @media (prefers-color-scheme: dark) { :root { --syntax-comment: #a8a2b9; --syntax-identifier: var(--text-color); --syntax-keyword1: #ffb496; --syntax-keyword2: #98dcfd; --syntax-operator: #ffa5a5; --syntax-function: #ffde9e; --syntax-literal: #ffcaf4; --syntax-string: #d6fbaa; --syntax-punct: #a8a2b9; } } .th-syntax-highlighting span { &.comment { --recursive-slnt: -8; color: var(--syntax-comment); } &.identifier { color: var(--syntax-identifier); } &.keyword1 { color: var(--syntax-keyword1); } &.keyword2 { color: var(--syntax-keyword2); } &.operator { color: var(--syntax-operator); } &.function { color: var(--syntax-function); } &.literal { color: var(--syntax-literal); } &.string { color: var(--syntax-string); } &.punct { color: var(--syntax-punct); } &.error { color: var(--error-color); text-decoration: wavy underline; } &.hidden { display: none; } &.type-hint { color: var(--syntax-comment); font-size: 80%; } } .th-syntax-highlighting th-comment-columns { display: grid; grid-template-columns: repeat(2, max-content); } .th-syntax-highlighting { & .export { text-decoration: underline dotted; cursor: help; text-decoration-color: transparent; transition: text-decoration-color var(--transition-duration); } &:hover, &:focus { & .export { text-decoration-color: var(--syntax-keyword1); } } } /* 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; }